Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/sculpt_paint/paint_image_proj.c')
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c118
1 files changed, 94 insertions, 24 deletions
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index c57490041bc..6a67c469955 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -197,6 +197,7 @@ BLI_INLINE unsigned char f_to_char(const float val)
*/
typedef struct ProjPaintImage {
Image *ima;
+ ImageUser iuser;
ImBuf *ibuf;
ImagePaintPartialRedraw *partRedrawRect;
/** Only used to build undo tiles during painting. */
@@ -530,6 +531,18 @@ BLI_INLINE const MPoly *ps_tri_index_to_mpoly(const ProjPaintState *ps, int tri_
/* Finish projection painting structs */
+static int project_paint_face_paint_tile(Image *ima, const float *uv)
+{
+ if (ima == NULL || ima->source != IMA_SRC_TILED) {
+ return 0;
+ }
+
+ /* Currently, faces are assumed to belong to one tile, so checking the first loop is enough. */
+ int tx = (int)uv[0];
+ int ty = (int)uv[1];
+ return 1001 + 10 * ty + tx;
+}
+
static TexPaintSlot *project_paint_face_paint_slot(const ProjPaintState *ps, int tri_index)
{
const MPoly *mp = ps_tri_index_to_mpoly(ps, tri_index);
@@ -729,9 +742,17 @@ static bool project_paint_PickColor(const ProjPaintState *ps,
ima = project_paint_face_paint_image(ps, tri_index);
/** we must have got the imbuf before getting here. */
- ibuf = BKE_image_get_first_ibuf(ima);
- if (!ibuf) {
- return 0;
+ int tile_number = project_paint_face_paint_tile(ima, lt_tri_uv[0]);
+ ImageUser iuser;
+ BKE_imageuser_default(&iuser);
+ iuser.tile = tile_number;
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ if (ibuf == NULL) {
+ iuser.tile = 0;
+ ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
+ if (ibuf == NULL) {
+ return 0;
+ }
}
if (interp) {
@@ -1154,6 +1175,8 @@ static bool check_seam(const ProjPaintState *ps,
const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
Image *tpage = project_paint_face_paint_image(ps, tri_index);
Image *orig_tpage = project_paint_face_paint_image(ps, orig_face);
+ int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
+ int orig_tile = project_paint_face_paint_tile(orig_tpage, orig_lt_tri_uv[0]);
BLI_assert(i1_fidx != -1);
@@ -1171,7 +1194,8 @@ static bool check_seam(const ProjPaintState *ps,
}
/* first test if they have the same image */
- if ((orig_tpage == tpage) && cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
+ if ((orig_tpage == tpage) && (orig_tile == tile) &&
+ cmp_uv(orig_lt_tri_uv[orig_i1_fidx], lt_tri_uv[i1_fidx]) &&
cmp_uv(orig_lt_tri_uv[orig_i2_fidx], lt_tri_uv[i2_fidx])) {
/* if faces don't have the same winding in uv space,
* they are on the same side so edge is boundary */
@@ -1817,6 +1841,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
pjIma->ima,
pjIma->ibuf,
tinf->tmpibuf,
+ pjIma->iuser.tile,
tx,
ty,
&pjIma->maskRect[tile_index],
@@ -1829,6 +1854,7 @@ static int project_paint_undo_subtiles(const TileInfo *tinf, int tx, int ty)
pjIma->ima,
pjIma->ibuf,
tinf->tmpibuf,
+ pjIma->iuser.tile,
tx,
ty,
NULL,
@@ -3486,6 +3512,7 @@ static void project_bucket_init(const ProjPaintState *ps,
ImBuf *ibuf = NULL;
Image *tpage_last = NULL, *tpage;
ImBuf *tmpibuf = NULL;
+ int tile_last = 0;
if (ps->image_tot == 1) {
/* Simple loop, no context switching */
@@ -3509,17 +3536,34 @@ static void project_bucket_init(const ProjPaintState *ps,
for (node = ps->bucketFaces[bucket_index]; node; node = node->next) {
tri_index = POINTER_AS_INT(node->link);
+ const MLoopTri *lt = &ps->mlooptri_eval[tri_index];
+ const float *lt_tri_uv[3] = {PS_LOOPTRI_AS_UV_3(ps->poly_to_loop_uv, lt)};
+
/* Image context switching */
tpage = project_paint_face_paint_image(ps, tri_index);
- if (tpage_last != tpage) {
+ int tile = project_paint_face_paint_tile(tpage, lt_tri_uv[0]);
+ if (tpage_last != tpage || tile_last != tile) {
tpage_last = tpage;
+ tile_last = tile;
+ ibuf = NULL;
for (image_index = 0; image_index < ps->image_tot; image_index++) {
- if (ps->projImages[image_index].ima == tpage_last) {
- ibuf = ps->projImages[image_index].ibuf;
+ ProjPaintImage *projIma = &ps->projImages[image_index];
+ if ((projIma->ima == tpage) && (projIma->iuser.tile == tile)) {
+ ibuf = projIma->ibuf;
break;
}
}
+ if (ibuf == NULL) {
+ /* Failed to find the specific tile, fall back to the primary tile. */
+ for (image_index = 0; image_index < ps->image_tot; image_index++) {
+ ProjPaintImage *projIma = &ps->projImages[image_index];
+ if ((projIma->ima == tpage) && (projIma->iuser.tile == 0)) {
+ ibuf = projIma->ibuf;
+ break;
+ }
+ }
+ }
}
/* context switching done */
@@ -4232,22 +4276,36 @@ static bool project_paint_winclip(const ProjPaintState *ps, const ProjPaintFaceC
}
#endif // PROJ_DEBUG_WINCLIP
+typedef struct PrepareImageEntry {
+ struct PrepareImageEntry *next, *prev;
+ Image *ima;
+ int tile;
+} PrepareImageEntry;
+
static void project_paint_build_proj_ima(ProjPaintState *ps,
MemArena *arena,
- LinkNode *image_LinkList)
+ ListBase *used_images)
{
ProjPaintImage *projIma;
- LinkNode *node;
+ PrepareImageEntry *entry;
int i;
/* build an array of images we use */
projIma = ps->projImages = BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot);
- for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) {
+ for (entry = used_images->first, i = 0; entry; entry = entry->next, i++, projIma++) {
+ memset(&projIma->iuser, 0, sizeof(ImageUser));
+ BKE_imageuser_default(&projIma->iuser);
+ projIma->iuser.tile = entry->tile;
int size;
- projIma->ima = node->link;
+ projIma->ima = entry->ima;
projIma->touch = 0;
- projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL);
+ projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, &projIma->iuser, NULL);
+ if (projIma->ibuf == NULL) {
+ projIma->iuser.tile = 0;
+ projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, &projIma->iuser, NULL);
+ BLI_assert(projIma->ibuf != NULL);
+ }
size = sizeof(void **) * ED_IMAGE_UNDO_TILE_NUMBER(projIma->ibuf->x) *
ED_IMAGE_UNDO_TILE_NUMBER(projIma->ibuf->y);
projIma->partRedrawRect = BLI_memarena_alloc(
@@ -4270,15 +4328,18 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
const bool is_multi_view)
{
/* Image Vars - keep track of images we have used */
- LinkNodePair image_LinkList = {NULL, NULL};
+ ListBase used_images = {NULL};
Image *tpage_last = NULL, *tpage;
TexPaintSlot *slot_last = NULL;
TexPaintSlot *slot = NULL;
+ int tile_last = -1, tile;
const MLoopTri *lt;
int image_index = -1, tri_index;
int prev_poly = -1;
+ BLI_assert(ps->image_tot == 0);
+
for (tri_index = 0, lt = ps->mlooptri_eval; tri_index < ps->totlooptri_eval; tri_index++, lt++) {
bool is_face_sel;
bool skip_tri = false;
@@ -4321,6 +4382,8 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
ps->poly_to_loop_uv[lt->poly] = mloopuv_base;
+ tile = project_paint_face_paint_tile(tpage, mloopuv_base[lt->tri[0]].uv);
+
#ifndef PROJ_DEBUG_NOSEAMBLEED
project_paint_bleed_add_face_user(ps, arena, lt, tri_index);
#endif
@@ -4382,18 +4445,24 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
}
}
- if (tpage_last != tpage) {
-
- image_index = BLI_linklist_index(image_LinkList.list, tpage);
+ if (tpage_last != tpage || tile_last != tile) {
+ image_index = 0;
+ for (PrepareImageEntry *e = used_images.first; e; e = e->next, image_index++) {
+ if (e->ima == tpage && e->tile == tile) {
+ break;
+ }
+ }
- if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) {
- /* MemArena doesn't have an append func */
- BLI_linklist_append(&image_LinkList, tpage);
- image_index = ps->image_tot;
+ if (image_index == ps->image_tot) {
+ PrepareImageEntry *e = MEM_callocN(sizeof(PrepareImageEntry), "PrepareImageEntry");
+ e->ima = tpage;
+ e->tile = tile;
+ BLI_addtail(&used_images, e);
ps->image_tot++;
}
tpage_last = tpage;
+ tile_last = tile;
}
if (image_index != -1) {
@@ -4406,11 +4475,11 @@ static void project_paint_prepare_all_faces(ProjPaintState *ps,
/* build an array of images we use*/
if (ps->is_shared_user == false) {
- project_paint_build_proj_ima(ps, arena, image_LinkList.list);
+ project_paint_build_proj_ima(ps, arena, &used_images);
}
/* we have built the array, discard the linked list */
- BLI_linklist_free(image_LinkList.list, NULL);
+ BLI_freelistN(&used_images);
}
/* run once per stroke before projection painting */
@@ -4675,7 +4744,7 @@ static bool project_image_refresh_tagged(ProjPaintState *ps)
pr = &(projIma->partRedrawRect[i]);
if (pr->x2 != -1) { /* TODO - use 'enabled' ? */
set_imapaintpartial(pr);
- imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true);
+ imapaint_image_update(NULL, projIma->ima, projIma->ibuf, &projIma->iuser, true);
redraw = 1;
}
@@ -6441,7 +6510,8 @@ static Image *proj_paint_image_create(wmOperator *op, Main *bmain, bool is_data)
gen_type,
color,
false,
- is_data);
+ is_data,
+ false); /* TODO(lukas): Add option */
return ima;
}