Made texture nodes accessible in the interface.
authorRobin Allen <roblovski@gmail.com>
Mon, 17 Aug 2009 18:37:58 +0000 (18:37 +0000)
committerRobin Allen <roblovski@gmail.com>
Mon, 17 Aug 2009 18:37:58 +0000 (18:37 +0000)
* Exposed Tex.use_nodes, Tex.nodetree, MTex.which_output in RNA
* Added node controls to texture buttons (Use Nodes and Use Output)
* Made new texture outputs have unique names by default, though unique names still aren't required.

Note: The preview window in the texture buttons only takes which_output into account when in "material" mode, and in the material half of "both" mode; the plain texture display ignores the user's output choice.

This is because ED_preview_draw draws a Tex* and not an MTex* -- still some work to do here.

release/ui/buttons_texture.py
source/blender/makesrna/intern/rna_texture.c
source/blender/nodes/intern/TEX_nodes/TEX_output.c
source/blender/nodes/intern/TEX_util.c

index 51a90b2c9ee25bf24f9537a4420cfb496055d9f6..a1b89bec0cee1f7dcb5eda69c48dda41e59413b0 100644 (file)
@@ -7,7 +7,8 @@ class TextureButtonsPanel(bpy.types.Panel):
        __context__ = "texture"
        
        def poll(self, context):
-               return (context.texture and context.texture.type != 'NONE')
+               tex = context.texture
+               return (tex and (tex.type != 'NONE' or tex.use_nodes))
                
 class TEXTURE_PT_preview(TextureButtonsPanel):
        __label__ = "Preview"
@@ -31,7 +32,7 @@ class TEXTURE_PT_preview(TextureButtonsPanel):
                        layout.template_preview(tex, parent=br)
                else:
                        layout.template_preview(tex)
-
+                       
 class TEXTURE_PT_context_texture(TextureButtonsPanel):
        __show_header__ = False
 
@@ -61,25 +62,62 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel):
                elif tex:
                        split.template_ID(space, "pin_id")
 
-               if (not space.pin_id) and (     context.sculpt_object or \
-                                                                       context.vertex_paint_object or \
-                                                                       context.weight_paint_object or \
-                                                                       context.texture_paint_object \
-                                                                       ):
+               if (not space.pin_id) and (
+                       context.sculpt_object or
+                       context.vertex_paint_object or
+                       context.weight_paint_object or
+                       context.texture_paint_object
+               ):
                        split.itemR(space, "brush_texture", text="Brush", toggle=True)
 
                if tex:
+                       layout.itemR(tex, "use_nodes")
+                       
                        split = layout.split(percentage=0.2)
+                       
+                       if tex.use_nodes:
+                               slot = context.texture_slot
+                               split.itemL(text="Output:")
+                               split.itemR(slot, "output_node", text="")
+
+                       else:
+                               split.itemL(text="Type:")
+                               split.itemR(tex, "type", text="")
+                       
+class TEXTURE_PT_colors(TextureButtonsPanel):
+       __label__ = "Colors"
+       __default_closed__ = True
+
+       def draw(self, context):
+               layout = self.layout
+               
+               tex = context.texture
+
+               layout.itemR(tex, "use_color_ramp", text="Ramp")
+               if tex.use_color_ramp:
+                       layout.template_color_ramp(tex.color_ramp, expand=True)
+
+               split = layout.split()
                
-                       split.itemL(text="Type:")
-                       split.itemR(tex, "type", text="")
+               split.itemR(tex, "rgb_factor", text="Multiply RGB")
 
-class TEXTURE_PT_mapping(TextureButtonsPanel):
+               col = split.column()
+               col.itemL(text="Adjust:")
+               col.itemR(tex, "brightness")
+               col.itemR(tex, "contrast")
+                       
+# Texture Slot Panels #
+                       
+class TextureSlotPanel(TextureButtonsPanel):
+       def poll(self, context):
+               return (
+                       context.texture_slot and 
+                       TextureButtonsPanel.poll(self, context)
+               )
+                               
+class TEXTURE_PT_mapping(TextureSlotPanel):
        __label__ = "Mapping"
        
-       def poll(self, context):
-               return (context.texture_slot and context.texture and context.texture.type != 'NONE')
-
        def draw(self, context):
                layout = self.layout
                
