Projection Painting, merge from branch
Additions/Features... - Painting onto multiple images at once. - Clone with an offset similar to the gimp, also an option to clone between UV layers, (not both offset and between layers atm) - Stencil layer, similar to The Gimp's quickmask. - Face mask mode - (painting onto only selected faces). - Texture brushes (so image and texture-node brushes too) - Seam bleed so you don't see gaps when painting over UV seams (new option set in the panit panel) - Occlusion (only point onto the first face under the paintbrush, can also be used for masking out parts of the model to paint onto) - (new option set in the paint panel) - Muti-threaded, each thread operates on its own bucket. - Support partial updates to speedup OpenGL texture refreshing. - Support tile based multiple undo's - Support float image buffers. - Backface culling (new option set in the paint panel) - All color blending modes - Add/Multiply.. etc. - Airbrush rate. (used to be broken) - Improve the way paint is mixed when painting, so painting with 0.2 alpha will not accumulate above 0.2 alpha on the image as you paint. - Option to use normals to fade out strokes on the edge of a surface to avoid ugly edges. (same as Vertex Paints "Normal" option) Known Problems - Not directly related to painting but changes in selection flags are not updated on the final derived mesh. - Smear tool has some distortion when in perspective mode. - While in perspective view any faces with 1 vert behind the viewpoint, will be completely ignored. - Painting can be initially slow while buckets are being initialized, a number of solutions exist. - Size 1 brushes don't work yet. - When painting onto large faces its still possible to get artifacts. - Spatial optimizations are needed to skip occluded faces and test pixel occlusion. (will look into using blenders BVH )
This commit is contained in:
commit
aa40953210
@ -41,7 +41,7 @@ struct ListBase;
|
||||
struct MemFile;
|
||||
|
||||
#define BLENDER_VERSION 248
|
||||
#define BLENDER_SUBVERSION 1
|
||||
#define BLENDER_SUBVERSION 2
|
||||
|
||||
#define BLENDER_MINVERSION 245
|
||||
#define BLENDER_MINSUBVERSION 15
|
||||
|
@ -53,6 +53,7 @@ int brush_clone_image_delete(struct Brush *brush);
|
||||
|
||||
/* sampling */
|
||||
float brush_sample_falloff(struct Brush *brush, float dist);
|
||||
float brush_sample_falloff_noalpha(struct Brush *brush, float dist);
|
||||
void brush_sample_tex(struct Brush *brush, float *xy, float *rgba);
|
||||
void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size,
|
||||
struct ImBuf **imbuf);
|
||||
|
@ -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);
|
||||
|
@ -328,6 +328,23 @@ float brush_sample_falloff(Brush *brush, float dist)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float brush_sample_falloff_noalpha(Brush *brush, float dist)
|
||||
{
|
||||
float outer, inner;
|
||||
|
||||
outer = brush->size >> 1;
|
||||
inner = outer*brush->innerradius;
|
||||
|
||||
if (dist <= inner) {
|
||||
return 1.0f;
|
||||
}
|
||||
else if ((dist < outer) && (inner < outer)) {
|
||||
return 1.0f - sqrt((dist - inner)/(outer - inner));
|
||||
}
|
||||
else
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void brush_sample_tex(Brush *brush, float *xy, float *rgba)
|
||||
{
|
||||
MTex *mtex= brush->mtex[brush->texact];
|
||||
|
@ -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)
|
||||
{
|
||||
@ -882,9 +964,13 @@ static CustomDataLayer *customData_add_layer__internal(CustomData *data,
|
||||
if(index > 0 && data->layers[index-1].type == type) {
|
||||
data->layers[index].active = data->layers[index-1].active;
|
||||
data->layers[index].active_rnd = data->layers[index-1].active_rnd;
|
||||
data->layers[index].active_clone = data->layers[index-1].active_clone;
|
||||
data->layers[index].active_mask = data->layers[index-1].active_mask;
|
||||
} else {
|
||||
data->layers[index].active = 0;
|
||||
data->layers[index].active_rnd = 0;
|
||||
data->layers[index].active_clone = 0;
|
||||
data->layers[index].active_mask = 0;
|
||||
}
|
||||
|
||||
customData_update_offsets(data);
|
||||
@ -944,6 +1030,8 @@ int CustomData_free_layer(CustomData *data, int type, int totelem, int index)
|
||||
for (; i < data->totlayer && data->layers[i].type == type; i++) {
|
||||
data->layers[i].active--;
|
||||
data->layers[i].active_rnd--;
|
||||
data->layers[i].active_clone--;
|
||||
data->layers[i].active_mask--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8007,6 +8007,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
|
||||
}
|
||||
}
|
||||
|
||||
if (main->versionfile < 248 || (main->versionfile == 248 && main->subversionfile < 2)) {
|
||||
Scene *sce;
|
||||
|
||||
/* Note, these will need to be added for painting */
|
||||
for (sce= main->scene.first; sce; sce= sce->id.next) {
|
||||
sce->toolsettings->imapaint.seam_bleed = 2;
|
||||
sce->toolsettings->imapaint.normal_angle = 80;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
|
||||
/* WATCH IT 2!: Userdef struct init has to be in src/usiblender.c! */
|
||||
|
||||
|
@ -80,6 +80,7 @@ void viewmove(int mode);
|
||||
void viewmoveNDOFfly(int mode);
|
||||
void viewmoveNDOF(int mode);
|
||||
void view_zoom_mouseloc(float dfac, short *mouseloc);
|
||||
int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist);
|
||||
|
||||
int get_view3d_viewplane(int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize);
|
||||
void setwinmatrixview3d(int winx, int winy, struct rctf *rect);
|
||||
|
@ -453,6 +453,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
|
||||
|
@ -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 */
|
||||
|
@ -345,7 +345,9 @@ typedef struct TimeMarker {
|
||||
typedef struct ImagePaintSettings {
|
||||
struct Brush *brush;
|
||||
short flag, tool;
|
||||
int pad3;
|
||||
|
||||
/* for projection painting only */
|
||||
short seam_bleed,normal_angle;
|
||||
} ImagePaintSettings;
|
||||
|
||||
typedef struct ParticleBrushData {
|
||||
@ -799,6 +801,15 @@ typedef struct Scene {
|
||||
#define IMAGEPAINT_DRAW_TOOL 2
|
||||
#define IMAGEPAINT_DRAW_TOOL_DRAWING 4
|
||||
|
||||
/* projection painting only */
|
||||
#define IMAGEPAINT_PROJECT_DISABLE 8 /* Non projection 3D painting */
|
||||
#define IMAGEPAINT_PROJECT_XRAY 16
|
||||
#define IMAGEPAINT_PROJECT_BACKFACE 32
|
||||
#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
|
||||
#define UVCALC_NO_ASPECT_CORRECT 2 /* would call this UVCALC_ASPECT_CORRECT, except it should be default with old file */
|
||||
|
@ -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;
|
||||
|
||||
@ -722,10 +722,10 @@ static void delete_customdata_layer(void *data1, void *data2)
|
||||
Mesh *me= (Mesh*)data1;
|
||||
CustomData *data= (G.obedit)? &G.editMesh->fdata: &me->fdata;
|
||||
CustomDataLayer *layer= (CustomDataLayer*)data2;
|
||||
void *actlayerdata, *rndlayerdata, *layerdata=layer->data;
|
||||
void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
|
||||
int type= layer->type;
|
||||
int index= CustomData_get_layer_index(data, type);
|
||||
int i, actindex, rndindex;
|
||||
int i, actindex, rndindex, cloneindex, maskindex;
|
||||
|
||||
/*ok, deleting a non-active layer needs to preserve the active layer indices.
|
||||
to do this, we store a pointer to the .data member of both layer and the active layer,
|
||||
@ -736,6 +736,8 @@ static void delete_customdata_layer(void *data1, void *data2)
|
||||
layer. */
|
||||
actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
|
||||
rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
|
||||
clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
|
||||
masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
|
||||
CustomData_set_layer_active(data, type, layer - &data->layers[index]);
|
||||
|
||||
/* Multires is handled seperately because the display data is separate
|
||||
@ -787,6 +789,33 @@ static void delete_customdata_layer(void *data1, void *data2)
|
||||
CustomData_set_layer_render(data, type, rndindex);
|
||||
}
|
||||
|
||||
if (clonelayerdata != layerdata) {
|
||||
/*find index. . .*/
|
||||
cloneindex = CustomData_get_layer_index(data, type);
|
||||
for (i=cloneindex; i<data->totlayer; i++) {
|
||||
if (data->layers[i].data == clonelayerdata) {
|
||||
cloneindex = i - cloneindex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*set index. . .*/
|
||||
CustomData_set_layer_clone(data, type, cloneindex);
|
||||
}
|
||||
|
||||
if (masklayerdata != layerdata) {
|
||||
/*find index. . .*/
|
||||
maskindex = CustomData_get_layer_index(data, type);
|
||||
for (i=maskindex; i<data->totlayer; i++) {
|
||||
if (data->layers[i].data == masklayerdata) {
|
||||
maskindex = i - maskindex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*set index. . .*/
|
||||
CustomData_set_layer_mask(data, type, maskindex);
|
||||
}
|
||||
|
||||
DAG_object_flush_update(G.scene, OBACT, OB_RECALC_DATA);
|
||||
|
||||
@ -802,9 +831,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 +857,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 +946,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 texture paint stencil layer", "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 +5008,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 Stencil UV Texture");
|
||||
allqueue(REDRAWBUTSEDIT, 0);
|
||||
}
|
||||
break;
|
||||
case B_FLIPNORM:
|
||||
if(G.obedit) {
|
||||
flip_editnormals();
|
||||
@ -6279,20 +6338,23 @@ void brush_buttons(uiBlock *block, short sima,
|
||||
ToolSettings *settings= G.scene->toolsettings;
|
||||
Brush *brush= settings->imapaint.brush;
|
||||
ID *id;
|
||||
int yco, xco, butw;
|
||||
int yco, xco, butw, but_idx;
|
||||
|
||||
short *menupoin = sima ? &(G.sima->menunr) : &(G.buts->menunr);
|
||||
short do_project = settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE ? 0:1;
|
||||
|
||||
yco= 160;
|
||||
|
||||
butw = sima ? 80 : 106;
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButS(block, ROW, evt_change, "Draw", 0, yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
|
||||
uiDefButS(block, ROW, evt_change, "Soften", butw, yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
|
||||
uiDefButS(block, ROW, evt_change, "Smear", butw*2, yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
|
||||
if (sima)
|
||||
uiDefButS(block, ROW, evt_change, "Clone", butw*3, yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");
|
||||
but_idx = 0;
|
||||
uiDefButS(block, ROW, evt_change, "Draw", butw*(but_idx++),yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_DRAW, 0, 0, "Draw brush");
|
||||
if (sima || do_project==0)
|
||||
uiDefButS(block, ROW, evt_change, "Soften", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SOFTEN, 0, 0, "Soften brush");
|
||||
uiDefButS(block, ROW, evt_change, "Smear", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_SMEAR, 0, 0, "Smear brush");
|
||||
if (sima || do_project)
|
||||
uiDefButS(block, ROW, evt_change, "Clone", butw*(but_idx++), yco,butw,19, &settings->imapaint.tool, 7.0, PAINT_TOOL_CLONE, 0, 0, "Clone brush, use RMB to drag source image");
|
||||
|
||||
uiBlockEndAlign(block);
|
||||
yco -= 30;
|
||||
@ -6307,16 +6369,44 @@ void brush_buttons(uiBlock *block, short sima,
|
||||
butw= 320-(xco+10);
|
||||
|
||||
uiDefButS(block, MENU, evt_nop, "Mix %x0|Add %x1|Subtract %x2|Multiply %x3|Lighten %x4|Darken %x5|Erase Alpha %x6|Add Alpha %x7", xco+10,yco,butw,19, &brush->blend, 0, 0, 0, 0, "Blending method for applying brushes");
|
||||
|
||||
uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, evt_change, "Wrap", xco+10,yco-25,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
|
||||
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, evt_change, "Airbrush", xco+10,yco-50,butw,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
|
||||
uiDefButF(block, NUM, evt_nop, "Rate ", xco+10,yco-70,butw,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
|
||||
uiDefButBitS(block, TOG|BIT, BRUSH_AIRBRUSH, evt_change, "Airbrush", xco+10,yco-25,butw/2,19, &brush->flag, 0, 0, 0, 0, "Keep applying paint effect while holding mouse (spray)");
|
||||
uiDefButF(block, NUM, evt_nop, "", xco+10 + butw/2,yco-25,butw/2,19, &brush->rate, 0.01, 1.0, 0, 0, "Number of paints per second for Airbrush");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
yco -= 25;
|
||||
|
||||
|
||||
if (sima) {
|
||||
uiDefButBitS(block, TOG|BIT, BRUSH_TORUS, evt_change, "Wrap", xco+10,yco-45,butw,19, &brush->flag, 0, 0, 0, 0, "Enables torus wrapping");
|
||||
yco -= 25;
|
||||
}
|
||||
else {
|
||||
yco -= 25;
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_DISABLE, B_REDR, "Project Paint", xco+10,yco-25,butw,19, &settings->imapaint.flag, 0, 0, 0, 0, "Use projection painting for improved consistency in the brush strokes");
|
||||
|
||||
if ((settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)==0) {
|
||||
|
||||
|
||||
/* Projection Painting */
|
||||
|
||||
uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_XRAY, B_NOP, "Occlude", xco+10,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Only paint onto the faces directly under the brush (slower)");
|
||||
uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_BACKFACE, B_NOP, "Cull", xco+10+butw/2,yco-45,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Ignore faces pointing away from the view (faster)");
|
||||
|
||||
uiDefButBitS(block, TOGN|BIT, IMAGEPAINT_PROJECT_FLAT, B_NOP, "Normal", xco+10,yco-65,butw/2,19, &settings->imapaint.flag, 0, 0, 0, 0, "Paint most on faces pointing towards the view");
|
||||
uiDefButS(block, NUM, B_NOP, "", xco+10 +(butw/2),yco-65,butw/2,19, &settings->imapaint.normal_angle, 10.0, 90.0, 0, 0, "Paint most on faces pointing towards the view acording to this angle");
|
||||
|
||||
uiDefButS(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, "Stencil Layer", 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);
|
||||
|
||||
}
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButF(block, COL, B_VPCOLSLI, "", 0,yco,200,19, brush->rgb, 0, 0, 0, 0, "");
|
||||
uiDefButF(block, NUMSLI, evt_nop, "Opacity ", 0,yco-20,180,19, &brush->alpha, 0.0, 1.0, 0, 0, "The amount of pressure on the brush");
|
||||
|
@ -3309,7 +3309,12 @@ void drawview3dspace(ScrArea *sa, void *spacedata)
|
||||
fdrawXORcirc((float)c[0], (float)c[1], (float)pset->brush[pset->brushtype].size);
|
||||
}
|
||||
}
|
||||
|
||||
if(!G.obedit && OBACT && G.f&G_TEXTUREPAINT && area_is_active_area(v3d->area) && G.scene->toolsettings->imapaint.brush){
|
||||
short c[2];
|
||||
getmouseco_areawin(c);
|
||||
fdrawXORcirc((float)c[0], (float)c[1], (float)G.scene->toolsettings->imapaint.brush->size/2);
|
||||
}
|
||||
|
||||
if(v3d->persp>1) drawviewborder();
|
||||
if(v3d->flag2 & V3D_FLYMODE) drawviewborder_flymode();
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1307,6 +1307,14 @@ static void winqreadview3dspace(ScrArea *sa, void *spacedata, BWinEvent *evt)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!G.obedit && OBACT && G.f&G_TEXTUREPAINT){
|
||||
if(G.scene->toolsettings->imapaint.brush &&
|
||||
event!=LEFTMOUSE && event!=RIGHTMOUSE && event!=MIDDLEMOUSE &&
|
||||
(event==MOUSEY || event==MOUSEX) && bwin_qtest(sa->win)==0) {
|
||||
allqueue(REDRAWVIEW3D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Handle retopo painting */
|
||||
if(retopo_mesh_paint_check()) {
|
||||
|
@ -796,12 +796,15 @@ void viewmoveNDOFfly(int mode)
|
||||
BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT);
|
||||
}
|
||||
|
||||
int view_autodist( float mouse_worldloc[3] ) //, float *autodist )
|
||||
/* Be sure to run persp(PERSP_VIEW) if this isnt set,
|
||||
*
|
||||
* mouse_worldloc - worldspace vector that is set
|
||||
* mval - screenspace location, or from getmouseco_areawin(mval)
|
||||
* dist - the size of the square to use when averaging the Z depth.
|
||||
*/
|
||||
int view_mouse_depth( float mouse_worldloc[3], short mval[2], int dist)
|
||||
{
|
||||
View3D *v3d = G.vd;
|
||||
|
||||
/* Zooms in on a border drawn by the user */
|
||||
short mval[2];
|
||||
rcti rect;
|
||||
|
||||
/* ZBuffer depth vars */
|
||||
@ -813,13 +816,13 @@ int view_autodist( float mouse_worldloc[3] ) //, float *autodist )
|
||||
|
||||
getmouseco_areawin(mval);
|
||||
|
||||
persp(PERSP_VIEW);
|
||||
/* persp(PERSP_VIEW); */
|
||||
|
||||
rect.xmax = mval[0] + 4;
|
||||
rect.ymax = mval[1] + 4;
|
||||
rect.xmax = mval[0] + dist;
|
||||
rect.ymax = mval[1] + dist;
|
||||
|
||||
rect.xmin = mval[0] - 4;
|
||||
rect.ymin = mval[1] - 4;
|
||||
rect.xmin = mval[0] - dist;
|
||||
rect.ymin = mval[1] - dist;
|
||||
|
||||
/* Get Z Depths, needed for perspective, nice for ortho */
|
||||
bgl_get_mats(&mats);
|
||||
@ -943,7 +946,8 @@ void viewmove(int mode)
|
||||
VecMulf(obofs, -1.0f);
|
||||
}
|
||||
else if (U.uiflag & USER_ORBIT_ZBUF) {
|
||||
if ((use_sel=view_autodist(obofs))) {
|
||||
persp(PERSP_VIEW);
|
||||
if ((use_sel=view_mouse_depth(obofs, mval_area, 4))) {
|
||||
if (G.vd->persp==V3D_PERSP) {
|
||||
float my_origin[3]; /* original G.vd->ofs */
|
||||
float my_pivot[3]; /* view */
|
||||
@ -974,6 +978,8 @@ void viewmove(int mode)
|
||||
} else {
|
||||
ofs[0] = ofs[1] = ofs[2] = 0.0f;
|
||||
}
|
||||
|
||||
persp(PERSP_WIN);
|
||||
}
|
||||
else
|
||||
ofs[0] = ofs[1] = ofs[2] = 0.0f;
|
||||
|
Loading…
Reference in New Issue
Block a user