svn merge -r39930:39947 https://svn.blender.org/svnroot/bf-blender/trunk/blender
authorCampbell Barton <ideasman42@gmail.com>
Tue, 6 Sep 2011 00:31:00 +0000 (00:31 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 6 Sep 2011 00:31:00 +0000 (00:31 +0000)
215 files changed:
CMakeLists.txt
intern/ghost/intern/GHOST_NDOFManager.cpp
intern/opennl/CMakeLists.txt
intern/smoke/CMakeLists.txt
intern/smoke/SConscript
intern/smoke/intern/FFT_NOISE.h
intern/smoke/intern/WTURBULENCE.cpp
source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenkernel/intern/texture.c
source/blender/blenlib/BLI_math_inline.h
source/blender/blenlib/BLI_math_matrix.h
source/blender/blenlib/BLI_math_vector.h
source/blender/blenlib/intern/math_matrix.c
source/blender/blenlib/intern/math_vector.c
source/blender/blenlib/intern/noise.c
source/blender/blenloader/CMakeLists.txt
source/blender/blenloader/SConscript
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/collada/AnimationExporter.cpp
source/blender/collada/AnimationImporter.cpp
source/blender/collada/AnimationImporter.h
source/blender/collada/ArmatureImporter.cpp
source/blender/collada/CMakeLists.txt
source/blender/collada/DocumentImporter.cpp
source/blender/collada/ErrorHandler.cpp [new file with mode: 0644]
source/blender/collada/ErrorHandler.h [new file with mode: 0644]
source/blender/collada/TransformReader.cpp
source/blender/collada/collada.cpp
source/blender/editors/animation/anim_ops.c
source/blender/editors/include/ED_node.h
source/blender/editors/include/ED_sequencer.h
source/blender/editors/interface/interface_layout.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/sound/sound_ops.c
source/blender/editors/space_graph/graph_ops.c
source/blender/editors/space_logic/logic_ops.c
source/blender/editors/space_logic/logic_window.c
source/blender/editors/space_node/drawnode.c
source/blender/editors/space_node/node_buttons.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_header.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/node_ops.c
source/blender/editors/space_node/node_select.c
source/blender/editors/space_node/node_state.c
source/blender/editors/space_node/space_node.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/transform/transform_conversions.c
source/blender/gpu/SConscript
source/blender/imbuf/intern/cineon/cineonlib.c
source/blender/imbuf/intern/cineon/logImageCore.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/RNA_access.h
source/blender/makesrna/RNA_enum_types.h
source/blender/makesrna/RNA_types.h
source/blender/makesrna/SConscript
source/blender/makesrna/intern/CMakeLists.txt
source/blender/makesrna/intern/SConscript
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_actuator.c
source/blender/makesrna/intern/rna_main_api.c
source/blender/makesrna/intern/rna_nodetree.c
source/blender/makesrna/intern/rna_nodetree_types.h
source/blender/makesrna/intern/rna_object.c
source/blender/makesrna/intern/rna_particle.c
source/blender/makesrna/intern/rna_rna.c
source/blender/makesrna/intern/rna_scene.c
source/blender/makesrna/intern/rna_screen.c
source/blender/makesrna/intern/rna_smoke.c
source/blender/makesrna/intern/rna_space.c
source/blender/makesrna/intern/rna_texture.c
source/blender/makesrna/intern/rna_wm.c
source/blender/modifiers/CMakeLists.txt
source/blender/modifiers/SConscript
source/blender/nodes/CMakeLists.txt
source/blender/nodes/NOD_composite.h [moved from source/blender/nodes/CMP_node.h with 94% similarity]
source/blender/nodes/NOD_shader.h [moved from source/blender/nodes/SHD_node.h with 90% similarity]
source/blender/nodes/NOD_socket.h [new file with mode: 0644]
source/blender/nodes/NOD_texture.h [moved from source/blender/nodes/TEX_node.h with 91% similarity]
source/blender/nodes/SConscript
source/blender/nodes/composite/node_composite_tree.c [new file with mode: 0644]
source/blender/nodes/composite/node_composite_util.c [moved from source/blender/nodes/intern/CMP_util.c with 99% similarity]
source/blender/nodes/composite/node_composite_util.h [moved from source/blender/nodes/intern/CMP_util.h with 98% similarity]
source/blender/nodes/composite/nodes/node_composite_alphaOver.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_alphaOver.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_bilateralblur.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_bilateralblur.c with 91% similarity]
source/blender/nodes/composite/nodes/node_composite_blur.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_blur.c with 96% similarity]
source/blender/nodes/composite/nodes/node_composite_brightness.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_brightness.c with 81% similarity]
source/blender/nodes/composite/nodes/node_composite_channelMatte.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c with 90% similarity]
source/blender/nodes/composite/nodes/node_composite_chromaMatte.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c with 89% similarity]
source/blender/nodes/composite/nodes/node_composite_colorMatte.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_colorMatte.c with 85% similarity]
source/blender/nodes/composite/nodes/node_composite_colorSpill.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_colorSpill.c with 93% similarity]
source/blender/nodes/composite/nodes/node_composite_colorbalance.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_colorbalance.c with 91% similarity]
source/blender/nodes/composite/nodes/node_composite_common.c [new file with mode: 0644]
source/blender/nodes/composite/nodes/node_composite_composite.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_composite.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_crop.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_crop.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_curves.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_curves.c with 78% similarity]
source/blender/nodes/composite/nodes/node_composite_defocus.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_defocus.c with 97% similarity]
source/blender/nodes/composite/nodes/node_composite_diffMatte.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_diffMatte.c with 85% similarity]
source/blender/nodes/composite/nodes/node_composite_dilate.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_dilate.c with 88% similarity]
source/blender/nodes/composite/nodes/node_composite_directionalblur.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_directionalblur.c with 88% similarity]
source/blender/nodes/composite/nodes/node_composite_displace.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_displace.c with 89% similarity]
source/blender/nodes/composite/nodes/node_composite_distanceMatte.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_distanceMatte.c with 85% similarity]
source/blender/nodes/composite/nodes/node_composite_filter.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_filter.c with 93% similarity]
source/blender/nodes/composite/nodes/node_composite_flip.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_flip.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_gamma.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_gamma.c with 82% similarity]
source/blender/nodes/composite/nodes/node_composite_glare.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_glare.c with 96% similarity]
source/blender/nodes/composite/nodes/node_composite_hueSatVal.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_hueSatVal.c with 83% similarity]
source/blender/nodes/composite/nodes/node_composite_huecorrect.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_huecorrect.c with 88% similarity]
source/blender/nodes/composite/nodes/node_composite_idMask.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_idMask.c with 86% similarity]
source/blender/nodes/composite/nodes/node_composite_image.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_image.c with 94% similarity]
source/blender/nodes/composite/nodes/node_composite_invert.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_invert.c with 85% similarity]
source/blender/nodes/composite/nodes/node_composite_lensdist.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_lensdist.c with 90% similarity]
source/blender/nodes/composite/nodes/node_composite_levels.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_levels.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_lummaMatte.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_lummaMatte.c with 84% similarity]
source/blender/nodes/composite/nodes/node_composite_mapUV.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_mapUV.c with 91% similarity]
source/blender/nodes/composite/nodes/node_composite_mapValue.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_mapValue.c with 82% similarity]
source/blender/nodes/composite/nodes/node_composite_math.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_math.c with 90% similarity]
source/blender/nodes/composite/nodes/node_composite_mixrgb.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_mixrgb.c with 83% similarity]
source/blender/nodes/composite/nodes/node_composite_normal.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_normal.c with 74% similarity]
source/blender/nodes/composite/nodes/node_composite_normalize.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_normalize.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_outputFile.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_outputFile.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_premulkey.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_premulkey.c with 81% similarity]
source/blender/nodes/composite/nodes/node_composite_rgb.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_rgb.c with 66% similarity]
source/blender/nodes/composite/nodes/node_composite_rotate.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_rotate.c with 85% similarity]
source/blender/nodes/composite/nodes/node_composite_scale.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_scale.c with 85% similarity]
source/blender/nodes/composite/nodes/node_composite_sepcombHSVA.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_sepcombHSVA.c with 81% similarity]
source/blender/nodes/composite/nodes/node_composite_sepcombRGBA.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_sepcombRGBA.c with 79% similarity]
source/blender/nodes/composite/nodes/node_composite_sepcombYCCA.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_sepcombYCCA.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_sepcombYUVA.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_sepcombYUVA.c with 80% similarity]
source/blender/nodes/composite/nodes/node_composite_setalpha.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_setalpha.c with 83% similarity]
source/blender/nodes/composite/nodes/node_composite_splitViewer.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_splitViewer.c with 89% similarity]
source/blender/nodes/composite/nodes/node_composite_texture.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_texture.c with 91% similarity]
source/blender/nodes/composite/nodes/node_composite_tonemap.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_tonemap.c with 90% similarity]
source/blender/nodes/composite/nodes/node_composite_translate.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_translate.c with 75% similarity]
source/blender/nodes/composite/nodes/node_composite_valToRgb.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_valToRgb.c with 81% similarity]
source/blender/nodes/composite/nodes/node_composite_value.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_value.c with 67% similarity]
source/blender/nodes/composite/nodes/node_composite_vecBlur.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_vecBlur.c with 82% similarity]
source/blender/nodes/composite/nodes/node_composite_viewer.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_viewer.c with 87% similarity]
source/blender/nodes/composite/nodes/node_composite_zcombine.c [moved from source/blender/nodes/intern/CMP_nodes/CMP_zcombine.c with 90% similarity]
source/blender/nodes/intern/SHD_util.c [deleted file]
source/blender/nodes/intern/node_common.c [new file with mode: 0644]
source/blender/nodes/intern/node_common.h [new file with mode: 0644]
source/blender/nodes/intern/node_exec.c [new file with mode: 0644]
source/blender/nodes/intern/node_exec.h [new file with mode: 0644]
source/blender/nodes/intern/node_socket.c [new file with mode: 0644]
source/blender/nodes/intern/node_util.c
source/blender/nodes/intern/node_util.h
source/blender/nodes/shader/node_shader_tree.c [new file with mode: 0644]
source/blender/nodes/shader/node_shader_util.c [new file with mode: 0644]
source/blender/nodes/shader/node_shader_util.h [moved from source/blender/nodes/intern/SHD_util.h with 88% similarity]
source/blender/nodes/shader/nodes/node_shader_camera.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_camera.c with 80% similarity]
source/blender/nodes/shader/nodes/node_shader_common.c [new file with mode: 0644]
source/blender/nodes/shader/nodes/node_shader_curves.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_curves.c with 77% similarity]
source/blender/nodes/shader/nodes/node_shader_dynamic.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_dynamic.c with 99% similarity]
source/blender/nodes/shader/nodes/node_shader_geom.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_geom.c with 84% similarity]
source/blender/nodes/shader/nodes/node_shader_hueSatVal.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_hueSatVal.c with 77% similarity]
source/blender/nodes/shader/nodes/node_shader_invert.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_invert.c with 82% similarity]
source/blender/nodes/shader/nodes/node_shader_mapping.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_mapping.c with 87% similarity]
source/blender/nodes/shader/nodes/node_shader_material.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_material.c with 77% similarity]
source/blender/nodes/shader/nodes/node_shader_math.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_math.c with 93% similarity]
source/blender/nodes/shader/nodes/node_shader_mixRgb.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_mixRgb.c with 80% similarity]
source/blender/nodes/shader/nodes/node_shader_normal.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_normal.c with 69% similarity]
source/blender/nodes/shader/nodes/node_shader_output.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_output.c with 85% similarity]
source/blender/nodes/shader/nodes/node_shader_rgb.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_rgb.c with 66% similarity]
source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_sepcombRGB.c with 74% similarity]
source/blender/nodes/shader/nodes/node_shader_squeeze.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_squeeze.c with 72% similarity]
source/blender/nodes/shader/nodes/node_shader_texture.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_texture.c with 89% similarity]
source/blender/nodes/shader/nodes/node_shader_valToRgb.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_valToRgb.c with 78% similarity]
source/blender/nodes/shader/nodes/node_shader_value.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_value.c with 68% similarity]
source/blender/nodes/shader/nodes/node_shader_vectMath.c [moved from source/blender/nodes/intern/SHD_nodes/SHD_vectMath.c with 88% similarity]
source/blender/nodes/texture/node_texture_tree.c [new file with mode: 0644]
source/blender/nodes/texture/node_texture_util.c [moved from source/blender/nodes/intern/TEX_util.c with 78% similarity]
source/blender/nodes/texture/node_texture_util.h [moved from source/blender/nodes/intern/TEX_util.h with 93% similarity]
source/blender/nodes/texture/nodes/node_texture_at.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_at.c with 82% similarity]
source/blender/nodes/texture/nodes/node_texture_bricks.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_bricks.c with 76% similarity]
source/blender/nodes/texture/nodes/node_texture_checker.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_checker.c with 79% similarity]
source/blender/nodes/texture/nodes/node_texture_common.c [new file with mode: 0644]
source/blender/nodes/texture/nodes/node_texture_compose.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_compose.c with 71% similarity]
source/blender/nodes/texture/nodes/node_texture_coord.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_coord.c with 85% similarity]
source/blender/nodes/texture/nodes/node_texture_curves.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_curves.c with 80% similarity]
source/blender/nodes/texture/nodes/node_texture_decompose.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_decompose.c with 80% similarity]
source/blender/nodes/texture/nodes/node_texture_distance.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_distance.c with 84% similarity]
source/blender/nodes/texture/nodes/node_texture_hueSatVal.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c with 78% similarity]
source/blender/nodes/texture/nodes/node_texture_image.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_image.c with 88% similarity]
source/blender/nodes/texture/nodes/node_texture_invert.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_invert.c with 82% similarity]
source/blender/nodes/texture/nodes/node_texture_math.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_math.c with 88% similarity]
source/blender/nodes/texture/nodes/node_texture_mixRgb.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_mixRgb.c with 79% similarity]
source/blender/nodes/texture/nodes/node_texture_output.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_output.c with 89% similarity]
source/blender/nodes/texture/nodes/node_texture_proc.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_proc.c with 72% similarity]
source/blender/nodes/texture/nodes/node_texture_rotate.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_rotate.c with 84% similarity]
source/blender/nodes/texture/nodes/node_texture_scale.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_scale.c with 84% similarity]
source/blender/nodes/texture/nodes/node_texture_texture.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_texture.c with 84% similarity]
source/blender/nodes/texture/nodes/node_texture_translate.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_translate.c with 82% similarity]
source/blender/nodes/texture/nodes/node_texture_valToNor.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_valToNor.c with 80% similarity]
source/blender/nodes/texture/nodes/node_texture_valToRgb.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_valToRgb.c with 78% similarity]
source/blender/nodes/texture/nodes/node_texture_viewer.c [moved from source/blender/nodes/intern/TEX_nodes/TEX_viewer.c with 83% similarity]
source/blender/render/intern/source/render_texture.c
source/blender/windowmanager/intern/wm_event_system.c
source/blender/windowmanager/intern/wm_operators.c
source/blenderplayer/bad_level_call_stubs/stubs.c
source/creator/CMakeLists.txt
source/gameengine/Converter/BL_SkinDeformer.cpp
source/gameengine/Converter/KX_BlenderSceneConverter.cpp
source/gameengine/VideoTexture/CMakeLists.txt

index 38ce868..b54b18a 100644 (file)
@@ -1267,6 +1267,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
        ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_POINTER_ARITH -Wpointer-arith)
        ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNUSED_PARAMETER -Wunused-parameter)
        ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_WRITE_STRINGS -Wwrite-strings)
+       ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_UNDEFINED -Wundef)
        # disable because it gives warnings for printf() & friends.
        # ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_DOUBLE_PROMOTION -Wdouble-promotion -Wno-error=double-promotion)
        ADD_CHECK_C_COMPILER_FLAG(C_WARNINGS C_WARN_NO_ERROR_UNUSED_BUT_SET_VARIABLE -Wno-error=unused-but-set-variable)
@@ -1274,6 +1275,7 @@ if(CMAKE_COMPILER_IS_GNUCC)
        ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_ALL -Wall)
        ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_INVALID_OFFSETOF -Wno-invalid-offsetof)
        ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_NO_SIGN_COMPARE -Wno-sign-compare)
+       ADD_CHECK_CXX_COMPILER_FLAG(CXX_WARNINGS CXX_WARN_UNDEFINED -Wundef)
 
 elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
 
index a24ccc3..c2e6f27 100644 (file)
@@ -366,11 +366,11 @@ void GHOST_NDOFManager::setDeadZone(float dz)
        }
        else if (dz > 0.5f) {
                // warn the rogue user/programmer, but allow it
-               printf("ndof: dead zone of %.2f is rather high...\n", dz);
+               GHOST_PRINTF("ndof: dead zone of %.2f is rather high...\n", dz);
        }
        m_deadZone = dz;
 
-       printf("ndof: dead zone set to %.2f\n", dz);
+       GHOST_PRINTF("ndof: dead zone set to %.2f\n", dz);
 }
 
 static bool atHomePosition(GHOST_TEventNDOFMotionData* ndof)
index 55b0bc5..7d6a579 100644 (file)
@@ -31,6 +31,13 @@ remove_strict_flags()
 # and debug gives a lot of prints on UV unwrapping. developers can enable if they need to.
 remove_flag("-DDEBUG")
 
