Cycles: svn merge -r40266:40358 https://svn.blender.org/svnroot/bf-blender/trunk...
[blender-staging.git] / source / blender / editors / space_node / node_edit.c
index a966caa4d7062ca3945f4184fb561c68a8c85294..2490bd33101b81121e7ce58068d38a7e40eb6afa 100644 (file)
 #include "MEM_guardedalloc.h"
 
 #include "DNA_ID.h"
-#include "DNA_object_types.h"
+#include "DNA_lamp_types.h"
 #include "DNA_material_types.h"
 #include "DNA_node_types.h"
+#include "DNA_object_types.h"
 #include "DNA_particle_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_world_types.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
@@ -95,6 +97,8 @@
 
 #include "RNA_enum_types.h"
 
+#include "GPU_material.h"
+
 #include "node_intern.h"
 
 static EnumPropertyItem socket_in_out_items[] = {
@@ -275,36 +279,57 @@ bNode *node_tree_get_editgroup(bNodeTree *nodetree)
 
 /* assumes nothing being done in ntree yet, sets the default in/out node */
 /* called from shading buttons or header */
-void ED_node_shader_default(Material *ma)
+void ED_node_shader_default(ID *id)
 {
        bNode *in, *out;
        bNodeSocket *fromsock, *tosock;
+       bNodeTree *ntree;
        bNodeTemplate ntemp;
+       int output_type, shader_type;
        
-       /* but lets check it anyway */
-       if(ma->nodetree) {
-               if (G.f & G_DEBUG)
-                       printf("error in shader initialize\n");
-               return;
+       ntree= ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0);
+
+       switch(GS(id->name)) {
+               case ID_MA:
+                       ((Material*)id)->nodetree = ntree;
+                       output_type = SH_NODE_OUTPUT_MATERIAL;
+                       shader_type = SH_NODE_BSDF_DIFFUSE;
+                       break;
+               case ID_WO:
+                       ((World*)id)->nodetree = ntree;
+                       output_type = SH_NODE_OUTPUT_WORLD;
+                       shader_type = SH_NODE_BACKGROUND;
+                       break;
+               case ID_LA:
+                       ((Lamp*)id)->nodetree = ntree;
+                       output_type = SH_NODE_OUTPUT_LAMP;
+                       shader_type = SH_NODE_EMISSION;
+                       break;
+               case ID_TE:
+                       ((Tex*)id)->nodetree = ntree;
+                       output_type = SH_NODE_OUTPUT_TEXTURE;
+                       shader_type = SH_NODE_TEX_CLOUDS;
+                       break;
+               default:
+                       printf("ED_node_shader_default called on wrong ID type.\n");
+                       return;
        }
        
-       ma->nodetree= ntreeAddTree("Shader Nodetree", NTREE_SHADER, 0);
-       
-       ntemp.type = SH_NODE_OUTPUT;
-       out= nodeAddNode(ma->nodetree, &ntemp);
+       ntemp.type = output_type;
+       out= nodeAddNode(ntree, &ntemp);
        out->locx= 300.0f; out->locy= 300.0f;
        
-       ntemp.type = SH_NODE_MATERIAL;
-       in= nodeAddNode(ma->nodetree, &ntemp);
+       ntemp.type = shader_type;
+       in= nodeAddNode(ntree, &ntemp);
        in->locx= 10.0f; in->locy= 300.0f;
-       nodeSetActive(ma->nodetree, in);
+       nodeSetActive(ntree, in);
        
        /* only a link from color to color */
        fromsock= in->outputs.first;
        tosock= out->inputs.first;
-       nodeAddLink(ma->nodetree, in, fromsock, out, tosock);
+       nodeAddLink(ntree, in, fromsock, out, tosock);
        
-       ntreeUpdateTree(ma->nodetree);
+       ntreeUpdateTree(ntree);
 }
 
 /* assumes nothing being done in ntree yet, sets the default in/out node */
@@ -351,6 +376,9 @@ void ED_node_composit_default(Scene *sce)
 /* called from shading buttons or header */
 void ED_node_texture_default(Tex *tx)
 {
+       ED_node_shader_default(&tx->id);
+
+#if 0
        bNode *in, *out;
        bNodeSocket *fromsock, *tosock;
        bNodeTemplate ntemp;
@@ -378,6 +406,7 @@ void ED_node_texture_default(Tex *tx)
        nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
        
        ntreeUpdateTree(tx->nodetree);
+#endif
 }
 
 /* id is supposed to contain a node tree */
@@ -395,13 +424,21 @@ void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *tre
                        *ntree= ((Material*)id)->nodetree;
                        if(treetype) *treetype= NTREE_SHADER;
                }
