Todo/feature request
authorTon Roosendaal <ton@blender.org>
Mon, 7 Feb 2011 16:41:57 +0000 (16:41 +0000)
committerTon Roosendaal <ton@blender.org>
Mon, 7 Feb 2011 16:41:57 +0000 (16:41 +0000)
When using masks or other simple 3D elements in composites, doing
a layer re-rendering on a node is a bit clumsy all the time.

This commit does two things to help:
- new hotkey "Z" in node editor automatically finds render layer
  that changed and re-renders it + composites
- option "Auto Render" does same, but then after every transform
  edit in 3D window

The latter is experimental; real & proper system for this requires
full threaded render support (like previews). But it works!

Demo file:
http://download.blender.org/demo/test/auto_composite.blend

Important fix:
After any render, all the render layers were tagged "changed", which
caused any edit to first totally recomposte everthing. Now it only
composites changes.

Implementation notes

- DAG scene flush now sets 'changed' flags in render layer nodes
- Added notifier for 'transform finished' to trigger the update,
  this is temporarily.

13 files changed:
release/scripts/ui/space_node.py
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/depsgraph.c
source/blender/blenkernel/intern/node.c
source/blender/editors/render/render_internal.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_intern.h
source/blender/editors/space_node/node_ops.c
source/blender/editors/space_node/space_node.c
source/blender/editors/transform/transform.c
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_space.c
source/blender/windowmanager/WM_types.h

index 31ac25ff41a2b28e8af7212b874a28f8a0b554e4..98c24d407de0b9b21611e25e5ddca1b85c457204 100644 (file)
@@ -71,6 +71,7 @@ class NODE_HT_header(bpy.types.Header):
             if snode.show_backdrop:
                 row = layout.row(align=True)
                 row.prop(snode, "backdrop_channels", text="", expand=True)
+            layout.prop(snode, "use_auto_render")
 
         layout.separator()
 
index 941083734b4c7433bf89855a796218ec9b8bf282..455e1739b98ed9c5b45a6a72f5aece764a5a80d7 100644 (file)
@@ -193,6 +193,7 @@ void                        nodeClearActiveID(struct bNodeTree *ntree, short idtype);
 
 void                   NodeTagChanged(struct bNodeTree *ntree, struct bNode *node);
 int                            NodeTagIDChanged(struct bNodeTree *ntree, struct ID *id);
+void                   ntreeClearTags(struct bNodeTree *ntree);
 
 /* ************** Groups ****************** */
 
index cedf4e9324770cf052ac9d1e3a0332f23690780f..0c5c72627cbc7dcb38e4d8debcf1cf045899dd14 100644 (file)
@@ -41,6 +41,7 @@
 #include "DNA_lattice_types.h"
 #include "DNA_key_types.h"
 #include "DNA_mesh_types.h"
+#include "DNA_node_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_windowmanager_types.h"
@@ -54,6 +55,7 @@
 #include "BKE_key.h"
 #include "BKE_library.h"
 #include "BKE_main.h"
+#include "BKE_node.h"
 #include "BKE_mball.h"
 #include "BKE_modifier.h"
 #include "BKE_object.h"
@@ -1923,6 +1925,28 @@ static void dag_scene_flush_layers(Scene *sce, int lay)
                        flush_layer_node(sce, itA->node, lasttime);
 }
 
+static void dag_tag_renderlayers(Scene *sce, unsigned int lay)
+{
+       if(sce->nodetree) {
+               bNode *node;
+               Base *base;
+               unsigned int lay_changed;
+               
+               for(base= sce->base.first; base; base= base->next)
+                       if(base->lay & lay)
+                               if(base->object->recalc)
+                                       lay_changed |= base->lay;
+                       
+               for(node= sce->nodetree->nodes.first; node; node= node->next) {
+                       if(node->id==(ID *)sce) {
+                               SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
+                               if(srl && (srl->lay & lay_changed))
+                                       NodeTagChanged(sce->nodetree, node);
+                       }
+               }
+       }
+}
+
 /* flushes all recalc flags in objects down the dependency tree */
 void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time)
 {
@@ -1967,6 +1991,8 @@ void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const sho
                        }
                }
        }
+       
+       dag_tag_renderlayers(sce, lay);
 }
 
 static int object_modifiers_use_time(Object *ob)