+
+# quiet compiler warnings about undefined defines
+add_definitions(
+       -DDEBUGlevel=0
+       -DPRNTlevel=0
+)
+
 set(INC
        extern
        superlu
index 094d398..228ff6e 100644 (file)
@@ -88,7 +88,7 @@ if(WITH_OPENMP)
 endif()
 
 if(WITH_FFTW3)
-       add_definitions(-DFFTW3=1)
+       add_definitions(-DWITH_FFTW3)
        list(APPEND INC
                ${FFTW3_INCLUDE_DIRS}
        )
index fa32c5f..0511257 100644 (file)
@@ -16,7 +16,7 @@ incs += ' ' + env['BF_PNG_INC'] + ' ' + env['BF_ZLIB_INC']
 incs += ' intern ../../extern/bullet2/src ../memutil ../guardealloc '
 
 if env['WITH_BF_FFTW3']:
-    defs += ' FFTW3=1'
+    defs += ' WITH_FFTW3'
     incs += env['BF_FFTW3_INC'] 
 
 env.BlenderLib ('bf_intern_smoke', sources, Split(incs), Split(defs), libtype=['intern'], priority=[40] )
index b0597d7..a087b4e 100644 (file)
@@ -25,7 +25,7 @@
 #ifndef FFT_NOISE_H_
 #define FFT_NOISE_H_
 
-#if FFTW3==1
+#ifdef WITH_FFTW3
 #include <iostream>
 #include <fftw3.h>
 #include <MERSENNETWISTER.h>
index 9934e30..cd18cf7 100644 (file)
@@ -155,7 +155,7 @@ void WTURBULENCE::setNoise(int type)
        if(type == (1<<1)) // FFT
        {
                // needs fft
-               #if FFTW3==1
+               #ifdef WITH_FFTW3
                std::string noiseTileFilename = std::string("noise.fft");
                generatTile_FFT(_noiseTile, noiseTileFilename);
                #endif
index 0f19cfb..742240d 100644 (file)
@@ -44,7 +44,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION                        259
-#define BLENDER_SUBVERSION             1
+#define BLENDER_SUBVERSION             2
 
 #define BLENDER_MINVERSION             250
 #define BLENDER_MINSUBVERSION  0
index e44b5d9..7207fb7 100644 (file)
  *  \ingroup bke
  */
 
+#include "DNA_listBase.h"
+
+#include "RNA_types.h"
+
 /* not very important, but the stack solver likes to know a maximum */
 #define MAX_SOCKET     64
 
@@ -46,63 +50,151 @@ struct bNodeLink;
 struct bNodeSocket;
 struct bNodeStack;
 struct bNodeTree;
+struct bNodeTreeExec;
 struct GPUMaterial;
 struct GPUNode;
 struct GPUNodeStack;
 struct ID;
 struct ListBase;
 struct Main;
+struct uiBlock;
+struct uiLayout;
 struct MTex;
 struct PointerRNA;
 struct rctf;
 struct RenderData;
 struct Scene;
 struct Tex;
-struct uiLayout;
-
+struct SpaceNode;
+struct ARegion;
+struct Object;
 
 /* ************** NODE TYPE DEFINITIONS ***** */
 
-typedef struct bNodeSocketType {
+/** Compact definition of a node socket.
+ * 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.
+ */
+typedef struct bNodeSocketTemplate {
        int type, limit;
-       const char *name;
-       float val1, val2, val3, val4;   /* default alloc value for inputs */
-       float min, max;                                 /* default range for inputs */
+       char name[32];
+       float val1, val2, val3, val4;   /* default alloc value for inputs */
+       float min, max;
+       PropertySubType subtype;
        
        /* after this line is used internal only */
-       struct bNodeSocket *sock;               /* used during verify_types */
+       struct bNodeSocket *sock;               /* used to hold verified socket */
+} 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[32];
+       char ui_description[128];
+       int ui_icon;
+       char ui_color[4];
+       
+       const char *value_structname;
+       int value_structsize;
+       
+       NodeSocketButtonFunction buttonfunc;
 } bNodeSocketType;
 
+/** Template for creating a node.
+ * Stored required parameters to make a new node of a specific type.
+ */
+typedef struct bNodeTemplate {
+       int type;
+       
+       /* group tree */
+       struct bNodeTree *ngroup;
+} bNodeTemplate;
+
+/** Defines a node type.
+ * Initial attributes and constants for a node as well as callback functions
+ * implementing the node behavior.
+ */
 typedef struct bNodeType {
        void *next,*prev;
+       short needs_free;               /* set for allocated types that need to be freed */
+       
        int type;
-       const char *name; /* can be allocated too */
+       char name[32];
        float width, minwidth, maxwidth;
+       float height, minheight, maxheight;
        short nclass, flag;
        
-       bNodeSocketType *inputs, *outputs;
+       /* templates for static sockets */
+       bNodeSocketTemplate *inputs, *outputs;
        
        char storagename[64];                   /* struct name for DNA */
        
-       void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
-       
-       /* this line is set on startup of blender */
+       /// Main draw function for the node.
+       void (*drawfunc)(const struct bContext *C, struct ARegion *ar, struct SpaceNode *snode, struct bNodeTree *ntree, struct bNode *node);
+       /// 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.
        void (*uifunc)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
+       /// Additional parameters in the side panel.
        void (*uifuncbut)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr);
+       /// Optional custom label function for the node header.
        const char *(*labelfunc)(struct bNode *);
-
-       void (*initfunc)(struct bNode *);
-       void (*freestoragefunc)(struct bNode *);
-       void (*copystoragefunc)(struct bNode *, struct bNode *);
+       /// Optional custom resize handle polling.
+       int (*resize_area_func)(struct bNode *node, int x, int y);
        
-       /* for use with dynamic typedefs */
-       ID *id;
-       void *pynode; /* holds pointer to python script */
-       void *pydict; /* holds pointer to python script dictionary (scope)*/
-
+       /// Called when the node is updated in the editor.
+       void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node);
+       /// Check and update if internal ID data has changed.
+       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);
+       
+       /// 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.
+        * \example Node groups can not be created inside their own node tree.
+        */
+       int (*validfunc)(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
+       
+       /// 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);
+       
+       
+       /* **** 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 **);
        /* 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);
 } bNodeType;
 
 /* node->exec, now in use for composites (#define for break is same as ready yes) */
@@ -113,72 +205,124 @@ typedef struct bNodeType {
 #define NODE_FREEBUFS  8
 #define NODE_SKIPPED   16
 
+/* sim_exec return value */
+#define NODE_EXEC_FINISHED     0
+#define NODE_EXEC_SUSPEND      1
+
 /* nodetype->nclass, for add-menu and themes */
-#define NODE_CLASS_INPUT               0
-#define NODE_CLASS_OUTPUT              1
-#define NODE_CLASS_OP_COLOR            3
-#define NODE_CLASS_OP_VECTOR   4
-#define NODE_CLASS_OP_FILTER   5
-#define NODE_CLASS_GROUP               6
-#define NODE_CLASS_FILE                        7
-#define NODE_CLASS_CONVERTOR   8
-#define NODE_CLASS_MATTE               9
-#define NODE_CLASS_DISTORT             10
-#define NODE_CLASS_OP_DYNAMIC  11
-#define NODE_CLASS_PATTERN 12
-#define NODE_CLASS_TEXTURE 13
+#define NODE_CLASS_INPUT                       0
+#define NODE_CLASS_OUTPUT                      1
+#define NODE_CLASS_OP_COLOR                    3
+#define NODE_CLASS_OP_VECTOR           4
+#define NODE_CLASS_OP_FILTER           5
+#define NODE_CLASS_GROUP                       6
+#define NODE_CLASS_FILE                                7
+#define NODE_CLASS_CONVERTOR           8
+#define NODE_CLASS_MATTE                       9
+#define NODE_CLASS_DISTORT                     10
+#define NODE_CLASS_OP_DYNAMIC          11
+#define NODE_CLASS_PATTERN                     12
+#define NODE_CLASS_TEXTURE                     13
+#define NODE_CLASS_EXECUTION           14
+#define NODE_CLASS_GETDATA                     15
+#define NODE_CLASS_SETDATA                     16
+#define NODE_CLASS_MATH                                17
+#define NODE_CLASS_MATH_VECTOR         18
+#define NODE_CLASS_MATH_ROTATION       19
+#define NODE_CLASS_PARTICLES           25
+#define NODE_CLASS_TRANSFORM           30
+#define NODE_CLASS_COMBINE                     31
+#define NODE_CLASS_LAYOUT                      100
 
 /* enum values for input/output */
 #define SOCK_IN                1
 #define SOCK_OUT       2
 
+struct bNodeTreeExec;
+
+typedef void (*bNodeTreeCallback)(void *calldata, struct ID *owner_id, struct bNodeTree *ntree);
+typedef struct bNodeTreeType
+{
+       int type;                                               /* type identifier */
+       char idname[64];                                /* id name for RNA identification */
+       
+       ListBase node_types;                    /* type definitions */
+       
+       /* 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 */
+
+       /* calls allowing threaded composite */
+       void (*localize)(struct bNodeTree *localtree, struct bNodeTree *ntree);
+       void (*local_sync)(struct bNodeTree *localtree, struct bNodeTree *ntree);
+       void (*local_merge)(struct bNodeTree *localtree, struct bNodeTree *ntree);
+
+       /* 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);
+} bNodeTreeType;
+
 /* ************** GENERIC API, TREES *************** */
 
-void                   ntreeVerifyTypes(struct bNodeTree *ntree);
+struct bNodeTreeType *ntreeGetType(int type);
+struct bNodeType *ntreeGetNodeType(struct bNodeTree *ntree);
+struct bNodeSocketType *ntreeGetSocketType(int type);
 
-struct bNodeTree *ntreeAddTree(const char *name, int type, const short is_group);
+struct bNodeTree *ntreeAddTree(const char *name, int type, int nodetype);
 void                   ntreeInitTypes(struct bNodeTree *ntree);
 
-//void                 ntreeMakeGroupSockets(struct bNodeTree *ntree);
-void                   ntreeUpdateType(struct bNodeTree *ntree, struct bNodeType *ntype);
 void                   ntreeFreeTree(struct bNodeTree *ntree);
 struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree);
 void                   ntreeSwitchID(struct bNodeTree *ntree, struct ID *sce_from, struct ID *sce_to);
 void                   ntreeMakeLocal(struct bNodeTree *ntree);
+int                            ntreeHasType(struct bNodeTree *ntree, int type);
 
 void                   ntreeSocketUseFlags(struct bNodeTree *ntree);
 
-void                   ntreeSolveOrder(struct bNodeTree *ntree);
+void                   ntreeUpdateTree(struct bNodeTree *ntree);
+/* XXX Currently each tree update call does call to ntreeVerifyNodes too.
+ * Some day this should be replaced by a decent depsgraph automatism!
+ */
+void                   ntreeVerifyNodes(struct Main *main, struct ID *id);
 
-void                   ntreeBeginExecTree(struct bNodeTree *ntree);
-void                   ntreeExecTree(struct bNodeTree *ntree, void *callerdata, int thread);
-void                   ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int do_previews);
-void                   ntreeEndExecTree(struct bNodeTree *ntree);
+void                   ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes);
 
+/* XXX old trees handle output flags automatically based on special output node types and last active selection.
+ * 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);
-                               
-                               /* calls allowing threaded composite */
+
+int                            ntreeNodeExists(struct bNodeTree *ntree, struct bNode *testnode);
+int                            ntreeOutputExists(struct bNode *node, struct bNodeSocket *testsock);
 struct bNodeTree *ntreeLocalize(struct bNodeTree *ntree);
 void                   ntreeLocalSync(struct bNodeTree *localtree, struct bNodeTree *ntree);
 void                   ntreeLocalMerge(struct bNodeTree *localtree, struct bNodeTree *ntree);
 
 /* ************** GENERIC API, NODES *************** */
 
-void                   nodeVerifyType(struct bNodeTree *ntree, struct bNode *node);
+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);
+void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
+void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
 
 void                   nodeAddToPreview(struct bNode *, float *, int, int, int);
 
+struct bNode   *nodeAddNode(struct bNodeTree *ntree, struct bNodeTemplate *ntemp);
 void                   nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
 void                   nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
-void                   nodeAddSockets(struct bNode *node, struct bNodeType *ntype);
-struct bNode   *nodeAddNodeType(struct bNodeTree *ntree, int type, struct bNodeTree *ngroup, struct ID *id);
-void                   nodeRegisterType(struct ListBase *typelist, const struct bNodeType *ntype) ;
-void                   nodeUpdateType(struct bNodeTree *ntree, struct bNode* node, struct bNodeType *ntype);
+
+void                   nodeRegisterType(struct ListBase *typelist, 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);
 
@@ -186,6 +330,10 @@ struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, s
 void                   nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
 void                   nodeRemSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
 
+void                   nodeSpaceCoords(struct bNode *node, float *locx, float *locy);
+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);
 
@@ -202,41 +350,71 @@ void                      NodeTagChanged(struct bNodeTree *ntree, struct bNode *node);
 int                            NodeTagIDChanged(struct bNodeTree *ntree, struct ID *id);
 void                   ntreeClearTags(struct bNodeTree *ntree);
 
-/* ************** Groups ****************** */
-
-struct bNode   *nodeMakeGroupFromSelected(struct bNodeTree *ntree);
-int                            nodeGroupUnGroup(struct bNodeTree *ntree, struct bNode *gnode);
-
-void                   nodeGroupVerify(struct bNodeTree *ngroup);
-void                   nodeGroupSocketUseFlags(struct bNodeTree *ngroup);
-
-void                   nodeGroupCopy(struct bNode *gnode);
+void                   nodeFreePreview(struct bNode *node);
 
-struct bNodeSocket *nodeGroupAddSocket(struct bNodeTree *ngroup, const char *name, int type, int in_out);
-struct bNodeSocket *nodeGroupExposeSocket(struct bNodeTree *ngroup, struct bNodeSocket *sock, int in_out);
-void                   nodeGroupExposeAllSockets(struct bNodeTree *ngroup);
-void                   nodeGroupRemoveSocket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out);
+/* ************** NODE TYPE ACCESS *************** */
 
-/* ************** COMMON NODES *************** */
+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);
 
 /* Init a new node type struct with default values and callbacks */
-void                   node_type_base(struct bNodeType *ntype, int type, const char *name, short nclass, short flag,
-                                                          struct bNodeSocketType *inputs, struct bNodeSocketType *outputs);
+void                   node_type_base(struct bNodeType *ntype, int type, 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_init(struct bNodeType *ntype, void (*initfunc)(struct bNode *));
+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_storage(struct bNodeType *ntype,
                                                                  const char *storagename,
                                                                  void (*freestoragefunc)(struct bNode *),
                                                                  void (*copystoragefunc)(struct bNode *, struct bNode *));
+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_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out));
-void                   node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *));
+void                   node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out));
+
+/* ************** COMMON NODES *************** */
 
 #define NODE_GROUP             2
-#define NODE_GROUP_MENU                1000
-#define NODE_DYNAMIC_MENU      4000
+#define NODE_FORLOOP   3
+#define NODE_WHILELOOP 4
+#define NODE_FRAME             5
+#define NODE_GROUP_MENU                10000
+#define NODE_DYNAMIC_MENU      20000
+
+/* 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);
+
+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);
 
-void register_node_type_group(ListBase *lb);
+struct bNode   *node_group_make_from_selected(struct bNodeTree *ntree);
+int                            node_group_ungroup(struct bNodeTree *ntree, struct bNode *gnode);
+
+/* in node_common.c */
+void register_node_type_frame(ListBase *lb);
 
 /* ************** SHADER NODES *************** */
 
@@ -286,11 +464,10 @@ struct ShadeResult;
 #define NODE_DYNAMIC_REPARSE   6 /* 64 */
 #define NODE_DYNAMIC_SET       15 /* sign */
 
-/* the type definitions array */
-extern struct ListBase node_all_shaders;
-
 /* API */
 
+struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree);
+void                   ntreeShaderEndExecTree(struct bNodeTreeExec *exec);
 void                   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);
@@ -415,11 +592,11 @@ void                      ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat);
 #define CMP_SCALE_RENDERPERCENT 3
 
 
-/* the type definitions array */
-extern struct ListBase node_all_composit;
-
 /* API */
 struct CompBuf;
+struct bNodeTreeExec *ntreeCompositBeginExecTree(struct bNodeTree *ntree);
+void ntreeCompositEndExecTree(struct bNodeTreeExec *exec);
+void ntreeCompositExecTree(struct bNodeTree *ntree, struct RenderData *rd, int do_previews);
 void ntreeCompositTagRender(struct Scene *sce);
 int ntreeCompositTagAnimated(struct bNodeTree *ntree);
 void ntreeCompositTagGenerators(struct bNodeTree *ntree);
@@ -459,23 +636,22 @@ struct TexResult;
 #define TEX_NODE_PROC      500
 #define TEX_NODE_PROC_MAX  600
 
-extern struct ListBase node_all_textures;
-
 /* API */
 int  ntreeTexTagAnimated(struct bNodeTree *ntree);
 void ntreeTexSetPreviewFlag(int);
-int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, int osatex, short thread, struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
 void ntreeTexCheckCyclics(struct bNodeTree *ntree);
 char* ntreeTexOutputMenu(struct bNodeTree *ntree);
 
+struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree);
+void ntreeTexEndExecTree(struct bNodeTreeExec *exec);
+int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, float *dxt, float *dyt, int osatex, short thread, struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex);
+
 
-/**/
+/*************************************************/
 
 void init_nodesystem(void);
 void free_nodesystem(void);
 
-/**/
-
 void clear_scene_in_nodes(struct Main *bmain, struct Scene *sce);
 
 #endif
index fac5bf1..3728dd4 100644 (file)
@@ -39,7 +39,6 @@
 
 struct PackedFile;
 struct bSound;
-struct bContext;
 struct ListBase;
 struct Main;
 struct Sequence;
@@ -65,12 +64,12 @@ struct bSound* sound_new_file(struct Main *main, const char *filename);
 
 // XXX unused currently
 #if 0
-struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source);
+struct bSound* sound_new_buffer(struct Main *bmain, struct bSound *source);
 
-struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, float start, float end);
+struct bSound* sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end);
 #endif
 
-void sound_delete(struct bContext *C, struct bSound* sound);
+void sound_delete(struct Main *bmain, struct bSound* sound);
 
 void sound_cache(struct bSound* sound);
 
@@ -124,7 +123,7 @@ void sound_play_scene(struct Scene *scene);
 
 void sound_stop_scene(struct Scene *scene);
 
-void sound_seek_scene(struct bContext *C);
+void sound_seek_scene(struct Main *bmain, struct Scene *scene);
 
 float sound_sync_scene(struct Scene *scene);
 
index 2961598..36631d5 100644 (file)
@@ -925,7 +925,8 @@ void init_render_material(Material *mat, int r_mode, float *amb)
        if(mat->nodetree && mat->use_nodes) {
                init_render_nodetree(mat->nodetree, mat, r_mode, amb);
                
-               ntreeBeginExecTree(mat->nodetree); /* has internal flag to detect it only does it once */
+               if (!mat->nodetree->execdata)
+                       mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree);
        }
 }
 
@@ -957,8 +958,10 @@ void init_render_materials(Main *bmain, int r_mode, float *amb)
 /* only needed for nodes now */
 void end_render_material(Material *mat)
 {
-       if(mat && mat->nodetree && mat->use_nodes)
-               ntreeEndExecTree(mat->nodetree); /* has internal flag to detect it only does it once */
+       if(mat && mat->nodetree && mat->use_nodes) {
+               if (mat->nodetree->execdata)
+                       ntreeShaderEndExecTree(mat->nodetree->execdata);
+       }
 }
 
 void end_render_materials(Main *bmain)
index 5f1a6c9..481893b 100644 (file)
 #include <limits.h>
 
 #include "DNA_anim_types.h"
-#include "DNA_action_types.h"
 #include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_action_types.h"
 
+#include "BLI_string.h"
+#include "BLI_math.h"
 #include "BLI_listbase.h"
-
-#include "RNA_access.h"
+#include "BLI_path_util.h"
+#include "BLI_utildefines.h"
 
 #include "BKE_animsys.h"
 #include "BKE_action.h"
 #include "BKE_fcurve.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
 #include "BKE_node.h"
 #include "BKE_utildefines.h"
+#include "BKE_utildefines.h"
 
-#include "PIL_time.h"
-
-#include "CMP_node.h"
-#include "intern/CMP_util.h"   /* stupid include path... */
+#include "BLI_listbase.h"
 
-#include "SHD_node.h"
-#include "TEX_node.h"
-#include "intern/TEX_util.h"
+#include "RNA_access.h"
 
-#include "GPU_material.h"
+#include "NOD_socket.h"
+#include "NOD_composite.h"
+#include "NOD_shader.h"
+#include "NOD_texture.h"
 
-static ListBase empty_list = {NULL, NULL};
-ListBase node_all_composit = {NULL, NULL};
-ListBase node_all_shaders = {NULL, NULL};
-ListBase node_all_textures = {NULL, NULL};
 
-/* ************** Type stuff **********  */
+bNodeTreeType *ntreeGetType(int type)
+{
+       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;
+       }
+       
+       if(type >= 0 && type < NUM_NTREE_TYPES) {
+               return types[type];
+       }
+       else {
+               return NULL;
+       }
+}
 
-static bNodeType *node_get_type(bNodeTree *ntree, int type, ID *id)
+static bNodeType *node_get_type(bNodeTree *ntree, int type)
 {
-       bNodeType *ntype = ntree->alltypes.first;
+       bNodeType *ntype = ntreeGetType(ntree->type)->node_types.first;
        for(; ntype; ntype= ntype->next)
-               if(ntype->type==type && id==ntype->id )
+               if(ntype->type==type)
                        return ntype;
        
        return NULL;
 }
 
-void ntreeInitTypes(bNodeTree *ntree)
+bNodeType *ntreeGetNodeType(bNodeTree *ntree)
 {
-       bNode *node, *next;
-       
-       if(ntree->type==NTREE_SHADER)
-               ntree->alltypes= node_all_shaders;
-       else if(ntree->type==NTREE_COMPOSIT)
-               ntree->alltypes= node_all_composit;
-       else if(ntree->type==NTREE_TEXTURE)
-               ntree->alltypes= node_all_textures;
+       return node_get_type(ntree, ntree->nodetype);
+}
+
+bNodeSocketType *ntreeGetSocketType(int type)
+{
+       static bNodeSocketType *types[NUM_SOCKET_TYPES]= {NULL};
+       static int types_init = 1;
+
+       if (types_init) {
+               node_socket_type_init(types);
+               types_init= 0;
+       }
+
+       if(type < NUM_SOCKET_TYPES) {
+               return types[type];
+       }
        else {
-               ntree->alltypes= empty_list;
-               printf("Error: no type definitions for nodes\n");
+               return NULL;
        }
+}
+
+void ntreeInitTypes(bNodeTree *ntree)
+{
+       bNode *node, *next;
        
        for(node= ntree->nodes.first; node; node= next) {
                next= node->next;
+               
+               node->typeinfo= node_get_type(ntree, node->type);
+               
                if(node->type==NODE_DYNAMIC) {
-                       bNodeType *stype= NULL;
-                       if(node->id==NULL) { /* empty script node */
-                               stype= node_get_type(ntree, node->type, NULL);
-                       } else { /* not an empty script node */
-                               stype= node_get_type(ntree, node->type, node->id);
-                               if(!stype) {
-                                       stype= node_get_type(ntree, node->type, NULL);
-                                       /* needed info if the pynode script fails now: */
-                                       if (node->id) node->storage= ntree;
-                               } else {
-                                       node->custom1= 0;
-                                       node->custom1= BSET(node->custom1,NODE_DYNAMIC_ADDEXIST);
-                               }
+                       /* needed info if the pynode script fails now: */
+                       node->storage= ntree;
+                       if(node->id!=NULL) { /* not an empty script node */
+                               node->custom1= 0;
+                               node->custom1= BSET(node->custom1,NODE_DYNAMIC_ADDEXIST);
                        }
-                       node->typeinfo= stype;
-                       if(node->typeinfo)
-                               node->typeinfo->initfunc(node);
-               } else {
-                       node->typeinfo= node_get_type(ntree, node->type, NULL);
+//                     if(node->typeinfo)
+//                             node->typeinfo->initfunc(node);
                }
 
                if(node->typeinfo==NULL) {
@@ -135,66 +158,51 @@ void ntreeInitTypes(bNodeTree *ntree)
        ntree->init |= NTREE_TYPE_INIT;
 }
 
-/* updates node with (modified) bNodeType.. this should be done for all trees */
-void ntreeUpdateType(bNodeTree *ntree, bNodeType *ntype)
+static bNodeSocket *make_socket(bNodeTree *UNUSED(ntree), int in_out, const char *name, int type)
 {
-       bNode *node;
-
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo== ntype) {
-                       nodeUpdateType(ntree, node, ntype);
-               }
-       }
+       bNodeSocketType *stype= ntreeGetSocketType(type);
+       bNodeSocket *sock;
+       
+       sock= MEM_callocN(sizeof(bNodeSocket), "sock");
+       
+       BLI_strncpy(sock->name, name, NODE_MAXSTR);
+       sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF);
+       sock->type= type;
+       sock->storage = NULL;
+       
+       if (stype->value_structsize > 0)
+               sock->default_value = MEM_callocN(stype->value_structsize, "default socket value");
+       
+       return sock;
 }
 
-/* only used internal... we depend on type definitions! */
-static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
+bNodeSocket *nodeAddSocket(bNodeTree *ntree, bNode *node, int in_out, const char *name, int type)
 {
-       bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock");
+       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);
        
-       BLI_strncpy(sock->name, stype->name, NODE_MAXSTR);
-       if(stype->limit==0) sock->limit= 0xFFF;
-       else sock->limit= stype->limit;
-       sock->type= stype->type;
+       ntree->update |= NTREE_UPDATE_NODES;
        
-       sock->ns.vec[0]= stype->val1;
-       sock->ns.vec[1]= stype->val2;
-       sock->ns.vec[2]= stype->val3;
-       sock->ns.vec[3]= stype->val4;
-       sock->ns.min= stype->min;
-       sock->ns.max= stype->max;
-       
-       if(lb)
-               BLI_addtail(lb, sock);
-
        return sock;
 }
 
-static bNodeSocket *node_add_group_socket(ListBase *lb, bNodeSocket *gsock)
+bNodeSocket *nodeInsertSocket(bNodeTree *ntree, bNode *node, int in_out, bNodeSocket *next_sock, const char *name, int type)
 {
-       bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock");
+       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);
        
-       /* make a copy of the group socket */
-       *sock = *gsock;
-       sock->link = NULL;
-       sock->next = sock->prev = NULL;
-       sock->new_sock = NULL;
-       sock->ns.data = NULL;
+       ntree->update |= NTREE_UPDATE_NODES;
        
-       sock->own_index = gsock->own_index;
-       sock->groupsock = gsock;
-       /* 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 = (gsock->limit==1 ? 0xFFF : 1);
-       
-       if(lb)
-               BLI_addtail(lb, sock);
-
        return sock;
 }
 
-static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock)
+void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
 {
        bNodeLink *link, *next;
        
@@ -205,428 +213,42 @@ static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock)
                }
        }
        
-       BLI_remlink(lb, sock);
-       MEM_freeN(sock);
-}
-
-static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
-{
-       bNodeSocket *sock;
-       
-       for(sock= lb->first; sock; sock= sock->next) {
-               if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0)
-                       break;
-       }
-       if(sock) {
-               sock->type= stype->type;                /* in future, read this from tydefs! */
-               if(stype->limit==0) sock->limit= 0xFFF;
-               else sock->limit= stype->limit;
-               
-               sock->ns.min= stype->min;
-               sock->ns.max= stype->max;
-               
-               BLI_remlink(lb, sock);
-               
-               return sock;
-       }
-       else {
-               return node_add_socket_type(NULL, stype);
-       }
-}
-
-static bNodeSocket *verify_group_socket(ListBase *lb, bNodeSocket *gsock)
-{
-       bNodeSocket *sock;
-       
-       for(sock= lb->first; sock; sock= sock->next) {
-               if(sock->own_index==gsock->own_index)
-                               break;
-       }
-       if(sock) {
-               sock->groupsock = gsock;
-               
-               strcpy(sock->name, gsock->name);
-               sock->type= 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 = (gsock->limit==1 ? 0xFFF : 1);
-               
-               sock->ns.min= gsock->ns.min;
-               sock->ns.max= gsock->ns.max;
-               
-               BLI_remlink(lb, sock);
-               
-               return sock;
-       }
-       else {
-               return node_add_group_socket(NULL, gsock);
-       }
-}
-
-static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *stype_first)
-{
-       bNodeSocketType *stype;
-       
-       /* no inputs anymore? */
-       if(stype_first==NULL) {
-               while(lb->first)
-                       node_rem_socket(ntree, lb, lb->first);
-       }
-       else {
-               /* step by step compare */
-               stype= stype_first;
-               while(stype->type != -1) {
-                       stype->sock= verify_socket(lb, stype);
-                       stype++;
-               }
-               /* leftovers are removed */
-               while(lb->first)
-                       node_rem_socket(ntree, lb, lb->first);
-               /* and we put back the verified sockets */
-               stype= stype_first;
-               while(stype->type != -1) {
-                       BLI_addtail(lb, stype->sock);
-                       stype++;
-               }
-       }
-}
-
-static void verify_group_socket_list(bNodeTree *ntree, ListBase *lb, ListBase *glb)
-{
-       bNodeSocket *gsock;
-       
-       /* step by step compare */
-       for (gsock= glb->first; gsock; gsock=gsock->next) {
-               /* abusing new_sock pointer for verification here! only used inside this function */
-               gsock->new_sock= verify_group_socket(lb, gsock);
-       }
-       /* leftovers are removed */
-       while(lb->first)
-               node_rem_socket(ntree, lb, lb->first);
-       /* and we put back the verified sockets */
-       for (gsock= glb->first; gsock; gsock=gsock->next) {
-               BLI_addtail(lb, gsock->new_sock);
-               gsock->new_sock = NULL;
-       }
-}
-
-void nodeVerifyType(bNodeTree *ntree, bNode *node)
-{
-       /* node groups don't have static sock lists, but use external sockets from the tree instead */
-       if (node->type==NODE_GROUP) {
-               bNodeTree *ngroup= (bNodeTree*)node->id;
-               if (ngroup) {
-                       verify_group_socket_list(ntree, &node->inputs, &ngroup->inputs);
-                       verify_group_socket_list(ntree, &node->outputs, &ngroup->outputs);
-               }
-       }
-       else {
-               bNodeType *ntype= node->typeinfo;
-               if(ntype) {
-                       verify_socket_list(ntree, &node->inputs, ntype->inputs);
-                       verify_socket_list(ntree, &node->outputs, ntype->outputs);
-               }
-       }
-}
-
-void ntreeVerifyTypes(bNodeTree *ntree)
-{
-       bNode *node;
-       
-       /* if((ntree->init & NTREE_TYPE_INIT)==0) */
-       ntreeInitTypes(ntree);
-
-       /* check inputs and outputs, and remove or insert them */
-       for(node= ntree->nodes.first; node; node= node->next)
-               nodeVerifyType(ntree, node);
+       /* this is fast, this way we don't need an in_out argument */
+       BLI_remlink(&node->inputs, sock);
+       BLI_remlink(&node->outputs, sock);
        
-}
-
-/* ************** Group stuff ********** */
-
-/* XXX group typeinfo struct is used directly in ntreeMakeOwnType, needs cleanup */
-static bNodeType ntype_group;
-
-/* groups display their internal tree name as label */
-static const char *group_label(bNode *node)
-{
-       return (node->id)? node->id->name+2: "Missing Datablock";
-}
-
-void register_node_type_group(ListBase *lb)
-{
-       node_type_base(&ntype_group, NODE_GROUP, "Group", NODE_CLASS_GROUP, NODE_OPTIONS, NULL, NULL);
-       node_type_size(&ntype_group, 120, 60, 200);
-       node_type_label(&ntype_group, group_label);
+       if (sock->default_value)
+               MEM_freeN(sock->default_value);
+       MEM_freeN(sock);
        
-       nodeRegisterType(lb, &ntype_group);
+       ntree->update |= NTREE_UPDATE_NODES;
 }
 
-static bNodeSocket *find_group_node_input(bNode *gnode, bNodeSocket *gsock)
+void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
 {
        bNodeSocket *sock;
-       for (sock=gnode->inputs.first; sock; sock=sock->next)
-               if (sock->groupsock == gsock)
-                       return sock;
-       return NULL;
-}
-
-static bNodeSocket *find_group_node_output(bNode *gnode, bNodeSocket *gsock)
-{
-       bNodeSocket *sock;
-       for (sock=gnode->outputs.first; sock; sock=sock->next)
-               if (sock->groupsock == gsock)
-                       return sock;
-       return NULL;
-}
-
-bNode *nodeMakeGroupFromSelected(bNodeTree *ntree)
-{
-       bNodeLink *link, *linkn;
-       bNode *node, *gnode, *nextn;
-       bNodeTree *ngroup;
-       bNodeSocket *gsock;
-       ListBase anim_basepaths = {NULL, NULL};
-       float min[2], max[2];
-       int totnode=0;
-       
-       INIT_MINMAX2(min, max);
-       
-       /* is there something to group? also do some clearing */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->flag & NODE_SELECT) {
-                       /* no groups in groups */
-                       if(node->type==NODE_GROUP)
-                               return NULL;
-                       DO_MINMAX2( (&node->locx), min, max);
-                       totnode++;
-               }
-               node->done= 0;
-       }
-       if(totnode==0) return NULL;
-       
-       /* 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->tonode->done |= 1;
-               if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT)
-                       link->fromnode->done |= 2;
-       }       
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if((node->flag & NODE_SELECT)==0)
-                       if(node->done==3)
-                               break;
-       }
-       if(node) 
-               return NULL;
+       bNodeLink *link, *next;
        
-       /* OK! new nodetree */
-       ngroup= ntreeAddTree("NodeGroup", ntree->type, TRUE);
-       
-       /* move nodes over */
-       for(node= ntree->nodes.first; node; node= nextn) {
-               nextn= node->next;
-               if(node->flag & NODE_SELECT) {
-                       /* 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));
-                       }
-                       
-                       /* change node-collection membership */
-                       BLI_remlink(&ntree->nodes, node);
-                       BLI_addtail(&ngroup->nodes, node);
-                       
-                       node->locx-= 0.5f*(min[0]+max[0]);
-                       node->locy-= 0.5f*(min[1]+max[1]);
-               }
-       }
-
-       /* 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);
+       for(link= ntree->links.first; link; link= next) {
+               next= link->next;
+               if(link->fromnode==node || link->tonode==node) {
+                       nodeRemLink(ntree, link);
                }
        }
        
-       /* make group node */
-       gnode= nodeAddNodeType(ntree, NODE_GROUP, ngroup, NULL);
-       gnode->locx= 0.5f*(min[0]+max[0]);
-       gnode->locy= 0.5f*(min[1]+max[1]);
+       for (sock=node->inputs.first; sock; sock=sock->next)
+               if (sock->default_value)
+                       MEM_freeN(sock->default_value);
+       BLI_freelistN(&node->inputs);
+       for (sock=node->outputs.first; sock; sock=sock->next)
+               if (sock->default_value)
+                       MEM_freeN(sock->default_value);
        
-       /* relink external sockets */
-       for(link= ntree->links.first; link; link= linkn) {
-               linkn= link->next;
-               
-               if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) {
-                       BLI_remlink(&ntree->links, link);
-                       BLI_addtail(&ngroup->links, link);
-               }
-               else if(link->tonode && (link->tonode->flag & NODE_SELECT)) {
-                       gsock = nodeGroupExposeSocket(ngroup, link->tosock, SOCK_IN);
-                       link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock);
-                       link->tosock = node_add_group_socket(&gnode->inputs, gsock);
-                       link->tonode = gnode;
-               }
-               else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) {
-                       /* 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 = nodeGroupExposeSocket(ngroup, link->fromsock, SOCK_OUT);
-                               gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock);
-                               link->fromsock = node_add_group_socket(&gnode->outputs, gsock);
-                       }
-                       else
-                               link->fromsock = find_group_node_output(gnode, gsock);
-                       link->fromnode = gnode;
-               }
-       }
-
-       /* update node levels */
-       ntreeSolveOrder(ntree);
-
-       return gnode;
-}
-
-/* here's a nasty little one, need to check users... */
-/* should become callbackable... */
-void nodeGroupVerify(bNodeTree *ngroup)
-{
-       /* group changed, so we rebuild the type definition */
-//     ntreeMakeGroupSockets(ngroup);
+       BLI_freelistN(&node->outputs);
        
-       if(ngroup->type==NTREE_SHADER) {
-               Material *ma;
-               for(ma= G.main->mat.first; ma; ma= ma->id.next) {
-                       if(ma->nodetree) {
-                               bNode *node;
-                               for(node= ma->nodetree->nodes.first; node; node= node->next)
-                                       if(node->id == (ID *)ngroup)
-                                               nodeVerifyType(ma->nodetree, node);
-                       }
-               }
-       }
-       else if(ngroup->type==NTREE_COMPOSIT) {
-               Scene *sce;
-               for(sce= G.main->scene.first; sce; sce= sce->id.next) {
-                       if(sce->nodetree) {
-                               bNode *node;
-                               for(node= sce->nodetree->nodes.first; node; node= node->next)
-                                       if(node->id == (ID *)ngroup)
-                                               nodeVerifyType(sce->nodetree, node);
-                       }
-               }
-       }
-       else if(ngroup->type==NTREE_TEXTURE) {
-               Tex *tx;
-               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
-                       if(tx->nodetree) {
-                               bNode *node;
-                               for(node= tx->nodetree->nodes.first; node; node= node->next)
-                                       if(node->id == (ID *)ngroup)
-                                               nodeVerifyType(tx->nodetree, node);
-                       }
-               }
-       }
+       ntree->update |= NTREE_UPDATE_NODES;
 }
 
-/* also to check all users of groups. Now only used in editor for hide/unhide */
-/* should become callbackable? */
-void nodeGroupSocketUseFlags(bNodeTree *ngroup)
-{
-       bNode *node;
-       bNodeSocket *sock;
-
-       /* clear flags */
-       for(node= ngroup->nodes.first; node; node= node->next) {
-               for(sock= node->inputs.first; sock; sock= sock->next)
-                       sock->flag &= ~SOCK_IN_USE;
-               for(sock= node->outputs.first; sock; sock= sock->next)
-                       sock->flag &= ~SOCK_IN_USE;
-       }
-       
-       /* tag all thats in use */
-       if(ngroup->type==NTREE_SHADER) {
-               Material *ma;
-               for(ma= G.main->mat.first; ma; ma= ma->id.next) {
-                       if(ma->nodetree) {
-                               for(node= ma->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id==&ngroup->id) {
-                                               for(sock= node->inputs.first; sock; sock= sock->next)
-                                                       if(sock->link)
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                               for(sock= node->outputs.first; sock; sock= sock->next)
-                                                       if(nodeCountSocketLinks(ma->nodetree, sock))
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                       }
-                               }
-                       }
-               }
-       }
-       else if(ngroup->type==NTREE_COMPOSIT) {
-               Scene *sce;
-               for(sce= G.main->scene.first; sce; sce= sce->id.next) {
-                       if(sce->nodetree) {
-                               for(node= sce->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id==(ID *)ngroup) {
-                                               for(sock= node->inputs.first; sock; sock= sock->next)
-                                                       if(sock->link)
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                               for(sock= node->outputs.first; sock; sock= sock->next)
-                                                       if(nodeCountSocketLinks(sce->nodetree, sock))
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                       }
-                               }
-                       }
-               }
-       }
-       else if(ngroup->type==NTREE_TEXTURE) {
-               Tex *tx;
-               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
-                       if(tx->nodetree) {
-                               for(node= tx->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id==(ID *)ngroup) {
-                                               for(sock= node->inputs.first; sock; sock= sock->next)
-                                                       if(sock->link)
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                               for(sock= node->outputs.first; sock; sock= sock->next)
-                                                       if(nodeCountSocketLinks(tx->nodetree, sock))
-                                                               if(sock->groupsock) 
-                                                                       sock->groupsock->flag |= SOCK_IN_USE;
-                                       }
-                               }
-                       }
-               }
-       }
-       
-}
 /* finds a node based on its name */
 bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
 {
@@ -669,341 +291,70 @@ int nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **nodep, int *sockin
        return 0;
 }
 
-/* returns 1 if its OK */
-int nodeGroupUnGroup(bNodeTree *ntree, bNode *gnode)
+/* ************** Add stuff ********** */
+static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype)
 {
-       bNodeLink *link, *linkn;
-       bNode *node, *nextn;
-       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
-        */
-       wgroup= ntreeCopyTree(ngroup);
-       
-       /* 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 pat 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);
+       bNodeSocketTemplate *sockdef;
+       bNodeSocket *sock;
+
+       if(ntype->inputs) {
+               sockdef= ntype->inputs;
+               while(sockdef->type != -1) {
+                       sock = node_add_input_from_template(ntree, node, sockdef);
                        
-                       if (path)
-                               BLI_addtail(&anim_basepaths, BLI_genericNodeN(path));
-               }
-               
-               /* migrate node */
-               BLI_remlink(&wgroup->nodes, node);
-               BLI_addtail(&ntree->nodes, node);
-               
-               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= find_group_node_input(gnode, gsock->link->fromsock);
-                                               if (insock->link) {
-                                                       link->fromnode = insock->link->fromnode;
-                                                       link->fromsock = insock->link->fromsock;
-                                               }
-                                       }
-                               }
-                               else {
-                                       /* constant group output: copy the stack value to the external socket.
-                                        * the link is kept here until all possible external users have been fixed.
-                                        */
-                                       QUATCOPY(link->tosock->ns.vec, gsock->ns.vec);
-                               }
-                       }
-               }
-       }
-       /* 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= 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 {
-                               /* uses group constant input. copy the input value and remove the dead link. */
-                               QUATCOPY(link->tosock->ns.vec, insock->ns.vec);
-                               nodeRemLink(wgroup, link);
-                       }
+                       sockdef++;
                }
        }
-       
-       /* 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 */
-       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 = copy_action(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;
+       if(ntype->outputs) {
+               sockdef= ntype->outputs;
+               while(sockdef->type != -1) {
+                       sock = node_add_output_from_template(ntree, node, sockdef);
                        
-                       MEM_freeN(ld->data);
-                       BLI_freelinkN(&anim_basepaths, ld);
+                       sockdef++;
                }
-               
-               /* free temp action too */
-               free_libblock(&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) */
-       free_libblock(&G.main->nodetree, wgroup);
-       
-       /* solve order goes fine, but the level tags not... doing it twice works for now. solve this once */
-       /* XXX is this still necessary with new groups? it may have been caused by non-updated sock->link pointers. lukas */
-       ntreeSolveOrder(ntree);
-       ntreeSolveOrder(ntree);
-
-       return 1;
 }
 
-void nodeGroupCopy(bNode *gnode)
-{
-       bNodeSocket *sock;
-
-       gnode->id->us--;
-       gnode->id= (ID *)ntreeCopyTree((bNodeTree *)gnode->id);
-
-       /* new_sock was set in nodeCopyNode */
-       for(sock=gnode->inputs.first; sock; sock=sock->next)
-               if(sock->groupsock)
-                       sock->groupsock= sock->groupsock->new_sock;
-
-       for(sock=gnode->outputs.first; sock; sock=sock->next)
-               if(sock->groupsock)
-                       sock->groupsock= sock->groupsock->new_sock;
-}
-
-bNodeSocket *nodeGroupAddSocket(bNodeTree *ngroup, const char *name, int type, int in_out)
-{
-       bNodeSocket *gsock = MEM_callocN(sizeof(bNodeSocket), "bNodeSocket");
-       
-       strncpy(gsock->name, name, sizeof(gsock->name));
-       gsock->type = type;
-       gsock->ns.sockettype = type;
-       gsock->ns.min = INT_MIN;
-       gsock->ns.max = INT_MAX;
-       zero_v4(gsock->ns.vec);
-       gsock->ns.data = NULL;
-       gsock->flag = 0;
-
-       gsock->next = gsock->prev = NULL;
-       gsock->new_sock = NULL;
-       gsock->link = NULL;
-       gsock->ns.data = NULL;
-       /* assign new unique index */
-       gsock->own_index = ngroup->cur_index++;
-       gsock->limit = (in_out==SOCK_IN ? 0xFFF : 1);
-       
-       BLI_addtail(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, gsock);
-       
-       return gsock;
-}
-
-bNodeSocket *nodeGroupExposeSocket(bNodeTree *ngroup, bNodeSocket *sock, int in_out)
-{
-       bNodeSocket *gsock= nodeGroupAddSocket(ngroup, sock->name, sock->type, in_out);
-       /* initialize the default socket value */
-       QUATCOPY(gsock->ns.vec, sock->ns.vec);
-       return gsock;
-}
-
-void nodeGroupExposeAllSockets(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 && !(sock->flag & SOCK_HIDDEN)) {
-                               gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_IN);
-                               /* initialize the default socket value */
-                               QUATCOPY(gsock->ns.vec, sock->ns.vec);
-                               sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
-                       }
-               }
-               for (sock=node->outputs.first; sock; sock=sock->next) {
-                       if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) {
-                               gsock = nodeGroupAddSocket(ngroup, sock->name, sock->type, SOCK_OUT);
-                               /* initialize the default socket value */
-                               QUATCOPY(gsock->ns.vec, sock->ns.vec);
-                               gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
-                       }
-               }
-       }
-}
-
-void nodeGroupRemoveSocket(bNodeTree *ngroup, bNodeSocket *gsock, int in_out)
-{
-       nodeRemSocketLinks(ngroup, gsock);
-       switch (in_out) {
-       case SOCK_IN:   BLI_remlink(&ngroup->inputs, gsock);    break;
-       case SOCK_OUT:  BLI_remlink(&ngroup->outputs, gsock);   break;
-       }
-       MEM_freeN(gsock);
-}
-
-/* ************** Add stuff ********** */
-void nodeAddSockets(bNode *node, bNodeType *ntype)
-{
-       if (node->type==NODE_GROUP) {
-               bNodeTree *ntree= (bNodeTree*)node->id;
-               if (ntree) {
-                       bNodeSocket *gsock;
-                       for (gsock=ntree->inputs.first; gsock; gsock=gsock->next)
-                               node_add_group_socket(&node->inputs, gsock);
-                       for (gsock=ntree->outputs.first; gsock; gsock=gsock->next)
-                               node_add_group_socket(&node->outputs, gsock);
-               }
-       }
-       else {
-               bNodeSocketType *stype;
-               
-               if(ntype->inputs) {
-                       stype= ntype->inputs;
-                       while(stype->type != -1) {
-                               node_add_socket_type(&node->inputs, stype);
-                               stype++;
-                       }
-               }
-               if(ntype->outputs) {
-                       stype= ntype->outputs;
-                       while(stype->type != -1) {
-                               node_add_socket_type(&node->outputs, stype);
-                               stype++;
-                       }
-               }
-       }
-}
-
-/* Find the first available, non-duplicate name for a given node */
-void nodeUniqueName(bNodeTree *ntree, bNode *node)
+/* Find the first available, non-duplicate name for a given node */
+void nodeUniqueName(bNodeTree *ntree, bNode *node)
 {
        BLI_uniquename(&ntree->nodes, node, "Node", '.', offsetof(bNode, name), sizeof(node->name));
 }
 
-bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
+bNode *nodeAddNode(bNodeTree *ntree, struct bNodeTemplate *ntemp)
 {
-       bNode *node= NULL;
-       bNodeType *ntype= NULL;
-
-       if (ngroup && BLI_findindex(&G.main->nodetree, ngroup)==-1) {
-               printf("nodeAddNodeType() error: '%s' not in main->nodetree\n", ngroup->id.name);
-               return NULL;
-       }
-
-       if(type>=NODE_DYNAMIC_MENU) {
-               int a=0, idx= type-NODE_DYNAMIC_MENU;
-               ntype= ntree->alltypes.first;
-               while(ntype) {
-                       if(ntype->type==NODE_DYNAMIC) {
-                               if(a==idx)
-                                       break;
-                               a++;
-                       }
-                       ntype= ntype->next;
-               }
-       } else
-               ntype= node_get_type(ntree, type, id);
-
+       bNode *node;
+       bNodeType *ntype;
+       
+       ntype= node_get_type(ntree, ntemp->type);
        if(ntype == NULL) {
-               printf("nodeAddNodeType() error: '%d' type invalid\n", type);
+               printf("nodeAddNodeType() error: '%d' type invalid\n", ntemp->type);
                return NULL;
        }
-
-       node= MEM_callocN(sizeof(bNode), "new node");
-       BLI_addtail(&ntree->nodes, node);
-       node->typeinfo= ntype;
-       if(type>=NODE_DYNAMIC_MENU)
-               node->custom2= type; /* for node_dynamic_init */
-
-       if(ngroup)
-               BLI_strncpy(node->name, ngroup->id.name+2, NODE_MAXSTR);
-       else if(type>NODE_DYNAMIC_MENU) {
-               BLI_strncpy(node->name, ntype->id->name+2, NODE_MAXSTR);
-       }
-       else
-               BLI_strncpy(node->name, ntype->name, NODE_MAXSTR);
-
-       nodeUniqueName(ntree, node);
+       /* 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;         /* small value only, allows print of first chars */
-
-       if(type==NODE_GROUP)
-               node->id= (ID *)ngroup;
-
-       /* need init handler later? */
-       /* got it-bob*/
+       node->miniwidth= 42.0f;
+       node->height= ntype->height;
+       
+       node_add_sockets_from_type(ntree, node, ntype);
+       
        if(ntype->initfunc!=NULL)
-               ntype->initfunc(node);
+               ntype->initfunc(ntree, node, ntemp);
        
-       nodeAddSockets(node, ntype);
+       /* initialize the node name with the node label */
+       BLI_strncpy(node->name, nodeLabel(node), NODE_MAXSTR);
+       nodeUniqueName(ntree, node);
+       
+       BLI_addtail(&ntree->nodes, node);
+       
+       ntree->update |= NTREE_UPDATE_NODES;
        
        return node;
 }
@@ -1011,9 +362,9 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
 void nodeMakeDynamicType(bNode *node)
 {
        /* find SH_DYNAMIC_NODE ntype */
-       bNodeType *ntype= node_all_shaders.first;
+       bNodeType *ntype= ntreeGetType(NTREE_SHADER)->node_types.first;
        while(ntype) {
-               if(ntype->type==NODE_DYNAMIC && ntype->id==NULL)
+               if(ntype->type==NODE_DYNAMIC)
                        break;
                ntype= ntype->next;
        }
@@ -1023,17 +374,11 @@ void nodeMakeDynamicType(bNode *node)
                /*node->typeinfo= MEM_dupallocN(ntype);*/
                bNodeType *newtype= MEM_callocN(sizeof(bNodeType), "dynamic bNodeType");
                *newtype= *ntype;
-               newtype->name= BLI_strdup(ntype->name);
+               strcpy(newtype->name, ntype->name);
                node->typeinfo= newtype;
        }
 }
 
-void nodeUpdateType(bNodeTree *ntree, bNode* node, bNodeType *ntype)
-{
-       verify_socket_list(ntree, &node->inputs, ntype->inputs);
-       verify_socket_list(ntree, &node->outputs, ntype->outputs);
-}
-
 /* keep socket listorder identical, for copying links */
 /* ntree is the target tree */
 bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
@@ -1045,19 +390,23 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
        nodeUniqueName(ntree, nnode);
        
        BLI_addtail(&ntree->nodes, nnode);
-       
+
        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 = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL);
        }
        
        BLI_duplicatelist(&nnode->outputs, &node->outputs);
        oldsock= node->outputs.first;
        for(sock= nnode->outputs.first; sock; sock= sock->next, oldsock= oldsock->next) {
-               sock->stack_index= 0;
-               sock->ns.data= NULL;
                oldsock->new_sock= sock;
+               sock->stack_index= 0;
+               
+               sock->default_value = (oldsock->default_value ? MEM_dupallocN(oldsock->default_value) : NULL);
        }
        
        /* don't increase node->id users, freenode doesn't decrement either */
@@ -1069,10 +418,11 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
        nnode->new_node= NULL;
        nnode->preview= NULL;
        
+       ntree->update |= NTREE_UPDATE_NODES;
+       
        return nnode;
 }
 
-/* fromsock and tosock can be NULL */
 /* 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)
 {
@@ -1095,6 +445,21 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock,
                                from= -1; /* OK but flip */
                }
        }
+       else {
+               /* 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)
@@ -1109,8 +474,22 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock,
                                to= -1; /* OK but flip */
                }
        }
+       else {
+               /* 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 */
+               }
+       }
        
-       /* this allows NULL sockets to work */
        if(from >= 0 && to >= 0) {
                link= MEM_callocN(sizeof(bNodeLink), "link");
                BLI_addtail(&ntree->links, link);
@@ -1128,6 +507,8 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock,
                link->tosock= fromsock;
        }
        
+       ntree->update |= NTREE_UPDATE_LINKS;
+       
        return link;
 }
 
@@ -1137,6 +518,8 @@ void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
        if(link->tosock)
                link->tosock->link= NULL;
        MEM_freeN(link);
+       
+       ntree->update |= NTREE_UPDATE_LINKS;
 }
 
 void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
@@ -1149,26 +532,73 @@ void nodeRemSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
                        nodeRemLink(ntree, link);
                }
        }
+       
+       ntree->update |= NTREE_UPDATE_LINKS;
 }
 
+/* transforms node location to area coords */
+void nodeSpaceCoords(bNode *node, float *locx, float *locy)
+{
+       if (node->parent) {
+               nodeSpaceCoords(node->parent, locx, locy);
+               *locx += node->locx;
+               *locy += node->locy;
+       }
+       else {
+               *locx = node->locx;
+               *locy = node->locy;
+       }
+}
 
-bNodeTree *ntreeAddTree(const char *name, int type, const short is_group)
+void nodeAttachNode(bNode *node, bNode *parent)
 {
-       bNodeTree *ntree;
+       float parentx, parenty;
+       
+       node->parent = parent;
+       /* transform to parent space */
+       nodeSpaceCoords(parent, &parentx, &parenty);
+       node->locx -= parentx;
+       node->locy -= parenty;
+}
 
-       if (is_group)
-               ntree= alloc_libblock(&G.main->nodetree, ID_NT, name);
-       else {
+void nodeDetachNode(struct bNode *node)
+{
+       float parentx, parenty;
+       
+       if (node->parent) {
+               /* transform to "global" (area) space */
+               nodeSpaceCoords(node->parent, &parentx, &parenty);
+               node->locx += parentx;
+               node->locy += parenty;
+               node->parent = NULL;
+       }
+}
+
+bNodeTree *ntreeAddTree(const char *name, int type, int nodetype)
+{
+       bNodeTree *ntree;
+       bNodeType *ntype;
+       
+       /* trees are created as local trees if they of compositor, material or texture type,
+        * node groups and other tree types are created as library data.
+        */
+       if (ELEM3(type, NTREE_COMPOSIT, NTREE_SHADER, NTREE_TEXTURE) && nodetype==0) {
                ntree= MEM_callocN(sizeof(bNodeTree), "new node tree");
                *( (short *)ntree->id.name )= ID_NT; /* not "type", as that is ntree->type */
                BLI_strncpy(ntree->id.name+2, name, sizeof(ntree->id.name));
        }
-
+       else
+               ntree= alloc_libblock(&G.main->nodetree, ID_NT, name);
+       
        ntree->type= type;
-       ntree->alltypes.first = NULL;
-       ntree->alltypes.last = NULL;
-
+       ntree->nodetype = nodetype;
+       
        ntreeInitTypes(ntree);
+       
+       ntype = node_get_type(ntree, ntree->nodetype);
+       if (ntype && ntype->inittreefunc)
+               ntype->inittreefunc(ntree);
+       
        return ntree;
 }
 
@@ -1199,9 +629,7 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree)
        id_us_plus((ID *)newtree->gpd);
 
        /* in case a running nodetree is copied */
-       newtree->init &= ~(NTREE_EXEC_INIT);
-       newtree->threadstack= NULL;
-       newtree->stack= NULL;
+       newtree->execdata= NULL;
        
        newtree->nodes.first= newtree->nodes.last= NULL;
        newtree->links.first= newtree->links.last= NULL;
@@ -1210,7 +638,10 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree)
        for(node= ntree->nodes.first; node; node= node->next) {
                node->new_node= NULL;
                nnode= nodeCopyNode(newtree, node);     /* sets node->new */
-               if(node==last) break;
+               
+               /* make sure we don't copy new nodes again! */
+               if (node==last)
+                       break;
        }
        
        /* socket definition for group usage */
@@ -1218,14 +649,15 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree)
        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 = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL);
        }
-       
        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 = (oldgsock->default_value ? MEM_dupallocN(oldgsock->default_value) : NULL);
        }
-
+       
        /* copy links */
        BLI_duplicatelist(&newtree->links, &ntree->links);
        for(link= newtree->links.first; link; link= link->next) {
@@ -1237,7 +669,13 @@ bNodeTree *ntreeCopyTree(bNodeTree *ntree)
                if (link->tosock)
                        link->tosock->link = link;
        }
-
+       
+       /* update node->parent pointers */
+       for (node=newtree->nodes.first; node; node=node->next) {
+               if (node->parent)
+                       node->parent = node->parent->new_node;
+       }
+       
        return newtree;
 }
 
@@ -1256,7 +694,7 @@ void ntreeSwitchID(bNodeTree *ntree, ID *id_from, ID *id_to)
 /* *************** preview *********** */
 /* if node->preview, then we assume the rect to exist */
 
-static void node_free_preview(bNode *node)
+void nodeFreePreview(bNode *node)
 {
        if(node->preview) {
                if(node->preview->rect)
@@ -1360,7 +798,6 @@ void nodeAddToPreview(bNode *node, float *col, int x, int y, int do_manage)
        }
 }
 
-
 /* ************** Free stuff ********** */
 
 /* goes over entire tree */
@@ -1395,50 +832,84 @@ void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
        }
 }
 
-static void composit_free_node_cache(bNode *node)
+static void node_unlink_attached(bNodeTree *ntree, bNode *parent)
 {
-       bNodeSocket *sock;
-       
-       for(sock= node->outputs.first; sock; sock= sock->next) {
-               if(sock->ns.data) {
-                       free_compbuf(sock->ns.data);
-                       sock->ns.data= NULL;
-               }
+       bNode *node;
+       for (node=ntree->nodes.first; node; node=node->next) {
+               if (node->parent == parent)
+                       nodeDetachNode(node);
        }
 }
 
 void nodeFreeNode(bNodeTree *ntree, bNode *node)
 {
+       bNodeTreeType *treetype= ntreeGetType(ntree->type);
+       bNodeSocket *sock, *nextsock;
+       
+       /* remove all references to this node */
        nodeUnlinkNode(ntree, node);
+       node_unlink_attached(ntree, node);
+       
        BLI_remlink(&ntree->nodes, node);
 
        /* since it is called while free database, node->id is undefined */
        
-       if(ntree->type==NTREE_COMPOSIT)
-               composit_free_node_cache(node);
-       BLI_freelistN(&node->inputs);
-       BLI_freelistN(&node->outputs);
+       if (treetype->free_node_cache)
+               treetype->free_node_cache(ntree, node);
        
-       node_free_preview(node);
+       for (sock=node->inputs.first; sock; sock = nextsock) {
+               nextsock = sock->next;
+               if (sock->default_value)
+                       MEM_freeN(sock->default_value);
+               MEM_freeN(sock);
+       }
+       for (sock=node->outputs.first; sock; sock = nextsock) {
+               nextsock = sock->next;
+               if (sock->default_value)
+                       MEM_freeN(sock->default_value);
+               MEM_freeN(sock);
+       }
+
+       nodeFreePreview(node);
 
        if(node->typeinfo && node->typeinfo->freestoragefunc) {
                node->typeinfo->freestoragefunc(node);
        }
 
        MEM_freeN(node);
+       
+       ntree->update |= NTREE_UPDATE_NODES;
 }
 
 /* do not free ntree itself here, free_libblock calls this function too */
 void ntreeFreeTree(bNodeTree *ntree)
 {
        bNode *node, *next;
+       bNodeSocket *sock;
        
        if(ntree==NULL) return;
        
-       ntreeEndExecTree(ntree);        /* checks for if it is still initialized */
+       /* XXX hack! node trees should not store execution graphs at all.
+        * This should be removed when old tree types no longer require it.
+        * Currently the execution data for texture nodes remains in the tree
+        * after execution, until the node tree is updated or freed.
+        */
+       if (ntree->execdata) {
+               switch (ntree->type) {
+               case NTREE_COMPOSIT:
+                       ntreeCompositEndExecTree(ntree->execdata);
+                       break;
+               case NTREE_SHADER:
+                       ntreeShaderEndExecTree(ntree->execdata);
+                       break;
+               case NTREE_TEXTURE:
+                       ntreeTexEndExecTree(ntree->execdata);
+                       break;
+               }
+       }
        
        BKE_free_animdata((ID *)ntree);
-
+       
        id_us_min((ID *)ntree->gpd);
 
        BLI_freelistN(&ntree->links);   /* do first, then unlink_node goes fast */
@@ -1448,25 +919,120 @@ void ntreeFreeTree(bNodeTree *ntree)
                nodeFreeNode(ntree, node);
        }
        
+       for (sock=ntree->inputs.first; sock; sock=sock->next)
+               if (sock->default_value)
+                       MEM_freeN(sock->default_value);
        BLI_freelistN(&ntree->inputs);
+       for (sock=ntree->outputs.first; sock; sock=sock->next)
+               if (sock->default_value)
+                       MEM_freeN(sock->default_value);
        BLI_freelistN(&ntree->outputs);
 }
 
 void ntreeFreeCache(bNodeTree *ntree)
 {
-       bNode *node;
+       bNodeTreeType *treetype;
        
        if(ntree==NULL) return;
+       
+       treetype= ntreeGetType(ntree->type);
+       if (treetype->free_cache)
+               treetype->free_cache(ntree);
+}
 
-       if(ntree->type==NTREE_COMPOSIT)
-               for(node= ntree->nodes.first; node; node= node->next)
-                       composit_free_node_cache(node);
+void ntreeSetOutput(bNodeTree *ntree)
+{
+       bNode *node;
+
+       /* find the active outputs, might become tree type dependant handler */
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+                       bNode *tnode;
+                       int output= 0;
+                       
+                       /* we need a check for which output node should be tagged like this, below an exception */
+                       if(node->type==CMP_NODE_OUTPUT_FILE)
+                          continue;
+                          
+                       /* there is more types having output class, each one is checked */
+                       for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
+                               if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+                                       
+                                       if(ntree->type==NTREE_COMPOSIT) {
+                                                       
+                                               /* same type, exception for viewer */
+                                               if(tnode->type==node->type ||
+                                                  (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
+                                                       ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
+                                                       if(tnode->flag & NODE_DO_OUTPUT) {
+                                                               output++;
+                                                               if(output>1)
+                                                                       tnode->flag &= ~NODE_DO_OUTPUT;
+                                                       }
+                                               }
+                                       }
+                                       else {
+                                               /* same type */
+                                               if(tnode->type==node->type) {
+                                                       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,
+               might be different for editor or for "real" use... */
+}
+
+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= 1;
+                       else cd->local= 1;
+               }
+       }
+}
 
+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)
 {
-       int local=0, lib=0;
+       bNodeTreeType *treetype= ntreeGetType(ntree->type);
+       MakeLocalCallData cd;
        
        /* - only lib users: do nothing
                * - only local users: set flag
@@ -1475,138 +1041,146 @@ void ntreeMakeLocal(bNodeTree *ntree)
        
        if(ntree->id.lib==NULL) return;
        if(ntree->id.us==1) {
-               ntree->id.lib= NULL;
+               ntree->id.lib= 0;
                ntree->id.flag= LIB_LOCAL;
-               new_id(NULL, (ID *)ntree, NULL);
+               new_id(0, (ID *)ntree, 0);
                return;
        }
        
        /* now check users of groups... again typedepending, callback... */
-       if(ntree->type==NTREE_SHADER) {
-               Material *ma;
-               for(ma= G.main->mat.first; ma; ma= ma->id.next) {
-                       if(ma->nodetree) {
-                               bNode *node;
-                               
-                               /* find if group is in tree */
-                               for(node= ma->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id == (ID *)ntree) {
-                                               if(ma->id.lib) lib= 1;
-                                               else local= 1;
-                                       }
-                               }
-                       }
-               }
+       cd.group_id = &ntree->id;
+       cd.new_id = NULL;
+       cd.local = 0;
+       cd.lib = 0;
+       
+       treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_CheckLocal);
+       
+       /* if all users are local, we simply make tree local */
+       if(cd.local && cd.lib==0) {
+               ntree->id.lib= NULL;
+               ntree->id.flag= LIB_LOCAL;
+               new_id(0, (ID *)ntree, 0);
        }