@@ -150,12 +188,9 @@ class TEXTURE_PT_mapping(TextureButtonsPanel):
                        row.column().itemR(tex, "offset")
                        row.column().itemR(tex, "size")
 
-class TEXTURE_PT_influence(TextureButtonsPanel):
+class TEXTURE_PT_influence(TextureSlotPanel):
        __label__ = "Influence"
        
-       def poll(self, context):
-               return (context.texture_slot and context.texture and context.texture.type != 'NONE' and (not context.brush))
-
        def draw(self, context):
                layout = self.layout
                
@@ -235,36 +270,16 @@ class TEXTURE_PT_influence(TextureButtonsPanel):
                if ma or wo:
                        col.itemR(tex, "default_value", text="DVar", slider=True)
 
-class TEXTURE_PT_colors(TextureButtonsPanel):
-       __label__ = "Colors"
-       __default_closed__ = True
-
-       def draw(self, context):
-               layout = self.layout
-               
-               tex = context.texture
-
-               layout.itemR(tex, "use_color_ramp", text="Ramp")
-               if tex.use_color_ramp:
-                       layout.template_color_ramp(tex.color_ramp, expand=True)
-
-               split = layout.split()
-               
-               split.itemR(tex, "rgb_factor", text="Multiply RGB")
-
-               col = split.column()
-               col.itemL(text="Adjust:")
-               col.itemR(tex, "brightness")
-               col.itemR(tex, "contrast")
-               
 # Texture Type Panels #
 
-class TEXTURE_PT_clouds(TextureButtonsPanel):
-       __label__ = "Clouds"
-       
+class TextureTypePanel(TextureButtonsPanel):
        def poll(self, context):
                tex = context.texture
-               return (tex and tex.type == 'CLOUDS')
+               return (tex and tex.type == self.tex_type and not tex.use_nodes)
+
+class TEXTURE_PT_clouds(TextureTypePanel):
+       __label__ = "Clouds"
+       tex_type = 'CLOUDS'
 
        def draw(self, context):
                layout = self.layout
@@ -281,12 +296,9 @@ class TEXTURE_PT_clouds(TextureButtonsPanel):
                flow.itemR(tex, "noise_depth", text="Depth")
                flow.itemR(tex, "nabla", text="Nabla")
 
-class TEXTURE_PT_wood(TextureButtonsPanel):
+class TEXTURE_PT_wood(TextureTypePanel):
        __label__ = "Wood"
-       
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'WOOD')
+       tex_type = 'WOOD'
 
        def draw(self, context):
                layout = self.layout
@@ -308,13 +320,10 @@ class TEXTURE_PT_wood(TextureButtonsPanel):
                flow.itemR(tex, "turbulence")
                flow.itemR(tex, "nabla")
                
-class TEXTURE_PT_marble(TextureButtonsPanel):
+class TEXTURE_PT_marble(TextureTypePanel):
        __label__ = "Marble"
+       tex_type = 'MARBLE'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'MARBLE')
-
        def draw(self, context):
                layout = self.layout
                
@@ -332,13 +341,10 @@ class TEXTURE_PT_marble(TextureButtonsPanel):
                flow.itemR(tex, "turbulence")
                flow.itemR(tex, "nabla")
 
-class TEXTURE_PT_magic(TextureButtonsPanel):
+class TEXTURE_PT_magic(TextureTypePanel):
        __label__ = "Magic"
+       tex_type = 'MAGIC'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'MAGIC')
-
        def draw(self, context):
                layout = self.layout
                
@@ -348,13 +354,10 @@ class TEXTURE_PT_magic(TextureButtonsPanel):
                row.itemR(tex, "noise_depth", text="Depth")
                row.itemR(tex, "turbulence")
 
-class TEXTURE_PT_blend(TextureButtonsPanel):
+class TEXTURE_PT_blend(TextureTypePanel):
        __label__ = "Blend"
+       tex_type = 'BLEND'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'BLEND')
-
        def draw(self, context):
                layout = self.layout
                
@@ -363,13 +366,10 @@ class TEXTURE_PT_blend(TextureButtonsPanel):
                layout.itemR(tex, "progression")
                layout.itemR(tex, "flip_axis")
                        
-class TEXTURE_PT_stucci(TextureButtonsPanel):
+class TEXTURE_PT_stucci(TextureTypePanel):
        __label__ = "Stucci"
