Cycles: svn merge -r41182:41205 ^/trunk/blender
[blender-staging.git] / source / blender / editors / space_node / node_edit.c
index 59e62c9b0e4b7e2907d395729a9e5b620618e30f..7fb81e77bcbfc8cfb92bf7cbe324735c6626647a 100644 (file)
 #include "MEM_guardedalloc.h"
 
 #include "DNA_ID.h"
 #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_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_particle_types.h"
 #include "DNA_scene_types.h"
+#include "DNA_world_types.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
@@ -61,6 +63,7 @@
 #include "BKE_material.h"
 #include "BKE_modifier.h"
 #include "BKE_paint.h"
 #include "BKE_material.h"
 #include "BKE_modifier.h"
 #include "BKE_paint.h"
+#include "BKE_scene.h"
 #include "BKE_screen.h"
 #include "BKE_texture.h"
 #include "BKE_report.h"
 #include "BKE_screen.h"
 #include "BKE_texture.h"
 #include "BKE_report.h"
@@ -89,6 +92,8 @@
 
 #include "RNA_enum_types.h"
 
 
 #include "RNA_enum_types.h"
 
+#include "GPU_material.h"
+
 #include "node_intern.h"
 
 static EnumPropertyItem socket_in_out_items[] = {
 #include "node_intern.h"
 
 static EnumPropertyItem socket_in_out_items[] = {
@@ -269,36 +274,91 @@ 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 */
 
 /* 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(Scene *scene, ID *id)
 {
        bNode *in, *out;
 {
        bNode *in, *out;
-       bNodeSocket *fromsock, *tosock;
+       bNodeSocket *fromsock, *tosock, *sock;
+       bNodeTree *ntree;
        bNodeTemplate ntemp;
        bNodeTemplate ntemp;
+       int output_type, shader_type;
+       float color[3], strength = 1.0f;
        
        
-       /* 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 *ma= (Material*)id;
+                       ma->nodetree = ntree;
+
+                       if(scene_use_new_shading_nodes(scene)) {
+                               output_type = SH_NODE_OUTPUT_MATERIAL;
+                               shader_type = SH_NODE_BSDF_DIFFUSE;
+                       }
+                       else {
+                               output_type = SH_NODE_OUTPUT;
+                               shader_type = SH_NODE_MATERIAL;
+                       }
+
+                       copy_v3_v3(color, &ma->r);
+                       strength= 0.0f;
+                       break;
+               }
+               case ID_WO: {
+                       World *wo= (World*)id;
+
+                       wo->nodetree = ntree;
+                       output_type = SH_NODE_OUTPUT_WORLD;
+                       shader_type = SH_NODE_BACKGROUND;
+
+                       copy_v3_v3(color, &wo->horr);
+                       strength= 1.0f;
+                       break;
+               }
+               case ID_LA: {
+                       Lamp *la= (Lamp*)id;
+
+                       ((Lamp*)id)->nodetree = ntree;
+                       output_type = SH_NODE_OUTPUT_LAMP;
+                       shader_type = SH_NODE_EMISSION;
+
+                       copy_v3_v3(color, &la->r);
+                       if(la->type == LA_LOCAL || la->type == LA_SPOT || la->type == LA_AREA)
+                               strength= 100.0f;
+                       else
+                               strength= 1.0f;
+                       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;
        
        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;
        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;
        
        /* 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);
+
+       /* default values */
+       if(scene_use_new_shading_nodes(scene)) {
+               sock= in->inputs.first;
+               copy_v3_v3(((bNodeSocketValueRGBA*)sock->default_value)->value, color);
+
+               if(strength != 0.0f) {
+                       sock= in->inputs.last;
+                       ((bNodeSocketValueFloat*)sock->default_value)->value= strength;
+               }
+       }
        
        
-       ntreeUpdateTree(ma->nodetree);
+       ntreeUpdateTree(ntree);
 }
 
 /* assumes nothing being done in ntree yet, sets the default in/out node */
 }
 
 /* assumes nothing being done in ntree yet, sets the default in/out node */
@@ -389,6 +449,14 @@ void node_tree_from_ID(ID *id, bNodeTree **ntree, bNodeTree **edittree, int *tre
                        *ntree= ((Material*)id)->nodetree;
                        if(treetype) *treetype= NTREE_SHADER;
                }
                        *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_SCE) {
                        *ntree= ((Scene*)id)->nodetree;
                        if(treetype) *treetype= NTREE_COMPOSIT;
@@ -430,11 +498,25 @@ void snode_set_context(SpaceNode *snode, Scene *scene)
        
        if(snode->treetype==NTREE_SHADER) {
                /* need active object, or we allow pinning... */
        
        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;
                        }
                }
        }
                        }
                }
        }
@@ -520,6 +602,8 @@ static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup)
 
 void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
 {
 
 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) {
        nodeSetActive(ntree, node);
        
        if(node->type!=NODE_GROUP) {
@@ -528,7 +612,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 */
                /* 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) {
                                nodeClearActiveID(ntree, ID_TE);
                        
                        if(node->type==SH_NODE_OUTPUT) {
@@ -543,6 +627,15 @@ void ED_node_set_active(Main *bmain, bNodeTree *ntree, bNode *node)
                                        ED_node_generic_update(bmain, ntree, 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) {
                        WM_main_add_notifier(NC_MATERIAL|ND_NODES, node->id);
                }
                else if(ntree->type==NTREE_COMPOSIT) {
@@ -3536,6 +3629,37 @@ void NODE_OT_add_file(wmOperatorType *ot)
        RNA_def_string(ot->srna, "name", "Image", 24, "Name", "Datablock name to assign");
 }
 
        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)
 /********************** New node tree operator *********************/
 
 static int new_node_tree_exec(bContext *C, wmOperator *op)