index f6487bf1d19d6a952e1abfdd35f3c46219f10aad..69f016331922169331b62aedba07565c79df4340 100644 (file)
@@ -3182,10 +3182,7 @@ int ntreeCompositTagAnimated(bNodeTree *ntree)
                        NodeTagChanged(ntree, node);
                        tagged= 1;
                }
-               else if(node->type==CMP_NODE_R_LAYERS) {
-                       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);
@@ -3210,6 +3207,21 @@ void ntreeCompositTagGenerators(bNodeTree *ntree)
        }
 }
 
+/* XXX after render animation system gets a refresh, this call allows composite to end clean */
+void ntreeClearTags(bNodeTree *ntree)
+{
+       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);
+       }
+}
+
+
 int ntreeTexTagAnimated(bNodeTree *ntree)
 {
        bNode *node;
index 96994ab1df43c33da1e3caf83522e7ef68bb19cf..f38a5691a6fe90bb1793b82c713b186886982739 100644 (file)
@@ -596,6 +596,9 @@ static void render_endjob(void *rjv)
        /* else the frame will not update for the original value */
        ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1);
        
+       /* XXX above function sets all tags in nodes */
+       ntreeClearTags(rj->scene->nodetree);
+       
        if(rj->srl) {
                NodeTagIDChanged(rj->scene->nodetree, &rj->scene->id);
                WM_main_add_notifier(NC_NODE|NA_EDITED, rj->scene);
@@ -648,6 +651,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        wmJob *steve;
        RenderJob *rj;
        Image *ima;
+       int jobflag;
        const short is_animation= RNA_boolean_get(op->ptr, "animation");
        const short is_write_still= RNA_boolean_get(op->ptr, "write_still");
        
@@ -701,6 +705,8 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        /* ensure at least 1 area shows result */
        screen_set_image_output(C, event->x, event->y);
 
+       jobflag= WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS;
+       
        /* single layer re-render */
        if(RNA_property_is_set(op->ptr, "layer")) {
                SceneRenderLayer *rl;
@@ -712,11 +718,12 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
 
                scn = (Scene *)BLI_findstring(&mainp->scene, scene_name, offsetof(ID, name) + 2);
                rl = (SceneRenderLayer *)BLI_findstring(&scene->r.layers, rl_name, offsetof(SceneRenderLayer, name));
-
+               
                if (scn && rl) {
                        scene = scn;
                        srl = rl;
                }
+               jobflag |= WM_JOB_SUSPEND;
        }
 
        /* job custom data */
@@ -733,7 +740,7 @@ static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event)
        rj->reports= op->reports;
 
        /* setup job */
-       steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS);
+       steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Render", jobflag);
        WM_jobs_customdata(steve, rj, render_freejob);
        WM_jobs_timer(steve, 0.2, NC_SCENE|ND_RENDER_RESULT, 0);
        WM_jobs_callbacks(steve, render_startjob, NULL, NULL, render_endjob);
index 834f34838716f31f418201e19aef022d8da68702..1279863802afb9bd6451973970c3760b18325b41 100644 (file)
@@ -2158,6 +2158,51 @@ void NODE_OT_read_fullsamplelayers(wmOperatorType *ot)
        ot->flag= 0;
 }
 
+int node_render_changed_exec(bContext *C, wmOperator *UNUSED(op))
+{
+       Scene *sce= CTX_data_scene(C);
+       bNode *node;
+       
+       for(node= sce->nodetree->nodes.first; node; node= node->next) {
+               if(node->id==(ID *)sce && node->need_exec) {
+                       break;
+               }
+       }
+       if(node) {
+               SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
+               
+               if(srl) {
+                       PointerRNA op_ptr;
+                       
+                       WM_operator_properties_create(&op_ptr, "RENDER_OT_render");
+                       RNA_string_set(&op_ptr, "layer", srl->name);
+                       RNA_string_set(&op_ptr, "scene", sce->id.name+2);
+                       
+                       WM_operator_name_call(C, "RENDER_OT_render", WM_OP_INVOKE_DEFAULT, &op_ptr);
+
+                       WM_operator_properties_free(&op_ptr);
+                       
+                       return OPERATOR_FINISHED;
+               }
+                  
+       }
+       return OPERATOR_CANCELLED;
+}
+
+void NODE_OT_render_changed(wmOperatorType *ot)
+{
+       
+       ot->name= "Render Changed Layer";
+       ot->idname= "NODE_OT_render_changed";
+       
+       ot->exec= node_render_changed_exec;
+       
+       ot->poll= composite_node_active;
+       
+       /* flags */
+       ot->flag= 0;
+}
+
 
 /* ****************** Make Group operator ******************* */
 