+       tex_type = 'STUCCI'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'STUCCI')
-
        def draw(self, context):
                layout = self.layout
                
@@ -384,13 +384,10 @@ class TEXTURE_PT_stucci(TextureButtonsPanel):
                row.itemR(tex, "noise_size", text="Size")
                row.itemR(tex, "turbulence")
                
-class TEXTURE_PT_image(TextureButtonsPanel):
+class TEXTURE_PT_image(TextureTypePanel):
        __label__ = "Image"
+       tex_type = 'IMAGE'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'IMAGE')
-
        def draw(self, context):
                layout = self.layout
                
@@ -398,14 +395,11 @@ class TEXTURE_PT_image(TextureButtonsPanel):
 
                layout.template_texture_image(tex)
 
-class TEXTURE_PT_image_sampling(TextureButtonsPanel):
+class TEXTURE_PT_image_sampling(TextureTypePanel):
        __label__ = "Image Sampling"
        __default_closed__ = True
+       tex_type = 'IMAGE'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'IMAGE')
-
        def draw(self, context):
                layout = self.layout
                
@@ -449,14 +443,11 @@ class TEXTURE_PT_image_sampling(TextureButtonsPanel):
                        else:
                                col.itemR(tex, "filter_eccentricity", text="Eccentricity")
 
-class TEXTURE_PT_image_mapping(TextureButtonsPanel):
+class TEXTURE_PT_image_mapping(TextureTypePanel):
        __label__ = "Image Mapping"
        __default_closed__ = True
+       tex_type = 'IMAGE'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'IMAGE')
-
        def draw(self, context):
                layout = self.layout
                
@@ -499,13 +490,10 @@ class TEXTURE_PT_image_mapping(TextureButtonsPanel):
                col.itemR(tex, "crop_max_x", text="X")
                col.itemR(tex, "crop_max_y", text="Y")
        
-class TEXTURE_PT_plugin(TextureButtonsPanel):
+class TEXTURE_PT_plugin(TextureTypePanel):
        __label__ = "Plugin"
+       tex_type = 'PLUGIN'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'PLUGIN')
-
        def draw(self, context):
                layout = self.layout
                
@@ -513,13 +501,10 @@ class TEXTURE_PT_plugin(TextureButtonsPanel):
                
                layout.itemL(text="Nothing yet")
                
-class TEXTURE_PT_envmap(TextureButtonsPanel):
+class TEXTURE_PT_envmap(TextureTypePanel):
        __label__ = "Environment Map"
+       tex_type = 'ENVIRONMENT_MAP'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'ENVIRONMENT_MAP')
-
        def draw(self, context):
                layout = self.layout
                
@@ -527,13 +512,10 @@ class TEXTURE_PT_envmap(TextureButtonsPanel):
                
                layout.itemL(text="Nothing yet")
                
-class TEXTURE_PT_musgrave(TextureButtonsPanel):
+class TEXTURE_PT_musgrave(TextureTypePanel):
        __label__ = "Musgrave"
+       tex_type = 'MUSGRAVE'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'MUSGRAVE')
-
        def draw(self, context):
                layout = self.layout
                
@@ -563,12 +545,9 @@ class TEXTURE_PT_musgrave(TextureButtonsPanel):
                row.itemR(tex, "noise_size", text="Size")
                row.itemR(tex, "nabla")
 
-class TEXTURE_PT_voronoi(TextureButtonsPanel):
+class TEXTURE_PT_voronoi(TextureTypePanel):
        __label__ = "Voronoi"
-       
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'VORONOI')
+       tex_type = 'VORONOI'
 
        def draw(self, context):
                layout = self.layout
@@ -600,13 +579,10 @@ class TEXTURE_PT_voronoi(TextureButtonsPanel):
                row.itemR(tex, "noise_size", text="Size")
                row.itemR(tex, "nabla")
                        
-class TEXTURE_PT_distortednoise(TextureButtonsPanel):
+class TEXTURE_PT_distortednoise(TextureTypePanel):
        __label__ = "Distorted Noise"
+       tex_type = 'DISTORTED_NOISE'
        
-       def poll(self, context):
-               tex = context.texture
-               return (tex and tex.type == 'DISTORTED_NOISE')
-
        def draw(self, context):
                layout = self.layout
                
