diff --git a/source/blender/blenkernel/BKE_bad_level_calls.h b/source/blender/blenkernel/BKE_bad_level_calls.h index 8b9454f1a9d..02e2f799103 100644 --- a/source/blender/blenkernel/BKE_bad_level_calls.h +++ b/source/blender/blenkernel/BKE_bad_level_calls.h @@ -217,6 +217,8 @@ void multires_update_levels(struct Mesh *me, const int render); void multires_calc_level_maps(struct MultiresLevel *lvl); struct Multires *multires_copy(struct Multires *orig); /* sculptmode.c */ +struct SculptData; +void sculpt_reset_curve(struct SculptData *sd); void sculptmode_free_all(struct Scene *sce); void sculptmode_init(struct Scene *sce); diff --git a/source/blender/blenkernel/bad_level_call_stubs/stubs.c b/source/blender/blenkernel/bad_level_call_stubs/stubs.c index 55931b50462..e0aa288c7b2 100644 --- a/source/blender/blenkernel/bad_level_call_stubs/stubs.c +++ b/source/blender/blenkernel/bad_level_call_stubs/stubs.c @@ -317,6 +317,7 @@ void multires_set_level(struct Object *ob, struct Mesh *me, const int render) {} void multires_update_levels(struct Mesh *me, const int render) {} void multires_calc_level_maps(struct MultiresLevel *lvl) {} struct Multires *multires_copy(struct Multires *orig) {return NULL;} +void sculpt_reset_curve(struct SculptData *sd) {} void sculptmode_init(struct Scene *sce) {} void sculptmode_free_all(struct Scene *sce) {} diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 8bbcc7016c1..553ab0eb168 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3323,6 +3323,12 @@ static void direct_link_scene(FileData *fd, Scene *sce) /* SculptData textures */ for(a=0; asculptdata.mtex[a]= newdataadr(fd,sce->sculptdata.mtex[a]); + /* Sculpt intensity curve */ + sce->sculptdata.cumap= newdataadr(fd, sce->sculptdata.cumap); + if(sce->sculptdata.cumap) + direct_link_curvemapping(fd, sce->sculptdata.cumap); + else + sculpt_reset_curve(&sce->sculptdata); if(sce->ed) { ListBase *old_seqbasep= &((Editing *)sce->ed)->seqbase; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index cfaae977bdd..d19c634e610 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1422,6 +1422,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase) for(a=0; asculptdata.mtex[a]); + if(sce->sculptdata.cumap) + write_curvemapping(wd, sce->sculptdata.cumap); ed= sce->ed; if(ed) { diff --git a/source/blender/include/BDR_sculptmode.h b/source/blender/include/BDR_sculptmode.h index c80f9ea8626..abbb17ac42b 100644 --- a/source/blender/include/BDR_sculptmode.h +++ b/source/blender/include/BDR_sculptmode.h @@ -99,12 +99,14 @@ SculptSession *sculpt_session(void); struct SculptData *sculpt_data(void); /* Memory */ +void sculpt_reset_curve(struct SculptData *sd); void sculptmode_init(struct Scene *); void sculptmode_free_all(struct Scene *); void sculptmode_correct_state(void); /* Interface */ void sculptmode_draw_interface_tools(struct uiBlock *block,unsigned short cx, unsigned short cy); +void sculptmode_draw_interface_brush(struct uiBlock *block,unsigned short cx, unsigned short cy); void sculptmode_draw_interface_textures(struct uiBlock *block,unsigned short cx, unsigned short cy); void sculptmode_rem_tex(void*,void*); void sculptmode_propset_init(PropsetMode mode); diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 412c40c7eb0..c82a1f9e510 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -424,6 +424,9 @@ typedef struct SculptData /* Pointers to all of sculptmodes's textures */ struct MTex *mtex[10]; + /* Editable brush shape */ + struct CurveMapping *cumap; + /* Settings for each brush */ BrushData drawbrush, smoothbrush, pinchbrush, inflatebrush, grabbrush, layerbrush, flattenbrush; short brush_type; diff --git a/source/blender/src/buttons_editing.c b/source/blender/src/buttons_editing.c index 83139fcfb0a..ca878933499 100644 --- a/source/blender/src/buttons_editing.c +++ b/source/blender/src/buttons_editing.c @@ -5046,10 +5046,18 @@ void editing_panel_sculpting_tools() sculptmode_draw_interface_tools(block,0,200); } +void editing_panel_sculpting_brush() +{ + uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_brush", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Brush", "Editing", 300, 0, 318, 204)==0) return; + + sculptmode_draw_interface_brush(block,0,200); +} + void editing_panel_sculpting_textures() { - uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_textures", UI_EMBOSS, UI_HELV, curarea->win); - if(uiNewPanel(curarea, block, "Brush", "Editing", 300, 0, 318, 204)==0) return; + uiBlock *block= uiNewBlock(&curarea->uiblocks, "editing_panel_sculpting_texture", UI_EMBOSS, UI_HELV, curarea->win); + if(uiNewPanel(curarea, block, "Texture", "Editing", 300, 0, 318, 204)==0) return; sculptmode_draw_interface_textures(block,0,200); } @@ -5057,11 +5065,10 @@ void editing_panel_sculpting_textures() void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned short cy) { SculptData *sd; - uiBut *but; if(!G.scene) return; sd= &G.scene->sculptdata; - + uiBlockBeginAlign(block); uiDefBut(block,LABEL,B_NOP,"Brush",cx,cy,90,19,NULL,0,0,0,0,""); @@ -5090,7 +5097,7 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned if(sd->brush_type!=GRAB_BRUSH) uiDefButC(block,TOG,B_NOP,"Airbrush",cx+178,cy,89,19,&sculptmode_brush()->airbrush,0,0,0,0,"Brush makes changes without waiting for the mouse to move"); cy-= 20; - but= uiDefButS(block,NUMSLI,B_NOP,"Size: ",cx,cy,268,19,&sculptmode_brush()->size,1.0,200.0,0,0,"Set brush radius in pixels"); + uiDefButS(block,NUMSLI,B_NOP,"Size: ",cx,cy,268,19,&sculptmode_brush()->size,1.0,200.0,0,0,"Set brush radius in pixels"); cy-= 20; if(sd->brush_type!=GRAB_BRUSH) uiDefButC(block,NUMSLI,B_NOP,"Strength: ",cx,cy,268,19,&sculptmode_brush()->strength,1.0,100.0,0,0,"Set brush strength"); @@ -5109,6 +5116,46 @@ void sculptmode_draw_interface_tools(uiBlock *block, unsigned short cx, unsigned cx+= 210; } +static void sculptmode_curves_reset(void *sd_v, void *j) +{ + SculptData *sd = sd_v; + sculpt_reset_curve(sd); + curvemapping_changed(sd->cumap, 0); +} + +void sculptmode_draw_interface_brush(uiBlock *block, unsigned short cx, unsigned short cy) +{ + SculptData *sd= sculpt_data(); + int orig_y = cy; + rctf rect; + uiBut *but; + + uiBlockBeginAlign(block); + cy-= 20; + uiDefButC(block,TOG,REDRAWBUTSEDIT, "Curve", cx,cy,80,19, &sd->texfade, 0,0,0,0,"Use curve control for radial brush intensity"); + cy-= 20; + but= uiDefBut(block, BUT, REDRAWBUTSEDIT, "Reset",cx,cy,80,19, NULL, 0,0,0,0, "Default curve preset"); + uiButSetFunc(but, sculptmode_curves_reset, sd, NULL); + cy-= 25; + uiBlockEndAlign(block); + + uiBlockBeginAlign(block); + uiDefButS(block,NUM,B_NOP, "Space", cx,cy,80,19, &sd->spacing, 0,500,20,0,"Non-zero inserts N pixels between dots"); + cy-= 20; + if(sd->brush_type == DRAW_BRUSH) + uiDefButC(block,NUM,B_NOP, "View", cx,cy,80,19, &sculptmode_brush()->view, 0,10,20,0,"Pulls brush direction towards view"); + uiBlockEndAlign(block); + + /* Draw curve */ + cx += 90; + cy = orig_y; + rect.xmin= cx; rect.xmax= cx + 178; + rect.ymin= cy - 160; rect.ymax= cy + 20; + uiBlockBeginAlign(block); + curvemap_buttons(block, sd->cumap, (char)0, B_NOP, 0, &rect); + uiBlockEndAlign(block); +} + void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsigned short cy) { SculptData *sd= sculpt_data(); @@ -5119,24 +5166,7 @@ void sculptmode_draw_interface_textures(uiBlock *block, unsigned short cx, unsig uiBut *but; uiBlockBeginAlign(block); - uiDefBut(block,LABEL,B_NOP,"Common",cx,cy,80,20,0,0,0,0,0,""); cy-= 20; - - uiBlockBeginAlign(block); - uiDefButC(block,TOG,B_NOP, "Fade", cx,cy,80,19, &sd->texfade, 0,0,0,0,"Smooth the edges of the texture"); - cy-= 20; - uiDefButS(block,NUM,B_NOP, "Space", cx,cy,80,19, &sd->spacing, 0,500,20,0,"Non-zero inserts N pixels between dots"); - cy-= 20; - if(sd->brush_type == DRAW_BRUSH) - uiDefButC(block,NUM,B_NOP, "View", cx,cy,80,19, &sculptmode_brush()->view, 0,10,20,0,"Pulls brush direction towards view"); - uiBlockEndAlign(block); - - cy= orig_y; - cx+= 85; - uiBlockBeginAlign(block); - uiDefBut(block,LABEL,B_NOP,"Texture",cx,cy,80,20,0,0,0,0,0,""); - cy-= 20; - /* TEX CHANNELS */ uiBlockBeginAlign(block); uiBlockSetCol(block, TH_BUT_NEUTRAL); @@ -6034,6 +6064,8 @@ void editing_panels() uiNewPanelTabbed("Multires", "Editing"); editing_panel_sculpting_tools(); uiNewPanelTabbed("Multires", "Editing"); + editing_panel_sculpting_brush(); + uiNewPanelTabbed("Multires", "Editing"); editing_panel_sculpting_textures(); } else { if(G.f & (G_VERTEXPAINT | G_TEXTUREPAINT | G_WEIGHTPAINT) ) { diff --git a/source/blender/src/drawview.c b/source/blender/src/drawview.c index b3ffd1263ad..5df1448ebc1 100644 --- a/source/blender/src/drawview.c +++ b/source/blender/src/drawview.c @@ -2252,7 +2252,7 @@ static void view3d_panel_object(short cntrl) // VIEW3D_HANDLER_OBJECT uiSetPanelHandler(VIEW3D_HANDLER_OBJECT); // for close and esc if((G.f & G_SCULPTMODE) && !G.obedit) { - if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 425, 234)) + if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234)) return; } else if(G.f & G_PARTICLEEDIT && !G.obedit){ if(!uiNewPanel(curarea, block, "Transform Properties", "View3d", 10, 230, 318, 234)) diff --git a/source/blender/src/sculptmode.c b/source/blender/src/sculptmode.c index 7dd668e1acb..010bf6f746c 100644 --- a/source/blender/src/sculptmode.c +++ b/source/blender/src/sculptmode.c @@ -53,6 +53,7 @@ #include "DNA_texture_types.h" #include "DNA_view3d_types.h" #include "DNA_userdef_types.h" +#include "DNA_color_types.h" #include "BKE_customdata.h" #include "BKE_DerivedMesh.h" @@ -66,6 +67,7 @@ #include "BKE_modifier.h" #include "BKE_texture.h" #include "BKE_utildefines.h" +#include "BKE_colortools.h" #include "BIF_editkey.h" #include "BIF_editview.h" @@ -190,6 +192,35 @@ SculptSession *sculpt_session(void) * Allocate/initialize/free data */ +// Default curve approximates 0.5 * (cos(pi * x) + 1), with 0 <= x <= 1; +void sculpt_reset_curve(SculptData *sd) +{ + CurveMap *cm = NULL; + + if(!sd->cumap) + sd->cumap = curvemapping_add(1, 0, 0, 1, 1); + + cm = sd->cumap->cm; + + if(cm->curve) + MEM_freeN(cm->curve); + cm->curve= MEM_callocN(6*sizeof(CurveMapPoint), "curve points"); + cm->flag &= ~CUMA_EXTEND_EXTRAPOLATE; + cm->totpoint= 6; + cm->curve[0].x= 0; + cm->curve[0].y= 1; + cm->curve[1].x= 0.1; + cm->curve[1].y= 0.97553; + cm->curve[2].x= 0.3; + cm->curve[2].y= 0.79389; + cm->curve[3].x= 0.9; + cm->curve[3].y= 0.02447; + cm->curve[4].x= 0.7; + cm->curve[4].y= 0.20611; + cm->curve[5].x= 1; + cm->curve[5].y= 0; +} + /* Initialize 'permanent' sculpt data that is saved with file kept after switching out of sculptmode. */ void sculptmode_init(Scene *sce) @@ -203,6 +234,9 @@ void sculptmode_init(Scene *sce) sd= &sce->sculptdata; + if(sd->cumap) + curvemapping_free(sd->cumap); + memset(sd, 0, sizeof(SculptData)); sd->drawbrush.size = sd->smoothbrush.size = sd->pinchbrush.size = @@ -227,6 +261,7 @@ void sculptmode_init(Scene *sce) sd->tablet_size=3; sd->tablet_strength=10; sd->rake=0; + sculpt_reset_curve(sd); } void sculptmode_free_session(Scene *); @@ -281,6 +316,9 @@ void sculptmode_free_all(Scene *sce) MEM_freeN(mtex); } } + + curvemapping_free(sd->cumap); + sd->cumap = NULL; } /* vertex_users is an array of Lists that store all the faces that use a @@ -735,12 +773,11 @@ void do_flatten_brush(const EditData *e, const ListBase *active_verts) } } -/* Creates a smooth curve for the brush shape. This is the cos(x) curve from - [0,PI] scaled to [0,len]. The range is scaled to [0,1]. */ -float simple_strength(float p, const float len) +/* Uses the brush curve control to find a strength value between 0 and 1 */ +float curve_strength(float p, const float len) { if(p > len) p= len; - return 0.5f * (cos(M_PI*p/len) + 1); + return curvemapping_evaluateF(G.scene->sculptdata.cumap, 0, p/len); } /* Uses symm to selectively flip any axis of a coordinate. */ @@ -883,7 +920,7 @@ float tex_strength(EditData *e, float *point, const float len,const unsigned vin } if(sd->texfade) - avg*= simple_strength(len,e->size); /* Smooth curve */ + avg*= curve_strength(len,e->size); /* Smooth curve */ return avg; } @@ -1323,7 +1360,7 @@ void sculptmode_propset_calctex() for(j=0; jtexfade) - pd->texdata[i*tsz+j]= simple_strength(magn,tsz/2); + pd->texdata[i*tsz+j]= curve_strength(magn,tsz/2); else pd->texdata[i*tsz+j]= magn < tsz/2 ? 1 : 0; }