index 66bf9310db876373140c4b3de79d68416f8daeff..5d67eb77e289a6d00c31a78539a940f61a656232 100644 (file)
@@ -92,7 +92,7 @@ void node_tree_verify_groups(bNodeTree *nodetree);
 void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace);
 int node_has_hidden_sockets(bNode *node);
 void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
-
+int node_render_changed_exec(bContext *, wmOperator *);
 
 void NODE_OT_duplicate(struct wmOperatorType *ot);
 void NODE_OT_delete(struct wmOperatorType *ot);
@@ -115,6 +115,7 @@ void NODE_OT_show_cyclic_dependencies(struct wmOperatorType *ot);
 void NODE_OT_link_viewer(struct wmOperatorType *ot);
 void NODE_OT_read_fullsamplelayers(struct wmOperatorType *ot);
 void NODE_OT_read_renderlayers(struct wmOperatorType *ot);
+void NODE_OT_render_changed(struct wmOperatorType *ot);
 
 void NODE_OT_backimage_move(struct wmOperatorType *ot);
 void NODE_OT_backimage_zoom(struct wmOperatorType *ot);
index 781682c9185dd531a17fdf75242080bc11eb73d6..db5c493dcd92899d7ff11962dcdee38b56e5f49d 100644 (file)
@@ -78,6 +78,7 @@ void node_operatortypes(void)
        
        WM_operatortype_append(NODE_OT_read_renderlayers);
        WM_operatortype_append(NODE_OT_read_fullsamplelayers);
+       WM_operatortype_append(NODE_OT_render_changed);
        
        WM_operatortype_append(NODE_OT_backimage_move);
        WM_operatortype_append(NODE_OT_backimage_zoom);
@@ -170,6 +171,8 @@ void node_keymap(struct wmKeyConfig *keyconf)
        
        WM_keymap_add_item(keymap, "NODE_OT_read_renderlayers", RKEY, KM_PRESS, KM_CTRL, 0);
        WM_keymap_add_item(keymap, "NODE_OT_read_fullsamplelayers", RKEY, KM_PRESS, KM_SHIFT, 0);
+       WM_keymap_add_item(keymap, "NODE_OT_render_changed", ZKEY, KM_PRESS, 0, 0);
+       
        
        transform_keymap_for_space(keyconf, keymap, SPACE_NODE);
 }
index eb8c34fe8bdef1031bfc815426f5be3bf6fbc507..dab6568bea63630edd91bb840e5ff951bd59ecba 100644 (file)
@@ -172,13 +172,21 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
                                case ND_FRAME:
                                        ED_area_tag_refresh(sa);
                                        break;
+                               case ND_TRANSFORM_DONE:
+                                       if(type==NTREE_COMPOSIT) {
+                                               if(snode->flag & SNODE_AUTO_RENDER) {
+                                                       snode->recalc= 1;
+                                                       ED_area_tag_refresh(sa);
+                                               }
+                                       }
+                                       break;
                        }
                        break;
                case NC_WM:
                        if(wmn->data==ND_FILEREAD)
                                ED_area_tag_refresh(sa);
                        break;
