Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Fri, 23 Mar 2018 11:05:55 +0000 (12:05 +0100)
committerCampbell Barton <ideasman42@gmail.com>
Fri, 23 Mar 2018 11:05:55 +0000 (12:05 +0100)
21 files changed:
1  2 
source/blender/blenkernel/intern/cloth.c
source/blender/blenkernel/intern/collision.c
source/blender/blenkernel/intern/dynamicpaint.c
source/blender/blenkernel/intern/mesh_validate.c
source/blender/blenkernel/intern/paint.c
source/blender/blenkernel/intern/particle_distribute.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/armature/armature_utils.c
source/blender/editors/armature/pose_select.c
source/blender/editors/interface/view2d.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/physics/dynamicpaint_ops.c
source/blender/editors/screen/screen_ops.c
source/blender/editors/sculpt_paint/CMakeLists.txt
source/blender/editors/sculpt_paint/paint_image.c
source/blender/editors/sculpt_paint/paint_image_proj.c
source/blender/editors/sculpt_paint/paint_image_undo.c
source/blender/editors/sculpt_paint/paint_intern.h
source/blender/editors/space_image/image_ops.c
source/blender/editors/space_view3d/view3d_select.c
source/blender/editors/transform/transform_orientations.c

index ac1e20d1e8487be83ae0982c54c8d2f487f7806f,e85af67b105744648f3a05003a709ea6ce841019..2b2dbb8a53b3440e6eaa15b23ad57fd3041f7ad7
@@@ -8406,9 -8104,8 +8406,9 @@@ static const char *dataname(short id_co
                case ID_WO: return "Data from WO";
                case ID_SCR: return "Data from SCR";
                case ID_VF: return "Data from VF";
-               case ID_TXT     : return "Data from TXT";
+               case ID_TXT: return "Data from TXT";
                case ID_SPK: return "Data from SPK";
 +              case ID_LP: return "Data from LP";
                case ID_SO: return "Data from SO";
                case ID_NT: return "Data from NT";
                case ID_BR: return "Data from BR";
index e068b898345760c1a6e5a4c4b26869c9bd3447fa,86db76bfcd643f5391d5ec7a8aeb3679bdf15c71..6360e6281c87661805106eb963ee6a8faeb02995
@@@ -365,9 -357,9 +365,9 @@@ static void dynamicPaint_bakeImageSeque
        frame = surface->start_frame;
        orig_frame = scene->r.cfra;
        scene->r.cfra = (int)frame;
 -      ED_update_for_newframe(job->bmain, scene, 1);
 +      ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
  
-       /* Init surface */
+       /* Init surface */
        if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
                job->success = 0;
                return;
index 969bf8f37b1d9be83277710635aa5dcb6bb4cc5d,c6472b258cab6f584366d4e17a109f4d32956318..b7cbdfecfe89ab3c74f4ab9a32a83d10b674319f
@@@ -52,9 -51,9 +51,8 @@@
  
  #include "BKE_colorband.h"
  #include "BKE_context.h"
 -#include "BKE_depsgraph.h"
  #include "BKE_DerivedMesh.h"
  #include "BKE_brush.h"
- #include "BKE_image.h"
  #include "BKE_main.h"
  #include "BKE_material.h"
  #include "BKE_node.h"
index 21612339eb5a02fca82a3daf729baf4658fda9db,60fe8555ba2913601d686595d47e09886ddf3675..58c03330256c2648e68994318d174fb3ee92ecd8
@@@ -5396,11 -5384,10 +5396,10 @@@ static int texture_paint_camera_project
  
        scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING;
  
-       ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name,
-                                ED_image_undo_restore, ED_image_undo_free, NULL);
+       ED_image_undo_push_begin(op->type->name);
  
        /* allocate and initialize spatial data structures */
 -      project_paint_begin(&ps, false, 0);
 +      project_paint_begin(C, &ps, false, 0);
  
        if (ps.dm == NULL) {
                BKE_brush_size_set(scene, ps.brush, orig_brush_size);
index 0000000000000000000000000000000000000000,b5b64eb3e163ae0e0d46cd87c8ace49e0430c42a..d080c324d6cd770212c4a7a4e748fc94fb74ba4a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,395 +1,396 @@@
 -#include "BKE_depsgraph.h"
+ /*
+  * ***** BEGIN GPL LICENSE BLOCK *****
+  *
+  * This program is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU General Public License
+  * as published by the Free Software Foundation; either version 2
+  * of the License, or (at your option) any later version.
+  *
+  * This program is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+  *
+  * along with this program; if not, write to the Free Software Foundation,
+  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+  *
+  * ***** END GPL LICENSE BLOCK *****
+  */
+ /** \file blender/editors/sculpt_paint/paint_image_undo.c
+  *  \ingroup edsculpt
+  */
+ #include "MEM_guardedalloc.h"
+ #include "BLI_math.h"
+ #include "BLI_blenlib.h"
+ #include "BLI_utildefines.h"
+ #include "BLI_threads.h"
+ #include "DNA_image_types.h"
+ #include "IMB_imbuf.h"
+ #include "IMB_imbuf_types.h"
+ #include "BKE_context.h"
 -              DAG_id_tag_update(&ima->id, 0);
+ #include "BKE_image.h"
+ #include "BKE_main.h"
++#include "DEG_depsgraph.h"
++
+ #include "ED_paint.h"
+ #include "GPU_draw.h"
+ #include "paint_intern.h"
+ typedef struct UndoImageTile {
+       struct UndoImageTile *next, *prev;
+       char idname[MAX_ID_NAME];  /* name instead of pointer*/
+       char ibufname[IMB_FILENAME_SIZE];
+       union {
+               float        *fp;
+               unsigned int *uint;
+               void         *pt;
+       } rect;
+       unsigned short *mask;
+       int x, y;
+       Image *ima;
+       short source, use_float;
+       char gen_type;
+       bool valid;
+ } UndoImageTile;
+ /* this is a static resource for non-globality,
+  * Maybe it should be exposed as part of the
+  * paint operation, but for now just give a public interface */
+ static SpinLock undolock;
+ void image_undo_init_locks(void)
+ {
+       BLI_spin_init(&undolock);
+ }
+ void image_undo_end_locks(void)
+ {
+       BLI_spin_end(&undolock);
+ }
+ /* UNDO */
+ typedef enum {
+       COPY = 0,
+       RESTORE = 1,
+       RESTORE_COPY = 2
+ } CopyMode;
+ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, CopyMode mode)
+ {
+       if (mode == COPY) {
+               /* copy or swap contents of tile->rect and region in ibuf->rect */
+               IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+                           tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+               if (ibuf->rect_float) {
+                       SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+               }
+               else {
+                       SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+               }
+       }
+       else {
+               if (mode == RESTORE_COPY) {
+                       IMB_rectcpy(tmpibuf, ibuf, 0, 0, tile->x * IMAPAINT_TILE_SIZE,
+                                   tile->y * IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+               }
+               /* swap to the tmpbuf for easy copying */
+               if (ibuf->rect_float) {
+                       SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+               }
+               else {
+                       SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+               }
+               IMB_rectcpy(ibuf, tmpibuf, tile->x * IMAPAINT_TILE_SIZE,
+                           tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE);
+               if (mode == RESTORE) {
+                       if (ibuf->rect_float) {
+                               SWAP(float *, tmpibuf->rect_float, tile->rect.fp);
+                       }
+                       else {
+                               SWAP(unsigned int *, tmpibuf->rect, tile->rect.uint);
+                       }
+               }
+       }
+ }
+ void *image_undo_find_tile(Image *ima, ImBuf *ibuf, int x_tile, int y_tile, unsigned short **mask, bool validate)
+ {
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+       UndoImageTile *tile;
+       short use_float = ibuf->rect_float ? 1 : 0;
+       for (tile = lb->first; tile; tile = tile->next) {
+               if (tile->x == x_tile && tile->y == y_tile && ima->gen_type == tile->gen_type && ima->source == tile->source) {
+                       if (tile->use_float == use_float) {
+                               if (STREQ(tile->idname, ima->id.name) && STREQ(tile->ibufname, ibuf->name)) {
+                                       if (mask) {
+                                               /* allocate mask if requested */
+                                               if (!tile->mask) {
+                                                       tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+                                                                                "UndoImageTile.mask");
+                                               }
+                                               *mask = tile->mask;
+                                       }
+                                       if (validate) {
+                                               tile->valid = true;
+                                       }
+                                       return tile->rect.pt;
+                               }
+                       }
+               }
+       }
+       return NULL;
+ }
+ void *image_undo_push_tile(
+         Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile,
+         unsigned short **mask, bool **valid, bool proj, bool find_prev)
+ {
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+       UndoImageTile *tile;
+       int allocsize;
+       short use_float = ibuf->rect_float ? 1 : 0;
+       void *data;
+       /* check if tile is already pushed */
+       /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */
+       if (find_prev) {
+               data = image_undo_find_tile(ima, ibuf, x_tile, y_tile, mask, true);
+               if (data) {
+                       return data;
+               }
+       }
+       if (*tmpibuf == NULL) {
+               *tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect);
+       }
+       tile = MEM_callocN(sizeof(UndoImageTile), "UndoImageTile");
+       BLI_strncpy(tile->idname, ima->id.name, sizeof(tile->idname));
+       tile->x = x_tile;
+       tile->y = y_tile;
+       /* add mask explicitly here */
+       if (mask) {
+               *mask = tile->mask = MEM_callocN(sizeof(unsigned short) * IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE,
+                                        "UndoImageTile.mask");
+       }
+       allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+       allocsize *= (ibuf->rect_float) ? sizeof(float) : sizeof(char);
+       tile->rect.pt = MEM_mapallocN(allocsize, "UndeImageTile.rect");
+       BLI_strncpy(tile->ibufname, ibuf->name, sizeof(tile->ibufname));
+       tile->gen_type = ima->gen_type;
+       tile->source = ima->source;
+       tile->use_float = use_float;
+       tile->valid = true;
+       tile->ima = ima;
+       if (valid) {
+               *valid = &tile->valid;
+       }
+       undo_copy_tile(tile, *tmpibuf, ibuf, COPY);
+       if (proj) {
+               BLI_spin_lock(&undolock);
+       }
+       undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, allocsize);
+       BLI_addtail(lb, tile);
+       if (proj) {
+               BLI_spin_unlock(&undolock);
+       }
+       return tile->rect.pt;
+ }
+ void image_undo_remove_masks(void)
+ {
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+       UndoImageTile *tile;
+       for (tile = lb->first; tile; tile = tile->next) {
+               if (tile->mask) {
+                       MEM_freeN(tile->mask);
+                       tile->mask = NULL;
+               }
+       }
+ }
+ static void image_undo_restore_runtime(ListBase *lb)
+ {
+       ImBuf *ibuf, *tmpibuf;
+       UndoImageTile *tile;
+       tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
+                                IB_rectfloat | IB_rect);
+       for (tile = lb->first; tile; tile = tile->next) {
+               Image *ima = tile->ima;
+               ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+               undo_copy_tile(tile, tmpibuf, ibuf, RESTORE);
+               GPU_free_image(ima); /* force OpenGL reload (maybe partial update will operate better?) */
+               if (ibuf->rect_float) {
+                       ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+               }
+               if (ibuf->mipmap[0]) {
+                       ibuf->userflags |= IB_MIPMAP_INVALID;  /* force mipmap recreatiom */
+               }
+               ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+       }
+       IMB_freeImBuf(tmpibuf);
+ }
+ static void image_undo_restore_list(bContext *C, ListBase *lb)
+ {
+       Main *bmain = CTX_data_main(C);
+       Image *ima = NULL;
+       ImBuf *ibuf, *tmpibuf;
+       UndoImageTile *tile;
+       tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32,
+                                IB_rectfloat | IB_rect);
+       for (tile = lb->first; tile; tile = tile->next) {
+               short use_float;
+               /* find image based on name, pointer becomes invalid with global undo */
+               if (ima && STREQ(tile->idname, ima->id.name)) {
+                       /* ima is valid */
+               }
+               else {
+                       ima = BLI_findstring(&bmain->image, tile->idname, offsetof(ID, name));
+               }
+               ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+               if (ima && ibuf && !STREQ(tile->ibufname, ibuf->name)) {
+                       /* current ImBuf filename was changed, probably current frame
+                        * was changed when painting on image sequence, rather than storing
+                        * full image user (which isn't so obvious, btw) try to find ImBuf with
+                        * matched file name in list of already loaded images */
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       ibuf = BKE_image_get_ibuf_with_name(ima, tile->ibufname);
+               }
+               if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       continue;
+               }
+               if (ima->gen_type != tile->gen_type || ima->source != tile->source) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       continue;
+               }
+               use_float = ibuf->rect_float ? 1 : 0;
+               if (use_float != tile->use_float) {
+                       BKE_image_release_ibuf(ima, ibuf, NULL);
+                       continue;
+               }
+               undo_copy_tile(tile, tmpibuf, ibuf, RESTORE_COPY);
+               GPU_free_image(ima); /* force OpenGL reload */
+               if (ibuf->rect_float) {
+                       ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */
+               }
+               if (ibuf->mipmap[0]) {
+                       ibuf->userflags |= IB_MIPMAP_INVALID;  /* force mipmap recreatiom */
+               }
+               ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
++              DEG_id_tag_update(&ima->id, 0);
+               BKE_image_release_ibuf(ima, ibuf, NULL);
+       }
+       IMB_freeImBuf(tmpibuf);
+ }
+ static void image_undo_free_list(ListBase *lb)
+ {
+       UndoImageTile *tile;
+       for (tile = lb->first; tile; tile = tile->next) {
+               MEM_freeN(tile->rect.pt);
+       }
+ }
+ void ED_image_undo_push_begin(const char *name)
+ {
+       ED_undo_paint_push_begin(UNDO_PAINT_IMAGE, name, image_undo_restore_list, image_undo_free_list, NULL);
+ }
+ void ED_image_undo_push_end(void)
+ {
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+       UndoImageTile *tile;
+       int deallocsize = 0;
+       int allocsize = IMAPAINT_TILE_SIZE * IMAPAINT_TILE_SIZE * 4;
+       /* first dispose of invalid tiles (may happen due to drag dot for instance) */
+       for (tile = lb->first; tile;) {
+               if (!tile->valid) {
+                       UndoImageTile *tmp_tile = tile->next;
+                       deallocsize += allocsize * ((tile->use_float) ? sizeof(float) : sizeof(char));
+                       MEM_freeN(tile->rect.pt);
+                       BLI_freelinkN(lb, tile);
+                       tile = tmp_tile;
+               }
+               else {
+                       tile = tile->next;
+               }
+       }
+       /* don't forget to remove the size of deallocated tiles */
+       undo_paint_push_count_alloc(UNDO_PAINT_IMAGE, -deallocsize);
+       ED_undo_paint_push_end(UNDO_PAINT_IMAGE);
+ }
+ static void image_undo_invalidate(void)
+ {
+       UndoImageTile *tile;
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+       for (tile = lb->first; tile; tile = tile->next) {
+               tile->valid = false;
+       }
+ }
+ /* restore painting image to previous state. Used for anchored and drag-dot style brushes*/
+ void ED_image_undo_restore(void)
+ {
+       ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE);
+       image_undo_restore_runtime(lb);
+       image_undo_invalidate();
+ }
index 6364df2af2b79b99ff797aed979d6c2dc2419da4,a52d4a1a69fb8e6ed9255f3d37ffc9f18dede442..0d37d0bd6809204a04425caa2bd641b85c558e46
@@@ -1988,34 -1982,12 +1988,34 @@@ static int do_armature_box_select
        return hits > 0 ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
  }
  
 +/**
 + * Compare result of 'GPU_select': 'uint[4]',
 + * needed for when we need to align with object draw-order.
 + */
 +static int opengl_select_buffer_cmp(const void *sel_a_p, const void *sel_b_p)
 +{
 +      /* 4th element is select id */
 +      const uint sel_a = ((uint *)sel_a_p)[3];
 +      const uint sel_b = ((uint *)sel_b_p)[3];
 +
 +      if (sel_a < sel_b) {
 +              return -1;
 +      }
 +      else if (sel_a > sel_b) {
 +              return 1;
 +      }
 +      else {
 +              return 0;
 +      }
 +}
 +
  static int do_object_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, bool select, bool extend)
  {
 +      EvaluationContext eval_ctx;
        Bone *bone;
        Object *ob = vc->obact;
-       unsigned int *vbuffer = NULL; /* selection buffer       */
-       unsigned int *col;          /* color in buffer  */
+       unsigned int *vbuffer = NULL; /* selection buffer */
+       unsigned int *col;            /* color in buffer */
        int bone_only;
        int bone_selected = 0;
        int totobj = MAXPICKBUF; /* XXX solve later */