diff options
author | Campbell Barton <ideasman42@gmail.com> | 2008-12-07 22:24:41 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2008-12-07 22:24:41 +0300 |
commit | 69298b7b768f825cd7e3d029569422779024f235 (patch) | |
tree | 56f53077b86f12d0facbb9dd1b873ed0899cdff2 /source/blender | |
parent | 00cc0f6852dfb2a5ed648f466ded4a95b0392c07 (diff) |
* layer mask (similar to the gimp), uses a UV layer's image as mask for painting.
* cloning between layers was broken
* Added buttons for selecting the souce clone/mask layer in the UV layer list.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/BKE_customdata.h | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/customdata.c | 84 | ||||
-rw-r--r-- | source/blender/include/butspace.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_customdata_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_scene_types.h | 9 | ||||
-rw-r--r-- | source/blender/src/buttons_editing.c | 92 | ||||
-rw-r--r-- | source/blender/src/imagepaint.c | 171 |
7 files changed, 270 insertions, 98 deletions
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index c84b690bc49..10791968f79 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -198,8 +198,12 @@ int CustomData_get_layer_index(const struct CustomData *data, int type); int CustomData_get_named_layer_index(const struct CustomData *data, int type, char *name); int CustomData_get_active_layer_index(const struct CustomData *data, int type); int CustomData_get_render_layer_index(const struct CustomData *data, int type); +int CustomData_get_clone_layer_index(const struct CustomData *data, int type); +int CustomData_get_mask_layer_index(const struct CustomData *data, int type); int CustomData_get_active_layer(const struct CustomData *data, int type); int CustomData_get_render_layer(const struct CustomData *data, int type); +int CustomData_get_clone_layer(const struct CustomData *data, int type); +int CustomData_get_mask_layer(const struct CustomData *data, int type); /* copies the data from source to the data element at index in the first * layer of type @@ -227,10 +231,14 @@ void *CustomData_set_layer_n(const struct CustomData *data, int type, int n, voi /* sets the nth layer of type as active */ void CustomData_set_layer_active(struct CustomData *data, int type, int n); void CustomData_set_layer_render(struct CustomData *data, int type, int n); +void CustomData_set_layer_clone(struct CustomData *data, int type, int n); +void CustomData_set_layer_mask(struct CustomData *data, int type, int n); /* same as above but works with an index from CustomData_get_layer_index */ void CustomData_set_layer_active_index(struct CustomData *data, int type, int n); void CustomData_set_layer_render_index(struct CustomData *data, int type, int n); +void CustomData_set_layer_clone_index(struct CustomData *data, int type, int n); +void CustomData_set_layer_mask_index(struct CustomData *data, int type, int n); /* adds flag to the layer flags */ void CustomData_set_layer_flag(struct CustomData *data, int type, int flag); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index e93266c85f3..f7fca8c1412 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -606,7 +606,7 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, { const LayerTypeInfo *typeInfo; CustomDataLayer *layer, *newlayer; - int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0; + int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0; for(i = 0; i < source->totlayer; ++i) { layer = &source->layers[i]; @@ -618,6 +618,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, number = 0; lastactive = layer->active; lastrender = layer->active_rnd; + lastclone = layer->active_clone; + lastmask = layer->active_mask; lasttype = type; } else @@ -637,6 +639,8 @@ void CustomData_merge(const struct CustomData *source, struct CustomData *dest, if(newlayer) { newlayer->active = lastactive; newlayer->active_rnd = lastrender; + newlayer->active_clone = lastclone; + newlayer->active_mask = lastmask; } } } @@ -736,6 +740,28 @@ int CustomData_get_render_layer_index(const CustomData *data, int type) return -1; } +int CustomData_get_clone_layer_index(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + data->layers[i].active_clone; + + return -1; +} + +int CustomData_get_mask_layer_index(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return i + data->layers[i].active_mask; + + return -1; +} + int CustomData_get_active_layer(const CustomData *data, int type) { int i; @@ -758,6 +784,27 @@ int CustomData_get_render_layer(const CustomData *data, int type) return -1; } +int CustomData_get_clone_layer(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return data->layers[i].active_clone; + + return -1; +} + +int CustomData_get_mask_layer(const CustomData *data, int type) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + return data->layers[i].active_mask; + + return -1; +} void CustomData_set_layer_active(CustomData *data, int type, int n) { @@ -777,6 +824,24 @@ void CustomData_set_layer_render(CustomData *data, int type, int n) data->layers[i].active_rnd = n; } +void CustomData_set_layer_clone(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_clone = n; +} + +void CustomData_set_layer_mask(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_mask = n; +} + /* for using with an index from CustomData_get_active_layer_index and CustomData_get_render_layer_index */ void CustomData_set_layer_active_index(CustomData *data, int type, int n) { @@ -796,6 +861,23 @@ void CustomData_set_layer_render_index(CustomData *data, int type, int n) data->layers[i].active_rnd = n-i; } +void CustomData_set_layer_clone_index(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_clone = n-i; +} + +void CustomData_set_layer_mask_index(CustomData *data, int type, int n) +{ + int i; + + for(i=0; i < data->totlayer; ++i) + if(data->layers[i].type == type) + data->layers[i].active_mask = n-i; +} void CustomData_set_layer_flag(struct CustomData *data, int type, int flag) { diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h index fd3f6e926b9..5612f56fee8 100644 --- a/source/blender/include/butspace.h +++ b/source/blender/include/butspace.h @@ -446,6 +446,8 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la #define B_GEN_SKELETON 2085 #define B_RETARGET_SKELETON 2086 +#define B_SETTFACE_CLONE 2087 +#define B_SETTFACE_MASK 2088 /* *********************** */ #define B_VGROUPBUTS 2100 diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 6c098e220bb..e6b18641d2a 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -37,6 +37,8 @@ typedef struct CustomDataLayer { int flag; /* general purpose flag */ int active; /* number of the active layer of this type */ int active_rnd; /* number of the layer to render*/ + int active_clone; /* number of the layer to render*/ + int active_mask; /* number of the layer to render*/ char pad[4]; char name[32]; /* layer name */ void *data; /* layer data */ diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 77cfaf10ac1..8b264602fee 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -347,8 +347,7 @@ typedef struct ImagePaintSettings { short flag, tool; /* for projection painting only - todo - use flags */ - char seam_bleed,normal_angle; - short clone_layer; + short seam_bleed,normal_angle; } ImagePaintSettings; typedef struct ParticleBrushData { @@ -806,8 +805,10 @@ typedef struct Scene { #define IMAGEPAINT_PROJECT_DISABLE 8 /* Non projection 3D painting */ #define IMAGEPAINT_PROJECT_XRAY 16 #define IMAGEPAINT_PROJECT_BACKFACE 32 -#define IMAGEPAINT_PROJECT_CLONE_LAYER 64 -#define IMAGEPAINT_PROJECT_FLAT 128 +#define IMAGEPAINT_PROJECT_FLAT 64 +#define IMAGEPAINT_PROJECT_LAYER_CLONE 128 +#define IMAGEPAINT_PROJECT_LAYER_MASK 256 +#define IMAGEPAINT_PROJECT_LAYER_MASK_INV 512 /* toolsettings->uvcalc_flag */ #define UVCALC_FILLHOLES 1 diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 46359aa2707..1157dc7b26a 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -184,7 +184,7 @@ static float editbutweight= 1.0; float editbutvweight= 1; -static int actmcol= 0, acttface= 0, acttface_rnd = 0, actmcol_rnd = 0; +static int actmcol= 0, acttface= 0, acttface_rnd = 0, acttface_clone = 0, acttface_mask = 0, actmcol_rnd = 0; extern ListBase editNurb; @@ -802,9 +802,9 @@ static void delete_customdata_layer(void *data1, void *data2) static int customdata_buttons( uiBlock *block, Mesh *me, CustomData *data, - int type, int *activep, int *renderp, - int setevt, int setevt_rnd, int newevt, - char *label, char *shortlabel, char *browsetip, char *browsetip_rnd, + int type, int *activep, int *renderp, int *clonep, int *maskp, + int setevt, int setevt_rnd, int setevt_clone, int setevt_mask, int newevt, + char *label, char *shortlabel, char *browsetip, char *browsetip_rnd, char *browsetip_clone, char *browsetip_mask, char *newtip, char *deltip, int x, int y) { CustomDataLayer *layer; @@ -828,12 +828,27 @@ static int customdata_buttons( layer= &data->layers[i]; if(layer->type == type) { + int xi = 0; *activep= layer->active + 1; *renderp= layer->active_rnd + 1; + if (clonep) *clonep= layer->active_clone + 1; + if (maskp) *maskp= layer->active_mask + 1; + uiDefIconButI(block, ROW, setevt, ICON_VIEW3D, x,y,25,19, activep, 1.0, count, 0, 0, browsetip); uiDefIconButI(block, ROW, setevt_rnd, ICON_SCENE, x+25,y,25,19, renderp, 1.0, count, 0, 0, browsetip_rnd); - but=uiDefBut(block, TEX, setevt, "", x+50,y,145,19, layer->name, 0.0, 31.0, 0, 0, label); + + if (clonep) { + uiDefIconButI(block, ROW, setevt_clone, ICON_TEXTURE, x+50,y,25,19, clonep, 1.0, count, 0, 0, browsetip_clone); + xi += 25; + } + + if (maskp) { + uiDefIconButI(block, ROW, setevt_mask, ICON_PAINT, x+50+xi,y,25,19, maskp, 1.0, count, 0, 0, browsetip_mask); + xi += 25; + } + + but=uiDefBut(block, TEX, setevt, "", x+50+xi,y,145-xi,19, layer->name, 0.0, 31.0, 0, 0, label); uiButSetFunc(but, verify_customdata_name_func, data, layer); but= uiDefIconBut(block, BUT, B_NOP, VICON_X, x+195,y,25,19, NULL, 0.0, 0.0, 0.0, 0.0, deltip); uiButSetFunc(but, delete_customdata_layer, me, layer); @@ -902,14 +917,14 @@ static void editing_panel_mesh_type(Object *ob, Mesh *me) uiBlockEndAlign(block); fdata= (G.obedit)? &G.editMesh->fdata: &me->fdata; - yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd, - B_SETTFACE, B_SETTFACE_RND, B_NEWTFACE, "UV Texture", "UV Texture:", - "Set active UV texture", "Set rendering UV texture", "Creates a new UV texture layer", + yco= customdata_buttons(block, me, fdata, CD_MTFACE, &acttface, &acttface_rnd, (G.f & G_TEXTUREPAINT ? &acttface_clone : NULL), (G.f & G_TEXTUREPAINT ? &acttface_mask : NULL), + B_SETTFACE, B_SETTFACE_RND, B_SETTFACE_CLONE, B_SETTFACE_MASK, B_NEWTFACE, "UV Texture", "UV Texture:", + "Set active UV texture", "Set rendering UV texture", "Set the layer used for texturepaint cloning", "Set the layer used for texturepaint masking", "Creates a new UV texture layer", "Removes the current UV texture layer", 190, 130); - yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd, - B_SETMCOL, B_SETMCOL_RND, B_NEWMCOL, "Vertex Color", "Vertex Color:", - "Sets active vertex color layer", "Sets rendering vertex color layer", "Creates a new vertex color layer", + yco= customdata_buttons(block, me, fdata, CD_MCOL, &actmcol, &actmcol_rnd, NULL, NULL, + B_SETMCOL, B_SETMCOL_RND, B_NOP, B_NOP, B_NEWMCOL, "Vertex Color", "Vertex Color:", + "Sets active vertex color layer", "Sets rendering vertex color layer", "", "", "Creates a new vertex color layer", "Removes the current vertex color layer", 190, yco-5); if(yco < 0) @@ -4964,7 +4979,22 @@ void do_meshbuts(unsigned short event) allqueue(REDRAWBUTSEDIT, 0); } break; - + case B_SETTFACE_CLONE: + if (G.obedit || me) { + CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata; + CustomData_set_layer_clone(fdata, CD_MTFACE, acttface_clone-1); + BIF_undo_push("Set Clone UV Texture"); + allqueue(REDRAWBUTSEDIT, 0); + } + break; + case B_SETTFACE_MASK: + if (G.obedit || me) { + CustomData *fdata= (G.obedit)? &em->fdata: &me->fdata; + CustomData_set_layer_mask(fdata, CD_MTFACE, acttface_mask-1); + BIF_undo_push("Set Mask UV Texture"); + allqueue(REDRAWBUTSEDIT, 0); + } + break; case B_FLIPNORM: if(G.obedit) { flip_editnormals(); @@ -6387,6 +6417,12 @@ static void editing_panel_mesh_paint(void) uiDefButC(block, NUM, B_NOP, "Bleed: ", xco+10,yco-85,butw,19, &settings->imapaint.seam_bleed, 0.0, 8.0, 0, 0, "Extend paint beyond the faces UVs to reduce seams (in pixels, slower)"); uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK, B_NOP, "Layer Mask", xco+10,yco-110,butw-30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Set the mask layer from the UV layer buttons"); + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_MASK_INV, B_NOP, "Inv", xco+10 + butw-30,yco-110,30,19, &settings->imapaint.flag, 0, 0, 0, 0, "Invert the mask"); + uiBlockEndAlign(block); + } uiBlockBeginAlign(block); @@ -6404,33 +6440,11 @@ static void editing_panel_mesh_paint(void) yco -= 110; if (settings->imapaint.tool == PAINT_TOOL_CLONE) { - Object *ob = OBACT; - if (ob) { - Mesh *me = ob->data; - int layercount = CustomData_number_of_layers(&me->fdata, CD_MTFACE); - if (layercount>1 && layercount < 12) { /* could allow any number but limit of 11 means no malloc needed */ - - butw = 80; - uiBlockBeginAlign(block); - uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_CLONE_LAYER, B_REDR, "Clone Layer", 0,yco,butw,20, &settings->imapaint.flag, 0, 0, 0, 0, "Use another UV layer as clone source, otherwise use 3D the cursor as the source"); - - if (settings->imapaint.flag & IMAGEPAINT_PROJECT_CLONE_LAYER) { - char str_menu[384], *str_pt; /*384 allows for 11 layers */ - - if (settings->imapaint.clone_layer >= layercount) { - settings->imapaint.clone_layer = 0; - } - - - - /*str_pt = (char *)MEM_mallocN(layercount*40 , "uvmenu"); str[0]='\0';*/ - str_pt = str_menu; - str_pt[0]='\0'; - mesh_layers_menu_concat(&me->fdata, CD_MTFACE, str_pt); - uiDefButI(block, MENU, B_NOP, str_menu ,butw,yco,(180-butw) + 20,20, &settings->imapaint.clone_layer, 0, 0, 0, 0, "Active UV Layer for editing"); - } - uiBlockEndAlign(block); - } + if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) { + butw = 130; + uiBlockBeginAlign(block); + uiDefButBitS(block, TOG|BIT, IMAGEPAINT_PROJECT_LAYER_CLONE, B_REDR, "Clone from Layer", 0,yco,butw,20, &settings->imapaint.flag, 0, 0, 0, 0, "Use another UV layer as clone source, otherwise use 3D the cursor as the source"); + uiBlockEndAlign(block); } } else { uiBlockSetCol(block, TH_BUT_SETTING2); diff --git a/source/blender/src/imagepaint.c b/source/blender/src/imagepaint.c index 9cb665bd8a9..d3efeba772c 100644 --- a/source/blender/src/imagepaint.c +++ b/source/blender/src/imagepaint.c @@ -218,6 +218,7 @@ typedef struct ProjPaintState { MFace *dm_mface; MTFace *dm_mtface; MTFace *dm_mtface_clone; /* other UV layer, use for cloning between layers */ + MTFace *dm_mtface_mask; /* projection painting only */ MemArena *arena_mt[BLENDER_MAX_THREADS];/* for multithreading, the first item is sometimes used for non threaded cases too */ @@ -245,11 +246,15 @@ typedef struct ProjPaintState { float screen_height; /* options for projection painting */ + int do_layer_clone; + int do_layer_mask; + int do_layer_mask_inv; + short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/ short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */ short do_mask_normal; /* mask out pixels based on their normals */ float normal_angle; /* what angle to mask at*/ - + short is_ortho; short is_airbrush; /* only to avoid using (ps.brush->flag & BRUSH_AIRBRUSH) */ short is_texbrush; /* only to avoid running */ @@ -258,7 +263,6 @@ typedef struct ProjPaintState { #endif /* clone vars */ float cloneOffset[2]; - int clone_layer; /* -1 when not in use */ float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ float viewMat[4][4]; @@ -1292,6 +1296,36 @@ static void screen_px_from_persp( VecWeightf(pixelScreenCo, v1co, v2co, v3co, w); } +static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4]) +{ + float *uvCo1, *uvCo2, *uvCo3; + float uv_other[2], x, y; + + uvCo1 = (float *)tf_other->uv[0]; + if (side==1) { + uvCo2 = (float *)tf_other->uv[2]; + uvCo3 = (float *)tf_other->uv[3]; + } + else { + uvCo2 = (float *)tf_other->uv[1]; + uvCo3 = (float *)tf_other->uv[2]; + } + + Vec2Weightf(uv_other, uvCo1, uvCo2, uvCo3, w); + + /* use */ + uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); + + + if (ibuf_other->rect_float) { /* from float to float */ + bilinear_interpolation_color(ibuf_other, NULL, rgba_f, x, y); + } + else { /* from char to float */ + bilinear_interpolation_color(ibuf_other, rgba_ub, NULL, x, y); + } + +} + /* run this outside project_paint_uvpixel_init since pixels with mask 0 dont need init */ float project_paint_uvpixel_mask( const ProjPaintState *ps, @@ -1301,6 +1335,40 @@ float project_paint_uvpixel_mask( { float mask, mask_angle; + /* Image Mask */ + if (ps->do_layer_mask) { + /* another UV layers image is masking this one's */ + ImBuf *ibuf_other; + const MTFace *tf_other = ps->dm_mtface_mask + face_index; + + if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) { + /* BKE_image_get_ibuf - TODO - this may be slow */ + unsigned char rgba_ub[4]; + float rgba_f[4]; + + project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f); + + if (ibuf_other->rect_float) { /* from float to float */ + mask = ((rgba_f[0]+rgba_f[1]+rgba_f[2])/3.0f) * rgba_f[3]; + } + else { /* from char to float */ + mask = ((rgba_ub[0]+rgba_ub[1]+rgba_ub[2])/(256*3.0f)) * (rgba_ub[3]/256.0f); + } + + if (!ps->do_layer_mask_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ + mask = (1.0f - mask); + + if (mask == 0.0f) { + return 0.0f; + } + } + else { + return 0.0f; + } + } else { + mask = 1.0f; + } + /* calculate mask */ if (ps->do_mask_normal) { MFace *mf = ps->dm_mface + face_index; @@ -1346,12 +1414,13 @@ float project_paint_uvpixel_mask( angle = NormalizedVecAngle2(viewDirPersp, no); } - /*if (angle >= (M_PI_2 / 90) * ps->normal_angle) { + if (angle >= (M_PI_2 / 90) * ps->normal_angle) { return 0.0f; } - else {*/ + else { + float mask_no; #if 0 - mask = 1.0f - (angle / PI_80_DEG); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */ + mask *= 1.0f - (angle / PI_80_DEG); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */ #endif /* trickier method that clips the normal so its more useful */ @@ -1361,15 +1430,14 @@ float project_paint_uvpixel_mask( /*printf("normal_angle : %f \n" ,ps->normal_angle); printf("mask_angle : %f \n" ,mask_angle);*/ - mask = (angle / mask_angle); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */ - mask = (1.0f - (mask * mask * mask)) * 1.4f; - if (mask > 1.0f) { - mask = 1.0f; + mask_no = (angle / mask_angle); /* map angle to 1.0-facing us, 0.0 right angles to the view direction */ + mask_no = (1.0f - (mask_no * mask_no * mask_no)) * 1.4f; + if (mask_no > 1.0f) { + mask_no = 1.0f; } - /*}*/ + + mask *= mask_no; } - else { - mask = 1.0f; } if (ps->is_airbrush==0) { @@ -1438,7 +1506,6 @@ static ProjPixel *project_paint_uvpixel_init( /* which bounding box cell are we in?, needed for undo */ projPixel->bb_cell_index = ((int)(((float)x_px/(float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + ((int)(((float)y_px/(float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV ; - /* done with view3d_project_float inline */ if (ps->tool==PAINT_TOOL_CLONE) { if (ps->dm_mtface_clone) { @@ -1448,48 +1515,24 @@ static ProjPixel *project_paint_uvpixel_init( if (tf_other->tpage && (ibuf_other = BKE_image_get_ibuf((Image *)tf_other->tpage, NULL))) { /* BKE_image_get_ibuf - TODO - this may be slow */ - float *uvCo1, *uvCo2, *uvCo3; - float uv_other[2], x, y; - - uvCo1 = (float *)tf_other->uv[0]; - if (side==1) { - uvCo2 = (float *)tf_other->uv[2]; - uvCo3 = (float *)tf_other->uv[3]; - } - else { - uvCo2 = (float *)tf_other->uv[1]; - uvCo3 = (float *)tf_other->uv[2]; - } - - Vec2Weightf(uv_other, uvCo1, uvCo2, uvCo3, w); - - /* use */ - uvco_to_wrapped_pxco(uv_other, ibuf->x, ibuf->y, &x, &y); - - if (x < 0.0f) x += 1.0f; - if (y < 0.0f) y += 1.0f; - - x = x * ibuf_other->x - 0.5f; - y = y * ibuf_other->y - 0.5f; - if (ibuf->rect_float) { if (ibuf_other->rect_float) { /* from float to float */ - bilinear_interpolation_color(ibuf_other, NULL, ((ProjPixelClone *)projPixel)->clonepx.f, x, y); + project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f); } else { /* from char to float */ unsigned char rgba_ub[4]; - bilinear_interpolation_color(ibuf_other, rgba_ub, NULL, x, y); + project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL); IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub); } } else { if (ibuf_other->rect_float) { /* float to char */ float rgba[4]; - bilinear_interpolation_color(ibuf_other, NULL, rgba, x, y); + project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba); IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba) } else { /* char to char */ - bilinear_interpolation_color(ibuf_other, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL, x, y); + project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); } } } @@ -2853,16 +2896,35 @@ static void project_paint_begin(ProjPaintState *ps, short mval[2]) /* use clone mtface? */ - if ( ps->tool != PAINT_TOOL_CLONE || - ps->clone_layer==-1 || - ps->clone_layer >= CustomData_number_of_layers(&ps->dm->faceData, CD_MTFACE) - ) { - ps->dm_mtface_clone = NULL; + + /* Note, use the original mesh for getting the clone and mask layer index + * this avoids re-generating the derived mesh just to get the new index */ + if (ps->do_layer_clone) { + //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE); + int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); + if (layer_num != -1) + ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); + + if (ps->dm_mtface_clone==NULL || ps->dm_mtface_clone==ps->dm_mtface) { + ps->do_layer_clone = 0; + ps->dm_mtface_clone= NULL; + } } - else { - ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, ps->clone_layer); + + if (ps->do_layer_mask) { + //int layer_num = CustomData_get_mask_layer(&ps->dm->faceData, CD_MTFACE); + int layer_num = CustomData_get_mask_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); + if (layer_num != -1) + ps->dm_mtface_mask = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); + + if (ps->dm_mtface_mask==NULL || ps->dm_mtface_mask==ps->dm_mtface) { + ps->do_layer_mask = 0; + ps->dm_mtface_mask = NULL; + } } + + ps->viewDir[0] = 0.0f; ps->viewDir[1] = 0.0f; ps->viewDir[2] = 1.0f; @@ -4458,12 +4520,13 @@ void imagepaint_paint(short mousebutton, short texpaint) ps.do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; ps.do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; ps.do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1;; - if (settings->imapaint.flag & IMAGEPAINT_PROJECT_CLONE_LAYER) { - ps.clone_layer = settings->imapaint.clone_layer; - } - else { - ps.clone_layer = -1; - } + + if (ps.tool == PAINT_TOOL_CLONE) + ps.do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE); + + ps.do_layer_mask = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_MASK) ? 1 : 0; + ps.do_layer_mask_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_MASK_INV) ? 1 : 0; + #ifndef PROJ_DEBUG_NOSEAMBLEED ps.seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */ |