Fix T45839 : Regression - Multi-layer image issues when using non-standard names
authorDalai Felinto <dfelinto@gmail.com>
Wed, 9 Sep 2015 14:41:46 +0000 (19:41 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 9 Sep 2015 14:42:35 +0000 (19:42 +0500)
This was introduced in the fix for T44336 .
The code is now what it should have been in the first place at the time
of multiview commit.

ImageUser->passtype is being removed in favour of bringing
ImageUser->pass back.

Reviewers: sergey

Differential Revision: https://developer.blender.org/D1504

source/blender/blenkernel/intern/image.c
source/blender/blenloader/intern/versioning_270.c
source/blender/compositor/nodes/COM_ImageNode.cpp
source/blender/compositor/operations/COM_MultilayerImageOperation.cpp
source/blender/compositor/operations/COM_MultilayerImageOperation.h
source/blender/editors/render/render_internal.c
source/blender/editors/space_image/image_buttons.c
source/blender/editors/space_image/space_image.c
source/blender/makesdna/DNA_image_types.h
source/blender/makesrna/intern/rna_image.c

index ef760f2da26b504b14ae2268952cf03895b9dcc7..36aeb97c3f07a196d9e9211b680645d276a250c3 100644 (file)
@@ -2578,21 +2578,10 @@ static void image_init_imageuser(Image *ima, ImageUser *iuser)
        RenderResult *rr = ima->rr;
 
        iuser->multi_index = 0;
-       iuser->layer = iuser->view = 0;
-       iuser->passtype = SCE_PASS_COMBINED;
-
-       if (rr) {
-               RenderLayer *rl = rr->layers.first;
-
-               if (rl) {
-                       RenderPass *rp = rl->passes.first;
-
-                       if (rp)
-                               iuser->passtype = rp->passtype;
-               }
+       iuser->layer = iuser->pass = iuser->view = 0;
 
+       if (rr)
                BKE_image_multilayer_index(rr, iuser);
-       }
 }
 
 void BKE_image_init_imageuser(Image *ima, ImageUser *iuser)
@@ -2740,6 +2729,52 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
        }
 }
 
+#define PASSTYPE_UNSET -1
+/* return renderpass for a given pass index and active view */
+/* fallback to available if there are missing passes for active view */
+static RenderPass *image_render_pass_get(RenderLayer *rl, const int pass, const int view, int *r_passindex)
+{
+       RenderPass *rpass_ret = NULL;
+       RenderPass *rpass;
+
+       int rp_index = 0;
+       int rp_passtype = PASSTYPE_UNSET;
+
+       for (rpass = rl->passes.first; rpass; rpass = rpass->next, rp_index++) {
+               if (rp_index == pass) {
+                       rpass_ret = rpass;
+                       if (view == 0) {
+                               /* no multiview or left eye */
+                               break;
+                       }
+                       else {
+                               rp_passtype = rpass->passtype;
+                       }
+               }
+               /* multiview */
+               else if ((rp_passtype != PASSTYPE_UNSET) &&
+                        (rpass->passtype == rp_passtype) &&
+                        (rpass->view_id == view))
+               {
+                       rpass_ret = rpass;
+                       break;
+               }
+       }
+
+       /* fallback to the first pass in the layer */
+       if (rpass_ret == NULL) {
+               rp_index = 0;
+               rpass_ret = rl->passes.first;
+       }
+
+       if (r_passindex) {
+               *r_passindex = (rpass == rpass_ret ? rp_index : pass);
+       }
+
+       return rpass_ret;
+}
+#undef PASSTYPE_UNSET
+
 /* if layer or pass changes, we need an index for the imbufs list */
 /* note it is called for rendered results, but it doesnt use the index! */
 /* and because rendered results use fake layer/passes, don't correct for wrong indices here */