-       else if(ntree->type==NTREE_COMPOSIT) {
-               Scene *sce;
-               for(sce= G.main->scene.first; sce; sce= sce->id.next) {
-                       if(sce->nodetree) {
-                               bNode *node;
-                               
-                               /* find if group is in tree */
-                               for(node= sce->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id == (ID *)ntree) {
-                                               if(sce->id.lib) lib= 1;
-                                               else local= 1;
-                                       }
-                               }
-                       }
-               }
-       }
-       else if(ntree->type==NTREE_TEXTURE) {
-               Tex *tx;
-               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
-                       if(tx->nodetree) {
-                               bNode *node;
-                               
-                               /* find if group is in tree */
-                               for(node= tx->nodetree->nodes.first; node; node= node->next) {
-                                       if(node->id == (ID *)ntree) {
-                                               if(tx->id.lib) lib= 1;
-                                               else local= 1;
-                                       }
-                               }
-                       }
-               }
-       }
-       
-       /* if all users are local, we simply make tree local */
-       if(local && lib==0) {
-               ntree->id.lib= NULL;
-               ntree->id.flag= LIB_LOCAL;
-               new_id(NULL, (ID *)ntree, NULL);
-       }
-       else if(local && lib) {
+       else if(cd.local && cd.lib) {
                /* this is the mixed case, we copy the tree and assign it to local users */
                bNodeTree *newtree= ntreeCopyTree(ntree);
                
                newtree->id.us= 0;
                
-               if(ntree->type==NTREE_SHADER) {
-                       Material *ma;
-                       for(ma= G.main->mat.first; ma; ma= ma->id.next) {
-                               if(ma->nodetree) {
-                                       bNode *node;
-                                       
-                                       /* find if group is in tree */
-                                       for(node= ma->nodetree->nodes.first; node; node= node->next) {
-                                               if(node->id == (ID *)ntree) {
-                                                       if(ma->id.lib==NULL) {
-                                                               node->id= &newtree->id;
-                                                               newtree->id.us++;
-                                                               ntree->id.us--;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-               else if(ntree->type==NTREE_COMPOSIT) {
-                       Scene *sce;
-                       for(sce= G.main->scene.first; sce; sce= sce->id.next) {
-                               if(sce->nodetree) {
-                                       bNode *node;
-                                       
-                                       /* find if group is in tree */
-                                       for(node= sce->nodetree->nodes.first; node; node= node->next) {
-                                               if(node->id == (ID *)ntree) {
-                                                       if(sce->id.lib==NULL) {
-                                                               node->id= &newtree->id;
-                                                               newtree->id.us++;
-                                                               ntree->id.us--;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
-               else if(ntree->type==NTREE_TEXTURE) {
-                       Tex *tx;
-                       for(tx= G.main->tex.first; tx; tx= tx->id.next) {
-                               if(tx->nodetree) {
-                                       bNode *node;
-                                       
-                                       /* find if group is in tree */
-                                       for(node= tx->nodetree->nodes.first; node; node= node->next) {
-                                               if(node->id == (ID *)ntree) {
-                                                       if(tx->id.lib==NULL) {
-                                                               node->id= &newtree->id;
-                                                               newtree->id.us++;
-                                                               ntree->id.us--;
-                                                       }
-                                               }
-                                       }
-                               }
+
+               cd.new_id = &newtree->id;
+               treetype->foreach_nodetree(G.main, &cd, &ntreeMakeLocal_LinkNew);
+       }
+}
+
+int ntreeNodeExists(bNodeTree *ntree, bNode *testnode)
+{
+       bNode *node= ntree->nodes.first;
+       for(; node; node= node->next)
+               if(node==testnode)
+                       return 1;
+       return 0;
+}
+
+int ntreeOutputExists(bNode *node, bNodeSocket *testsock)
+{
+       bNodeSocket *sock= node->outputs.first;
+       for(; sock; sock= sock->next)
+               if(sock==testsock)
+                       return 1;
+       return 0;
+}
+
+/* returns localized tree for execution in threads */
+bNodeTree *ntreeLocalize(bNodeTree *ntree)
+{
+       bNodeTreeType *ntreetype= ntreeGetType(ntree->type);
+
+       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 dont 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;
+       }
+
+       /* node copy func */
+       ltree= ntreeCopyTree(ntree);
+
+       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 */
+
+       /* 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 (ntreetype->localize)
+               ntreetype->localize(ltree, ntree);
+
+       return ltree;
+}
+
+/* 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)
+{
+       bNodeTreeType *ntreetype= ntreeGetType(ntree->type);
+
+       if (ntreetype->local_sync)
+               ntreetype->local_sync(localtree, ntree);
+}
+
+/* merge local tree results back, and free local tree */
+/* we have to assume the editor already changed completely */
+void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
+{
+       bNodeTreeType *ntreetype= ntreeGetType(ntree->type);
+       bNode *lnode;
+       
+       /* 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;
                        }
                }
        }
-}
 
+       if (ntreetype->local_merge)
+               ntreetype->local_merge(localtree, ntree);
+
+       ntreeFreeTree(localtree);
+       MEM_freeN(localtree);
+}
 
 /* ************ find stuff *************** */
 
-static int ntreeHasType(bNodeTree *ntree, int type)
+int ntreeHasType(bNodeTree *ntree, int type)
 {
        bNode *node;
        
@@ -1735,1662 +1309,360 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
                                tnode->flag &= ~NODE_ACTIVE_ID;
                }
        }
-       
-       node->flag |= NODE_ACTIVE;
-       if(node->id)
-               node->flag |= NODE_ACTIVE_ID;
-}
-
-/* use flags are not persistant yet, groups might need different tagging, so we do it each time
-   when we need to get this info */
-void ntreeSocketUseFlags(bNodeTree *ntree)
-{
-       bNode *node;
-       bNodeSocket *sock;
-       bNodeLink *link;
-       
-       /* clear flags */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               for(sock= node->inputs.first; sock; sock= sock->next)
-                       sock->flag &= ~SOCK_IN_USE;
-               for(sock= node->outputs.first; sock; sock= sock->next)
-                       sock->flag &= ~SOCK_IN_USE;
-       }
-       
-       /* tag all thats in use */
-       for(link= ntree->links.first; link; link= link->next) {
-       
-               if(link->fromsock) // FIXME, see below
-                       link->fromsock->flag |= SOCK_IN_USE;
-               if(link->tosock) // FIXME This can be NULL, when dragging a new link in the UI, should probably copy the node tree for preview render - campbell
-                       link->tosock->flag |= SOCK_IN_USE;
-       }
-}
-
-/* ************** dependency stuff *********** */
-
-/* node is guaranteed to be not checked before */
-static int node_recurs_check(bNode *node, bNode ***nsort)
-{
-       bNode *fromnode;
-       bNodeSocket *sock;
-       int level = 0xFFF;
-       
-       node->done= 1;
-       
-       for(sock= node->inputs.first; sock; sock= sock->next) {
-               if(sock->link) {
-                       fromnode= sock->link->fromnode;
-                       if(fromnode) {
-                               if (fromnode->done==0)
-                                       fromnode->level= node_recurs_check(fromnode, nsort);
-                               if (fromnode->level <= level)
-                                       level = fromnode->level - 1;
-                       }
-               }
-       }
-       **nsort= node;
-       (*nsort)++;
-       
-       return level;
-}
-
-
-static void ntreeSetOutput(bNodeTree *ntree)
-{
-       bNode *node;
-
-       /* find the active outputs, might become tree type dependant handler */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
-                       bNode *tnode;
-                       int output= 0;
-                       
-                       /* we need a check for which output node should be tagged like this, below an exception */
-                       if(node->type==CMP_NODE_OUTPUT_FILE)
-                          continue;
-                          
-                       /* there is more types having output class, each one is checked */
-                       for(tnode= ntree->nodes.first; tnode; tnode= tnode->next) {
-                               if(tnode->typeinfo->nclass==NODE_CLASS_OUTPUT) {
-                                       
-                                       if(ntree->type==NTREE_COMPOSIT) {
-                                                       
-                                               /* same type, exception for viewer */
-                                               if(tnode->type==node->type ||
-                                                  (ELEM(tnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) &&
-                                                       ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))) {
-                                                       if(tnode->flag & NODE_DO_OUTPUT) {
-                                                               output++;
-                                                               if(output>1)
-                                                                       tnode->flag &= ~NODE_DO_OUTPUT;
-                                                       }
-                                               }
-                                       }
-                                       else {
-                                               /* same type */
-                                               if(tnode->type==node->type) {
-                                                       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,
-               might be different for editor or for "real" use... */
-}
-
-void ntreeSolveOrder(bNodeTree *ntree)
-{
-       bNode *node, **nodesort, **nsort;
-       bNodeSocket *sock;
-       bNodeLink *link;
-       int a, totnode=0;
-       
-       /* the solve-order is called on each tree change, so we should be sure no exec can be running */
-       ntreeEndExecTree(ntree);
-
-       /* set links pointers the input sockets, to find dependencies */
-       /* first clear data */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               node->done= 0;
-               totnode++;
-               for(sock= node->inputs.first; sock; sock= sock->next)
-                       sock->link= NULL;
-       }
-       /* clear group socket links */
-       for(sock= ntree->outputs.first; sock; sock= sock->next)
-               sock->link= NULL;
-       if(totnode==0)
-               return;
-       
-       for(link= ntree->links.first; link; link= link->next) {
-               link->tosock->link= link;
-       }
-       
-       nsort= nodesort= MEM_callocN(totnode*sizeof(void *), "sorted node array");
-       
-       /* recursive check */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->done==0) {
-                       node->level= node_recurs_check(node, &nsort);
-               }
-       }
-       
-       /* re-insert nodes in order, first a paranoia check */
-       for(a=0; a<totnode; a++) {
-               if(nodesort[a]==NULL)
-                       break;
-       }
-       if(a<totnode)
-               printf("sort error in node tree");
-       else {
-               ntree->nodes.first= ntree->nodes.last= NULL;
-               for(a=0; a<totnode; a++)
-                       BLI_addtail(&ntree->nodes, nodesort[a]);
-       }
-       
-       MEM_freeN(nodesort);
-
-       ntreeSetOutput(ntree);
-}
-
-
-/* Should be callback! */
-/* Do not call execs here */
-void NodeTagChanged(bNodeTree *ntree, bNode *node)
-{
-       if(ntree->type==NTREE_COMPOSIT) {
-               bNodeSocket *sock;
-
-               for(sock= node->outputs.first; sock; sock= sock->next) {
-                       if(sock->ns.data) {
-                               //free_compbuf(sock->ns.data);
-                               //sock->ns.data= NULL;
-                       }
-               }
-               node->need_exec= 1;
-       }
-}
-
-int NodeTagIDChanged(bNodeTree *ntree, ID *id)
-{
-       int change = FALSE;
-
-       if(ELEM(NULL, id, ntree))
-               return change;
-       
-       if(ntree->type==NTREE_COMPOSIT) {
-               bNode *node;
-               
-               for(node= ntree->nodes.first; node; node= node->next) {
-                       if(node->id==id) {
-                               change= TRUE;
-                               NodeTagChanged(ntree, node);
-                       }
-               }
-       }
-       
-       return change;
-}
-
-
-
-/* ******************* executing ************* */
-
-/* for a given socket, find the actual stack entry */
-static bNodeStack *get_socket_stack(bNodeStack *stack, bNodeSocket *sock, bNodeStack **gin)
-{
-       switch (sock->stack_type) {
-       case SOCK_STACK_LOCAL:
-               return stack + sock->stack_index;
-       case SOCK_STACK_EXTERN:
-               return (gin ? gin[sock->stack_index] : NULL);
-       case SOCK_STACK_CONST:
-               return sock->stack_ptr;
-       }
-       return NULL;
-}
-
-/* see notes at ntreeBeginExecTree */
-static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out, bNodeStack **gin)
-{
-       bNodeSocket *sock;
-       
-       /* build pointer stack */
-       if (in) {
-               for(sock= node->inputs.first; sock; sock= sock->next) {
-                       *(in++) = get_socket_stack(stack, sock, gin);
-               }
-       }
-       
-       if (out) {
-               for(sock= node->outputs.first; sock; sock= sock->next) {
-                       *(out++) = get_socket_stack(stack, sock, gin);
-               }
-       }
-}
-
-static void node_group_execute(bNodeStack *stack, void *data, bNode *gnode, bNodeStack **in)
-{
-       bNode *node;
-       bNodeTree *ntree= (bNodeTree *)gnode->id;
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
-       
-       if(ntree==NULL) return;
-       
-       stack+= gnode->stack_index;
-               
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo->execfunc) {
-                       node_get_stack(node, stack, nsin, nsout, in);
-                       
-                       /* for groups, only execute outputs for edited group */
-                       if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
-                               if(node->type==CMP_NODE_OUTPUT_FILE || (gnode->flag & NODE_GROUP_EDIT))
-                                       node->typeinfo->execfunc(data, node, nsin, nsout);
-                       }
-                       else
-                               node->typeinfo->execfunc(data, node, nsin, nsout);
-               }
-       }
-       
-       /* free internal buffers */
-       if (ntree->type==NTREE_COMPOSIT) {
-               bNodeSocket *sock;
-               bNodeStack *ns;
-               
-               /* clear hasoutput on all local stack data,
-                * only the group output will be used from now on
-                */
-               for (node=ntree->nodes.first; node; node=node->next) {
-                       for (sock=node->outputs.first; sock; sock=sock->next) {
-                               if (sock->stack_type==SOCK_STACK_LOCAL) {
-                                       ns= get_socket_stack(stack, sock, in);
-                                       ns->hasoutput = 0;
-                               }
-                       }
-               }
-               /* use the hasoutput flag to tag external sockets */
-               for (sock=ntree->outputs.first; sock; sock=sock->next) {
-                       if (sock->stack_type==SOCK_STACK_LOCAL) {
-                               ns= get_socket_stack(stack, sock, in);
-                               ns->hasoutput = 1;
-                       }
-               }
-               /* now free all stacks that are not used from outside */
-               for (node=ntree->nodes.first; node; node=node->next) {
-                       for (sock=node->outputs.first; sock; sock=sock->next) {
-                               if (sock->stack_type==SOCK_STACK_LOCAL ) {
-                                       ns= get_socket_stack(stack, sock, in);
-                                       if (ns->hasoutput==0 && ns->data) {
-                                               free_compbuf(ns->data);
-                                               ns->data = NULL;
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-static int set_stack_indexes_default(bNode *node, int index)
-{
-       bNodeSocket *sock;
-       
-       for (sock=node->inputs.first; sock; sock=sock->next) {
-               if (sock->link && sock->link->fromsock) {
-                       sock->stack_type = sock->link->fromsock->stack_type;
-                       sock->stack_index = sock->link->fromsock->stack_index;
-                       sock->stack_ptr = sock->link->fromsock->stack_ptr;
-               }
-               else {
-                       sock->stack_type = SOCK_STACK_CONST;
-                       sock->stack_index = -1;
-                       sock->stack_ptr = &sock->ns;
-               }
-       }
-       
-       for (sock=node->outputs.first; sock; sock=sock->next) {
-               sock->stack_type = SOCK_STACK_LOCAL;
-               sock->stack_index = index++;
-               sock->stack_ptr = NULL;
-       }
-       
-       return index;
-}
-
-static int ntree_begin_exec_tree(bNodeTree *ntree);
-static int set_stack_indexes_group(bNode *node, int index)
-{
-       bNodeTree *ngroup= (bNodeTree*)node->id;
-       bNodeSocket *sock;
-       
-       if(ngroup && (ngroup->init & NTREE_TYPE_INIT)==0)
-               ntreeInitTypes(ngroup);
-       
-       node->stack_index = index;
-       if(ngroup)
-               index += ntree_begin_exec_tree(ngroup);
-       
-       for (sock=node->inputs.first; sock; sock=sock->next) {
-               if (sock->link && sock->link->fromsock) {
-                       sock->stack_type = sock->link->fromsock->stack_type;
-                       sock->stack_index = sock->link->fromsock->stack_index;
-                       sock->stack_ptr = sock->link->fromsock->stack_ptr;
-               }
-               else {
-                       sock->stack_type = SOCK_STACK_CONST;
-                       sock->stack_index = -1;
-                       sock->stack_ptr = &sock->ns;
-               }
-       }
-       
-       /* identify group node outputs from internal group sockets */
-       for(sock= node->outputs.first; sock; sock= sock->next) {
-               if (sock->groupsock) {
-                       bNodeSocket *insock, *gsock = sock->groupsock;
-                       switch (gsock->stack_type) {
-                       case SOCK_STACK_EXTERN:
-                               /* extern stack is resolved for this group node instance */
-                               insock= find_group_node_input(node, gsock->link->fromsock);
-                               sock->stack_type = insock->stack_type;
-                               sock->stack_index = insock->stack_index;
-                               sock->stack_ptr = insock->stack_ptr;
-                               break;
-                       case SOCK_STACK_LOCAL:
-                               sock->stack_type = SOCK_STACK_LOCAL;
-                               /* local stack index must be offset by group node instance */
-                               sock->stack_index = gsock->stack_index + node->stack_index;
-                               sock->stack_ptr = NULL;
-                               break;
-                       case SOCK_STACK_CONST:
-                               sock->stack_type = SOCK_STACK_CONST;
-                               sock->stack_index = -1;
-                               sock->stack_ptr = gsock->stack_ptr;
-                               break;
-                       }
-               }
-               else {
-                       sock->stack_type = SOCK_STACK_LOCAL;
-                       sock->stack_index = index++;
-                       sock->stack_ptr = NULL;
-               }
-       }
-       
-       return index;
-}
-
-/* recursively called for groups */
-/* we set all trees on own local indices, but put a total counter
-   in the groups, so each instance of a group has own stack */
-static int ntree_begin_exec_tree(bNodeTree *ntree)
-{
-       bNode *node;
-       bNodeSocket *gsock;
-       int index= 0, i;
-       
-       if((ntree->init & NTREE_TYPE_INIT)==0)
-               ntreeInitTypes(ntree);
-       
-       /* group inputs are numbered 0..totinputs, so external stack can easily be addressed */
-       i = 0;
-       for(gsock=ntree->inputs.first; gsock; gsock = gsock->next) {
-               gsock->stack_type = SOCK_STACK_EXTERN;
-               gsock->stack_index = i++;
-               gsock->stack_ptr = NULL;
-       }
-       
-       /* create indices for stack, check preview */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               /* XXX can this be done by a generic one-for-all function?
-                * otherwise should use node-type callback.
-                */
-               if(node->type==NODE_GROUP)
-                       index = set_stack_indexes_group(node, index);
-               else
-                       index = set_stack_indexes_default(node, index);
-       }
-       
-       /* group outputs */
-       for(gsock=ntree->outputs.first; gsock; gsock = gsock->next) {
-               if (gsock->link && gsock->link->fromsock) {
-                       gsock->stack_type = gsock->link->fromsock->stack_type;
-                       gsock->stack_index = gsock->link->fromsock->stack_index;
-                       gsock->stack_ptr = gsock->link->fromsock->stack_ptr;
-               }
-               else {
-                       gsock->stack_type = SOCK_STACK_CONST;
-                       gsock->stack_index = -1;
-                       gsock->stack_ptr = &gsock->ns;
-               }
-       }
-       
-       return index;
-}
-
-/* copy socket compbufs to stack, initialize usage of curve nodes */
-static void composit_begin_exec(bNodeTree *ntree, bNodeStack *stack)
-{
-       bNode *node;
-       bNodeSocket *sock;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               
-               /* initialize needed for groups */
-               node->exec= 0;  
-               
-               for(sock= node->outputs.first; sock; sock= sock->next) {
-                       bNodeStack *ns= get_socket_stack(stack, sock, NULL);
-                       if(ns && sock->ns.data) {
-                               ns->data= sock->ns.data;
-                               sock->ns.data= NULL;
-                       }
-               }
-               
-               /* cannot initialize them while using in threads */
-               if(ELEM4(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB, CMP_NODE_HUECORRECT)) {
-                       curvemapping_initialize(node->storage);
-                       if(node->type==CMP_NODE_CURVE_RGB)
-                               curvemapping_premultiply(node->storage, 0);
-               }
-               if(node->type==NODE_GROUP && node->id)
-                       composit_begin_exec((bNodeTree *)node->id, stack + node->stack_index);
-
-       }
-}
-
-/* copy stack compbufs to sockets */
-static void composit_end_exec(bNodeTree *ntree, bNodeStack *stack)
-{
-       bNode *node;
-       bNodeStack *ns;
-
-       for(node= ntree->nodes.first; node; node= node->next) {
-               bNodeSocket *sock;
-               
-               for(sock= node->outputs.first; sock; sock= sock->next) {
-                       ns = get_socket_stack(stack, sock, NULL);
-                       if(ns && ns->data) {
-                               sock->ns.data= ns->data;
-                               ns->data= NULL;
-                       }
-               }
-               
-               if(node->type==CMP_NODE_CURVE_RGB)
-                       curvemapping_premultiply(node->storage, 1);
-               
-               if(node->type==NODE_GROUP && node->id)
-                       composit_end_exec((bNodeTree *)node->id, stack + node->stack_index);
-
-               node->need_exec= 0;
-       }
-}
-
-static void group_tag_used_outputs(bNode *gnode, bNodeStack *stack, bNodeStack **gin)
-{
-       bNodeTree *ntree= (bNodeTree *)gnode->id;
-       bNode *node;
-       bNodeSocket *sock;
-       
-       stack+= gnode->stack_index;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo->execfunc) {
-                       for(sock= node->inputs.first; sock; sock= sock->next) {
-                               bNodeStack *ns = get_socket_stack(stack, sock, gin);
-                               ns->hasoutput= 1;
-                       }
-               }
-               
-               /* non-composite trees do all nodes by default */
-               if (ntree->type!=NTREE_COMPOSIT)
-                       node->need_exec = 1;
-               
-               for(sock= node->inputs.first; sock; sock= sock->next) {
-                       bNodeStack *ns = get_socket_stack(stack, sock, gin);
-                       if (ns) {
-                               ns->hasoutput = 1;
-                               
-                               /* sock type is needed to detect rgba or value or vector types */
-                               if(sock->link && sock->link->fromsock)
-                                       ns->sockettype= sock->link->fromsock->type;
-                               else
-                                       sock->ns.sockettype= sock->type;
-                       }
-                       
-                       if(sock->link) {
-                               bNodeLink *link= sock->link;
-                               /* this is the test for a cyclic case */
-                               if(link->fromnode && link->tonode) {
-                                       if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF);
-                                       else {
-                                               node->need_exec= 0;
-                                       }
-                               }
-                       }
-               }
-               
-               /* set stack types (for local stack entries) */
-               for(sock= node->outputs.first; sock; sock= sock->next) {
-                       bNodeStack *ns = get_socket_stack(stack, sock, gin);
-                       if (ns)
-                               ns->sockettype = sock->type;
-               }
-       }
-}
-
-/* notes below are ancient! (ton) */
-/* stack indices make sure all nodes only write in allocated data, for making it thread safe */
-/* only root tree gets the stack, to enable instances to have own stack entries */
-/* per tree (and per group) unique indices are created */
-/* the index_ext we need to be able to map from groups to the group-node own stack */
-
-typedef struct bNodeThreadStack {
-       struct bNodeThreadStack *next, *prev;
-       bNodeStack *stack;
-       int used;
-} bNodeThreadStack;
-
-static bNodeThreadStack *ntreeGetThreadStack(bNodeTree *ntree, int thread)
-{
-       ListBase *lb= &ntree->threadstack[thread];
-       bNodeThreadStack *nts;
-       
-       for(nts=lb->first; nts; nts=nts->next) {
-               if(!nts->used) {
-                       nts->used= 1;
-                       return nts;
-               }
-       }
-       nts= MEM_callocN(sizeof(bNodeThreadStack), "bNodeThreadStack");
-       nts->stack= MEM_dupallocN(ntree->stack);
-       nts->used= 1;
-       BLI_addtail(lb, nts);
-
-       return nts;
-}
-
-static void ntreeReleaseThreadStack(bNodeThreadStack *nts)
-{
-       nts->used= 0;
-}
-
-/* free texture delegates */
-static void tex_end_exec(bNodeTree *ntree)
-{
-       bNodeThreadStack *nts;
-       bNodeStack *ns;
-       int th, a;
-       
-       if(ntree->threadstack) {
-               for(th=0; th<BLENDER_MAX_THREADS; th++) {
-                       for(nts=ntree->threadstack[th].first; nts; nts=nts->next) {
-                               for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++) {
-                                       if(ns->data) {
-                                               MEM_freeN(ns->data);
-                                               ns->data= NULL;
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-void ntreeBeginExecTree(bNodeTree *ntree)
-{
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       
-       /* let's make it sure */
-       if(ntree->init & NTREE_EXEC_INIT)
-               return;
-       
-       /* allocate the thread stack listbase array */
-       if(ntree->type!=NTREE_COMPOSIT)
-               ntree->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array");
-
-       /* goes recursive over all groups */
-       ntree->stacksize= ntree_begin_exec_tree(ntree);
-
-       if(ntree->stacksize) {
-               bNode *node;
-               bNodeStack *ns;
-               int a;
-               
-               /* allocate the base stack */
-               ns=ntree->stack= MEM_callocN(ntree->stacksize*sizeof(bNodeStack), "node stack");
-               
-               /* tag inputs, the get_stack() gives own socket stackdata if not in use */
-               for(a=0; a<ntree->stacksize; a++, ns++) ns->hasinput= 1;
-               
-               /* tag used outputs, so we know when we can skip operations */
-               for(node= ntree->nodes.first; node; node= node->next) {
-                       bNodeSocket *sock;
-                       
-                       /* non-composite trees do all nodes by default */
-                       if(ntree->type!=NTREE_COMPOSIT)
-                               node->need_exec= 1;
-
-                       for(sock= node->inputs.first; sock; sock= sock->next) {
-                               ns = get_socket_stack(ntree->stack, sock, NULL);
-                               if (ns) {
-                                       ns->hasoutput = 1;
-                                       
-                                       /* sock type is needed to detect rgba or value or vector types */
-                                       if(sock->link && sock->link->fromsock)
-                                               ns->sockettype= sock->link->fromsock->type;
-                                       else
-                                               sock->ns.sockettype= sock->type;
-                               }
-                               
-                               if(sock->link) {
-                                       bNodeLink *link= sock->link;
-                                       /* this is the test for a cyclic case */
-                                       if(link->fromnode && link->tonode) {
-                                               if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF);
-                                               else {
-                                                       node->need_exec= 0;
-                                               }
-                                       }
-                               }
-                       }
-                       
-                       /* set stack types (for local stack entries) */
-                       for(sock= node->outputs.first; sock; sock= sock->next) {
-                               ns = get_socket_stack(ntree->stack, sock, NULL);
-                               if (ns)
-                                       ns->sockettype = sock->type;
-                       }
-                       
-                       if(node->type==NODE_GROUP && node->id) {
-                               node_get_stack(node, ntree->stack, nsin, NULL, NULL);
-                               group_tag_used_outputs(node, ntree->stack, nsin);
-                       }
-               }
-               
-               if(ntree->type==NTREE_COMPOSIT)
-                       composit_begin_exec(ntree, ntree->stack);
-               
-               /* ensures only a single output node is enabled, texnode allows multiple though */
-               if(ntree->type!=NTREE_TEXTURE)
-                       ntreeSetOutput(ntree);
-               
-       }
-       
-       ntree->init |= NTREE_EXEC_INIT;
-}
-
-void ntreeEndExecTree(bNodeTree *ntree)
-{
-       bNodeStack *ns;
-       
-       if(ntree->init & NTREE_EXEC_INIT) {
-               bNodeThreadStack *nts;
-               int a;
-               
-               /* another callback candidate! */
-               if(ntree->type==NTREE_COMPOSIT) {
-                       composit_end_exec(ntree, ntree->stack);
-                       
-                       for(ns= ntree->stack, a=0; a<ntree->stacksize; a++, ns++) {
-                               if(ns->data) {
-                                       printf("freed leftover buffer from stack\n");
-                                       free_compbuf(ns->data);
-                                       ns->data= NULL;
-                               }
-                       }
-               }
-               else if(ntree->type==NTREE_TEXTURE)
-                       tex_end_exec(ntree);
-               
-               if(ntree->stack) {
-                       MEM_freeN(ntree->stack);
-                       ntree->stack= NULL;
-               }
-
-               if(ntree->threadstack) {
-                       for(a=0; a<BLENDER_MAX_THREADS; a++) {
-                               for(nts=ntree->threadstack[a].first; nts; nts=nts->next)
-                                       if (nts->stack) MEM_freeN(nts->stack);
-                               BLI_freelistN(&ntree->threadstack[a]);
-                       }
-
-                       MEM_freeN(ntree->threadstack);
-                       ntree->threadstack= NULL;
-               }
-
-               ntree->init &= ~NTREE_EXEC_INIT;
-       }
-}
-
-/* nodes are presorted, so exec is in order of list */
-void ntreeExecTree(bNodeTree *ntree, void *callerdata, int thread)
-{
-       bNode *node;
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
-       bNodeStack *stack;
-       bNodeThreadStack *nts = NULL;
-       
-       /* only when initialized */
-       if((ntree->init & NTREE_EXEC_INIT)==0)
-               ntreeBeginExecTree(ntree);
-       
-       /* composite does 1 node per thread, so no multiple stacks needed */
-       if(ntree->type==NTREE_COMPOSIT) {
-               stack= ntree->stack;
-       }
-       else {
-               nts= ntreeGetThreadStack(ntree, thread);
-               stack= nts->stack;
-       }
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->need_exec) {
-                       if(node->typeinfo->execfunc) {
-                               node_get_stack(node, stack, nsin, nsout, NULL);
-                               node->typeinfo->execfunc(callerdata, node, nsin, nsout);
-                       }
-                       else if(node->type==NODE_GROUP && node->id) {
-                               node_get_stack(node, stack, nsin, NULL, NULL);
-                               node_group_execute(stack, callerdata, node, nsin);
-                       }
-               }
-       }
-
-       if(nts)
-               ntreeReleaseThreadStack(nts);
-}
-
-
-/* ***************************** threaded version for execute composite nodes ************* */
-/* these are nodes without input, only giving values */
-/* or nodes with only value inputs */
-static int node_only_value(bNode *node)
-{
-       bNodeSocket *sock;
-       
-       if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_VALUE, CMP_NODE_RGB))
-               return 1;
-       
-       /* doing this for all node types goes wrong. memory free errors */
-       if(node->inputs.first && node->type==CMP_NODE_MAP_VALUE) {
-               int retval= 1;
-               for(sock= node->inputs.first; sock; sock= sock->next) {
-                       if(sock->link && sock->link->fromnode)
-                               retval &= node_only_value(sock->link->fromnode);
-               }
-               return retval;
-       }
-       return 0;
-}
-
-
-/* not changing info, for thread callback */
-typedef struct ThreadData {
-       bNodeStack *stack;
-       RenderData *rd;
-} ThreadData;
-
-static void *exec_composite_node(void *node_v)
-{
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
-       bNode *node= node_v;
-       ThreadData *thd= (ThreadData *)node->threaddata;
-       
-       node_get_stack(node, thd->stack, nsin, nsout, NULL);
-       
-       if((node->flag & NODE_MUTED) && (!node_only_value(node))) {
-               /* viewers we execute, for feedback to user */
-               if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) 
-                       node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
-               else
-                       node_compo_pass_on(node, nsin, nsout);
-       }
-       else if(node->typeinfo->execfunc) {
-               node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
-       }
-       else if(node->type==NODE_GROUP && node->id) {
-               node_group_execute(thd->stack, thd->rd, node, nsin); 
-       }
-       
-       node->exec |= NODE_READY;
-       return NULL;
-}
-
-/* return total of executable nodes, for timecursor */
-/* only compositor uses it */
-static int setExecutableNodes(bNodeTree *ntree, ThreadData *thd)
-{
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
-       bNode *node;
-       bNodeSocket *sock;
-       int totnode= 0, group_edit= 0;
-       
-       /* note; do not add a dependency sort here, the stack was created already */
-       
-       /* if we are in group edit, viewer nodes get skipped when group has viewer */
-       for(node= ntree->nodes.first; node; node= node->next)
-               if(node->type==NODE_GROUP && (node->flag & NODE_GROUP_EDIT))
-                       if(ntreeHasType((bNodeTree *)node->id, CMP_NODE_VIEWER))
-                               group_edit= 1;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               int a;
-               
-               node_get_stack(node, thd->stack, nsin, nsout, NULL);
-               
-               /* test the outputs */
-               /* skip value-only nodes (should be in type!) */
-               if(!node_only_value(node)) {
-                       for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
-                               if(nsout[a]->data==NULL && nsout[a]->hasoutput) {
-                                       node->need_exec= 1;
-                                       break;
-                               }
-                       }
-               }
-               
-               /* test the inputs */
-               for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
-                       /* skip viewer nodes in bg render or group edit */
-                       if( ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER) && (G.background || group_edit))
-                               node->need_exec= 0;
-                       /* is sock in use? */
-                       else if(sock->link) {
-                               bNodeLink *link= sock->link;
-                               
-                               /* this is the test for a cyclic case */
-                               if(link->fromnode==NULL || link->tonode==NULL);
-                               else if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
-                                       if(link->fromnode->need_exec) {
-                                               node->need_exec= 1;
-                                               break;
-                                       }
-                               }
-                               else {
-                                       node->need_exec= 0;
-                                       printf("Node %s skipped, cyclic dependency\n", node->name);
-                               }
-                       }
-               }
-               
-               if(node->need_exec) {
-                       
-                       /* free output buffers */
-                       for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
-                               if(nsout[a]->data) {
-                                       free_compbuf(nsout[a]->data);
-                                       nsout[a]->data= NULL;
-                               }
-                       }
-                       totnode++;
-                       /* printf("node needs exec %s\n", node->name); */
-                       
-                       /* tag for getExecutableNode() */
-                       node->exec= 0;
-               }
-               else {
-                       /* tag for getExecutableNode() */
-                       node->exec= NODE_READY|NODE_FINISHED|NODE_SKIPPED;
-                       
-               }
-       }
-       
-       /* last step: set the stack values for only-value nodes */
-       /* just does all now, compared to a full buffer exec this is nothing */
-       if(totnode) {
-               for(node= ntree->nodes.first; node; node= node->next) {
-                       if(node->need_exec==0 && node_only_value(node)) {
-                               if(node->typeinfo->execfunc) {
-                                       node_get_stack(node, thd->stack, nsin, nsout, NULL);
-                                       node->typeinfo->execfunc(thd->rd, node, nsin, nsout);
-                               }
-                       }
-               }
-       }
-       
-       return totnode;
-}
-
-/* while executing tree, free buffers from nodes that are not needed anymore */
-static void freeExecutableNode(bNodeTree *ntree)
-{
-       /* node outputs can be freed when:
-       - not a render result or image node
-       - when node outputs go to nodes all being set NODE_FINISHED
-       */
-       bNode *node;
-       bNodeSocket *sock;
-       
-       /* set exec flag for finished nodes that might need freed */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->type!=CMP_NODE_R_LAYERS)
-                       if(node->exec & NODE_FINISHED)
-                               node->exec |= NODE_FREEBUFS;
-       }
-       /* clear this flag for input links that are not done yet */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if((node->exec & NODE_FINISHED)==0) {
-                       for(sock= node->inputs.first; sock; sock= sock->next)
-                               if(sock->link && sock->link->fromnode)
-                                       sock->link->fromnode->exec &= ~NODE_FREEBUFS;
-               }
-       }
-       /* now we can free buffers */
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->exec & NODE_FREEBUFS) {
-                       for(sock= node->outputs.first; sock; sock= sock->next) {
-                               bNodeStack *ns= get_socket_stack(ntree->stack, sock, NULL);
-                               if(ns && ns->data) {
-                                       free_compbuf(ns->data);
-                                       ns->data= NULL;
-                                       // printf("freed buf node %s \n", node->name);
-                               }
-                       }
-               }
-       }
-}
-
-static bNode *getExecutableNode(bNodeTree *ntree)
-{
-       bNode *node;
-       bNodeSocket *sock;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->exec==0) {
-                       
-                       /* input sockets should be ready */
-                       for(sock= node->inputs.first; sock; sock= sock->next) {
-                               if(sock->link && sock->link->fromnode)
-                                       if((sock->link->fromnode->exec & NODE_READY)==0)
-                                               break;
-                       }
-                       if(sock==NULL)
-                               return node;
-               }
-       }
-       return NULL;
-}
-
-/* check if texture nodes need exec or end */
-static  void ntree_composite_texnode(bNodeTree *ntree, int init)
-{
-       bNode *node;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->type==CMP_NODE_TEXTURE && node->id) {
-                       Tex *tex= (Tex *)node->id;
-                       if(tex->nodetree && tex->use_nodes) {
-                               /* has internal flag to detect it only does it once */
-                               if(init)
-                                       ntreeBeginExecTree(tex->nodetree); 
-                               else
-                                       ntreeEndExecTree(tex->nodetree);
-                       }
-               }
-       }
-
-}
-
-/* optimized tree execute test for compositing */
-void ntreeCompositExecTree(bNodeTree *ntree, RenderData *rd, int do_preview)
-{
-       bNode *node;
-       ListBase threads;
-       ThreadData thdata;
-       int totnode, curnode, rendering= 1;
-       
-       if(ntree==NULL) return;
-       
-       if(do_preview)
-               ntreeInitPreview(ntree, 0, 0);
-       
-       ntreeBeginExecTree(ntree);
-       ntree_composite_texnode(ntree, 1);
-       
-       /* prevent unlucky accidents */
-       if(G.background)
-               rd->scemode &= ~R_COMP_CROP;
-       
-       /* setup callerdata for thread callback */
-       thdata.rd= rd;
-       thdata.stack= ntree->stack;
-       
-       /* fixed seed, for example noise texture */
-       BLI_srandom(rd->cfra);
-
-       /* sets need_exec tags in nodes */
-       curnode = totnode= setExecutableNodes(ntree, &thdata);
-
-       BLI_init_threads(&threads, exec_composite_node, rd->threads);
-       
-       while(rendering) {
-               
-               if(BLI_available_threads(&threads)) {
-                       node= getExecutableNode(ntree);
-                       if(node) {
-                               if(ntree->progress && totnode)
-                                       ntree->progress(ntree->prh, (1.0f - curnode/(float)totnode));
-                               if(ntree->stats_draw) {
-                                       char str[64];
-                                       sprintf(str, "Compositing %d %s", curnode, node->name);
-                                       ntree->stats_draw(ntree->sdh, str);
-                               }
-                               curnode--;
-                               
-                               node->threaddata = &thdata;
-                               node->exec= NODE_PROCESSING;
-                               BLI_insert_thread(&threads, node);
-                       }
-                       else
-                               PIL_sleep_ms(50);
-               }
-               else
-                       PIL_sleep_ms(50);
-               
-               rendering= 0;
-               /* test for ESC */
-               if(ntree->test_break && ntree->test_break(ntree->tbh)) {
-                       for(node= ntree->nodes.first; node; node= node->next)
-                               node->exec |= NODE_READY;
-               }
-               
-               /* check for ready ones, and if we need to continue */
-               for(node= ntree->nodes.first; node; node= node->next) {
-                       if(node->exec & NODE_READY) {
-                               if((node->exec & NODE_FINISHED)==0) {
-                                       BLI_remove_thread(&threads, node); /* this waits for running thread to finish btw */
-                                       node->exec |= NODE_FINISHED;
-                                       
-                                       /* freeing unused buffers */
-                                       if(rd->scemode & R_COMP_FREE)
-                                               freeExecutableNode(ntree);
-                               }
-                       }
-                       else rendering= 1;
-               }
-       }
-       
-       BLI_end_threads(&threads);
-       
-       ntreeEndExecTree(ntree);
-}
-
-
-/* ********** copy composite tree entirely, to allow threaded exec ******************* */
-/* ***************** do NOT execute this in a thread!               ****************** */
-
-/* returns localized tree for execution in threads */
-/* local tree then owns all compbufs (for composite) */
-bNodeTree *ntreeLocalize(bNodeTree *ntree)
-{
-       bNodeTree *ltree;
-       bNode *node;
-       bNodeSocket *sock;
-       
-       bAction *action_backup= NULL, *tmpact_backup= NULL;
-       
-       /* Workaround for copying an action on each render!
-        * set action to NULL so animdata actions dont 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;
-       }
-
-       /* node copy func */
-       ltree= ntreeCopyTree(ntree);
-
-       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 */
-
-       /* ensures only a single output node is enabled */
-       ntreeSetOutput(ltree);
-
-       for(node= ntree->nodes.first; node; node= node->next) {
-               
-               /* store new_node pointer to original */
-               node->new_node->new_node= node;
-               
-               if(ntree->type==NTREE_COMPOSIT) {
-                       /* ensure new user input gets handled ok, only composites (texture nodes will break, for painting since it uses no tags) */
-                       node->need_exec= 0;
-                       
-                       /* move over the compbufs */
-                       /* right after ntreeCopyTree() oldsock pointers are valid */
-                       
-                       if(ELEM(node->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
-                               if(node->id) {
-                                       if(node->flag & NODE_DO_OUTPUT)
-                                               node->new_node->id= (ID *)copy_image((Image *)node->id);
-                                       else
-                                               node->new_node->id= NULL;
-                               }
-                       }
-                       
-                       for(sock= node->outputs.first; sock; sock= sock->next) {
-                               
-                               sock->new_sock->ns.data= sock->ns.data;
-                               compbuf_set_node(sock->new_sock->ns.data, node->new_node);
-                               
-                               sock->ns.data= NULL;
-                               sock->new_sock->new_sock= sock;
-                       }
-               }
-       }
-       
-       return ltree;
-}
-
-static int node_exists(bNodeTree *ntree, bNode *testnode)
-{
-       bNode *node= ntree->nodes.first;
-       for(; node; node= node->next)
-               if(node==testnode)
-                       return 1;
-       return 0;
-}
-
-static int outsocket_exists(bNode *node, bNodeSocket *testsock)
-{
-       bNodeSocket *sock= node->outputs.first;
-       for(; sock; sock= sock->next)
-               if(sock==testsock)
-                       return 1;
-       return 0;
-}
-
-
-/* sync local composite with real tree */
-/* local composite 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)
-{
-       bNode *lnode;
-       
-       if(ntree->type==NTREE_COMPOSIT) {
-               /* 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(node_exists(ntree, lnode->new_node)) {
-                                       
-                                       if(lnode->preview && lnode->preview->rect) {
-                                               node_free_preview(lnode->new_node);
-                                               lnode->new_node->preview= lnode->preview;
-                                               lnode->preview= NULL;
-                                       }
-                               }
-                       }
-               }
-       }
-       else if(ELEM(ntree->type, NTREE_SHADER, NTREE_TEXTURE)) {
-               /* copy over contents of previews */
-               for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
-                       if(node_exists(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);
-                                       }
-                               }
-                       }
-               }
-       }
-}
-
-/* merge local tree results back, and free local tree */
-/* we have to assume the editor already changed completely */
-void ntreeLocalMerge(bNodeTree *localtree, bNodeTree *ntree)
-{
-       bNode *lnode;
-       bNodeSocket *lsock;
-       
-       /* move over the compbufs and previews */
-       for(lnode= localtree->nodes.first; lnode; lnode= lnode->next) {
-               if(node_exists(ntree, lnode->new_node)) {
-                       
-                       if(lnode->preview && lnode->preview->rect) {
-                               node_free_preview(lnode->new_node);
-                               lnode->new_node->preview= lnode->preview;
-                               lnode->preview= NULL;
-                       }
-                       
-                       if(ELEM(lnode->type, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER)) {
-                               if(lnode->id && (lnode->flag & NODE_DO_OUTPUT)) {
-                                       /* image_merge does sanity check for pointers */
-                                       BKE_image_merge((Image *)lnode->new_node->id, (Image *)lnode->id);
-                               }
-                       }
-                       
-                       for(lsock= lnode->outputs.first; lsock; lsock= lsock->next) {
-                               if(outsocket_exists(lnode->new_node, lsock->new_sock)) {
-                                       lsock->new_sock->ns.data= lsock->ns.data;
-                                       compbuf_set_node(lsock->new_sock->ns.data, lnode->new_node);
-                                       lsock->ns.data= NULL;
-                                       lsock->new_sock= NULL;
-                               }
-                       }
-               }
-       }
-       ntreeFreeTree(localtree);
-       MEM_freeN(localtree);
+       
+       node->flag |= NODE_ACTIVE;
+       if(node->id)
+               node->flag |= NODE_ACTIVE_ID;
 }
 