index ccb5e5b2f9513ea8ee5c7e132cc8da0797b6c3ad..76cb99863067ac053aceb61375c1a2782eb99f4f 100644 (file)
@@ -36,6 +36,9 @@
 #include "DNA_material_types.h"
 #include "DNA_texture_types.h"
 #include "DNA_world_types.h"
+#include "DNA_node_types.h"
+
+#include "BKE_node.h"
 
 #include "WM_types.h"
 
@@ -107,6 +110,43 @@ static void rna_TextureSlot_name_get(PointerRNA *ptr, char *str)
                strcpy(str, "");
 }
 
+static EnumPropertyItem *rna_TextureSlot_output_node_itemf(bContext *C, PointerRNA *ptr, int *free)
+{
+       MTex *mtex= ptr->data;
+       Tex *tex= mtex->tex;
+       EnumPropertyItem *item= NULL;
+       int totitem= 0;
+       
+       if(tex)
+       {
+               bNodeTree *ntree= tex->nodetree;
+               if(ntree)
+               {
+                       EnumPropertyItem tmp= {0, "", 0, "", ""};
+                       bNode *node;
+                       
+                       tmp.value = 0;
+                       tmp.name = "Not Specified";
+                       tmp.identifier = "NOT_SPECIFIED";
+                       RNA_enum_item_add(&item, &totitem, &tmp);
+                       
+                       for(node= ntree->nodes.first; node; node= node->next) {
+                               if(node->type == TEX_NODE_OUTPUT) {
+                                       tmp.value= node->custom1;
+                                       tmp.name= ((TexNodeOutput*)node->storage)->name;
+                                       tmp.identifier = tmp.name;
+                                       RNA_enum_item_add(&item, &totitem, &tmp);
+                               }
+                       }
+               }
+       }
+       
+       RNA_enum_item_end(&item, &totitem);
+       
+       *free = 1;
+       return item;
+}
+
 static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value)
 {
        Tex *tex= (Tex*)ptr->data;
@@ -118,6 +158,18 @@ static void rna_Texture_use_color_ramp_set(PointerRNA *ptr, int value)
                tex->coba= add_colorband(0);
 }
 
+void rna_Texture_use_nodes_set(PointerRNA *ptr, int v)
+{
+       Tex *tex= (Tex*)ptr->data;
+       
+       tex->use_nodes = v;
+       tex->type = 0;
+       
+       if(v && tex->nodetree==NULL) {
+               node_texture_default(tex);
+       }
+}
+
 static void rna_ImageTexture_mipmap_set(PointerRNA *ptr, int value)
 {
        Tex *tex= (Tex*)ptr->data;
@@ -287,6 +339,10 @@ static void rna_def_mtex(BlenderRNA *brna)
                {MTEX_MAP_MODE_3D, "3D", 0, "3D", ""},
                {0, NULL, 0, NULL, NULL}};
 
+       static EnumPropertyItem output_node_items[] = {
+               {0, "DUMMY", 0, "Dummy", ""},
+               {0, NULL, 0, NULL, NULL}};
+               
        srna= RNA_def_struct(brna, "TextureSlot", NULL);
        RNA_def_struct_sdna(srna, "MTex");
        RNA_def_struct_ui_text(srna, "Texture Slot", "Texture slot defining the mapping and influence of a texture.");
@@ -373,6 +429,13 @@ static void rna_def_mtex(BlenderRNA *brna)
        RNA_def_property_ui_range(prop, 0, 5, 10, 3);
        RNA_def_property_ui_text(prop, "Normal Factor", "Amount texture affects normal values.");
        RNA_def_property_update(prop, NC_TEXTURE, NULL);
+       
+       prop= RNA_def_property(srna, "output_node", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_sdna(prop, NULL, "which_output");
+       RNA_def_property_enum_items(prop, output_node_items);
+       RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_TextureSlot_output_node_itemf");
+       RNA_def_property_ui_text(prop, "Output Node", "Which output node to use, for node-based textures.");
+       RNA_def_property_update(prop, NC_TEXTURE, NULL);
 }
 
 static void rna_def_filter_size_common(StructRNA *srna) 
@@ -1285,7 +1348,19 @@ static void rna_def_texture(BlenderRNA *brna)
        RNA_def_property_range(prop, 0, 2);
        RNA_def_property_ui_text(prop, "RGB Factor", "");
        RNA_def_property_update(prop, NC_TEXTURE, NULL);