+               else if(idtype == ID_LA) {
+                       *ntree= ((Lamp*)id)->nodetree;
+                       if(treetype) *treetype= NTREE_SHADER;
+               }
+               else if(idtype == ID_WO) {
+                       *ntree= ((World*)id)->nodetree;
+                       if(treetype) *treetype= NTREE_SHADER;
+               }
                else if(idtype == ID_SCE) {
                        *ntree= ((Scene*)id)->nodetree;
                        if(treetype) *treetype= NTREE_COMPOSIT;
                }
                else if(idtype == ID_TE) {
                        *ntree= ((Tex*)id)->nodetree;
-                       if(treetype) *treetype= NTREE_TEXTURE;
+                       if(treetype) *treetype= (*ntree)? (*ntree)->type: NTREE_SHADER;
                }
                else {
                        if(treetype) *treetype= 0;
@@ -436,11 +473,25 @@ void snode_set_context(SpaceNode *snode, Scene *scene)
        
        if(snode->treetype==NTREE_SHADER) {
                /* need active object, or we allow pinning... */
-               if(ob) {
-                       Material *ma= give_current_material(ob, ob->actcol);
-                       if(ma) {
-                               snode->from= &ob->id;
-                               snode->id= &ma->id;
+               if(snode->shaderfrom == SNODE_SHADER_OBJECT) {
+                       if(ob) {
+                               if(ob->type == OB_LAMP) {
+                                       snode->from= &ob->id;
+                                       snode->id= ob->data;
+                               }
+                               else {
+                                       Material *ma= give_current_material(ob, ob->actcol);
+                                       if(ma) {
+                                               snode->from= &ob->id;
+                                               snode->id= &ma->id;
+                                       }
+                               }
+                       }
+               }
+               else { /* SNODE_SHADER_WORLD */
+                       if(scene->world) {
+                               snode->from= NULL;
+                               snode->id= &scene->world->id;
                        }
                }
        }
@@ -526,6 +577,8 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
 
 void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
 {
+       int was_active_texture = (node->flag & NODE_ACTIVE_TEXTURE);
+
        nodeSetActive(ntree, node);
        
        if(node->type!=NODE_GROUP) {
@@ -534,7 +587,7 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
                /* tree specific activate calls */
                if(ntree->type==NTREE_SHADER) {
                        /* when we select a material, active texture is cleared, for buttons */
-                       if(node->id && GS(node->id->name)==ID_MA)
+                       if(node->id && ELEM3(GS(node->id->name), ID_MA, ID_LA, ID_WO))
                                nodeClearActiveID(ntree, ID_TE);
                        
                        if(node->type==SH_NODE_OUTPUT) {
@@ -549,6 +602,15 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
                                        ED_node_generic_update(bmain, ntree, node);
                        }
 
+                       /* if active texture changed, free glsl materials */
+                       if((node->flag & NODE_ACTIVE_TEXTURE) && !was_active_texture) {
+                               Material *ma;
+
+                               for(ma=bmain->mat.first; ma; ma=ma->id.next)
+                                       if(ma->nodetree && ma->use_nodes && has_nodetree(ma->nodetree, ntree))
+                                               GPU_material_free(ma);
+                       }
+
                        WM_main_add_notifier(NC_MATERIAL|ND_NODES, node->id);
                }
                else if(ntree->type==NTREE_COMPOSIT) {
@@ -3537,6 +3599,37 @@ void NODE_OT_add_file(wmOperatorType *ot)
        RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Datablock name to assign");
 }
 
+/* ****************** Auto Layout Operator  ******************* */
+
+static int node_auto_layout_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       SpaceNode *snode= CTX_wm_space_node(C);
+       bNode *node;
+
+       for(node=snode->edittree->nodes.first; node; node=node->next)
+               if(node->flag & SELECT)
+                       ED_node_tree_auto_layout(snode->edittree, node);
+
+       snode_notify(C, snode);
+       
+       return OPERATOR_FINISHED;
+}
+
+void NODE_OT_auto_layout(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name= "Auto Layout Nodes";
+       ot->description= "Automatically layout nodes with the selected nodes as root";
+       ot->idname= "NODE_OT_auto_layout";
+       
+       /* callbacks */
+       ot->exec= node_auto_layout_exec;
+       ot->poll= ED_operator_node_active;
+       
+       /* flags */
+       ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
 /********************** New node tree operator *********************/
 
 static int new_node_tree_exec(bContext *C, wmOperator *op)
@@ -3565,7 +3658,6 @@ static int new_node_tree_exec(bContext *C, wmOperator *op)
        
        /* hook into UI */
        uiIDContextProperty(C, &ptr, &prop);
-
        if(prop) {
                RNA_id_pointer_create(&ntree->id, &idptr);
                RNA_property_pointer_set(&ptr, prop, idptr);
@@ -3601,3 +3693,4 @@ void NODE_OT_new_node_tree(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", nodetree_type_items, NTREE_COMPOSIT, "Tree Type", "");
        RNA_def_string(ot->srna, "name", "NodeTree", MAX_ID_NAME-2, "Name", "");
 }
+