-/* *********************************************** */
-
-/* GPU material from shader nodes */
-
-static void gpu_from_node_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+/* use flags are not persistant yet, groups might need different tagging, so we do it each time
+   when we need to get this info */
+void ntreeSocketUseFlags(bNodeTree *ntree)
 {
+       bNode *node;
        bNodeSocket *sock;
-       int i;
-
-       for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
-               memset(&gs[i], 0, sizeof(gs[i]));
-
-               QUATCOPY(gs[i].vec, ns[i]->vec);
-               gs[i].link= ns[i]->data;
-
-               if (sock->type == SOCK_VALUE)
-                       gs[i].type= GPU_FLOAT;
-               else if (sock->type == SOCK_VECTOR)
-                       gs[i].type= GPU_VEC3;
-               else if (sock->type == SOCK_RGBA)
-                       gs[i].type= GPU_VEC4;
-               else
-                       gs[i].type= GPU_NONE;
-
-               gs[i].name = "";
-               gs[i].hasinput= ns[i]->hasinput && ns[i]->data;
-               gs[i].hasoutput= ns[i]->hasoutput && ns[i]->data;
-               gs[i].sockettype= ns[i]->sockettype;
+       bNodeLink *link;
+       
+       /* clear flags */
+       for(node= ntree->nodes.first; node; node= node->next) {
+               for(sock= node->inputs.first; sock; sock= sock->next)
+                       sock->flag &= ~SOCK_IN_USE;
+               for(sock= node->outputs.first; sock; sock= sock->next)
+                       sock->flag &= ~SOCK_IN_USE;
+       }
+       
+       /* tag all thats in use */
+       for(link= ntree->links.first; link; link= link->next) {
+       
+               if(link->fromsock) // FIXME, see below
+                       link->fromsock->flag |= SOCK_IN_USE;
+               if(link->tosock) // FIXME This can be NULL, when dragging a new link in the UI, should probably copy the node tree for preview render - campbell
+                       link->tosock->flag |= SOCK_IN_USE;
        }
-
-       gs[i].type= GPU_NONE;
 }
 