@@ -2759,27 +2794,16 @@ RenderPass *BKE_image_multilayer_index(RenderResult *rr, ImageUser *iuser)
                if (RE_HasFakeLayer(rr)) rl_index += 1;
 
                for (rl = rr->layers.first; rl; rl = rl->next, rl_index++) {
-                       for (rpass = rl->passes.first; rpass; rpass = rpass->next, index++) {
-                               if (iuser->layer == rl_index &&
-                                   iuser->passtype == rpass->passtype &&
-                                   rv_index == rpass->view_id)
-                               {
-                                       break;
-                               }
-                       }
-                       if (rpass)
+                       if (iuser->layer == rl_index) {
+                               int rp_index;
+                               rpass = image_render_pass_get(rl, iuser->pass, rv_index, &rp_index);
+                               iuser->multi_index = index + rp_index;
                                break;
+                       }
+                       else {
+                               index += BLI_listbase_count(&rl->passes);
+                       }
                }
-               iuser->multi_index = (rpass ? index : 0);
-       }
-
-       if (rpass == NULL) {
-               rl = rr->layers.first;
-               if (rl)
-                       rpass = rl->passes.first;
-
-               if (rpass && iuser)
-                       iuser->passtype = rpass->passtype;
        }
 
        return rpass;
@@ -3613,7 +3637,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
        float *rectf, *rectz;
        unsigned int *rect;
        float dither;
-       int channels, layer, passtype;
+       int channels, layer, pass;
        ImBuf *ibuf;
        int from_render = (ima->render_slot == ima->last_render_slot);
        int actview;
@@ -3630,7 +3654,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
 
        channels = 4;
        layer = iuser->layer;
-       passtype = iuser->passtype;
+       pass = iuser->pass;
        actview = iuser->view;
 
        if ((ima->flag & IMA_IS_STEREO) && (iuser->flag & IMA_SHOW_STEREO))