-
+       
+       /* nodetree */
+       prop= RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "use_nodes", 1);
+       RNA_def_property_boolean_funcs(prop, NULL, "rna_Texture_use_nodes_set");
+       RNA_def_property_ui_text(prop, "Use Nodes", "Make this a node-based texture");
+       RNA_def_property_update(prop, NC_TEXTURE, NULL);
+       
+       prop= RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
+       RNA_def_property_pointer_sdna(prop, NULL, "nodetree");
+       RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node-based textures");
+       RNA_def_property_update(prop, NC_TEXTURE, NULL);
+       
        rna_def_animdata_common(srna);
 
        /* specific types */
index 060ea8d7e67348b9db3dd663675614e482c98ad9..d0538d119007ff722b27c9fa14cbad94a717bce1 100644 (file)
@@ -64,11 +64,64 @@ static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
        }
 }
 
-static void init(bNode* node)
+static void unique_name(bNode *node)
 {
-   TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
-   strcpy(tno->name, "Default");
-   node->storage= tno;
+       TexNodeOutput *tno = (TexNodeOutput *)node->storage;
+       char *new_name = 0;
+       int new_len;
+       int suffix;
+       bNode *i;
+       char *name = tno->name;
+       
+       i = node;
+       while(i->prev) i = i->prev;
+       for(; i; i=i->next) {
+               if(
+                       i == node ||
+                       i->type != TEX_NODE_OUTPUT ||
+                       strcmp(name, ((TexNodeOutput*)(i->storage))->name)
+               )
+                       continue;
+               
+               if(!new_name) {
+                       int len = strlen(name);
+                       if(len >= 4 && sscanf(name + len - 4, ".%03d", &suffix) == 1) {
+                               new_len = len;
+                       } else {
+                               suffix = 0;
+                               new_len = len + 4;
+                               if(new_len > 31)
+                                       new_len = 31;
+                       }
+                       
+                       new_name = malloc(new_len + 1);
+                       strcpy(new_name, name);
+                       name = new_name;
+               }
+               sprintf(new_name + new_len - 4, ".%03d", ++suffix);
+       }
+       
+       if(new_name) {
+               strcpy(tno->name, new_name);
+               free(new_name);
+       }
+}
+
+static void init(bNode *node)
+{
+       TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
+       node->storage= tno;
+       
+       strcpy(tno->name, "Default");
+       unique_name(node);
+       ntreeTexAssignIndex(0, node);
+}
+
+static void copy(bNode *orig, bNode *new)
+{
+       node_copy_standard_storage(orig, new);
+       unique_name(new);
+       ntreeTexAssignIndex(0, new);
 }
 
 
@@ -85,6 +138,6 @@ bNodeType tex_node_output= {
        /* butfunc         */  NULL,
        /* initfunc        */  init,
        /* freestoragefunc */  node_free_standard_storage,
-       /* copystoragefunc */  node_copy_standard_storage,  
+       /* copystoragefunc */  copy,  
        /* id              */  NULL
 };
index 867e754f9608a62553844ac7712dda04d6264f51..d25decd411153d7892746b8b2a72691884565e62 100644 (file)
@@ -197,6 +197,10 @@ void ntreeTexExecTree(bNodeTree *nodes, TexResult *texres, float *coord, char do
        TexResult dummy_texres;
        TexCallData data;
        
+       /* 0 means don't care, so just use first */
+       if(which_output == 0)
+               which_output = 1;
+       
        if(!texres) texres = &dummy_texres;
        data.coord = coord;
        data.target = texres;
@@ -270,10 +274,17 @@ char* ntreeTexOutputMenu(bNodeTree *ntree)
 void ntreeTexAssignIndex(struct bNodeTree *ntree, struct bNode *node)
 {
        bNode *tnode;
-       int index = 0;
+       int index = 1;
+       
+       if(ntree) 
+               tnode = ntree->nodes.first;
+       else {
+               tnode = node;
+               while(tnode->prev) tnode = tnode->prev;
+       }
        
        check_index:
-       for(tnode= ntree->nodes.first; tnode; tnode= tnode->next)
+       for(; tnode; tnode= tnode->next)
                if(tnode->type == TEX_NODE_OUTPUT && tnode != node)
                        if(tnode->custom1 == index) {
                                index ++;