-static void data_from_gpu_stack(ListBase *sockets, bNodeStack **ns, GPUNodeStack *gs)
+/* ************** dependency stuff *********** */
+
+/* node is guaranteed to be not checked before */
+static int node_get_deplist_recurs(bNode *node, bNode ***nsort)
 {
+       bNode *fromnode;
        bNodeSocket *sock;
-       int i;
-
-       for (sock=sockets->first, i=0; sock; sock=sock->next, i++) {
-               ns[i]->data= gs[i].link;
-               ns[i]->sockettype= gs[i].sockettype;
+       int level = 0xFFF;
+       
+       node->done= 1;
+       
+       /* check linked nodes */
+       for(sock= node->inputs.first; sock; sock= sock->next) {
+               if(sock->link) {
+                       fromnode= sock->link->fromnode;
+                       if(fromnode) {
+                               if (fromnode->done==0)
+                                       fromnode->level= node_get_deplist_recurs(fromnode, nsort);
+                               if (fromnode->level <= level)
+                                       level = fromnode->level - 1;
+                       }
+               }
+       }
+       
+       /* check parent node */
+       if (node->parent) {
+               if (node->parent->done==0)
+                       node->parent->level= node_get_deplist_recurs(node->parent, nsort);
+               if (node->parent->level <= level)
+                       level = node->parent->level - 1;
+       }
+       
+       if (nsort) {
+               **nsort= node;
+               (*nsort)++;
        }
+       
+       return level;
 }
 
-static void gpu_node_group_execute(bNodeStack *stack, GPUMaterial *mat, bNode *gnode, bNodeStack **in)
+void ntreeGetDependencyList(struct bNodeTree *ntree, struct bNode ***deplist, int *totnodes)
 {
-       bNode *node;
-       bNodeTree *ntree= (bNodeTree *)gnode->id;
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
-       GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
-       int doit = 0;
+       bNode *node, **nsort;
        
-       if(ntree==NULL) return;
+       *totnodes=0;
        
-       stack+= gnode->stack_index;
-               
+       /* first clear data */
        for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo->gpufunc) {
-                       node_get_stack(node, stack, nsin, nsout, in);
-
-                       doit = 0;
-                       
-                       /* for groups, only execute outputs for edited group */
-                       if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
-                               if(gnode->flag & NODE_GROUP_EDIT)
-                                       if(node->flag & NODE_DO_OUTPUT)
-                                               doit = 1;
-                       }
-                       else
-                               doit = 1;
-
-                       if(doit)  {
-                               gpu_from_node_stack(&node->inputs, nsin, gpuin);
-                               gpu_from_node_stack(&node->outputs, nsout, gpuout);
-                               if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
-                                       data_from_gpu_stack(&node->outputs, nsout, gpuout);
-                       }
+               node->done= 0;
+               (*totnodes)++;
+       }
+       if(*totnodes==0) {
+               *deplist = NULL;
+               return;
+       }
+       
+       nsort= *deplist= MEM_callocN((*totnodes)*sizeof(bNode*), "sorted node array");
+       
+       /* recursive check */
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->done==0) {
+                       node->level= node_get_deplist_recurs(node, &nsort);
                }
        }
 }
 
-void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat)
+static void ntree_update_link_pointers(bNodeTree *ntree)
 {
        bNode *node;
-       bNodeStack *stack;
-       bNodeStack *nsin[MAX_SOCKET];   /* arbitrary... watch this */
-       bNodeStack *nsout[MAX_SOCKET];  /* arbitrary... watch this */
-       GPUNodeStack gpuin[MAX_SOCKET+1], gpuout[MAX_SOCKET+1];
-
-       if((ntree->init & NTREE_EXEC_INIT)==0)
-               ntreeBeginExecTree(ntree);
-
-       stack= ntree->stack;
-
+       bNodeSocket *sock;
+       bNodeLink *link;
+       
+       /* first clear data */
        for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->typeinfo->gpufunc) {
-                       node_get_stack(node, stack, nsin, nsout, NULL);
-                       gpu_from_node_stack(&node->inputs, nsin, gpuin);
-                       gpu_from_node_stack(&node->outputs, nsout, gpuout);
-                       if(node->typeinfo->gpufunc(mat, node, gpuin, gpuout))
-                               data_from_gpu_stack(&node->outputs, nsout, gpuout);
-               }
-               else if(node->type==NODE_GROUP && node->id) {
-                       node_get_stack(node, stack, nsin, nsout, NULL);
-                       gpu_node_group_execute(stack, mat, node, nsin);
-               }
+               for(sock= node->inputs.first; sock; sock= sock->next)
+                       sock->link= NULL;
        }
+       /* clear socket links */
+       for(sock= ntree->outputs.first; sock; sock= sock->next)
+               sock->link= NULL;
 
-       ntreeEndExecTree(ntree);
+       for(link= ntree->links.first; link; link= link->next) {
+               if (link->tosock)
+                       link->tosock->link= link;
+       }
 }
 
-/* **************** call to switch lamploop for material node ************ */
-
-void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
-
-void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
+void ntree_validate_links(bNodeTree *ntree)
 {
-       node_shader_lamp_loop= lamp_loop_func;
+       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))
+                               link->flag &= ~NODE_LINK_VALID;
+               }
+       }
 }
 
-/* clumsy checking... should do dynamic outputs once */
-static void force_hidden_passes(bNode *node, int passflag)
-{
-       bNodeSocket *sock;
-       
-       for(sock= node->outputs.first; sock; sock= sock->next)
-               sock->flag &= ~SOCK_UNAVAIL;
-       
-       sock= BLI_findlink(&node->outputs, RRES_OUT_Z);
-       if(!(passflag & SCE_PASS_Z)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_NORMAL);
-       if(!(passflag & SCE_PASS_NORMAL)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_VEC);
-       if(!(passflag & SCE_PASS_VECTOR)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_UV);
-       if(!(passflag & SCE_PASS_UV)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_RGBA);
-       if(!(passflag & SCE_PASS_RGBA)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_DIFF);
-       if(!(passflag & SCE_PASS_DIFFUSE)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_SPEC);
-       if(!(passflag & SCE_PASS_SPEC)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_SHADOW);
-       if(!(passflag & SCE_PASS_SHADOW)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_AO);
-       if(!(passflag & SCE_PASS_AO)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_REFLECT);
-       if(!(passflag & SCE_PASS_REFLECT)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_REFRACT);
-       if(!(passflag & SCE_PASS_REFRACT)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_INDIRECT);
-       if(!(passflag & SCE_PASS_INDIRECT)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXOB);
-       if(!(passflag & SCE_PASS_INDEXOB)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_INDEXMA);
-       if(!(passflag & SCE_PASS_INDEXMA)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_MIST);
-       if(!(passflag & SCE_PASS_MIST)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_EMIT);
-       if(!(passflag & SCE_PASS_EMIT)) sock->flag |= SOCK_UNAVAIL;
-       sock= BLI_findlink(&node->outputs, RRES_OUT_ENV);
-       if(!(passflag & SCE_PASS_ENVIRONMENT)) sock->flag |= SOCK_UNAVAIL;
-       
-}
-
-/* based on rules, force sockets hidden always */
-void ntreeCompositForceHidden(bNodeTree *ntree, Scene *curscene)
+static void ntree_verify_nodes_cb(void *calldata, struct ID *UNUSED(owner_id), struct bNodeTree *ntree)
 {
+       ID *id= (ID*)calldata;
        bNode *node;
        
-       if(ntree==NULL) return;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if( node->type==CMP_NODE_R_LAYERS) {
-                       Scene *sce= node->id?(Scene *)node->id:curscene;
-                       SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
-                       if(srl)
-                               force_hidden_passes(node, srl->passflag);
-               }
-               else if( node->type==CMP_NODE_IMAGE) {
-                       Image *ima= (Image *)node->id;
-                       if(ima) {
-                               if(ima->rr) {
-                                       ImageUser *iuser= node->storage;
-                                       RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
-                                       if(rl)
-                                               force_hidden_passes(node, rl->passflag);
-                                       else
-                                               force_hidden_passes(node, 0);
-                               }
-                               else if(ima->type!=IMA_TYPE_MULTILAYER) {       /* if ->rr not yet read we keep inputs */
-                                       force_hidden_passes(node, RRES_OUT_Z);
-                               }
-                               else
-                                       force_hidden_passes(node, 0);
-                       }
-                       else
-                               force_hidden_passes(node, 0);
-               }
-       }
-
+       for (node=ntree->nodes.first; node; node=node->next)
+               if (node->typeinfo->verifyfunc)
+                       node->typeinfo->verifyfunc(ntree, node, id);
 }
 
-/* called from render pipeline, to tag render input and output */
-/* need to do all scenes, to prevent errors when you re-render 1 scene */
-void ntreeCompositTagRender(Scene *curscene)
+void ntreeVerifyNodes(struct Main *main, struct ID *id)
 {
-       Scene *sce;
+       bNodeTreeType *ntreetype;
+       bNodeTree *ntree;
+       int n;
        
-       for(sce= G.main->scene.first; sce; sce= sce->id.next) {
-               if(sce->nodetree) {
-                       bNode *node;
-                       
-                       for(node= sce->nodetree->nodes.first; node; node= node->next) {
-                               if(node->id==(ID *)curscene || node->type==CMP_NODE_COMPOSITE)
-                                       NodeTagChanged(sce->nodetree, node);
-                               else if(node->type==CMP_NODE_TEXTURE) /* uses scene sizex/sizey */
-                                       NodeTagChanged(sce->nodetree, node);
-                       }
-               }
+       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);
 }
 
-static int node_animation_properties(bNodeTree *ntree, bNode *node)
+void ntreeUpdateTree(bNodeTree *ntree)
 {
-       bNodeSocket *sock;
-       const ListBase *lb;
-       Link *link;
-       PointerRNA ptr;
-       PropertyRNA *prop;
-       
-       /* check to see if any of the node's properties have fcurves */
-       RNA_pointer_create((ID *)ntree, &RNA_Node, node, &ptr);
-       lb = RNA_struct_type_properties(ptr.type);
-       
-       for (link=lb->first; link; link=link->next) {
-               int driven, len=1, index;
-               prop = (PropertyRNA *)link;
-               
-               if (RNA_property_array_check(prop))
-                       len = RNA_property_array_length(&ptr, prop);
-               
-               for (index=0; index<len; index++) {
-                       if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
-                               NodeTagChanged(ntree, node);
-                               return 1;
-                       }
-               }
-       }
+       bNodeTreeType *ntreetype= ntreeGetType(ntree->type);
+       bNode *node;
+       bNode **deplist;
+       int totnodes, n;
+       
+       ntree_update_link_pointers(ntree);
        
-       /* now check node sockets */
-       for (sock = node->inputs.first; sock; sock=sock->next) {
-               int driven, len=1, index;
+       /* also updates the node level! */
+       ntreeGetDependencyList(ntree, &deplist, &totnodes);
+       
+       if (deplist) {
+               /* update individual nodes */
+               for (n=0; n < totnodes; ++n) {
+                       node = deplist[n];
+                       if (ntreetype->update_node)
+                               ntreetype->update_node(ntree, node);
+                       else if (node->typeinfo->updatefunc)
+                               node->typeinfo->updatefunc(ntree, node);
+               }
                
-               RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr);
-               prop = RNA_struct_find_property(&ptr, "default_value");
+               MEM_freeN(deplist);
                
-               if (RNA_property_array_check(prop))
-                       len = RNA_property_array_length(&ptr, prop);
+               /* ensures only a single output node is enabled, texnode allows multiple though */
+               if(ntree->type!=NTREE_TEXTURE)
+                       ntreeSetOutput(ntree);
                
-               for (index=0; index<len; index++) {
-                       if (rna_get_fcurve(&ptr, prop, index, NULL, &driven)) {
-                               NodeTagChanged(ntree, node);
-                               return 1;
-                       }
-               }
        }
+       
+       /* general tree updates */
+       if (ntree->update & (NTREE_UPDATE_LINKS|NTREE_UPDATE_NODES)) {
+               ntree_validate_links(ntree);
+       }
+       
+       /* update tree */
+       if (ntreetype->update)
+               ntreetype->update(ntree);
+       else {
+               bNodeType *ntype= node_get_type(ntree, ntree->nodetype);
+               if (ntype && ntype->updatetreefunc)
+                       ntype->updatetreefunc(ntree);
+       }
+       
+       /* XXX hack, should be done by depsgraph!! */
+       ntreeVerifyNodes(G.main, &ntree->id);
+       
+       /* clear the update flag */
+       ntree->update = 0;
+}
 
-       return 0;
+void NodeTagChanged(bNodeTree *ntree, bNode *node)
+{
+       bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
+       
+       if (ntreetype->update_node)
+               ntreetype->update_node(ntree, node);
+       else if (node->typeinfo->updatefunc)
+               node->typeinfo->updatefunc(ntree, node);
 }
 
-/* tags nodes that have animation capabilities */
-int ntreeCompositTagAnimated(bNodeTree *ntree)
+int NodeTagIDChanged(bNodeTree *ntree, ID *id)
 {
+       bNodeTreeType *ntreetype = ntreeGetType(ntree->type);
        bNode *node;
-       int tagged= 0;
-       
-       if(ntree==NULL) return 0;
+       int change = FALSE;
+
+       if(ELEM(NULL, id, ntree))
+               return change;
        
-       for(node= ntree->nodes.first; node; node= node->next) {
-               
-               tagged = node_animation_properties(ntree, node);
-               
-               /* otherwise always tag these node types */
-               if(node->type==CMP_NODE_IMAGE) {
-                       Image *ima= (Image *)node->id;
-                       if(ima && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) {
-                               NodeTagChanged(ntree, node);
-                               tagged= 1;
+       if (ntreetype->update_node) {
+               for(node= ntree->nodes.first; node; node= node->next) {
+                       if(node->id==id) {
+                               change = TRUE;
+                               ntreetype->update_node(ntree, node);
                        }
                }
-               else if(node->type==CMP_NODE_TIME) {
-                       NodeTagChanged(ntree, node);
-                       tagged= 1;
-               }
-               /* here was tag render layer, but this is called after a render, so re-composites fail */
-               else if(node->type==NODE_GROUP) {
-                       if( ntreeCompositTagAnimated((bNodeTree *)node->id) ) {
-                               NodeTagChanged(ntree, node);
+       }
+       else {
+               for(node= ntree->nodes.first; node; node= node->next) {
+                       if(node->id==id) {
+                               change = TRUE;
+                               if (node->typeinfo->updatefunc)
+                                       node->typeinfo->updatefunc(ntree, node);
                        }
                }
        }
        
-       return tagged;
+       return change;
 }
 
 
-/* called from image window preview */
-void ntreeCompositTagGenerators(bNodeTree *ntree)
+/* ************* node type access ********** */
+
+int nodeValid(bNodeTree *ntree, bNodeTemplate *ntemp)
 {
-       bNode *node;
-       
-       if(ntree==NULL) return;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if( ELEM(node->type, CMP_NODE_R_LAYERS, CMP_NODE_IMAGE))
-                       NodeTagChanged(ntree, node);
+       bNodeType *ntype= node_get_type(ntree, ntemp->type);
+       if (ntype) {
+               if (ntype->validfunc)
+                       return ntype->validfunc(ntree, ntemp);
+               else
+                       return 1;
        }
+       else
+               return 0;
 }
 
-/* XXX after render animation system gets a refresh, this call allows composite to end clean */
-void ntreeClearTags(bNodeTree *ntree)
+const char* nodeLabel(bNode *node)
 {
-       bNode *node;
-       
-       if(ntree==NULL) return;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               node->need_exec= 0;
-               if(node->type==NODE_GROUP)
-                       ntreeClearTags((bNodeTree *)node->id);
-       }
+       if (node->label[0]!='\0')
+               return node->label;
+       else if (node->typeinfo->labelfunc)
+               return node->typeinfo->labelfunc(node);
+       else
+               return node->typeinfo->name;
 }
 
+struct bNodeTree *nodeGroupEditGet(struct bNode *node)
+{
+       if (node->typeinfo->group_edit_get)
+               return node->typeinfo->group_edit_get(node);
+       else
+               return NULL;
+}
 
-int ntreeTexTagAnimated(bNodeTree *ntree)
+struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit)
 {
-       bNode *node;
-       
-       if(ntree==NULL) return 0;
-       
-       for(node= ntree->nodes.first; node; node= node->next) {
-               if(node->type==TEX_NODE_CURVE_TIME) {
-                       NodeTagChanged(ntree, node);
-                       return 1;
-               }
-               else if(node->type==NODE_GROUP) {
-                       if( ntreeTexTagAnimated((bNodeTree *)node->id) ) {
-                               return 1;
-                       }
-               }
-       }
-       
-       return 0;
+       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;
+}
+
+void nodeGroupEditClear(struct bNode *node)
+{
+       if (node->typeinfo->group_edit_clear)
+               node->typeinfo->group_edit_clear(node);
 }
 
-/* ************* node definition init ********** */
+struct bNodeTemplate nodeMakeTemplate(struct bNode *node)
+{
+       bNodeTemplate ntemp;
+       if (node->typeinfo->templatefunc)
+               return node->typeinfo->templatefunc(node);
+       else {
+               ntemp.type = node->type;
+               return ntemp;
+       }
+}
 
-void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag,
-                                       struct bNodeSocketType *inputs, struct bNodeSocketType *outputs)
+void node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
 {
        memset(ntype, 0, sizeof(bNodeType));
        
        ntype->type = type;
-       ntype->name = name;
+       BLI_strncpy(ntype->name, name, sizeof(ntype->name));
        ntype->nclass = nclass;
        ntype->flag = flag;
        
-       ntype->inputs = inputs;
-       ntype->outputs = outputs;
-       
        /* default size values */
        ntype->width = 140;
        ntype->minwidth = 100;
        ntype->maxwidth = 320;
+       ntype->height = 100;
+       ntype->minheight = 30;
+       ntype->maxheight = FLT_MAX;
+}
+
+void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
+{
+       ntype->inputs = inputs;
+       ntype->outputs = outputs;
 }
 
-void node_type_init(bNodeType *ntype, void (*initfunc)(struct bNode *))
+void node_type_init(struct bNodeType *ntype, void (*initfunc)(struct bNodeTree *ntree, struct bNode *node, struct bNodeTemplate *ntemp))
 {
        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;
        ntype->minwidth = minwidth;
-       ntype->maxwidth = maxwidth;
+       if (maxwidth <= minwidth)
+               ntype->maxwidth = FLT_MAX;
+       else
+               ntype->maxwidth = maxwidth;
 }
 
 void node_type_storage(bNodeType *ntype, const char *storagename, void (*freestoragefunc)(struct bNode *), void (*copystoragefunc)(struct bNode *, struct bNode *))
@@ -3403,47 +1675,92 @@ void node_type_storage(bNodeType *ntype, const char *storagename, void (*freesto
        ntype->freestoragefunc = freestoragefunc;
 }
 
+void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *))
+{
+       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))
+{
+       ntype->updatefunc = updatefunc;
+       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 **))
+{
+       ntype->initexecfunc = initexecfunc;
+       ntype->freeexecfunc = freeexecfunc;
+       ntype->newexecfunc = newexecfunc;
+}
+
 void node_type_gpu(struct bNodeType *ntype, int (*gpufunc)(struct GPUMaterial *mat, struct bNode *node, struct GPUNodeStack *in, struct GPUNodeStack *out))
 {
        ntype->gpufunc = gpufunc;
 }
 
-void node_type_label(struct bNodeType *ntype, const char *(*labelfunc)(struct bNode *))
+void node_type_gpu_ext(struct bNodeType *ntype, int (*gpuextfunc)(struct GPUMaterial *mat, struct bNode *node, void *nodedata, struct GPUNodeStack *in, struct GPUNodeStack *out))
 {
-       ntype->labelfunc = labelfunc;
+       ntype->gpuextfunc = gpuextfunc;
 }
 
-static bNodeType *is_nodetype_registered(ListBase *typelist, int type, ID *id) 
+
+static bNodeType *is_nodetype_registered(ListBase *typelist, int type) 
 {
        bNodeType *ntype= typelist->first;
        
        for(;ntype; ntype= ntype->next )
-               if(ntype->type==type && ntype->id==id)
+               if(ntype->type==type)
                        return ntype;
        
        return NULL;
 }
 