-                       
+               
                /* future: add ID checks? */
                case NC_MATERIAL:
                        if(type==NTREE_SHADER) {
@@ -212,7 +220,7 @@ static void node_area_listener(ScrArea *sa, wmNotifier *wmn)
 
                case NC_IMAGE:
                        if (wmn->action == NA_EDITED) {
-                               if(snode->treetype==NTREE_COMPOSIT) {
+                               if(type==NTREE_COMPOSIT) {
                                        Scene *scene= wmn->window->screen->scene;
                                        
                                        /* note that NodeTagIDChanged is alredy called by BKE_image_signal() on all
@@ -241,8 +249,15 @@ static void node_area_refresh(const struct bContext *C, struct ScrArea *sa)
                }
                else if(snode->treetype==NTREE_COMPOSIT) {
                        Scene *scene= (Scene *)snode->id;
-                       if(scene->use_nodes)
-                               snode_composite_job(C, sa);
+                       if(scene->use_nodes) {
+                               /* recalc is set on 3d view changes for auto compo */
+                               if(snode->recalc) {
+                                       snode->recalc= 0;
+                                       node_render_changed_exec((struct bContext*)C, NULL);
+                               }
+                               else 
+                                       snode_composite_job(C, sa);
+                       }
                }
                else if(snode->treetype==NTREE_TEXTURE) {
                        Tex *tex= (Tex *)snode->id;
index 2d541b63bd06dbed49634552b93a882ca45a7fd9..394dd4330602d9ba75c3ee60686dfca8de1bc66e 100644 (file)
@@ -338,7 +338,7 @@ static void viewRedrawForce(const bContext *C, TransInfo *t)
        }
 }
 
-static void viewRedrawPost(TransInfo *t)
+static void viewRedrawPost(bContext *C, TransInfo *t)
 {
        ED_area_headerprint(t->sa, NULL);
        
@@ -346,6 +346,10 @@ static void viewRedrawPost(TransInfo *t)
                /* if autokeying is enabled, send notifiers that keyframes were added */
                if (IS_AUTOKEY_ON(t->scene))
                        WM_main_add_notifier(NC_ANIMATION|ND_KEYFRAME|NA_EDITED, NULL);
+               
+               /* XXX temp, first hack to get auto-render in compositor work (ton) */
+               WM_event_add_notifier(C, NC_SCENE|ND_TRANSFORM_DONE, CTX_data_scene(C));
+
        }
        
 #if 0 // TRANSFORM_FIX_ME
@@ -1817,7 +1821,7 @@ int transformEnd(bContext *C, TransInfo *t)
                postTrans(C, t);
 
                /* send events out for redraws */
-               viewRedrawPost(t);
+               viewRedrawPost(C, t);
 
                /*  Undo as last, certainly after special_trans_update! */
 
index 49a4df043fb7cb753fe13224829df14deff09317..90961a5cc1571d5bd12346d8d8ae12ee707d8f0d 100644 (file)
@@ -396,8 +396,9 @@ typedef struct SpaceNode {
        float mx, my;           /* mousepos for drawing socketless link */
        
        struct bNodeTree *nodetree, *edittree;
-       int treetype;                   /* treetype: as same nodetree->type */
-       short texfrom, pad;             /* texfrom object, world or brush */
+       int treetype;           /* treetype: as same nodetree->type */
+       short texfrom;          /* texfrom object, world or brush */
+       short recalc;           /* currently on 0/1, for auto compo */
        
        struct bGPdata *gpd;            /* grease-pencil data */
 } SpaceNode;
@@ -407,6 +408,7 @@ typedef struct SpaceNode {
 #define SNODE_DISPGP           4
 #define SNODE_USE_ALPHA                8
 #define SNODE_SHOW_ALPHA       16
+#define SNODE_AUTO_RENDER      32
 
 /* snode->texfrom */
 #define SNODE_TEX_OBJECT       0
index 45622f500dfef55920e70102115c36ddc43b866a..afb0b82b8a50a7b535c1f8b44423c12ad75b1081 100644 (file)
@@ -2263,6 +2263,11 @@ static void rna_def_space_node(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Backdrop", "Use active Viewer Node output as backdrop for compositing nodes");
        RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NODE_VIEW, NULL);
 
+       prop= RNA_def_property(srna, "use_auto_render", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "flag", SNODE_AUTO_RENDER);
+       RNA_def_property_ui_text(prop, "Auto Render", "Re-render and composite changed layer on 3D edits");
+       RNA_def_property_update(prop, NC_SPACE|ND_SPACE_NODE_VIEW, NULL);
+       
        prop= RNA_def_property(srna, "backdrop_zoom", PROP_FLOAT, PROP_NONE);
        RNA_def_property_float_sdna(prop, NULL, "zoom");
        RNA_def_property_range(prop, 0.01f, FLT_MAX);
index 728e5f1a8000c2da87593f09c9d552a1a13632db..8590534df303ca0f2610696277a7419467070645 100644 (file)
@@ -193,6 +193,7 @@ typedef struct wmNotifier {
 #define ND_TOOLSETTINGS                (15<<16)
 #define ND_LAYER                       (16<<16)
 #define ND_FRAME_RANGE         (17<<16)
+#define ND_TRANSFORM_DONE      (18<<16)
 #define ND_WORLD                       (92<<16)
 #define ND_LAYER_CONTENT       (101<<16)