@@ -3693,19 +3717,10 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
        else if (rres.layers.first) {
                RenderLayer *rl = BLI_findlink(&rres.layers, layer - (rres.have_combined ? 1 : 0));
                if (rl) {
-                       RenderPass *rpass;
-
-                       for (rpass = rl->passes.first; rpass; rpass = rpass->next) {
-                               if (passtype == rpass->passtype &&
-                                   actview == rpass->view_id)
-                               {
-                                       break;
-                               }
-                       }
-
+                       RenderPass *rpass = image_render_pass_get(rl, pass, actview, NULL);
                        if (rpass) {
                                rectf = rpass->rect;
-                               if (passtype == SCE_PASS_COMBINED) {
+                               if (pass == 0) {
                                        if (rectf == NULL) {
                                                /* Happens when Save Buffers is enabled.
                                                 * Use display buffer stored in the render layer.
index 6af6a7aff4fd17df81f17af9c976bbd4115c9bb9..5518b1513f4bfca4bd3fc46246af658d2730b510 100644 (file)
@@ -767,7 +767,6 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main)
                                                {
                                                        SpaceImage *sima = (SpaceImage *) sl;
                                                        sima->iuser.flag |= IMA_SHOW_STEREO;
-                                                       sima->iuser.passtype = SCE_PASS_COMBINED;
                                                        break;
                                                }
                                        }
index 572e63a2cedacebea5022e5d79359fc3013689a2..facd422c21732b0f134c1ea42e08e62cef6c98d6 100644 (file)
@@ -40,19 +40,19 @@ ImageNode::ImageNode(bNode *editorNode) : Node(editorNode)
 
 }
 NodeOperation *ImageNode::doMultilayerCheck(NodeConverter &converter, RenderLayer *rl, Image *image, ImageUser *user,
-                                            int framenumber, int outputsocketIndex, int passtype, int view, DataType datatype) const
+                                            int framenumber, int outputsocketIndex, int passindex, int view, DataType datatype) const
 {
        NodeOutput *outputSocket = this->getOutputSocket(outputsocketIndex);
        MultilayerBaseOperation *operation = NULL;
        switch (datatype) {
                case COM_DT_VALUE:
-                       operation = new MultilayerValueOperation(passtype, view);
+                       operation = new MultilayerValueOperation(passindex, view);
                        break;
                case COM_DT_VECTOR:
-                       operation = new MultilayerVectorOperation(passtype, view);
+                       operation = new MultilayerVectorOperation(passindex, view);
                        break;
                case COM_DT_COLOR:
-                       operation = new MultilayerColorOperation(passtype, view);
+                       operation = new MultilayerColorOperation(passindex, view);
                        break;
                default:
                        break;
@@ -124,20 +124,21 @@ void ImageNode::convertToOperations(NodeConverter &converter, const CompositorCo
                                        }
 
                                        if (rpass) {
+                                               int passindex = BLI_findindex(&rl->passes, rpass);
                                                switch (rpass->channels) {
                                                        case 1:
                                                                operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
-                                                                                             rpass->passtype, view, COM_DT_VALUE);
+                                                                                             passindex, view, COM_DT_VALUE);
                                                                break;
                                                                /* using image operations for both 3 and 4 channels (RGB and RGBA respectively) */
                                                                /* XXX any way to detect actual vector images? */
                                                        case 3:
                                                                operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
-                                                                                             rpass->passtype, view, COM_DT_VECTOR);
+                                                                                             passindex, view, COM_DT_VECTOR);
                                                                break;
                                                        case 4:
                                                                operation = doMultilayerCheck(converter, rl, image, imageuser, framenumber, index,
-                                                                                             rpass->passtype, view, COM_DT_COLOR);
+                                                                                             passindex, view, COM_DT_COLOR);
                                                                break;
                                                        default:
                                                                /* dummy operation is added below */
index 00be3b1cddeb4870921e9ee59c74e7dccda93b0a..b57dd4e32c328ab32b9524ecdc3a4c02c9175779 100644 (file)
@@ -27,9 +27,9 @@ extern "C" {
 #  include "IMB_imbuf_types.h"
 }
 
-MultilayerBaseOperation::MultilayerBaseOperation(int passtype, int view) : BaseImageOperation()
+MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view) : BaseImageOperation()
 {
-       this->m_passtype = passtype;
+       this->m_passId = passindex;
        this->m_view = view;
 }
 
@@ -39,7 +39,7 @@ ImBuf *MultilayerBaseOperation::getImBuf()
        int view = this->m_imageUser->view;
 
        this->m_imageUser->view = this->m_view;
-       this->m_imageUser->passtype = this->m_passtype;
+       this->m_imageUser->pass = this->m_passId;
 
        if (BKE_image_multilayer_index(this->m_image->rr, this->m_imageUser)) {
                ImBuf *ibuf = BaseImageOperation::getImBuf();
index 2e140577d74e42615f31411ebcdc4559d790f0f9..46a9319c373515dc6d9afa99d0f0c5a15e0334a4 100644 (file)
@@ -29,7 +29,7 @@
 
 class MultilayerBaseOperation : public BaseImageOperation {
 private:
-       int m_passtype;
+       int m_passId;
        int m_view;
        RenderLayer *m_renderlayer;
 protected:
@@ -38,13 +38,13 @@ public:
        /**
         * Constructor
         */
-       MultilayerBaseOperation(int passtype, int view);
+       MultilayerBaseOperation(int passindex, int view);
        void setRenderLayer(RenderLayer *renderlayer) { this->m_renderlayer = renderlayer; }
 };
 
 class MultilayerColorOperation : public MultilayerBaseOperation {
 public:
-       MultilayerColorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
+       MultilayerColorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
                this->addOutputSocket(COM_DT_COLOR);
        }
        void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -52,7 +52,7 @@ public:
 
 class MultilayerValueOperation : public MultilayerBaseOperation {
 public:
-       MultilayerValueOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
+       MultilayerValueOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
                this->addOutputSocket(COM_DT_VALUE);
        }
        void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
@@ -60,7 +60,7 @@ public:
 
 class MultilayerVectorOperation : public MultilayerBaseOperation {
 public:
-       MultilayerVectorOperation(int passtype, int view) : MultilayerBaseOperation(passtype, view) {
+       MultilayerVectorOperation(int passindex, int view) : MultilayerBaseOperation(passindex, view) {
                this->addOutputSocket(COM_DT_VECTOR);
        }
        void executePixelSampled(float output[4], float x, float y, PixelSampler sampler);
index 755b8dd303dd8a8ac3774c72474e1f578156f86f..10de2d667ea3de3dbe5c424260fd181fcf32951e 100644 (file)
@@ -190,7 +190,7 @@ static void image_buffer_rect_update(RenderJob *rj, RenderResult *rr, ImBuf *ibu
         *                                              - sergey -
         */
        /* TODO(sergey): Need to check has_combined here? */
-       if (iuser->passtype == SCE_PASS_COMBINED) {
+       if (iuser->pass == 0) {
                RenderView *rv;
                size_t view_id = BKE_scene_multiview_view_id_get(&scene->r, viewname);
                rv = RE_RenderViewGetById(rr, view_id);
@@ -525,6 +525,7 @@ static void render_image_update_pass_and_layer(RenderJob *rj, RenderResult *rr,
                        }
                }
 
+               iuser->pass = sima->iuser.pass;
                iuser->layer = sima->iuser.layer;
 
                RE_ReleaseResult(rj->re);
@@ -898,7 +899,6 @@ static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *even
        rj->write_still = is_write_still && !is_animation;
        rj->iuser.scene = scene;
        rj->iuser.ok = 1;
-       rj->iuser.passtype = SCE_PASS_COMBINED;
        rj->reports = op->reports;
        rj->orig_layer = 0;
        rj->last_layer = 0;
index 579860726c6de512e86c61b96e5b9a53506ab4e3..3af210f376b8eccaf233dacf65ddc984911e6556 100644 (file)
@@ -418,7 +418,7 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
 
        uiItemS(layout);
 
-       nr = (rl ? BLI_listbase_count(&rl->passes) : 0) - 1;
+       nr = 0;
        fake_name = ui_imageuser_pass_fake_name(rl);
 
        if (fake_name) {
@@ -427,7 +427,8 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
        }
 
        /* rendered results don't have a Combined pass */
-       for (rpass = rl ? rl->passes.last : NULL; rpass; rpass = rpass->prev, nr--) {
+       /* multiview: the ordering must be ascending, so the left-most pass is always the one picked */
+       for (rpass = rl ? rl->passes.first : NULL; rpass; rpass = rpass->next, nr++) {
 
                /* just show one pass of each kind */
                if (passflag & rpass->passtype)
@@ -436,18 +437,17 @@ static void ui_imageuser_pass_menu(bContext *UNUSED(C), uiLayout *layout, void *
                passflag |= rpass->passtype;
 
 final:
-               uiDefButI(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
-                         UI_UNIT_X * 5, UI_UNIT_X, &iuser->passtype, (float) rpass->passtype, 0.0, 0, -1, "");
+               uiDefButS(block, UI_BTYPE_BUT_MENU, B_NOP, IFACE_(rpass->internal_name), 0, 0,
+                         UI_UNIT_X * 5, UI_UNIT_X, &iuser->pass, (float) nr, 0.0, 0, -1, "");
        }
 
        if (fake_name) {
                fake_name = NULL;
                rpass = &rpass_fake;
+               nr = 0;
                goto final;
        }
 
-       BLI_assert(nr == -1);
-
        BKE_image_release_renderresult(scene, image);
 }
 
@@ -550,7 +550,6 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
        ImageUser *iuser = iuser_v;
        RenderLayer *rl;
        RenderPass *rp;
-       RenderPass *next = NULL;
        int layer = iuser->layer;
 
        if (RE_HasFakeLayer(rr))
@@ -559,20 +558,20 @@ static void image_multi_incpass_cb(bContext *C, void *rr_v, void *iuser_v)
        rl = BLI_findlink(&rr->layers, layer);
 
        if (rl) {
-               for (rp = rl->passes.first; rp; rp = rp->next) {
-                       if (rp->passtype == iuser->passtype) {
-                               next = rp->next;
-                               if (next != NULL && next->passtype == rp->passtype)
-                                       next = next->next;
+               RenderPass *rpass = BLI_findlink(&rl->passes, iuser->pass);
+               int rp_index = iuser->pass + 1;
+
+               if (rpass == NULL)
+                       return;
+
+               for (rp = rpass->next; rp; rp = rp->next, rp_index++) {
+                       if (rp->passtype != rpass->passtype) {
+                               iuser->pass = rp_index;
+                               BKE_image_multilayer_index(rr, iuser);
+                               WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
                                break;
                        }
                }
-
-               if (next != NULL && iuser->passtype != next->passtype) {
-                       iuser->passtype = next->passtype;
-                       BKE_image_multilayer_index(rr, iuser);
-                       WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
-               }
        }
 }
 static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v) 
@@ -581,29 +580,31 @@ static void image_multi_decpass_cb(bContext *C, void *rr_v, void *iuser_v)
        ImageUser *iuser = iuser_v;
        RenderLayer *rl;
        RenderPass *rp;
-       RenderPass *prev = NULL;
        int layer = iuser->layer;
 
+       if (iuser->pass == 0)
+               return;
+
        if (RE_HasFakeLayer(rr))
                layer -= 1;
 
        rl = BLI_findlink(&rr->layers, layer);
 
        if (rl) {
-               for (rp = rl->passes.last; rp; rp = rp->prev) {
-                       if (rp->passtype == iuser->passtype) {
-                               prev = rp->prev;
-                               if (prev != NULL && prev->passtype == rp->passtype)
-                                       prev = prev->prev;
+               RenderPass *rpass = BLI_findlink(&rl->passes, iuser->pass);
+               int rp_index = 0;
+
+               if (rpass == NULL)
+                       return;
+
+               for (rp = rl->passes.first; rp; rp = rp->next, rp_index++) {
+                       if (rp->passtype == rpass->passtype) {
+                               iuser->pass = rp_index - 1;
+                               BKE_image_multilayer_index(rr, iuser);
+                               WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
                                break;
                        }
                }
-
-               if (prev != NULL && iuser->passtype != prev->passtype) {
-                       iuser->passtype = prev->passtype;
-                       BKE_image_multilayer_index(rr, iuser);
-                       WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
-               }
        }
 }
 
@@ -692,7 +693,7 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, Image *image, RenderRes
 
                /* pass */
                fake_name = ui_imageuser_pass_fake_name(rl);
-               rpass = (rl ? RE_pass_find_by_type(rl, iuser->passtype, ((RenderView *)rr->views.first)->name) : NULL);
+               rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass  - (fake_name ? 1 : 0)) : NULL);
 
                display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : "");
                but = uiDefMenuBut(block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name),
index 928e064b73076e7d11480b42186763b8dd78c4bf..98a0752f64d9cc54fbf5ea36752a3c23b8bfa3be 100644 (file)
@@ -157,7 +157,6 @@ static SpaceLink *image_new(const bContext *UNUSED(C))
        simage->iuser.fie_ima = 2;
        simage->iuser.frames = 100;
        simage->iuser.flag = IMA_SHOW_STEREO;
-       simage->iuser.passtype = SCE_PASS_COMBINED;
 
        scopes_new(&simage->scopes);
        simage->sample_line_hist.height = 100;
index 6088dccd4e9c27b1bd29d84b421b5cc0377401ec..56a8842a8d2f1390d6f3b7e8d7f0061ee358facd 100644 (file)
@@ -55,7 +55,8 @@ typedef struct ImageUser {
        char ok;
 
        char multiview_eye;                     /* multiview current eye - for internal use of drawing routines */
-       int passtype;
+       short pass;
+       short pad;
 
        short multi_index, view, layer;  /* listbase indices, for menu browsing or retrieve buffer */
        short flag;
index 0d0b440ec0872c837b5e1a74ce62a73750db61f6..561f5c9dd2663a7132e30f52185bd1895a74911e 100644 (file)
@@ -539,6 +539,11 @@ static void rna_def_imageuser(BlenderRNA *brna)
        RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
        RNA_def_property_ui_text(prop, "Layer", "Layer in multilayer image");
 
+       prop = RNA_def_property(srna, "multilayer_pass", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "pass");
+       RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */
+       RNA_def_property_ui_text(prop, "Pass", "Pass in multilayer image");
+
        prop = RNA_def_property(srna, "multilayer_view", PROP_INT, PROP_UNSIGNED);
        RNA_def_property_int_sdna(prop, NULL, "view");
        RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* image_multi_cb */