-/* type can be from a static array, we make copy for duplicate types (like group) */
-void nodeRegisterType(ListBase *typelist, const bNodeType *ntype) 
+void nodeRegisterType(ListBase *typelist, bNodeType *ntype) 
 {
-       bNodeType *found= is_nodetype_registered(typelist, ntype->type, ntype->id);
+       bNodeType *found= is_nodetype_registered(typelist, ntype->type);
        
-       if(found==NULL) {
-               bNodeType *ntypen= MEM_callocN(sizeof(bNodeType), "node type");
-               *ntypen= *ntype;
-               BLI_addtail(typelist, ntypen);
-        }
+       if(found==NULL)
+               BLI_addtail(typelist, ntype);
 }
 
 static void registerCompositNodes(ListBase *ntypelist)
 {
-       register_node_type_group(ntypelist);
+       register_node_type_frame(ntypelist);
+       
+       register_node_type_cmp_group(ntypelist);
+//     register_node_type_cmp_forloop(ntypelist);
+//     register_node_type_cmp_whileloop(ntypelist);
        
        register_node_type_cmp_rlayers(ntypelist);
        register_node_type_cmp_image(ntypelist);
@@ -3519,7 +1836,11 @@ static void registerCompositNodes(ListBase *ntypelist)
 
 static void registerShaderNodes(ListBase *ntypelist) 
 {
-       register_node_type_group(ntypelist);
+       register_node_type_frame(ntypelist);
+       
+       register_node_type_sh_group(ntypelist);
+//     register_node_type_sh_forloop(ntypelist);
+//     register_node_type_sh_whileloop(ntypelist);
        
        register_node_type_sh_output(ntypelist);
        register_node_type_sh_mix_rgb(ntypelist);
@@ -3548,7 +1869,11 @@ static void registerShaderNodes(ListBase *ntypelist)
 
 static void registerTextureNodes(ListBase *ntypelist)
 {
-       register_node_type_group(ntypelist);
+       register_node_type_frame(ntypelist);
+       
+       register_node_type_tex_group(ntypelist);
+//     register_node_type_tex_forloop(ntypelist);
+//     register_node_type_tex_whileloop(ntypelist);
        
        register_node_type_tex_math(ntypelist);
        register_node_type_tex_mix_rgb(ntypelist);
@@ -3589,53 +1914,47 @@ static void registerTextureNodes(ListBase *ntypelist)
        register_node_type_tex_proc_distnoise(ntypelist);
 }
 
-static void remove_dynamic_typeinfos(ListBase *list)
+static void free_dynamic_typeinfo(bNodeType *ntype)
 {
-       bNodeType *ntype= list->first;
-       bNodeType *next= NULL;
-       while(ntype) {
-               next= ntype->next;
-               if(ntype->type==NODE_DYNAMIC && ntype->id!=NULL) {
-                       BLI_remlink(list, ntype);
-                       if(ntype->inputs) {
-                               bNodeSocketType *sock= ntype->inputs;
-                               while(sock->type!=-1) {
-                                       MEM_freeN((void *)sock->name);
-                                       sock++;
-                               }
-                               MEM_freeN(ntype->inputs);
-                       }
-                       if(ntype->outputs) {
-                               bNodeSocketType *sock= ntype->outputs;
-                               while(sock->type!=-1) {
-                                       MEM_freeN((void *)sock->name);
-                                       sock++;
-                               }
-                               MEM_freeN(ntype->outputs);
-                       }
-                       if(ntype->name) {
-                               MEM_freeN((void *)ntype->name);
-                       }
-                       MEM_freeN(ntype);
+       if(ntype->type==NODE_DYNAMIC) {
+               if(ntype->inputs) {
+                       MEM_freeN(ntype->inputs);
+               }
+               if(ntype->outputs) {
+                       MEM_freeN(ntype->outputs);
                }
-               ntype= next;
+               if(ntype->name) {
+                       MEM_freeN((void *)ntype->name);
+               }
+       }
+}
+
+static void free_typeinfos(ListBase *list)
+{
+       bNodeType *ntype, *next;
+       for(ntype=list->first; ntype; ntype=next) {
+               next = ntype->next;
+               
+               if(ntype->type==NODE_DYNAMIC)
+                       free_dynamic_typeinfo(ntype);
+               
+               if(ntype->needs_free)
+                       MEM_freeN(ntype);
        }
 }
 
 void init_nodesystem(void) 
 {
-       registerCompositNodes(&node_all_composit);
-       registerShaderNodes(&node_all_shaders);
-       registerTextureNodes(&node_all_textures);
+       registerCompositNodes(&ntreeGetType(NTREE_COMPOSIT)->node_types);
+       registerShaderNodes(&ntreeGetType(NTREE_SHADER)->node_types);
+       registerTextureNodes(&ntreeGetType(NTREE_TEXTURE)->node_types);
 }
 
 void free_nodesystem(void) 
 {
-       /*remove_dynamic_typeinfos(&node_all_composit);*/ /* unused for now */
-       BLI_freelistN(&node_all_composit);
-       remove_dynamic_typeinfos(&node_all_shaders);
-       BLI_freelistN(&node_all_shaders);
-       BLI_freelistN(&node_all_textures);
+       free_typeinfos(&ntreeGetType(NTREE_COMPOSIT)->node_types);
+       free_typeinfos(&ntreeGetType(NTREE_SHADER)->node_types);
+       free_typeinfos(&ntreeGetType(NTREE_TEXTURE)->node_types);
 }
 
 /* called from unlink_scene, when deleting a scene goes over all scenes
index 9ef30bd..dbb2e78 100644 (file)
@@ -3603,6 +3603,7 @@ Sequence *sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
 #ifdef WITH_AUDASPACE
 Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
 {
+       Main *bmain= CTX_data_main(C);
        Scene *scene= CTX_data_scene(C); /* only for sound */
        Editing *ed= seq_give_editing(scene, TRUE);
        bSound *sound;
@@ -3624,7 +3625,7 @@ Sequence *sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo
        info = AUD_getInfo(sound->playback_handle);
 
        if (info.specs.channels == AUD_CHANNELS_INVALID) {
-               sound_delete(C, sound);
+               sound_delete(bmain, sound);
                //if(op)
                //      BKE_report(op->reports, RPT_ERROR, "Unsupported audio format");
                return NULL;
index 74f4830..ff518d6 100644 (file)
@@ -203,7 +203,7 @@ void sound_exit(void)
 
 // XXX unused currently
 #if 0
-struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source)
+struct bSound* sound_new_buffer(struct Main *bmain, struct bSound *source)
 {
        bSound* sound = NULL;
 
@@ -211,23 +211,23 @@ struct bSound* sound_new_buffer(struct bContext *C, struct bSound *source)
        strcpy(name, "buf_");
        strcpy(name + 4, source->id.name);
 
-       sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
+       sound = alloc_libblock(&bmain->sound, ID_SO, name);
 
        sound->child_sound = source;
        sound->type = SOUND_TYPE_BUFFER;
 
-       sound_load(CTX_data_main(C), sound);
+       sound_load(bmain, sound);
 
        if(!sound->playback_handle)
        {
-               free_libblock(&CTX_data_main(C)->sound, sound);
+               free_libblock(&bmain->sound, sound);
                sound = NULL;
        }
 
        return sound;
 }
 
-struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, float start, float end)
+struct bSound* sound_new_limiter(struct Main *bmain, struct bSound *source, float start, float end)
 {
        bSound* sound = NULL;
 
@@ -235,18 +235,18 @@ struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, floa
        strcpy(name, "lim_");
        strcpy(name + 4, source->id.name);
 
-       sound = alloc_libblock(&CTX_data_main(C)->sound, ID_SO, name);
+       sound = alloc_libblock(&bmain->sound, ID_SO, name);
 
        sound->child_sound = source;
        sound->start = start;
        sound->end = end;
        sound->type = SOUND_TYPE_LIMITER;
 
-       sound_load(CTX_data_main(C), sound);
+       sound_load(bmain, sound);
 
        if(!sound->playback_handle)
        {
-               free_libblock(&CTX_data_main(C)->sound, sound);
+               free_libblock(&bmain->sound, sound);
                sound = NULL;
        }
 
@@ -254,13 +254,13 @@ struct bSound* sound_new_limiter(struct bContext *C, struct bSound *source, floa
 }
 #endif
 
-void sound_delete(struct bContext *C, struct bSound* sound)
+void sound_delete(struct Main *bmain, struct bSound* sound)
 {
        if(sound)
        {
                sound_free(sound);
 
-               free_libblock(&CTX_data_main(C)->sound, sound);
+               free_libblock(&bmain->sound, sound);
        }
 }
 
@@ -538,10 +538,11 @@ void sound_stop_scene(struct Scene *scene)
        }
 }
 
-void sound_seek_scene(struct bContext *C)
+void sound_seek_scene(struct Main *bmain, struct Scene *scene)
 {
-       struct Scene *scene = CTX_data_scene(C);
        AUD_Status status;
+       bScreen *screen;
+       int animation_playing;
 
        AUD_lock();
 
@@ -560,7 +561,12 @@ void sound_seek_scene(struct bContext *C)
                AUD_pause(scene->sound_scene_handle);
        }
 
-       if(scene->audio.flag & AUDIO_SCRUB && !CTX_wm_screen(C)->animtimer)
+       animation_playing = 0;
+       for(screen=bmain->screen.first; screen; screen=screen->id.next)
+               if(screen->animtimer)
+                       animation_playing = 1;
+
+       if(scene->audio.flag & AUDIO_SCRUB && !animation_playing)
        {
                if(scene->audio.flag & AUDIO_SYNC)
                {
@@ -758,7 +764,7 @@ void sound_move_scene_sound(struct Scene *UNUSED(scene), void* UNUSED(handle), i
 static void sound_start_play_scene(struct Scene *UNUSED(scene)) {}
 void sound_play_scene(struct Scene *UNUSED(scene)) {}
 void sound_stop_scene(struct Scene *UNUSED(scene)) {}
-void sound_seek_scene(struct bContext *UNUSED(C)) {}
+void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
 float sound_sync_scene(struct Scene *UNUSED(scene)) { return 0.0f; }
 int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
 int sound_read_sound_buffer(struct bSound* UNUSED(sound), float* UNUSED(buffer), int UNUSED(length), float UNUSED(start), float UNUSED(end)) { return 0; }
index 493baeb..6119a85 100644 (file)
@@ -766,7 +766,9 @@ Tex *copy_texture(Tex *tex)
        if(tex->preview) texn->preview = BKE_previewimg_copy(tex->preview);
 
        if(tex->nodetree) {
-               ntreeEndExecTree(tex->nodetree);
+               if (tex->nodetree->execdata) {
+                       ntreeTexEndExecTree(tex->nodetree->execdata);
+               }
                texn->nodetree= ntreeCopyTree(tex->nodetree); 
        }
        
index 0f8493e..122b267 100644 (file)
@@ -45,7 +45,7 @@ extern "C" {
 #define MALWAYS_INLINE MINLINE
 #else
 #define MINLINE static inline
-#define MALWAYS_INLINE static __attribute__((always_inline))
+#define MALWAYS_INLINE static inline __attribute__((always_inline))
 #endif
 #else
 #define MINLINE
index d8719f3..18955c1 100644 (file)
@@ -66,6 +66,9 @@ void swap_m4m4(float A[4][4], float B[4][4]);
 void add_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
 void add_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
 
+void sub_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
+void sub_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
+
 void mul_m3_m3m3(float R[3][3], float A[3][3], float B[3][3]);
 void mul_m4_m4m4(float R[4][4], float A[4][4], float B[4][4]);
 void mul_m4_m3m4(float R[4][4], float A[3][3], float B[4][4]);
index c8b598a..d30168c 100644 (file)
@@ -124,6 +124,7 @@ void interp_v3_v3v3v3(float p[3], const float v1[3], const float v2[3], const fl
 void interp_v3_v3v3v3v3(float p[3], const float v1[3], const float v2[3], const float v3[3], const float v4[3], const float w[4]);
 void interp_v4_v4v4(float r[4], const float a[4], const float b[4], const float t);
 void interp_v4_v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float w[3]);
+void interp_v4_v4v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float v4[4], const float w[4]);
 
 void mid_v3_v3v3(float r[3], const float a[3], const float b[3]);
 
index 3c79a77..e2f5943 100644 (file)
@@ -451,6 +451,24 @@ void add_m4_m4m4(float m1[][4], float m2[][4], float m3[][4])
                        m1[i][j]= m2[i][j] + m3[i][j];
 }
 
+void sub_m3_m3m3(float m1[][3], float m2[][3], float m3[][3])
+{
+       int i, j;
+
+       for(i=0;i<3;i++)
+               for(j=0;j<3;j++)
+                       m1[i][j]= m2[i][j] - m3[i][j];
+}
+
+void sub_m4_m4m4(float m1[][4], float m2[][4], float m3[][4])
+{
+       int i, j;
+
+       for(i=0;i<4;i++)
+               for(j=0;j<4;j++)
+                       m1[i][j]= m2[i][j] - m3[i][j];
+}
+
 int invert_m3(float m[3][3])
 {
        float tmp[3][3];
index 15d671e..7dbceff 100644 (file)
@@ -96,6 +96,14 @@ void interp_v4_v4v4v4(float p[4], const float v1[4], const float v2[4], const fl
        p[3] = v1[3]*w[0] + v2[3]*w[1] + v3[3]*w[2];
 }
 
+void interp_v4_v4v4v4v4(float p[4], const float v1[4], const float v2[4], const float v3[4], const float v4[4], const float w[4])
+{
+       p[0] = v1[0]*w[0] + v2[0]*w[1] + v3[0]*w[2] + v4[0]*w[3];
+       p[1] = v1[1]*w[0] + v2[1]*w[1] + v3[1]*w[2] + v4[1]*w[3];
+       p[2] = v1[2]*w[0] + v2[2]*w[1] + v3[2]*w[2] + v4[2]*w[3];
+       p[3] = v1[3]*w[0] + v2[3]*w[1] + v3[3]*w[2] + v4[3]*w[3];
+}
+
 void mid_v3_v3v3(float v[3], const float v1[3], const float v2[3])
 {
        v[0]= 0.5f*(v1[0] + v2[0]);
index 9bc666d..9efe8dc 100644 (file)
@@ -263,13 +263,21 @@ static float newPerlinU(float x, float y, float z)
 static float orgBlenderNoise(float x, float y, float z)
 {
        register float cn1, cn2, cn3, cn4, cn5, cn6, i, *h;
-       float ox, oy, oz, jx, jy, jz;
+       float fx, fy, fz, ox, oy, oz, jx, jy, jz;
        float n= 0.5;
        int ix, iy, iz, b00, b01, b10, b11, b20, b21;
 
-       ox= (x- (ix= (int)floor(x)) );
-       oy= (y- (iy= (int)floor(y)) );
-       oz= (z- (iz= (int)floor(z)) );
+       fx= floor(x);
+       fy= floor(y);
+       fz= floor(z);
+
+       ox= x- fx;
+       oy= y- fy;
+       oz= z- fz;
+
+       ix= (int)fx;
+       iy= (int)fy;
+       iz= (int)fz;
 
        jx= ox-1;
        jy= oy-1;
index 4088481..ab00a8e 100644 (file)
@@ -30,6 +30,7 @@ set(INC
        ../blenlib
        ../makesdna
        ../makesrna
+       ../nodes
        ../render/extern/include
        ../../../intern/guardedalloc
 )
index be9908d..d5d2df3 100644 (file)
@@ -5,7 +5,7 @@ sources = env.Glob('intern/*.c')
 
 incs = '. #/intern/guardedalloc ../blenlib ../blenkernel'
 incs += ' ../makesdna ../editors/include'
-incs += ' ../render/extern/include ../makesrna'
+incs += ' ../render/extern/include ../makesrna ../nodes'
 
 incs += ' ' + env['BF_ZLIB_INC']
 
index 3a89c5c..5518e13 100644 (file)
 #include "BKE_utildefines.h" // SWITCH_INT DATA ENDB DNA1 O_BINARY GLOB USER TEST REND
 #include "BKE_sound.h"
 
+#include "NOD_socket.h"
+
 //XXX #include "BIF_butspace.h" // badlevel, for do_versions, patching event codes
 //XXX #include "BIF_filelist.h" // badlevel too, where to move this? - elubie
 //XXX #include "BIF_previewrender.h" // bedlelvel, for struct RenderInfo
@@ -2052,10 +2054,21 @@ static void lib_link_nodetree(FileData *fd, Main *main)
        }
 }
 
+static void lib_nodetree_init_types_cb(void *UNUSED(data), ID *UNUSED(id), bNodeTree *ntree)
+{
+       bNode *node;
+       
+       ntreeInitTypes(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
  * external links to/from the group node are preserved.
  */
-static void lib_node_do_versions_group(bNode *gnode)
+static void lib_node_do_versions_group_indices(bNode *gnode)
 {
        bNodeTree *ngroup= (bNodeTree*)gnode->id;
        bNode *intnode;
@@ -2088,92 +2101,101 @@ static void lib_node_do_versions_group(bNode *gnode)
 }
 
 /* updates external links for all group nodes in a tree */
-static void lib_nodetree_do_versions_group(bNodeTree *ntree)
+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))
-                               lib_node_do_versions_group(node);
+                       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))
 {
-       Scene *sce;
-       Material *ma;
-       Tex *tx;
        bNodeTree *ntree;
-       
+       int i;
+       bNodeTreeType *ntreetype;
+
        /* this crashes blender on undo/redo
                if(open==1) {
                        reinit_nodesystem();
                }*/
        
-       /* now create the own typeinfo structs an verify nodes */
-       /* here we still assume no groups in groups */
-       for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
-               ntreeVerifyTypes(ntree);                /* internal nodes, no groups! */
+       /* 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)
+               ntreeInitTypes(ntree);
        
        {
-               /*int has_old_groups=0;*/ /*UNUSED*/
+               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
                 * actual group node updates.
                 */
                for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
-                       if (ntree->flag & NTREE_DO_VERSIONS) {
+                       if (ntree->flag & NTREE_DO_VERSIONS_GROUP_EXPOSE) {
                                /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */
-                               nodeGroupExposeAllSockets(ntree);
-                               /*has_old_groups = 1;*/ /*UNUSED*/
+                               node_group_expose_all_sockets(ntree);
+                               has_old_groups = 1;
                        }
                }
-               /* now verify all types in material trees, groups are set OK now */
-               for(ma= main->mat.first; ma; ma= ma->id.next) {
-                       if(ma->nodetree)
-                               lib_nodetree_do_versions_group(ma->nodetree);
-               }
-               /* and scene trees */
-               for(sce= main->scene.first; sce; sce= sce->id.next) {
-                       if(sce->nodetree)
-                               lib_nodetree_do_versions_group(sce->nodetree);
-               }
-               /* and texture trees */
-               for(tx= main->tex.first; tx; tx= tx->id.next) {
-                       if(tx->nodetree)
-                               lib_nodetree_do_versions_group(tx->nodetree);
+               
+               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);
+                       }
                }
                
                for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
-                       ntree->flag &= ~NTREE_DO_VERSIONS;
+                       ntree->flag &= ~NTREE_DO_VERSIONS_GROUP_EXPOSE;
        }
-
-       /* now verify all types in material trees, groups are set OK now */
-       for(ma= main->mat.first; ma; ma= ma->id.next) {
-               if(ma->nodetree)
-                       ntreeVerifyTypes(ma->nodetree);
-       }
-       /* and scene trees */
-       for(sce= main->scene.first; sce; sce= sce->id.next) {
-               if(sce->nodetree)
-                       ntreeVerifyTypes(sce->nodetree);
+       
+       /* verify all group user nodes */
+       for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
+               ntreeVerifyNodes(main, &ntree->id);
        }
-       /* and texture trees */
-       for(tx= main->tex.first; tx; tx= tx->id.next) {
-               if(tx->nodetree)
-                       ntreeVerifyTypes(tx->nodetree);
+       
+       /* make update calls where necessary */
+       {
+               for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next)
+                       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);
+               }
        }
 }
 
-
+static void direct_link_node_socket(FileData *fd, bNodeSocket *sock)
+{
+       sock->link= newdataadr(fd, sock->link);
+       sock->storage= newdataadr(fd, sock->storage);
+       sock->default_value= newdataadr(fd, sock->default_value);
+       sock->cache= NULL;
+}
 
 /* ntree itself has been read! */
 static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
@@ -2185,6 +2207,7 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        
        ntree->init= 0;         /* to set callbacks and force setting types */
        ntree->progress= NULL;
+       ntree->execdata= NULL;
        
        ntree->adt= newdataadr(fd, ntree->adt);
        direct_link_animdata(fd, ntree->adt);
@@ -2197,9 +2220,11 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                        node->typeinfo= NULL;
                }
                
+               link_list(fd, &node->inputs);
+               link_list(fd, &node->outputs);
+               
                node->storage= newdataadr(fd, node->storage);
                if(node->storage) {
-                       
                        /* could be handlerized at some point */
                        if(ntree->type==NTREE_SHADER && (node->type==SH_NODE_CURVE_VEC || node->type==SH_NODE_CURVE_RGB))
                                direct_link_curvemapping(fd, node->storage);
@@ -2216,8 +2241,6 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                                        ((ImageUser *)node->storage)->ok= 1;
                        }
                }
-               link_list(fd, &node->inputs);
-               link_list(fd, &node->outputs);
        }
        link_list(fd, &ntree->links);
        
@@ -2227,15 +2250,19 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
        
        /* 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)
-                       sock->link= newdataadr(fd, sock->link);
+                       direct_link_node_socket(fd, sock);
                for(sock= node->outputs.first; sock; sock= sock->next)
-                       sock->ns.data= NULL;
+                       direct_link_node_socket(fd, sock);
        }
+       for(sock= ntree->inputs.first; sock; sock= sock->next)
+               direct_link_node_socket(fd, sock);
        for(sock= ntree->outputs.first; sock; sock= sock->next)
-               sock->link= newdataadr(fd, sock->link);
+               direct_link_node_socket(fd, sock);
        
        for(link= ntree->links.first; link; link= link->next) {
                link->fromnode= newdataadr(fd, link->fromnode);
@@ -4964,15 +4991,22 @@ static void lib_link_screen(FileData *fd, Main *main)
                                                SpaceNode *snode= (SpaceNode *)sl;
                                                
                                                snode->id= newlibadr(fd, sc->id.lib, snode->id);
+                                               snode->edittree= NULL;
                                                
-                                               /* internal data, a bit patchy */
-                                               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;
+                                               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_SCE)
+                                                                       snode->nodetree= ((Scene *)snode->id)->nodetree;
+                                                               else if(GS(snode->id->name)==ID_TE)
+                                                                       snode->nodetree= ((Tex *)snode->id)->nodetree;
+                                                       }
+                                               }
+                                               else {
+                                                       snode->nodetree= newlibadr_us(fd, sc->id.lib, snode->nodetree);
                                                }
                                                
                                                snode->linkdrag.first = snode->linkdrag.last = NULL;
@@ -5192,15 +5226,19 @@ void lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *curscene)
                                        snode->id= restore_pointer_by_name(newmain, snode->id, 1);
                                        snode->edittree= NULL;
                                        
-                                       if(snode->id==NULL)
+                                       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;
+                                               }
+                                       }
                                        else {
-                                               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;
+                                               snode->nodetree= restore_pointer_by_name(newmain, &snode->nodetree->id, 1);
                                        }
                                }
                        }
@@ -5429,7 +5467,6 @@ static void direct_link_screen(FileData *fd, bScreen *sc)
                                        snode->gpd= newdataadr(fd, snode->gpd);
                                        direct_link_gpencil(fd, snode->gpd);
                                }
-                               snode->nodetree= snode->edittree= NULL;
                        }
                        else if(sl->spacetype==SPACE_TIME) {
                                SpaceTime *stime= (SpaceTime *)sl;
@@ -6938,6 +6975,53 @@ static void do_version_bone_roll_256(Bone *bone)
                do_version_bone_roll_256(child);
 }
 
+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;
+       }
+}
+
+static void 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 do_versions(FileData *fd, Library *lib, Main *main)
 {
        /*&nb