diff options
author | Campbell Barton <ideasman42@gmail.com> | 2011-06-09 19:20:29 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2011-06-09 19:20:29 +0400 |
commit | f122a74b1e778bc902fa57f0689ac89c1dacbcef (patch) | |
tree | 7138ce2ab1fba31d94fc393534ce3bcc9aefc389 /source/blender | |
parent | 522f9111a56268f2155c93d562abad86c1883332 (diff) | |
parent | d4ae38cc6c4ec8e3d13f26d12f85bca561f64f0f (diff) |
svn merge -r37078:37335 https://svn.blender.org/svnroot/bf-blender/trunk/blender
Diffstat (limited to 'source/blender')
164 files changed, 4487 insertions, 1163 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 1aeb2b5fce6..ba9036e1b05 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -89,6 +89,7 @@ extern int BKE_undo_valid(const char *name); extern void BKE_reset_undo(void); extern char *BKE_undo_menu_string(void); extern void BKE_undo_number(struct bContext *C, int nr); +extern char *BKE_undo_get_name(int nr, int *active); void BKE_undo_save(char *fname); extern void BKE_undo_save_quit(void); extern struct Main *BKE_undo_get_main(struct Scene **scene); diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index ad736cd07bf..ebb9714cd1b 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -71,7 +71,7 @@ float brush_curve_strength(struct Brush *br, float p, const float len); /* used /* sampling */ void brush_sample_tex(struct Brush *brush, float *xy, float *rgba, const int thread); void brush_imbuf_new(struct Brush *brush, short flt, short texfalloff, int size, - struct ImBuf **imbuf); + struct ImBuf **imbuf, int use_color_correction); /* painting */ struct BrushPainter; @@ -82,7 +82,7 @@ BrushPainter *brush_painter_new(struct Brush *brush); void brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size); int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, - double time, float pressure, void *user); + double time, float pressure, void *user, int use_color_correction); void brush_painter_break_stroke(BrushPainter *painter); void brush_painter_free(BrushPainter *painter); diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index a9ac201beda..64cea929573 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -59,9 +59,9 @@ float defvert_array_find_weight_safe(const struct MDeformVert *dvert, int index void defvert_copy(struct MDeformVert *dvert_r, const struct MDeformVert *dvert); void defvert_sync(struct MDeformVert *dvert_r, const struct MDeformVert *dvert, int use_verify); -void defvert_sync_mapped(struct MDeformVert *dvert_r, const struct MDeformVert *dvert, int *flip_map, int use_verify); +void defvert_sync_mapped(struct MDeformVert *dvert_r, const struct MDeformVert *dvert, const int *flip_map, int use_verify); void defvert_remap (struct MDeformVert *dvert, int *map); -void defvert_flip(struct MDeformVert *dvert, int *flip_map); +void defvert_flip(struct MDeformVert *dvert, const int *flip_map); void defvert_normalize(struct MDeformVert *dvert); /* utility function, note that 32 chars is the maximum string length since its only diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 0360acbea32..d21b0428d76 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -145,6 +145,7 @@ typedef struct Global { #define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */ #define G_FILE_RECOVER (1 << 23) #define G_FILE_RELATIVE_REMAP (1 << 24) +#define G_FILE_HISTORY (1 << 25) /* G.windowstate */ #define G_WINDOWSTATE_USERDEF 0 diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 25b56a371e7..01fcc51a441 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -99,6 +99,7 @@ void multires_topology_changed(struct Scene *scene, struct Object *ob); void old_mdisps_bilinear(float out[3], float (*disps)[3], const int st, float u, float v); void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, const float x, const float y, float *u, float *v); int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y); +int mdisp_rot_face_to_quad_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y); void mdisp_apply_weight(const int S, const int corners, int x, int y, const int face_side, float crn_weight[4][2], float *u_r, float *v_r); void mdisp_flip_disp(const int S, const int corners, const float axis_x[2], const float axis_y[2], float disp[3]); void mdisp_join_tris(struct MDisps *dst, struct MDisps *tri1, struct MDisps *tri2); diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index e794d0f6172..a1822848048 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -523,7 +523,8 @@ void BKE_write_undo(bContext *C, const char *name) static int counter= 0; char filepath[FILE_MAXDIR+FILE_MAXFILE]; char numstr[32]; - + int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */ + /* calculate current filepath */ counter++; counter= counter % U.undosteps; @@ -531,7 +532,7 @@ void BKE_write_undo(bContext *C, const char *name) BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter); BLI_make_file_string("/", filepath, btempdir, numstr); - success= BLO_write_file(CTX_data_main(C), filepath, G.fileflags, NULL, NULL); + success= BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); BLI_strncpy(curundo->str, filepath, sizeof(curundo->str)); } @@ -619,7 +620,7 @@ void BKE_reset_undo(void) /* based on index nr it does a restore */ void BKE_undo_number(bContext *C, int nr) { - curundo= BLI_findlink(&undobase, nr - 1); + curundo= BLI_findlink(&undobase, nr); BKE_undo_step(C, 0); } @@ -645,6 +646,21 @@ int BKE_undo_valid(const char *name) return undobase.last != undobase.first; } +/* get name of undo item, return null if no item with this index */ +/* if active pointer, set it to 1 if true */ +char *BKE_undo_get_name(int nr, int *active) +{ + UndoElem *uel= BLI_findlink(&undobase, nr); + + if(active) *active= 0; + + if(uel) { + if(active && uel==curundo) + *active= 1; + return uel->name; + } + return NULL; +} char *BKE_undo_menu_string(void) { diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 25b60fef6dd..a4ceb62ab55 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -521,7 +521,7 @@ void brush_sample_tex(Brush *brush, float *xy, float *rgba, const int thread) } -void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf) +void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf **outbuf, int use_color_correction) { ImBuf *ibuf; float xy[2], dist, rgba[4], *dstf; @@ -529,7 +529,8 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf const int radius= brush_size(brush); char *dst, crgb[3]; const float alpha= brush_alpha(brush); - + float brush_rgb[3]; + imbflag= (flt)? IB_rectfloat: IB_rect; xoff = -bufsize/2.0f + 0.5f; yoff = -bufsize/2.0f + 0.5f; @@ -541,6 +542,11 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf ibuf= IMB_allocImBuf(bufsize, bufsize, 32, imbflag); if (flt) { + copy_v3_v3(brush_rgb, brush->rgb); + if(use_color_correction){ + srgb_to_linearrgb_v3_v3(brush_rgb, brush_rgb); + } + for (y=0; y < ibuf->y; y++) { dstf = ibuf->rect_float + y*rowbytes; @@ -551,7 +557,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf if (texfall == 0) { dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); - VECCOPY(dstf, brush->rgb); + VECCOPY(dstf, brush_rgb); dstf[3]= alpha*brush_curve_strength_clamp(brush, dist, radius); } else if (texfall == 1) { @@ -561,10 +567,7 @@ void brush_imbuf_new(Brush *brush, short flt, short texfall, int bufsize, ImBuf dist = sqrt(xy[0]*xy[0] + xy[1]*xy[1]); brush_sample_tex(brush, xy, rgba, 0); - - dstf[0] = rgba[0]*brush->rgb[0]; - dstf[1] = rgba[1]*brush->rgb[1]; - dstf[2] = rgba[2]*brush->rgb[2]; + mul_v3_v3v3(dstf, rgba, brush_rgb); dstf[3] = rgba[3]*alpha*brush_curve_strength_clamp(brush, dist, radius); } } @@ -862,7 +865,7 @@ static void brush_painter_fixed_tex_partial_update(BrushPainter *painter, float brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos); } -static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) +static void brush_painter_refresh_cache(BrushPainter *painter, float *pos, int use_color_correction) { Brush *brush= painter->brush; BrushPainterCache *cache= &painter->cache; @@ -889,11 +892,11 @@ static void brush_painter_refresh_cache(BrushPainter *painter, float *pos) size= (cache->size)? cache->size: diameter; if (brush->flag & BRUSH_FIXED_TEX) { - brush_imbuf_new(brush, flt, 3, size, &cache->maskibuf); + brush_imbuf_new(brush, flt, 3, size, &cache->maskibuf, use_color_correction); brush_painter_fixed_tex_partial_update(painter, pos); } else - brush_imbuf_new(brush, flt, 2, size, &cache->ibuf); + brush_imbuf_new(brush, flt, 2, size, &cache->ibuf, use_color_correction); cache->lastsize= diameter; cache->lastalpha= alpha; @@ -952,7 +955,7 @@ void brush_jitter_pos(Brush *brush, float *pos, float *jitterpos) } } -int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) +int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user, int use_color_correction) { Brush *brush= painter->brush; int totpaintops= 0; @@ -970,7 +973,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_apply_pressure(painter, brush, pressure); if (painter->cache.enabled) - brush_painter_refresh_cache(painter, pos); + brush_painter_refresh_cache(painter, pos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, pos, pos); painter->lasttime= time; @@ -1043,7 +1046,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_jitter_pos(brush, paintpos, finalpos); if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos); + brush_painter_refresh_cache(painter, finalpos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); @@ -1057,7 +1060,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_jitter_pos(brush, pos, finalpos); if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos); + brush_painter_refresh_cache(painter, finalpos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, pos, finalpos); @@ -1085,7 +1088,7 @@ int brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, doubl brush_jitter_pos(brush, pos, finalpos); if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos); + brush_painter_refresh_cache(painter, finalpos, use_color_correction); totpaintops += func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 6e255438fa8..bb01de6e8d5 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -470,6 +470,7 @@ static void layerSwap_mdisps(void *data, const int *ci) } } +#if 1 /* BMESH_TODO: place holder function, dont actually interp */ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), float *UNUSED(sub_weights), int UNUSED(count), void *dest) { @@ -479,11 +480,128 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), if(!d->totdisp) { d->totdisp = ((MDisps*)sources[0])->totdisp; } - + if (!d->disps && d->totdisp) d->disps = BLI_cellalloc_calloc(sizeof(float)*3*d->totdisp, "blank mdisps in layerInterp_mdisps"); } +#else // BMESH_TODO + +static void layerInterp_mdisps(void **sources, float *UNUSED(weights), + float *sub_weights, int count, void *dest) +{ + MDisps *d = dest; + MDisps *s = NULL; + int st, stl; + int i, x, y; + int side, S, dst_corners, src_corners; + float crn_weight[4][2]; + float (*sw)[4] = (void*)sub_weights; + float (*disps)[3], (*out)[3]; + + /* happens when flipping normals of newly created mesh */ + if(!d->totdisp) + return; + + s = sources[0]; + dst_corners = multires_mdisp_corners(d); + src_corners = multires_mdisp_corners(s); + + if(sub_weights && count == 2 && src_corners == 3) { + src_corners = multires_mdisp_corners(sources[1]); + + /* special case -- converting two triangles to quad */ + if(src_corners == 3 && dst_corners == 4) { + MDisps tris[2]; + int vindex[4] = {0}; + + S = 0; + for(i = 0; i < 2; i++) + for(y = 0; y < 4; y++) + for(x = 0; x < 4; x++) + if(sw[x+i*4][y]) + vindex[x] = y; + + for(i = 0; i < 2; i++) { + float sw_m4[4][4] = {{0}}; + int a = 7 & ~(1 << vindex[i*2] | 1 << vindex[i*2+1]); + + sw_m4[0][vindex[i*2+1]] = 1; + sw_m4[1][vindex[i*2]] = 1; + + for(x = 0; x < 3; x++) + if(a & (1 << x)) + sw_m4[2][x] = 1; + + tris[i] = *((MDisps*)sources[i]); + tris[i].disps = MEM_dupallocN(tris[i].disps); + layerInterp_mdisps(&sources[i], NULL, (float*)sw_m4, 1, &tris[i]); + } + + mdisp_join_tris(d, &tris[0], &tris[1]); + + for(i = 0; i < 2; i++) + MEM_freeN(tris[i].disps); + + return; + } + } + + /* For now, some restrictions on the input */ + if(count != 1 || !sub_weights) { + for(i = 0; i < d->totdisp; ++i) + zero_v3(d->disps[i]); + + return; + } + + /* Initialize the destination */ + disps = MEM_callocN(3*d->totdisp*sizeof(float), "iterp disps"); + + side = sqrt(d->totdisp / dst_corners); + st = (side<<1)-1; + stl = st - 1; + + sw= (void*)sub_weights; + for(i = 0; i < 4; ++i) { + crn_weight[i][0] = 0 * sw[i][0] + stl * sw[i][1] + stl * sw[i][2] + 0 * sw[i][3]; + crn_weight[i][1] = 0 * sw[i][0] + 0 * sw[i][1] + stl * sw[i][2] + stl * sw[i][3]; + } + + multires_mdisp_smooth_bounds(s); + + out = disps; + for(S = 0; S < dst_corners; S++) { + float base[2], axis_x[2], axis_y[2]; + + mdisp_apply_weight(S, dst_corners, 0, 0, st, crn_weight, &base[0], &base[1]); + mdisp_apply_weight(S, dst_corners, side-1, 0, st, crn_weight, &axis_x[0], &axis_x[1]); + mdisp_apply_weight(S, dst_corners, 0, side-1, st, crn_weight, &axis_y[0], &axis_y[1]); + + sub_v2_v2(axis_x, base); + sub_v2_v2(axis_y, base); + normalize_v2(axis_x); + normalize_v2(axis_y); + + for(y = 0; y < side; ++y) { + for(x = 0; x < side; ++x, ++out) { + int crn; + float face_u, face_v, crn_u, crn_v; + + mdisp_apply_weight(S, dst_corners, x, y, st, crn_weight, &face_u, &face_v); + crn = mdisp_rot_face_to_quad_crn(src_corners, st, face_u, face_v, &crn_u, &crn_v); + + old_mdisps_bilinear((*out), &s->disps[crn*side*side], side, crn_u, crn_v); + mdisp_flip_disp(crn, dst_corners, axis_x, axis_y, *out); + } + } + } + + MEM_freeN(d->disps); + d->disps = disps; +} +#endif // BMESH_TODO + static void layerCopy_mdisps(const void *source, void *dest, int count) { int i; diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 0c4d1d067e6..e4b4732e21a 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -122,7 +122,7 @@ void defvert_sync (MDeformVert *dvert_r, const MDeformVert *dvert, int use_verif } /* be sure all flip_map values are valid */ -void defvert_sync_mapped (MDeformVert *dvert_r, const MDeformVert *dvert, int *flip_map, int use_verify) +void defvert_sync_mapped (MDeformVert *dvert_r, const MDeformVert *dvert, const int *flip_map, int use_verify) { if(dvert->totweight && dvert_r->totweight) { int i; @@ -171,7 +171,7 @@ void defvert_normalize (MDeformVert *dvert) } } -void defvert_flip (MDeformVert *dvert, int *flip_map) +void defvert_flip (MDeformVert *dvert, const int *flip_map) { MDeformWeight *dw; int i; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 01ef39487d6..3dfec66d2e5 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -339,7 +339,6 @@ static void multires_reallocate_mdisps(int totloop, MDisps *mdisps, int lvl) } } - static void column_vectors_to_mat3(float mat[][3], float v1[3], float v2[3], float v3[3]) { copy_v3_v3(mat[0], v1); @@ -444,7 +443,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire int lvl = multires_get_level(ob, mmd, 0); int levels = mmd->totlvl - lvl; MDisps *mdisps; - + multires_set_tot_mdisps(me, mmd->totlvl); CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); mdisps= CustomData_get_layer(&me->ldata, CD_MDISPS); @@ -458,7 +457,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire multires_set_tot_level(ob, mmd, lvl); } -DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple) +static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple) { MultiresModifierData mmd= {{NULL}}; @@ -833,7 +832,6 @@ static void multiresModifier_update(DerivedMesh *dm) ob = ccgdm->multires.ob; me = ccgdm->multires.ob->data; mmd = ccgdm->multires.mmd; - multires_set_tot_mdisps(me, mmd->totlvl); CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop); mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS); @@ -1770,7 +1768,7 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) DMGridData **gridData, **subGridData; Mesh *me= (Mesh*)ob->data; MPoly *mpoly= me->mpoly; - MLoop *mloop = me->mloop; + /* MLoop *mloop = me->mloop; */ /* UNUSED */ MDisps *mdisps; int *gridOffset; int i, /*numGrids,*/ gridSize, dGridSize, dSkip, totvert; @@ -1895,6 +1893,60 @@ void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) multires_apply_smat(scene, ob, mat); } +/* update multires data after topology changing */ +#if 0 // BMESH_TODO +void multires_topology_changed(Scene *scene, Object *ob) +{ + Mesh *me= (Mesh*)ob->data; + MDisps *mdisp= NULL, *cur= NULL; + int i, grid= 0, corners; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 1); + + if(mmd) + multires_set_tot_mdisps(me, mmd->totlvl); + + CustomData_external_read(&me->fdata, &me->id, CD_MASK_MDISPS, me->totface); + mdisp= CustomData_get_layer(&me->fdata, CD_MDISPS); + + if(!mdisp) return; + + cur= mdisp; + for(i = 0; i < me->totface; i++, cur++) { + if(mdisp->totdisp) { + corners= multires_mdisp_corners(mdisp); + grid= mdisp->totdisp / corners; + + break; + } + } + + for(i = 0; i < me->totface; i++, mdisp++) { + int nvert= me->mface[i].v4 ? 4 : 3; + + /* allocate memory for mdisp, the whole disp layer would be erased otherwise */ + if(!mdisp->totdisp || !mdisp->disps) { + if(grid) { + mdisp->totdisp= nvert*grid; + mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology"); + } + + continue; + } + + corners= multires_mdisp_corners(mdisp); + + if(corners!=nvert) { + mdisp->totdisp= (mdisp->totdisp/corners)*nvert; + + if(mdisp->disps) + MEM_freeN(mdisp->disps); + + mdisp->disps= MEM_callocN(mdisp->totdisp*sizeof(float)*3, "mdisp topology"); + } + } +} +#endif // BMESH_TODO + /* makes displacement along grid boundary symmetrical */ void multires_mdisp_smooth_bounds(MDisps *disps) { @@ -2114,6 +2166,7 @@ void mdisp_rot_crn_to_face(const int S, const int corners, const int face_side, } } +/* Find per-corner coordinate with given per-face UV coord */ int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y) { const float offset = face_side*0.5f - 0.5f; @@ -2139,6 +2192,61 @@ int mdisp_rot_face_to_crn(const int corners, const int face_side, const float u, *y = v - offset; } } else { + int grid_size = offset; + float w = (face_side - 1) - u - v; + float W1, W2; + + if (u >= v && u >= w) {S = 0; W1= w; W2= v;} + else if (v >= u && v >= w) {S = 1; W1 = u; W2 = w;} + else {S = 2; W1 = v; W2 = u;} + + W1 /= (face_side-1); + W2 /= (face_side-1); + + *x = (1-(2*W1)/(1-W2)) * grid_size; + *y = (1-(2*W2)/(1-W1)) * grid_size; + } + + return S; +} + +/* Find per-corner coordinate with given per-face UV coord + Practically as the previous funciton but it assumes a bit different coordinate system for triangles + which is optimized for MDISP layer interpolation: + + v + ^ + | /| + | / | + | / | + |/______|___> u + + */ +int mdisp_rot_face_to_quad_crn(const int corners, const int face_side, const float u, const float v, float *x, float *y) +{ + const float offset = face_side*0.5f - 0.5f; + int S = 0; + + if (corners == 4) { + if(u <= offset && v <= offset) S = 0; + else if(u > offset && v <= offset) S = 1; + else if(u > offset && v > offset) S = 2; + else if(u <= offset && v >= offset) S = 3; + + if(S == 0) { + *y = offset - u; + *x = offset - v; + } else if(S == 1) { + *x = u - offset; + *y = offset - v; + } else if(S == 2) { + *y = u - offset; + *x = v - offset; + } else if(S == 3) { + *x= offset - u; + *y = v - offset; + } + } else { float crn[3][4][2]; float p[2] = {u, v}; @@ -2265,7 +2373,7 @@ void mdisp_join_tris(MDisps *dst, MDisps *tri1, MDisps *tri2) face_v = st - 1 - face_v; } else src = tri1; - crn = mdisp_rot_face_to_crn(3, st, face_u, face_v, &crn_u, &crn_v); + crn = mdisp_rot_face_to_quad_crn(3, st, face_u, face_v, &crn_u, &crn_v); old_mdisps_bilinear((*out), &src->disps[crn*side*side], side, crn_u, crn_v); (*out)[0] = 0; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index ba2434bba23..3a8a2ae9c09 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -350,7 +350,7 @@ static bNodeType ntype_group; /* groups display their internal tree name as label */ static const char *group_label(bNode *node) { - return node->id->name+2; + return (node->id)? node->id->name+2: "Missing Datablock"; } void register_node_type_group(ListBase *lb) @@ -2072,11 +2072,12 @@ static int set_stack_indexes_group(bNode *node, int index) bNodeTree *ngroup= (bNodeTree*)node->id; bNodeSocket *sock; - if((ngroup->init & NTREE_TYPE_INIT)==0) + if(ngroup && (ngroup->init & NTREE_TYPE_INIT)==0) ntreeInitTypes(ngroup); node->stack_index = index; - index += ntree_begin_exec_tree(ngroup); + if(ngroup) + index += ntree_begin_exec_tree(ngroup); for (sock=node->inputs.first; sock; sock=sock->next) { if (sock->link && sock->link->fromsock) { @@ -2199,7 +2200,7 @@ static void composit_begin_exec(bNodeTree *ntree, bNodeStack *stack) if(node->type==CMP_NODE_CURVE_RGB) curvemapping_premultiply(node->storage, 0); } - if(node->type==NODE_GROUP) + if(node->type==NODE_GROUP && node->id) composit_begin_exec((bNodeTree *)node->id, stack + node->stack_index); } @@ -2225,7 +2226,7 @@ static void composit_end_exec(bNodeTree *ntree, bNodeStack *stack) if(node->type==CMP_NODE_CURVE_RGB) curvemapping_premultiply(node->storage, 1); - if(node->type==NODE_GROUP) + if(node->type==NODE_GROUP && node->id) composit_end_exec((bNodeTree *)node->id, stack + node->stack_index); node->need_exec= 0; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 84e54e0adaa..4b40897af18 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2400,24 +2400,42 @@ void object_set_dimensions(Object *ob, const float *value) void minmax_object(Object *ob, float *min, float *max) { BoundBox bb; - Mesh *me; - Curve *cu; float vec[3]; int a; + short change= FALSE; switch(ob->type) { - case OB_CURVE: case OB_FONT: case OB_SURF: - cu= ob->data; - - if(cu->bb==NULL) tex_space_curve(cu); - bb= *(cu->bb); - - for(a=0; a<8; a++) { - mul_m4_v3(ob->obmat, bb.vec[a]); - DO_MINMAX(bb.vec[a], min, max); + { + Curve *cu= ob->data; + + if(cu->bb==NULL) tex_space_curve(cu); + bb= *(cu->bb); + + for(a=0; a<8; a++) { + mul_m4_v3(ob->obmat, bb.vec[a]); + DO_MINMAX(bb.vec[a], min, max); + } + change= TRUE; + } + break; + case OB_LATTICE: + { + Lattice *lt= ob->data; + BPoint *bp= lt->def; + int u, v, w; + + for(w=0; w<lt->pntsw; w++) { + for(v=0; v<lt->pntsv; v++) { + for(u=0; u<lt->pntsu; u++, bp++) { + mul_v3_m4v3(vec, ob->obmat, bp->vec); + DO_MINMAX(vec, min, max); + } + } + } + change= TRUE; } break; case OB_ARMATURE: @@ -2429,25 +2447,27 @@ void minmax_object(Object *ob, float *min, float *max) mul_v3_m4v3(vec, ob->obmat, pchan->pose_tail); DO_MINMAX(vec, min, max); } - break; + change= TRUE; } - /* no break, get_mesh will give NULL and it passes on to default */ + break; case OB_MESH: - me= get_mesh(ob); - - if(me) { - bb = *mesh_get_bb(ob); - - for(a=0; a<8; a++) { - mul_m4_v3(ob->obmat, bb.vec[a]); - DO_MINMAX(bb.vec[a], min, max); + { + Mesh *me= get_mesh(ob); + + if(me) { + bb = *mesh_get_bb(ob); + + for(a=0; a<8; a++) { + mul_m4_v3(ob->obmat, bb.vec[a]); + DO_MINMAX(bb.vec[a], min, max); + } + change= TRUE; } } - if(min[0] < max[0] ) break; - - /* else here no break!!!, mesh can be zero sized */ - - default: + break; + } + + if(change == FALSE) { DO_MINMAX(ob->obmat[3], min, max); copy_v3_v3(vec, ob->obmat[3]); @@ -2457,7 +2477,6 @@ void minmax_object(Object *ob, float *min, float *max) copy_v3_v3(vec, ob->obmat[3]); sub_v3_v3(vec, ob->size); DO_MINMAX(vec, min, max); - break; } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d02661075fc..dc91f220033 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -4020,7 +4020,11 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, &pind, state); - if(!keyed && !cached) { + if(pind.dm) { + mul_m4_v3(sim->ob->obmat, state->co); + mul_mat3_m4_v3(sim->ob->obmat, state->vel); + } + else if(!keyed && !cached && !(psys->flag & PSYS_GLOBAL_HAIR)) { if((pa->flag & PARS_REKEY)==0) { psys_mat_hair_to_global(sim->ob, sim->psmd->dm, part->from, pa, hairmat); mul_m4_v3(hairmat, state->co); diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index d2f05a8ca53..c19a74deff6 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -3021,10 +3021,15 @@ void sequence_effect_speed_rebuild_map(Scene *scene, Sequence * seq, int force) /* if not already done, load / initialize data */ get_sequence_effect(seq); - if (!(force || seq->len != v->length || !v->frameMap)) { + if ( (force == FALSE) && + (seq->len == v->length) && + (v->frameMap != NULL) + ) { return; } - if (!seq->seq1) { /* make coverity happy and check for (CID 598) + if ( (seq->seq1 == NULL) || + (seq->len < 1) + ) { /* make coverity happy and check for (CID 598) input strip ... */ return; } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 009665f3a1f..b82ac69fc9e 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -587,8 +587,22 @@ void calc_sequence(Scene *scene, Sequence *seq) if (seq->seq1) { seq->start= seq->startdisp= MAX3(seq->seq1->startdisp, seq->seq2->startdisp, seq->seq3->startdisp); seq->enddisp= MIN3(seq->seq1->enddisp, seq->seq2->enddisp, seq->seq3->enddisp); + /* we cant help if strips don't overlap, it wont give useful results. + * but at least ensure 'len' is never negative which causes bad bugs elsewhere. */ + if(seq->enddisp < seq->startdisp) { + /* simple start/end swap */ + seq->start= seq->enddisp; + seq->enddisp = seq->startdisp; + seq->startdisp= seq->start; + seq->flag |= SEQ_INVALID_EFFECT; + } + else { + seq->flag &= ~SEQ_INVALID_EFFECT; + } + seq->len= seq->enddisp - seq->startdisp; - } else { + } + else { calc_sequence_disp(scene, seq); } diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 6912be63daa..bd21851534e 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -164,6 +164,9 @@ void barycentric_transform(float pt_tar[3], float const pt_src[3], void barycentric_weights_v2(const float v1[2], const float v2[2], const float v3[2], const float co[2], float w[3]); +void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]); +void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]); + /***************************** View & Projection *****************************/ void lookat_m4(float mat[4][4], float vx, float vy, diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 1f56694f85b..e93bc244bd3 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -60,6 +60,8 @@ MINLINE void swap_v4_v4(float a[4], float b[4]); /********************************* Arithmetic ********************************/ +MINLINE void add_v3_fl(float r[3], float f); +MINLINE void add_v4_fl(float r[4], float f); MINLINE void add_v2_v2(float r[2], const float a[2]); MINLINE void add_v2_v2v2(float r[2], const float a[2], const float b[2]); MINLINE void add_v3_v3(float r[3], const float a[3]); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index c81ab01e468..88816d78967 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -103,6 +103,12 @@ #define FTOCHAR(val) ((val)<=0.0f)? 0 : (((val)>(1.0f-0.5f/255.0f))? 255 : (char)((255.0f*(val))+0.5f)) #define FTOUSHORT(val) ((val >= 1.0f-0.5f/65535)? 65535: (val <= 0.0f)? 0: (unsigned short)(val*65535.0f + 0.5f)) +#define F3TOCHAR3(v2,v1) (v1)[0]=FTOCHAR((v2[0])); (v1)[1]=FTOCHAR((v2[1])); (v1)[2]=FTOCHAR((v2[2])) +#define F3TOCHAR4(v2,v1) { (v1)[0]=FTOCHAR((v2[0])); (v1)[1]=FTOCHAR((v2[1])); (v1)[2]=FTOCHAR((v2[2])); \ + (v1)[3]=FTOCHAR((v2[3])); (v1)[3] = 255; } +#define F4TOCHAR4(v2,v1) { (v1)[0]=FTOCHAR((v2[0])); (v1)[1]=FTOCHAR((v2[1])); (v1)[2]=FTOCHAR((v2[2])); \ + (v1)[3]=FTOCHAR((v2[3])); (v1)[3]=FTOCHAR((v2[3])); } + #define VECCOPY(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1); *(v1+2)= *(v2+2);} #define VECCOPY2D(v1,v2) {*(v1)= *(v2); *(v1+1)= *(v2+1);} diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index dffa7aa2ca3..6c3775f59f3 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -1809,6 +1809,80 @@ void interp_cubic_v3(float x[3], float v[3], const float x1[3], const float v1[3 v[2]= 3*a[2]*t2 + 2*b[2]*t + v1[2]; } +/* unfortunately internal calculations have to be done at double precision to achieve correct/stable results. */ + +#define IS_ZERO(x) ((x>(-DBL_EPSILON) && x<DBL_EPSILON) ? 1 : 0) + +/* Barycentric reverse */ +void resolve_tri_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2]) +{ + /* find UV such that + t= u*t0 + v*t1 + (1-u-v)*t2 + u*(t0-t2) + v*(t1-t2)= t-t2 */ + const double a= st0[0]-st2[0], b= st1[0]-st2[0]; + const double c= st0[1]-st2[1], d= st1[1]-st2[1]; + const double det= a*d - c*b; + + if(IS_ZERO(det)==0) { /* det should never be zero since the determinant is the signed ST area of the triangle. */ + const double x[]= {st[0]-st2[0], st[1]-st2[1]}; + + uv[0]= (float)((d*x[0] - b*x[1])/det); + uv[1]= (float)(((-c)*x[0] + a*x[1])/det); + } else zero_v2(uv); +} + +/* bilinear reverse */ +void resolve_quad_uv(float uv[2], const float st[2], const float st0[2], const float st1[2], const float st2[2], const float st3[2]) +{ + const double signed_area= (st0[0]*st1[1] - st0[1]*st1[0]) + (st1[0]*st2[1] - st1[1]*st2[0]) + + (st2[0]*st3[1] - st2[1]*st3[0]) + (st3[0]*st0[1] - st3[1]*st0[0]); + + /* X is 2D cross product (determinant) + A= (p0-p) X (p0-p3)*/ + const double a= (st0[0]-st[0])*(st0[1]-st3[1]) - (st0[1]-st[1])*(st0[0]-st3[0]); + + /* B= ( (p0-p) X (p1-p2) + (p1-p) X (p0-p3) ) / 2 */ + const double b= 0.5 * ( ((st0[0]-st[0])*(st1[1]-st2[1]) - (st0[1]-st[1])*(st1[0]-st2[0])) + + ((st1[0]-st[0])*(st0[1]-st3[1]) - (st1[1]-st[1])*(st0[0]-st3[0])) ); + + /* C = (p1-p) X (p1-p2) */ + const double fC= (st1[0]-st[0])*(st1[1]-st2[1]) - (st1[1]-st[1])*(st1[0]-st2[0]); + const double denom= a - 2*b + fC; + + // clear outputs + zero_v2(uv); + + if(IS_ZERO(denom)!=0) { + const double fDen= a-fC; + if(IS_ZERO(fDen)==0) + uv[0]= (float)(a / fDen); + } else { + const double desc_sq= b*b - a*fC; + const double desc= sqrt(desc_sq<0.0?0.0:desc_sq); + const double s= signed_area>0 ? (-1.0) : 1.0; + + uv[0]= (float)(( (a-b) + s * desc ) / denom); + } + + /* find UV such that + fST = (1-u)(1-v)*ST0 + u*(1-v)*ST1 + u*v*ST2 + (1-u)*v*ST3 */ + { + const double denom_s= (1-uv[0])*(st0[0]-st3[0]) + uv[0]*(st1[0]-st2[0]); + const double denom_t= (1-uv[0])*(st0[1]-st3[1]) + uv[0]*(st1[1]-st2[1]); + int i= 0; double denom= denom_s; + + if(fabs(denom_s)<fabs(denom_t)) { + i= 1; + denom=denom_t; + } + + if(IS_ZERO(denom)==0) + uv[1]= (float) (( (1-uv[0])*(st0[i]-st[i]) + uv[0]*(st1[i]-st[i]) ) / denom); + } +} + +#undef IS_ZERO + /***************************** View & Projection *****************************/ void orthographic_m4(float matrix[][4], const float left, const float right, const float bottom, const float top, const float nearClip, const float farClip) diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index dc3baf1698a..873b06f043b 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -102,6 +102,21 @@ MINLINE void swap_v4_v4(float a[4], float b[4]) /********************************* Arithmetic ********************************/ +MINLINE void add_v3_fl(float r[3], float f) +{ + r[0] += f; + r[1] += f; + r[2] += f; +} + +MINLINE void add_v4_fl(float r[4], float f) +{ + r[0] += f; + r[1] += f; + r[2] += f; + r[3] += f; +} + MINLINE void add_v2_v2(float *r, const float *a) { r[0] += a[0]; diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index e0a08d0b890..af87707fb90 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -153,7 +153,7 @@ void BLI_stringenc(char *string, const char *head, const char *tail, unsigned sh int BLI_split_name_num(char *left, int *nr, const char *name, const char delim) { int a; - + *nr= 0; a= strlen(name); memcpy(left, name, (a + 1) * sizeof(char)); @@ -216,13 +216,13 @@ int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, cons int number; int len= BLI_split_name_num(left, &number, name, delim); do { - int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, number); + int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number); if(newlen >= name_len) { len -= ((newlen + 1) - name_len); if(len < 0) len= number= 0; left[len]= '\0'; } - } while(number++, unique_check(arg, tempname)); + } while(unique_check(arg, tempname)); BLI_strncpy(name, tempname, name_len); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 614144028af..d0b0f3aa1e3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1725,7 +1725,6 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list) static void direct_link_fmodifiers(FileData *fd, ListBase *list) { FModifier *fcm; - int a; for (fcm= list->first; fcm; fcm= fcm->next) { /* relink general data */ @@ -1741,6 +1740,7 @@ static void direct_link_fmodifiers(FileData *fd, ListBase *list) data->coefficients= newdataadr(fd, data->coefficients); if(fd->flags & FD_FLAGS_SWITCH_ENDIAN) { + unsigned int a; for(a = 0; a < data->arraysize; a++) SWITCH_INT(data->coefficients[a]); } @@ -2095,7 +2095,7 @@ static void lib_nodetree_do_versions_group(bNodeTree *ntree) for (node=ntree->nodes.first; node; node=node->next) { if (node->type==NODE_GROUP) { bNodeTree *ngroup= (bNodeTree*)node->id; - if (ngroup->flag & NTREE_DO_VERSIONS) + if (ngroup && (ngroup->flag & NTREE_DO_VERSIONS)) lib_node_do_versions_group(node); } } @@ -3909,26 +3909,10 @@ static void lib_link_object(FileData *fd, Main *main) if(smd && smd->type == MOD_SMOKE_TYPE_DOMAIN && smd->domain) { - smd->domain->coll_group = newlibadr_us(fd, ob->id.lib, smd->domain->coll_group); - smd->domain->eff_group = newlibadr_us(fd, ob->id.lib, smd->domain->eff_group); - smd->domain->fluid_group = newlibadr_us(fd, ob->id.lib, smd->domain->fluid_group); - - smd->domain->effector_weights->group = newlibadr(fd, ob->id.lib, smd->domain->effector_weights->group); - smd->domain->flags |= MOD_SMOKE_FILE_LOAD; /* flag for refreshing the simulation after loading */ } } - { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); - - if(clmd) - { - clmd->sim_parms->effector_weights->group = newlibadr(fd, ob->id.lib, clmd->sim_parms->effector_weights->group); - clmd->coll_parms->group= newlibadr(fd, ob->id.lib, clmd->coll_parms->group); - } - } - /* texture field */ if(ob->pd) lib_link_partdeflect(fd, &ob->id, ob->pd); @@ -5724,11 +5708,10 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *a while(bhead && bhead->code==DATA) { void *data; #if 0 - /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */ + /* XXX DUMB DEBUGGING OPTION TO GIVE NAMES for guarded malloc errors */ short *sp= fd->filesdna->structs[bhead->SDNAnr]; - char *allocname = fd->filesdna->types[ sp[0] ]; char *tmp= malloc(100); - + allocname = fd->filesdna->types[ sp[0] ]; strcpy(tmp, allocname); data= read_struct(fd, bhead, tmp); #else @@ -6346,7 +6329,7 @@ static void area_add_header_region(ScrArea *sa, ListBase *lb) BLI_addtail(lb, ar); ar->regiontype= RGN_TYPE_HEADER; - if(sa->headertype==1) + if(sa->headertype==HEADERDOWN) ar->alignment= RGN_ALIGN_BOTTOM; else ar->alignment= RGN_ALIGN_TOP; @@ -12789,7 +12772,6 @@ static int object_in_any_scene(Main *mainvar, Object *ob) return 0; } -/* when *lib set, it also does objects that were in the appended group */ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const short idcode, const short is_link) { Object *ob; @@ -12824,8 +12806,14 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const /* when appending, make sure any indirectly loaded objects * get a base else they cant be accessed at all [#27437] */ if(ob->id.us==1 && is_link==FALSE && ob->id.lib==lib) { - if(object_in_any_scene(mainvar, ob)==0) { - do_it= 1; + + /* we may be appending from a scene where we already + * have a linked object which is not in any scene [#27616] */ + if((ob->id.flag & LIB_PRE_EXISTING)==0) { + + if(object_in_any_scene(mainvar, ob)==0) { + do_it= 1; + } } } } @@ -12846,7 +12834,6 @@ static void give_base_to_objects(Main *mainvar, Scene *sce, Library *lib, const } } -/* when *lib set, it also does objects that were in the appended group */ static void give_base_to_groups(Main *mainvar, Scene *scene) { Group *group; diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index de0d47ea85c..75a758476b7 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2522,6 +2522,41 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil return endwrite(wd); } +/* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */ +/* return: success(0), failure(1) */ +static int do_history(const char *name, ReportList *reports) +{ + char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE]; + int hisnr= U.versions; + + if(U.versions==0) return 0; + if(strlen(name)<2) { + BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short"); + return 1; + } + + while(hisnr > 1) { + BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1); + BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr); + + if(BLI_rename(tempname1, tempname2)) { + BKE_report(reports, RPT_ERROR, "Unable to make version backup"); + return 1; + } + hisnr--; + } + + /* is needed when hisnr==1 */ + BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr); + + if(BLI_rename(name, tempname1)) { + BKE_report(reports, RPT_ERROR, "Unable to make version backup"); + return 1; + } + + return 0; +} + /* return: success (1) */ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb) { @@ -2573,45 +2608,52 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb); close(file); - /* rename/compress */ - if(!err) { - if(write_flags & G_FILE_COMPRESS) { - /* compressed files have the same ending as regular files... only from 2.4!!! */ - char gzname[FILE_MAXDIR+FILE_MAXFILE+4]; - int ret; + if (err) { + BKE_report(reports, RPT_ERROR, strerror(errno)); + remove(tempname); - /* first write compressed to separate @.gz */ - BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath); - ret = BLI_gzip(tempname, gzname); - - if(0==ret) { - /* now rename to real file name, and delete temp @ file too */ - if(BLI_rename(gzname, filepath) != 0) { - BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @."); - return 0; - } + return 0; + } - BLI_delete(tempname, 0, 0); - } - else if(-1==ret) { - BKE_report(reports, RPT_ERROR, "Failed opening .gz file."); - return 0; - } - else if(-2==ret) { - BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression."); + /* file save to temporary file was successful */ + /* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */ + if (write_flags & G_FILE_HISTORY) { + int err_hist = do_history(filepath, reports); + if (err_hist) { + BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @"); + return 0; + } + } + + if(write_flags & G_FILE_COMPRESS) { + /* compressed files have the same ending as regular files... only from 2.4!!! */ + char gzname[FILE_MAXDIR+FILE_MAXFILE+4]; + int ret; + + /* first write compressed to separate @.gz */ + BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath); + ret = BLI_gzip(tempname, gzname); + + if(0==ret) { + /* now rename to real file name, and delete temp @ file too */ + if(BLI_rename(gzname, filepath) != 0) { + BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @."); return 0; } + + BLI_delete(tempname, 0, 0); } - else if(BLI_rename(tempname, filepath) != 0) { - BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @"); + else if(-1==ret) { + BKE_report(reports, RPT_ERROR, "Failed opening .gz file."); + return 0; + } + else if(-2==ret) { + BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression."); return 0; } - } - else { - BKE_report(reports, RPT_ERROR, strerror(errno)); - remove(tempname); - + else if(BLI_rename(tempname, filepath) != 0) { + BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @"); return 0; } diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index ff714533199..0bbf714137e 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -273,7 +273,7 @@ void EffectsExporter::operator()(Material *ma, Object *ob) std::string uvname = strlen(t->uvname) ? t->uvname : active_uv; // color - if (t->mapto & MAP_COL) { + if (t->mapto & MAP_COL | MAP_COLSPEC) { ep.setDiffuse(createTexture(ima, uvname, sampler)); } // ambient diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index f755df79986..9145cc2b79d 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1881,6 +1881,7 @@ static void ANIM_OT_channels_select_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= animchannels_borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= animedit_poll_channels_nla_tweakmode_off; diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index c802ba621f1..c6e55427034 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -717,7 +717,7 @@ static void ed_marker_move_apply(wmOperator *op) } /* only for modal */ -static void ed_marker_move_cancel(bContext *C, wmOperator *op) +static int ed_marker_move_cancel(bContext *C, wmOperator *op) { RNA_int_set(op->ptr, "frames", 0); ed_marker_move_apply(op); @@ -725,6 +725,8 @@ static void ed_marker_move_cancel(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCENE|ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION|ND_MARKERS, NULL); + + return OPERATOR_CANCELLED; } @@ -886,6 +888,7 @@ static void MARKER_OT_move(wmOperatorType *ot) ot->invoke= ed_marker_move_invoke_wrapper; ot->modal= ed_marker_move_modal; ot->poll= ed_markers_poll_selected_markers; + ot->cancel= ed_marker_move_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -980,6 +983,7 @@ static void MARKER_OT_duplicate(wmOperatorType *ot) ot->invoke= ed_marker_duplicate_invoke_wrapper; ot->modal= ed_marker_move_modal; ot->poll= ed_markers_poll_selected_markers; + ot->cancel= ed_marker_move_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -1185,6 +1189,7 @@ static void MARKER_OT_select_border(wmOperatorType *ot) ot->exec= ed_marker_border_select_exec; ot->invoke= ed_marker_select_border_invoke_wrapper; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ed_markers_poll_markers_exist; diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 93d99c59a0e..7a94a21d41e 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -199,8 +199,8 @@ static int previewrange_define_exec(bContext *C, wmOperator *op) * - must clamp within allowable limits * - end must not be before start (though this won't occur most of the time) */ - if (sfra < 1) sfra = 1.0f; - if (efra < 1) efra = 1.0f; + FRAMENUMBER_MIN_CLAMP(sfra); + FRAMENUMBER_MIN_CLAMP(efra); if (efra < sfra) efra= sfra; scene->r.flag |= SCER_PRV_RANGE; @@ -224,6 +224,7 @@ static void ANIM_OT_previewrange_set(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= previewrange_define_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_animview_active; diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 8761297b979..ae86905a91d 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -29,41 +29,48 @@ set(INC_SYS set(SRC Bfont.c - add.png.c bfont.ttf.c - blenderbuttons.c - blob.png.c - blur.png.c bmonofont.ttf.c - clay.png.c - clone.png.c - crease.png.c - darken.png.c - draw.png.c - fill.png.c - flatten.png.c - grab.png.c - inflate.png.c - layer.png.c - lighten.png.c - mix.png.c - multiply.png.c - nudge.png.c - pinch.png.c - preview.blend.c - prvicons.c - scrape.png.c - smear.png.c - smooth.png.c - snake_hook.png.c - soften.png.c - splash.png.c startup.blend.c - subtract.png.c - texdraw.png.c - thumb.png.c - twist.png.c - vertexdraw.png.c + preview.blend.c ) +if(NOT WITH_HEADLESS) + list(APPEND SRC + splash.png.c + blenderbuttons.c + + # brushes + add.png.c + blob.png.c + blur.png.c + clay.png.c + clone.png.c + crease.png.c + darken.png.c + draw.png.c + fill.png.c + flatten.png.c + grab.png.c + inflate.png.c + layer.png.c + lighten.png.c + mix.png.c + multiply.png.c + nudge.png.c + pinch.png.c + prvicons.c + scrape.png.c + smear.png.c + smooth.png.c + snake_hook.png.c + soften.png.c + subtract.png.c + texdraw.png.c + thumb.png.c + twist.png.c + vertexdraw.png.c + ) +endif() + blender_add_lib(bf_editor_datafiles "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/datafiles/startup.blend.c b/source/blender/editors/datafiles/startup.blend.c index 6900f458a2b..1121eb5a299 100644 --- a/source/blender/editors/datafiles/startup.blend.c +++ b/source/blender/editors/datafiles/startup.blend.c @@ -8854,8 +8854,8 @@ char datatoc_startup_blend[]= { 0, 0, 0, 0, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,114,114,114,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,255, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,165,165,165,127, 0, 0, 0,255, 0, 0, 0,255,255,255,255,255,160,160,160,100,127,112,112,100, 0, 0, 0, 0, 64, 64, 64,255, 0, 0, 0,255, -241, 88, 0,255, 0, 0, 0, 40,255,140, 25,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, - 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,255, 32, 32,255, 75, 75, 75,255,204, 0,153,255, 0, 0, 0, 18,255,133, 0, 60, +241, 88, 0,255, 0, 0, 0, 40,255,170, 64,255, 8, 48, 8,255, 85,187, 85,255,255,255,255,255, 0, 0, 0,255,255,133, 0,255, + 0, 0, 0,255,255,160, 0,255,219, 37, 18,255,32, 255,255,255, 75, 75, 75,255,204, 0,153,255, 0, 0, 0, 18,255,133, 0, 60, 255,133, 0,255, 32, 0, 0,255, 0, 32, 0,255, 0, 0,128,255, 0, 0, 0, 0, 34,221,221,255, 35, 97,221,255,200,200,200,255, 80,200,255, 80, 0, 0, 0, 0, 0, 0, 0, 0, 96,192, 64,255,144,144, 0,255,128, 48, 96,255,219, 37, 18,255,240,255, 64,255, 240,144,160,255,255,255,255,255, 0, 0, 0,255,144,144, 0,255, 64,144, 48,255,128, 48, 96,255, 0, 0, 0,255,240,255, 64,255, diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index cab6a23b19b..dc30c7b5355 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -251,10 +251,10 @@ struct bDeformGroup *ED_vgroup_add(struct Object *ob); struct bDeformGroup *ED_vgroup_add_name(struct Object *ob, const char *name); void ED_vgroup_delete(struct Object *ob, struct bDeformGroup *defgroup); void ED_vgroup_select_by_name(struct Object *ob, const char *name); -void ED_vgroup_data_create(struct ID *id); +int ED_vgroup_data_create(struct ID *id); int ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot); int ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from); -void ED_vgroup_mirror(struct Object *ob, int mirror_weights, int flip_vgroups); +void ED_vgroup_mirror(struct Object *ob, const short mirror_weights, const short flip_vgroups); int ED_vgroup_object_is_edit_mode(struct Object *ob); diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index 23997e06aef..f2973d0d070 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -71,8 +71,9 @@ void PE_undo_push(struct Scene *scene, const char *str); void PE_undo_step(struct Scene *scene, int step); void PE_undo(struct Scene *scene); void PE_redo(struct Scene *scene); -void PE_undo_menu(struct Scene *scene, struct Object *ob); int PE_undo_valid(struct Scene *scene); +void PE_undo_number(struct Scene *scene, int nr); +char *PE_undo_get_name(struct Scene *scene, int nr, int *active); #endif /* ED_PARTICLE_H */ diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 93ce82fa483..f2ef4e16852 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -90,6 +90,7 @@ void ED_area_headerprint(ScrArea *sa, const char *str); void ED_area_newspace(struct bContext *C, ScrArea *sa, int type); void ED_area_prevspace(struct bContext *C, ScrArea *sa); void ED_area_swapspace(struct bContext *C, ScrArea *sa1, ScrArea *sa2); +int ED_area_headersize(void); /* screens */ void ED_screens_initialize(struct wmWindowManager *wm); @@ -106,7 +107,7 @@ void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event); void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen); void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable); void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh); -int ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type); +ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type); void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa); void ED_screen_full_restore(struct bContext *C, ScrArea *sa); struct ScrArea *ED_screen_full_toggle(struct bContext *C, struct wmWindow *win, struct ScrArea *sa); diff --git a/source/blender/editors/include/ED_types.h b/source/blender/editors/include/ED_types.h index 0218b8d9c2d..c1c31372011 100644 --- a/source/blender/editors/include/ED_types.h +++ b/source/blender/editors/include/ED_types.h @@ -40,10 +40,6 @@ #define SELECT 1 #define ACTIVE 2 -/* buttons */ -#define XIC 20 -#define YIC 20 - /* proposal = put scene pointers on function calls? */ // #define BASACT (scene->basact) // #define OBACT (BASACT? BASACT->object: NULL) diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index 7261d348928..5d433879882 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -59,6 +59,7 @@ void ED_undo_redo (struct bContext *C); void ED_OT_undo (struct wmOperatorType *ot); void ED_OT_undo_push (struct wmOperatorType *ot); void ED_OT_redo (struct wmOperatorType *ot); +void ED_OT_undo_history (struct wmOperatorType *ot); int ED_undo_operator_repeat(struct bContext *C, struct wmOperator *op); /* convenience since UI callbacks use this mostly*/ @@ -76,11 +77,7 @@ void undo_editmode_push(struct bContext *C, const char *name, int (*validate_undo)(void *, void *)); -void *undo_editmode_get_prev (struct Object *ob); -struct uiBlock *editmode_undohistorymenu(struct bContext *C, struct ARegion *ar, void *arg_unused); -void undo_editmode_menu (struct bContext *C); void undo_editmode_clear (void); -void undo_editmode_step (struct bContext *C, int step); /* crazyspace.c */ float *crazyspace_get_mapped_editverts(struct Scene *scene, struct Object *obedit); diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index 236502e5005..06d1131cf1d 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -269,6 +269,7 @@ struct ARegion *ED_view3d_context_region_unlock(struct bContext *C); int ED_operator_rv3d_unlock_poll(struct bContext *C); void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d); +void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d); int ED_view3d_scene_layer_set(int lay, const int *values, int *active); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index d6988aa9618..1a26079800c 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -35,6 +35,7 @@ #define UI_INTERFACE_H #include "RNA_types.h" +#include "DNA_userdef_types.h" /* Struct Declarations */ @@ -100,8 +101,8 @@ typedef struct uiLayout uiLayout; #define UI_BLOCK_RET_1 4 /* XXX 2.5 not implemented */ #define UI_BLOCK_NUMSELECT 8 /*#define UI_BLOCK_ENTER_OK 16*/ /*UNUSED*/ -/*#define UI_BLOCK_NOSHADOW 32*/ /*UNUSED*/ -/*#define UI_BLOCK_UNUSED 64*/ /*UNUSED*/ +#define UI_BLOCK_CLIPBOTTOM 32 +#define UI_BLOCK_CLIPTOP 64 #define UI_BLOCK_MOVEMOUSE_QUIT 128 #define UI_BLOCK_KEEP_OPEN 256 #define UI_BLOCK_POPUP 512 @@ -622,8 +623,8 @@ void UI_exit(void); #define UI_LAYOUT_MENU 2 #define UI_LAYOUT_TOOLBAR 3 -#define UI_UNIT_X 20 -#define UI_UNIT_Y 20 +#define UI_UNIT_X U.widget_unit +#define UI_UNIT_Y U.widget_unit #define UI_LAYOUT_ALIGN_EXPAND 0 #define UI_LAYOUT_ALIGN_LEFT 1 diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 50b14cb832a..b6837a4b3c9 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -49,6 +49,10 @@ typedef struct IconFile { #define ICON_DEFAULT_HEIGHT 16 #define ICON_DEFAULT_WIDTH 16 + +#define ICON_DEFAULT_HEIGHT_SCALE (UI_UNIT_Y * 0.8f) +#define ICON_DEFAULT_WIDTH_SCALE (UI_UNIT_X * 0.8f) + #define PREVIEW_DEFAULT_HEIGHT 96 /* diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 9902cac8857..6dd7af70e33 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -63,6 +63,10 @@ if(WITH_INTERNATIONAL) add_definitions(-DINTERNATIONAL) endif() +if(WITH_HEADLESS) + add_definitions(-DWITH_HEADLESS) +endif() + if(WITH_PYTHON) add_definitions(-DWITH_PYTHON) endif() diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 68d669b37cb..99b4b68b42d 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -74,6 +74,9 @@ #define MENU_ITEM_HEIGHT 20 #define MENU_SEP_HEIGHT 6 +#define PRECISION_FLOAT_MAX 7 +#define PRECISION_FLOAT_MAX_POW 10000000 /* pow(10, PRECISION_FLOAT_MAX) */ + /* * a full doc with API notes can be found in bf-blender/trunk/blender/doc/guides/interface_API.txt * @@ -449,6 +452,57 @@ void uiCenteredBoundsBlock(uiBlock *block, int addval) /* link line drawing is not part of buttons or theme.. so we stick with it here */ +static int ui_but_float_precision(uiBut *but, double value) +{ + int prec; + + /* first check if prec is 0 and fallback to a simple default */ + if((prec= (int)but->a2) == 0) { + prec= (but->hardmax < 10.001f) ? 3 : 2; + } + + /* check on the number of decimal places neede to display + * the number, this is so 0.00001 is not displayed as 0.00, + * _but_, this is only for small values si 10.0001 will not get + * the same treatment */ + if(value != 0.0 && (value= ABS(value)) < 0.1) { + int value_i= (int)((value * PRECISION_FLOAT_MAX_POW) + 0.5); + if(value_i != 0) { + const int prec_span= 3; /* show: 0.01001, 5 would allow 0.0100001 for eg. */ + int test_prec; + int prec_min= -1; + int dec_flag= 0; + int i= PRECISION_FLOAT_MAX; + while(i && value_i) { + if(value_i % 10) { + dec_flag |= 1<<i; + prec_min= i; + } + value_i /= 10; + i--; + } + + /* even though its a small value, if the second last digit is not 0, use it */ + test_prec = prec_min; + + dec_flag= (dec_flag >> (prec_min + 1)) & ((1 << prec_span) - 1); + + while(dec_flag) { + test_prec++; + dec_flag = dec_flag >> 1; + } + + if(test_prec > prec) { + prec= test_prec; + } + } + } + + CLAMP(prec, 1, PRECISION_FLOAT_MAX); + + return prec; +} + static void ui_draw_linkline(uiLinkLine *line) { rcti rect; @@ -892,13 +946,14 @@ void uiDrawBlock(const bContext *C, uiBlock *block) /* widgets */ for(but= block->buttons.first; but; but= but->next) { - ui_but_to_pixelrect(&rect, ar, block, but); + if(!(but->flag & (UI_HIDDEN|UI_SCROLLED))) { + ui_but_to_pixelrect(&rect, ar, block, but); - if(!(but->flag & UI_HIDDEN) && /* XXX: figure out why invalid coordinates happen when closing render window */ /* and material preview is redrawn in main window (temp fix for bug #23848) */ - rect.xmin < rect.xmax && rect.ymin < rect.ymax) - ui_draw_but(C, ar, &style, but, &rect); + if(rect.xmin < rect.xmax && rect.ymin < rect.ymax) + ui_draw_but(C, ar, &style, but, &rect); + } } /* restore matrix */ @@ -1444,8 +1499,8 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va if(scene->unit.scale_length<0.0001f) scene->unit.scale_length= 1.0f; // XXX do_versions /* Sanity checks */ - if(precision>7) precision= 7; - else if(precision==0) precision= 2; + if(precision > PRECISION_FLOAT_MAX) precision= PRECISION_FLOAT_MAX; + else if(precision==0) precision= 2; bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precision, scene->unit.system, unit_type>>16, do_split, pad); } @@ -1529,10 +1584,7 @@ void ui_get_but_string(uiBut *but, char *str, int maxlen) ui_get_but_string_unit(but, str, maxlen, value, 0); } else { - int prec= (int)but->a2; - if(prec==0) prec= 3; - else CLAMP(prec, 1, 7); - + const int prec= ui_but_float_precision(but, value); BLI_snprintf(str, maxlen, "%.*f", prec, value); } } @@ -1668,7 +1720,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) return 0; } -void ui_set_but_default(bContext *C, uiBut *but, short all) +void ui_set_but_default(bContext *C, short all) { PointerRNA ptr; @@ -2008,10 +2060,7 @@ void ui_check_but(uiBut *but) BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, new_str); } else { - int prec= (int)but->a2; - if(prec==0) prec= (but->hardmax < 10.001f) ? 3 : 2; - else CLAMP(prec, 1, 7); - + const int prec= ui_but_float_precision(but, value); BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value); } } @@ -2029,11 +2078,9 @@ void ui_check_but(uiBut *but) case LABEL: if(ui_is_but_float(but)) { - int prec= (int)but->a2; + int prec; value= ui_get_but_val(but); - if(prec==0) prec= 3; - else CLAMP(prec, 1, 7); - + prec= ui_but_float_precision(but, value); BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%.*f", but->str, prec, value); } else { @@ -2481,28 +2528,8 @@ static uiBut *ui_def_but_rna(uiBlock *block, int type, int retval, const char *s icon= RNA_property_ui_icon(prop); } } - - if(!tip) { - if(type == ROW && proptype == PROP_ENUM) { - EnumPropertyItem *item; - int i, totitem, free; - - RNA_property_enum_items(block->evil_C, ptr, prop, &item, &totitem, &free); - - for(i=0; i<totitem; i++) { - if(item[i].identifier[0] && item[i].value == (int)max) { - if(item[i].description[0]) - tip= item[i].description; - break; - } - } - - if(free) - MEM_freeN(item); - } - } - if(!tip) + if(!tip && proptype != PROP_ENUM) tip= RNA_property_ui_description(prop); if(min == max || a1 == -1 || a2 == -1) { diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index f9c97c36bdd..c7f11116834 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -471,6 +471,9 @@ void uiEmboss(float x1, float y1, float x2, float y2, int sel) void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *UNUSED(but), uiWidgetColors *UNUSED(wcol), rcti *rect) { +#ifdef WITH_HEADLESS + (void)rect; +#else extern char datatoc_splash_png[]; extern int datatoc_splash_png_size; ImBuf *ibuf; @@ -507,6 +510,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *UNUSED(but), uiWidgetColors * */ IMB_freeImBuf(ibuf); +#endif } #if 0 @@ -1116,7 +1120,7 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) ColorBand *coba; CBData *cbd; float x1, y1, sizex, sizey; - float dx, v3[2], v1[2], v2[2], v1a[2], v2a[2]; + float v3[2], v1[2], v2[2], v1a[2], v2a[2]; int a; float pos, colf[4]= {0,0,0,0}; /* initialize incase the colorband isnt valid */ @@ -1127,18 +1131,17 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) y1= rect->ymin; sizex= rect->xmax-x1; sizey= rect->ymax-y1; - + /* first background, to show tranparency */ - dx= sizex/12.0f; - v1[0]= x1; - for(a=0; a<12; a++) { - if(a & 1) glColor3f(0.3, 0.3, 0.3); else glColor3f(0.8, 0.8, 0.8); - glRectf(v1[0], y1, v1[0]+dx, y1+0.5f*sizey); - if(a & 1) glColor3f(0.8, 0.8, 0.8); else glColor3f(0.3, 0.3, 0.3); - glRectf(v1[0], y1+0.5f*sizey, v1[0]+dx, y1+sizey); - v1[0]+= dx; - } - + + glColor4ub(UI_TRANSP_DARK, UI_TRANSP_DARK, UI_TRANSP_DARK, 255); + glRectf(x1, y1, x1+sizex, y1+sizey); + glEnable(GL_POLYGON_STIPPLE); + glColor4ub(UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, 255); + glPolygonStipple(checker_stipple_sml); + glRectf(x1, y1, x1+sizex, y1+sizey); + glDisable(GL_POLYGON_STIPPLE); + glShadeModel(GL_FLAT); glEnable(GL_BLEND); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 55ae6af750f..99a31e039c8 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -81,6 +81,7 @@ static void ui_add_link(bContext *C, uiBut *from, uiBut *to); #define BUTTON_TOOLTIP_DELAY 0.500 #define BUTTON_FLASH_DELAY 0.020 +#define MENU_SCROLL_INTERVAL 0.1 #define BUTTON_AUTO_OPEN_THRESH 0.3 #define BUTTON_MOUSE_TOWARDS_THRESH 1.0 @@ -4445,7 +4446,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, wmEvent *event) else if(ELEM(event->type, DELKEY, PADPERIOD) && event->val == KM_PRESS) { /* ctrl+del - reset active button; del - reset a whole array*/ if (!(ELEM3(but->type, HSVCIRCLE, HSVCUBE, HISTOGRAM))) - ui_set_but_default(C, but, !event->ctrl); + ui_set_but_default(C, !event->ctrl); } /* handle menu */ else if(event->type == RIGHTMOUSE && event->val == KM_PRESS) { @@ -4743,6 +4744,8 @@ static uiBut *ui_but_find_mouse_over(ARegion *ar, int x, int y) continue; if(but->flag & UI_HIDDEN) continue; + if(but->flag & UI_SCROLLED) + continue; if(ui_but_contains_pt(but, mx, my)) butover= but; } @@ -5572,6 +5575,76 @@ static int ui_mouse_motion_towards_check(uiBlock *block, uiPopupBlockHandle *men return menu->dotowards; } +static char ui_menu_scroll_test(uiBlock *block, int my) +{ + if(block->flag & (UI_BLOCK_CLIPTOP|UI_BLOCK_CLIPBOTTOM)) { + if(block->flag & UI_BLOCK_CLIPTOP) + if(my > block->maxy-14) + return 't'; + if(block->flag & UI_BLOCK_CLIPBOTTOM) + if(my < block->miny+14) + return 'b'; + } + return 0; +} + +static int ui_menu_scroll(ARegion *ar, uiBlock *block, int my) +{ + char test= ui_menu_scroll_test(block, my); + + if(test) { + uiBut *b1= block->buttons.first; + uiBut *b2= block->buttons.last; + uiBut *bnext; + uiBut *bprev; + int dy= 0; + + /* get first and last visible buttons */ + while(b1 && ui_but_next(b1) && (b1->flag & UI_SCROLLED)) + b1= ui_but_next(b1); + while(b2 && ui_but_prev(b2) && (b2->flag & UI_SCROLLED)) + b2= ui_but_prev(b2); + /* skips separators */ + bnext= ui_but_next(b1); + bprev= ui_but_prev(b2); + + if(bnext==NULL || bprev==NULL) + return 0; + + if(test=='t') { + /* bottom button is first button */ + if(b1->y1 < b2->y1) + dy= bnext->y1 - b1->y1; + /* bottom button is last button */ + else + dy= bprev->y1 - b2->y1; + } + else if(test=='b') { + /* bottom button is first button */ + if(b1->y1 < b2->y1) + dy= b1->y1 - bnext->y1; + /* bottom button is last button */ + else + dy= b2->y1 - bprev->y1; + } + if(dy) { + + for(b1= block->buttons.first; b1; b1= b1->next) { + b1->y1 -= dy; + b1->y2 -= dy; + } + /* set flags again */ + ui_popup_block_scrolltest(block); + + ED_region_tag_redraw(ar); + + return 1; + } + } + + return 0; +} + static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle *menu, int UNUSED(topmenu)) { ARegion *ar; @@ -5603,11 +5676,22 @@ static int ui_handle_menu_event(bContext *C, wmEvent *event, uiPopupBlockHandle * and don't handle events */ ui_mouse_motion_towards_init(menu, mx, my, 1); } - else if(event->type != TIMER) { + else if(event->type == TIMER) { + if(event->customdata == menu->scrolltimer) + ui_menu_scroll(ar, block, my); + } + else { /* for ui_mouse_motion_towards_block */ - if(event->type == MOUSEMOVE) + if(event->type == MOUSEMOVE) { ui_mouse_motion_towards_init(menu, mx, my, 0); - + + /* add menu scroll timer, if needed */ + if(ui_menu_scroll_test(block, my)) + if(menu->scrolltimer==NULL) + menu->scrolltimer= + WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, MENU_SCROLL_INTERVAL); + } + /* first block own event func */ if(block->block_event_func && block->block_event_func(C, block, event)); /* events not for active search menu button */ diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 037cc22f879..3bf2a9ddd02 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -461,6 +461,7 @@ static void vicon_move_down_draw(int x, int y, int w, int h, float UNUSED(alpha) glDisable(GL_LINE_SMOOTH); } +#ifndef WITH_HEADLESS static void init_brush_icons(void) { @@ -588,7 +589,7 @@ static void init_internal_icons(void) IMB_freeImBuf(bbuf); } - +#endif // WITH_HEADLESS static void init_iconfile_list(struct ListBase *list) { @@ -704,6 +705,7 @@ ListBase *UI_iconfile_list(void) void UI_icons_free(void) { +#ifndef WITH_HEADLESS if(icongltex.id) { glDeleteTextures(1, &icongltex.id); icongltex.id= 0; @@ -711,6 +713,7 @@ void UI_icons_free(void) free_iconfile_list(&iconfilelist); BKE_icons_free(); +#endif } void UI_icons_free_drawinfo(void *drawinfo) @@ -792,10 +795,14 @@ int UI_icon_get_height(int icon_id) void UI_icons_init(int first_dyn_id) { +#ifdef WITH_HEADLESS + (void)first_dyn_id; +#else init_iconfile_list(&iconfilelist); BKE_icons_init(first_dyn_id); init_internal_icons(); init_brush_icons(); +#endif } /* Render size for preview images and icons @@ -945,6 +952,7 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al Icon *icon = NULL; DrawInfo *di = NULL; IconImage *iimg; + float fdraw_size= UI_DPI_FAC*draw_size; int w, h; icon = BKE_icon_get(icon_id); @@ -965,8 +973,8 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al } /* scale width and height according to aspect */ - w = (int)(draw_size/aspect + 0.5f); - h = (int)(draw_size/aspect + 0.5f); + w = (int)(fdraw_size/aspect + 0.5f); + h = (int)(fdraw_size/aspect + 0.5f); if(di->type == ICON_TYPE_VECTOR) { /* vector icons use the uiBlock transformation, they are not drawn diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6cca689d115..8475090b468 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -45,6 +45,7 @@ struct uiHandleButtonData; struct wmEvent; struct wmOperatorType; struct wmWindow; +struct wmTimer; struct uiStyle; struct uiWidgetColors; struct uiLayout; @@ -107,8 +108,8 @@ typedef enum { #define UI_PANEL_MINY 70 /* uiBut->flag */ -#define UI_SELECT 1 /* use when the button is pressed */ -/*#define UI_MOUSE_OVER 2*/ /*UNUSED, free flag*/ +#define UI_SELECT 1 /* use when the button is pressed */ +#define UI_SCROLLED 2 /* temp hidden, scrolled away */ #define UI_ACTIVE 4 #define UI_HAS_ICON 8 #define UI_TEXTINPUT 16 @@ -116,8 +117,8 @@ typedef enum { /* warn: rest of uiBut->flag in UI_interface.h */ /* internal panel drawing defines */ -#define PNL_GRID 4 -#define PNL_HEADER 20 +#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */ +#define PNL_HEADER UI_UNIT_Y /* 20 default */ /* panel->flag */ #define PNL_SELECT 1 @@ -369,7 +370,7 @@ extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, int maxlen); extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str); extern int ui_get_but_string_max_length(uiBut *but); -extern void ui_set_but_default(struct bContext *C, uiBut *but, short all); +extern void ui_set_but_default(struct bContext *C, short all); extern void ui_set_but_soft_range(uiBut *but, double value); @@ -395,6 +396,8 @@ struct uiPopupBlockHandle { void (*popup_func)(struct bContext *C, void *arg, int event); void (*cancel_func)(void *arg); void *popup_arg; + + struct wmTimer *scrolltimer; /* for operator popups */ struct wmOperatorType *optype; @@ -416,9 +419,11 @@ void ui_block_func_ICONTEXTROW(struct bContext *C, uiLayout *layout, void *arg_b struct ARegion *ui_tooltip_create(struct bContext *C, struct ARegion *butregion, uiBut *but); void ui_tooltip_free(struct bContext *C, struct ARegion *ar); -uiBut *ui_popup_menu_memory(uiBlock *block, uiBut *but); +uiBut *ui_popup_menu_memory(struct uiBlock *block, struct uiBut *but); + +float *ui_block_hsv_get(struct uiBlock *block); +void ui_popup_block_scrolltest(struct uiBlock *block); -float *ui_block_hsv_get(uiBlock *block); /* searchbox for string button */ ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but); @@ -481,6 +486,11 @@ void ui_widget_color_init(struct ThemeUI *tui); void ui_draw_menu_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); void ui_draw_preview_item(struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); +extern unsigned char checker_stipple_sml[]; +/* used for transp checkers */ +#define UI_TRANSP_DARK 100 +#define UI_TRANSP_LIGHT 160 + /* interface_style.c */ void uiStyleInit(void); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index b68634acd1e..55c1488291b 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -651,6 +651,9 @@ PointerRNA uiItemFullO(uiLayout *layout, const char *opname, const char *name, i if (flag & UI_ITEM_R_NO_BG) uiBlockSetEmboss(block, UI_EMBOSS); + if(layout->redalert) + uiButSetFlag(but, UI_BUT_REDALERT); + /* assign properties */ if(properties || (flag & UI_ITEM_O_RETURN_PROPS)) { PointerRNA *opptr= uiButGetOperatorPtrRNA(but); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 6677f2b1bae..9ed3cabb4cb 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -334,10 +334,13 @@ static void uiPanelPop(uiBlock *UNUSED(block)) void UI_DrawTriIcon(float x, float y, char dir) { if(dir=='h') { - ui_draw_anti_tria( x-3,y-5, x-3,y+5, x+7,y ); + ui_draw_anti_tria( x-3, y-5, x-3, y+5, x+7,y ); } - else { - ui_draw_anti_tria( x-5,y+3, x+5,y+3, x,y-7); + else if(dir=='t') { + ui_draw_anti_tria( x-5, y-7, x+5, y-7, x, y+3); + } + else { /* 'v' = vertical, down */ + ui_draw_anti_tria( x-5, y+3, x+5, y+3, x, y-7); } } @@ -381,7 +384,7 @@ static void ui_draw_x_icon(float x, float y) } -#define PNL_ICON 20 +#define PNL_ICON UI_UNIT_X /* could be UI_UNIT_Y too */ static void ui_draw_panel_scalewidget(rcti *rect) { diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 624f06db3c1..623651083d2 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -67,7 +67,6 @@ #include "interface_intern.h" -#define MENU_BUTTON_HEIGHT 20 #define MENU_SEPR_HEIGHT 6 #define B_NOP -1 #define MENU_SHADOW_SIDE 8 @@ -370,6 +369,27 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) data->color[data->totline]= 0xFFFFFF; data->totline++; } + + if(but->type == ROW) { + EnumPropertyItem *item; + int i, totitem, free; + + RNA_property_enum_items(C, &but->rnapoin, but->rnaprop, &item, &totitem, &free); + + for(i=0; i<totitem; i++) { + if(item[i].identifier[0] && item[i].value == (int)but->hardmax) { + if(item[i].description[0]) { + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), "%s: %s", item[i].name, item[i].description); + data->color[data->totline]= 0xFFFFFF; + data->totline++; + } + break; + } + } + + if(free) + MEM_freeN(item); + } } if(but->tip && strlen(but->tip)) { @@ -654,7 +674,7 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon int uiSearchBoxhHeight(void) { - return SEARCH_ITEMS*MENU_BUTTON_HEIGHT + 2*MENU_TOP; + return SEARCH_ITEMS*UI_UNIT_Y + 2*MENU_TOP; } /* ar is the search box itself */ @@ -951,8 +971,6 @@ static void ui_searchbox_region_free_cb(ARegion *ar) ar->regiondata= NULL; } -static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, uiBlock *block); - ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) { uiStyle *style= U.uistyles.first; // XXX pass on as arg @@ -1208,18 +1226,26 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if(but) { int left=0, right=0, top=0, down=0; int winx, winy; - int offscreen; + // int offscreen; wm_window_get_size(window, &winx, &winy); if(block->direction & UI_CENTER) center= ysize/2; else center= 0; - + + /* check if there's space at all */ if( butrct.xmin-xsize > 0.0f) left= 1; if( butrct.xmax+xsize < winx) right= 1; if( butrct.ymin-ysize+center > 0.0f) down= 1; if( butrct.ymax+ysize-center < winy) top= 1; + if(top==0 && down==0) { + if (butrct.ymin-ysize < winy-butrct.ymax-ysize) + top= 1; + else + down= 1; + } + dir1= block->direction & UI_DIRECTION; /* secundary directions */ @@ -1284,7 +1310,7 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, if(top==0 && down==0) { if(dir1==UI_LEFT || dir1==UI_RIGHT) { // align with bottom of screen - yof= ysize; + // yof= ysize; (not with menu scrolls) } } @@ -1299,15 +1325,16 @@ static void ui_block_position(wmWindow *window, ARegion *butregion, uiBut *but, // apply requested offset in the block xof += block->xofs/block->aspect; yof += block->yofs/block->aspect; - +#if 0 /* clamp to window bounds, could be made into an option if its ever annoying */ if( (offscreen= (block->miny+yof)) < 0) yof -= offscreen; /* bottom */ else if((offscreen= (block->maxy+yof)-winy) > 0) yof -= offscreen; /* top */ if( (offscreen= (block->minx+xof)) < 0) xof -= offscreen; /* left */ else if((offscreen= (block->maxx+xof)-winx) > 0) xof -= offscreen; /* right */ +#endif } - /* apply */ + /* apply offset, buttons in window coords */ for(bt= block->buttons.first; bt; bt= bt->next) { ui_block_to_window_fl(butregion, but->block, &bt->x1, &bt->y1); @@ -1381,6 +1408,62 @@ static void ui_block_region_draw(const bContext *C, ARegion *ar) uiDrawBlock(C, block); } +static void ui_popup_block_clip(wmWindow *window, uiBlock *block) +{ + int winx, winy; + + wm_window_get_size(window, &winx, &winy); + + if(block->minx < MENU_SHADOW_SIDE) + block->minx= MENU_SHADOW_SIDE; + if(block->maxx > winx-MENU_SHADOW_SIDE) + block->maxx= winx-MENU_SHADOW_SIDE; + + if(block->miny < MENU_SHADOW_BOTTOM) + block->miny= MENU_SHADOW_BOTTOM; + if(block->maxy > winy-MENU_TOP) + block->maxy= winy-MENU_TOP; +} + +void ui_popup_block_scrolltest(uiBlock *block) +{ + uiBut *bt; + + block->flag &= ~(UI_BLOCK_CLIPBOTTOM|UI_BLOCK_CLIPTOP); + + for(bt= block->buttons.first; bt; bt= bt->next) + bt->flag &= ~UI_SCROLLED; + + if(block->buttons.first==block->buttons.last) + return; + + /* mark buttons that are outside boundary and the ones next to it for arrow(s) */ + for(bt= block->buttons.first; bt; bt= bt->next) { + if(bt->y1 < block->miny) { + bt->flag |= UI_SCROLLED; + block->flag |= UI_BLOCK_CLIPBOTTOM; + /* make space for arrow */ + if(bt->y2 < block->miny +10) { + if(bt->next && bt->next->y1 > bt->y1) + bt->next->flag |= UI_SCROLLED; + if(bt->prev && bt->prev->y1 > bt->y1) + bt->prev->flag |= UI_SCROLLED; + } + } + if(bt->y2 > block->maxy) { + bt->flag |= UI_SCROLLED; + block->flag |= UI_BLOCK_CLIPTOP; + /* make space for arrow */ + if(bt->y1 > block->maxy -10) { + if(bt->next && bt->next->y2 < bt->y2) + bt->next->flag |= UI_SCROLLED; + if(bt->prev && bt->prev->y2 < bt->y2) + bt->prev->flag |= UI_SCROLLED; + } + } + } +} + uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut *but, uiBlockCreateFunc create_func, uiBlockHandleCreateFunc handle_create_func, void *arg) { wmWindow *window= CTX_wm_window(C); @@ -1451,6 +1534,9 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut block->flag |= UI_BLOCK_POPUP|UI_BLOCK_NUMSELECT; } + /* clip block with window boundary */ + ui_popup_block_clip(window, block); + /* the block and buttons were positioned in window space as in 2.4x, now * these menu blocks are regions so we bring it back to region space. * additionally we add some padding for the menu shadow or rounded menus */ @@ -1458,7 +1544,7 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut ar->winrct.xmax= block->maxx + MENU_SHADOW_SIDE; ar->winrct.ymin= block->miny - MENU_SHADOW_BOTTOM; ar->winrct.ymax= block->maxy + MENU_TOP; - + block->minx -= ar->winrct.xmin; block->maxx -= ar->winrct.xmin; block->miny -= ar->winrct.ymin; @@ -1470,12 +1556,15 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut bt->y1 -= ar->winrct.ymin; bt->y2 -= ar->winrct.ymin; } - + block->flag |= UI_BLOCK_LOOP; /* adds subwindow */ ED_region_init(C, ar); + /* checks which buttons are visible, sets flags to prevent draw (do after region init) */ + ui_popup_block_scrolltest(block); + /* get winmat now that we actually have the subwindow */ wmSubWindowSet(window, ar->swinid); @@ -1490,6 +1579,10 @@ uiPopupBlockHandle *ui_popup_block_create(bContext *C, ARegion *butregion, uiBut void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle) { ui_remove_temporary_region(C, CTX_wm_screen(C), handle->region); + + if(handle->scrolltimer) + WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), handle->scrolltimer); + MEM_freeN(handle); } @@ -2150,7 +2243,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi the offset is negative because we are inverse moving the block to be under the mouse */ offset[0]= -(bt->x1 + 0.8f*(bt->x2 - bt->x1)); - offset[1]= -(bt->y1 + 0.5f*MENU_BUTTON_HEIGHT); + offset[1]= -(bt->y1 + 0.5f*UI_UNIT_Y); } else { /* position mouse at 0.8*width of the button and below the tile @@ -2159,7 +2252,7 @@ static uiBlock *ui_block_func_POPUP(bContext *C, uiPopupBlockHandle *handle, voi for(bt=block->buttons.first; bt; bt=bt->next) offset[0]= MIN2(offset[0], -(bt->x1 + 0.8f*(bt->x2 - bt->x1))); - offset[1]= 1.5*MENU_BUTTON_HEIGHT; + offset[1]= 1.5*UI_UNIT_Y; } block->minbounds= minwidth; @@ -2263,10 +2356,10 @@ uiPopupMenu *uiPupMenuBegin(bContext *C, const char *title, int icon) if(icon) { sprintf(titlestr, " %s", title); - uiDefIconTextBut(pup->block, LABEL, 0, icon, titlestr, 0, 0, 200, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, ""); + uiDefIconTextBut(pup->block, LABEL, 0, icon, titlestr, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); } else { - but= uiDefBut(pup->block, LABEL, 0, title, 0, 0, 200, MENU_BUTTON_HEIGHT, NULL, 0.0, 0.0, 0, 0, ""); + but= uiDefBut(pup->block, LABEL, 0, title, 0, 0, 200, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); but->flag= UI_TEXT_LEFT; } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 69e3a1792c6..bbd1bd8773b 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -751,7 +751,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, Modif if ((ob->type==OB_MESH) && modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) { /* -- convert to rna ? */ - but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode"); + but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode"); if (index < cageIndex) uiButSetFlag(but, UI_BUT_DISABLED); uiButSetFunc(but, modifiers_setOnCage, ob, md); @@ -763,7 +763,7 @@ static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, Modif if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { /* add disabled pre-tesselated button, so users could have message for this modifiers */ - but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "This modifier could be applied on splines' points only"); + but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "This modifier could be applied on splines' points only"); uiButSetFlag(but, UI_BUT_DISABLED); } else if (mti->type != eModifierTypeType_Constructive) { /* constructive modifiers tesselates curve before applying */ @@ -1281,31 +1281,32 @@ static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v) /* offset aligns from bottom, standard width 300, height 115 */ static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb) { - uiBut *bt; uiLayout *row; + const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */ + const int line2_y= yoffs + 65; if(coba==NULL) return; - bt= uiDefBut(block, BUT, 0, "Add", 0+xoffs,100+yoffs,40,20, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband"); + bt= uiDefBut(block, BUT, 0, "Add", 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband"); uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); - bt= uiDefBut(block, BUT, 0, "Delete", 45+xoffs,100+yoffs,45,20, NULL, 0, 0, 0, 0, "Delete the active position"); + bt= uiDefBut(block, BUT, 0, "Delete", 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Delete the active position"); uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); /* XXX, todo for later - convert to operator - campbell */ - bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,100+yoffs,20,20, NULL, 0, 0, 0, 0, "Flip colorband"); + bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Flip colorband"); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); - uiDefButS(block, NUM, 0, "", 120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop"); + uiDefButS(block, NUM, 0, "", 120+xoffs,line1_y,80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop"); bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", - 210+xoffs, 100+yoffs, 90, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); + 210+xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); uiBlockEndAlign(block); - bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, ""); + bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1330,11 +1331,11 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand float xs= butr->xmin; uiBlockBeginAlign(block); - bt= uiDefBut(block, BUT, 0, "Add", xs,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband"); + bt= uiDefBut(block, BUT, 0, "Add", xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband"); uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); - bt= uiDefBut(block, BUT, 0, "Delete", xs+2.0f*unit,butr->ymin+20.0f,1.5f*unit,20, NULL, 0, 0, 0, 0, "Delete the active position"); + bt= uiDefBut(block, BUT, 0, "Delete", xs+2.0f*unit,butr->ymin+UI_UNIT_Y,1.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Delete the active position"); uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); - bt= uiDefBut(block, BUT, 0, "F", xs+3.5f*unit,butr->ymin+20.0f,0.5f*unit,20, NULL, 0, 0, 0, 0, "Flip the color ramp"); + bt= uiDefBut(block, BUT, 0, "F", xs+3.5f*unit,butr->ymin+UI_UNIT_Y,0.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Flip the color ramp"); uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); uiBlockEndAlign(block); @@ -1346,10 +1347,10 @@ static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand } bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4", - xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); + xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops"); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); - bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, ""); + bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); uiBlockEndAlign(block); @@ -1422,7 +1423,7 @@ void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname hist = (Histogram *)cptr.data; - hist->height= (hist->height<=20)?20:hist->height; + hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height; bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1459,7 +1460,7 @@ void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) block= uiLayoutAbsoluteBlock(layout); - scopes->wavefrm_height= (scopes->wavefrm_height<=20)?20:scopes->wavefrm_height; + scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height; bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); (void)bt; // UNUSED @@ -1496,7 +1497,7 @@ void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propna block= uiLayoutAbsoluteBlock(layout); - scopes->vecscope_height= (scopes->vecscope_height<=20)?20:scopes->vecscope_height; + scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height; bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); @@ -1993,7 +1994,7 @@ void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer)) icon = ICON_LAYER_USED; - but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, 10, 10); + but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2); uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer)); but->type= TOG; } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 58ed1e31b81..41bb12e4433 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -159,6 +159,18 @@ static float check_tria_vert[6][2]= { static int check_tria_face[4][3]= { {3, 2, 4}, {3, 4, 5}, {1, 0, 3}, {0, 2, 3}}; +GLubyte checker_stipple_sml[32*32/8] = +{ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ + 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ +}; + /* ************************************************* */ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3) @@ -614,22 +626,10 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) if(wtb->inner) { if(wcol->shaded==0) { if (wcol->alpha_check) { - GLubyte checker_stipple_sml[32*32/8] = - { - 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ - 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ - 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ - 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ - 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ - 255,0,255,0,255,0,255,0,255,0,255,0,255,0,255,0, \ - 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ - 0,255,0,255,0,255,0,255,0,255,0,255,0,255,0,255, \ - }; - float x_mid= 0.0f; /* used for dumb clamping of values */ /* dark checkers */ - glColor4ub(100, 100, 100, 255); + glColor4ub(UI_TRANSP_DARK, UI_TRANSP_DARK, UI_TRANSP_DARK, 255); glBegin(GL_POLYGON); for(a=0; a<wtb->totvert; a++) { glVertex2fv(wtb->inner_v[a]); @@ -638,7 +638,7 @@ static void widgetbase_draw(uiWidgetBase *wtb, uiWidgetColors *wcol) /* light checkers */ glEnable(GL_POLYGON_STIPPLE); - glColor4ub(160, 160, 160, 255); + glColor4ub(UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, UI_TRANSP_LIGHT, 255); glPolygonStipple(checker_stipple_sml); glBegin(GL_POLYGON); for(a=0; a<wtb->totvert; a++) { @@ -771,7 +771,7 @@ static void widget_draw_preview(BIFIconID icon, float UNUSED(alpha), rcti *rect) /* icons have been standardized... and this call draws in untransformed coordinates */ -#define ICON_HEIGHT 16.0f +#define ICON_HEIGHT UI_DPI_FAC*16.0f static void widget_draw_icon(uiBut *but, BIFIconID icon, float alpha, rcti *rect) { @@ -3081,6 +3081,18 @@ void ui_draw_menu_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) else wt->draw(&wt->wcol, rect, 0, 0); + if(block) { + if(block->flag & UI_BLOCK_CLIPTOP) { + /* XXX no scaling for UI here yet */ + glColor3ubv((unsigned char*)wt->wcol.text); + UI_DrawTriIcon((rect->xmax+rect->xmin)/2, rect->ymax-8, 't'); + } + if(block->flag & UI_BLOCK_CLIPBOTTOM) { + /* XXX no scaling for UI here yet */ + glColor3ubv((unsigned char*)wt->wcol.text); + UI_DrawTriIcon((rect->xmax+rect->xmin)/2, rect->ymin+10, 'v'); + } + } } void ui_draw_search_back(uiStyle *UNUSED(style), uiBlock *block, rcti *rect) diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 1a2a2906f1a..6527e0140b8 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -585,7 +585,7 @@ void ui_theme_init_default(void) SETCOL(btheme->tv3d.wire, 0x0, 0x0, 0x0, 255); SETCOL(btheme->tv3d.lamp, 0, 0, 0, 40); SETCOL(btheme->tv3d.select, 241, 88, 0, 255); - SETCOL(btheme->tv3d.active, 255, 140, 25, 255); + SETCOL(btheme->tv3d.active, 255, 170, 64, 255); SETCOL(btheme->tv3d.group, 8, 48, 8, 255); SETCOL(btheme->tv3d.group_active, 85, 187, 85, 255); SETCOL(btheme->tv3d.transform, 0xff, 0xff, 0xff, 255); @@ -604,7 +604,7 @@ void ui_theme_init_default(void) SETCOL(btheme->tv3d.face_dot, 255, 133, 0, 255); SETCOL(btheme->tv3d.editmesh_active, 255, 255, 255, 128); SETCOLF(btheme->tv3d.edge_crease, 0.8, 0, 0.6, 1.0); - SETCOL(btheme->tv3d.edge_sharp, 255, 32, 32, 255); + SETCOL(btheme->tv3d.edge_sharp, 0, 255, 255, 255); SETCOL(btheme->tv3d.header_text, 0, 0, 0, 255); SETCOL(btheme->tv3d.header_text_hi, 255, 255, 255, 255); SETCOL(btheme->tv3d.button_text, 0, 0, 0, 255); @@ -1578,6 +1578,8 @@ void init_userdef_do_versions(void) } if (U.dragthreshold == 0 ) U.dragthreshold= 5; + if (U.widget_unit==0) + U.widget_unit= (U.dpi * 20 + 36)/72; /* funny name, but it is GE stuff, moves userdef stuff to engine */ // XXX space_set_commmandline_options(); diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index f7bff168a33..434334258af 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -876,6 +876,13 @@ static void view_zoomdrag_exit(bContext *C, wmOperator *op) } } +static int view_zoomdrag_cancel(bContext *C, wmOperator *op) +{ + view_zoomdrag_exit(C, op); + + return OPERATOR_CANCELLED; +} + /* for 'redo' only, with no user input */ static int view_zoomdrag_exec(bContext *C, wmOperator *op) { @@ -1065,6 +1072,7 @@ static void VIEW2D_OT_zoom(wmOperatorType *ot) ot->exec= view_zoomdrag_exec; ot->invoke= view_zoomdrag_invoke; ot->modal= view_zoomdrag_modal; + ot->cancel= view_zoomdrag_cancel; ot->poll= view_zoom_poll; @@ -1165,6 +1173,7 @@ static void VIEW2D_OT_zoom_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= view_borderzoom_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= view_zoom_poll; @@ -1352,7 +1361,14 @@ static void scroller_activate_exit(bContext *C, wmOperator *op) ED_region_tag_redraw(CTX_wm_region(C)); } -} +} + +static int scroller_activate_cancel(bContext *C, wmOperator *op) +{ + scroller_activate_exit(C, op); + + return OPERATOR_CANCELLED; +} /* apply transform to view (i.e. adjust 'cur' rect) */ static void scroller_activate_apply(bContext *C, wmOperator *op) @@ -1561,6 +1577,8 @@ static void VIEW2D_OT_scroller_activate(wmOperatorType *ot) /* api callbacks */ ot->invoke= scroller_activate_invoke; ot->modal= scroller_activate_modal; + ot->cancel= scroller_activate_cancel; + ot->poll= view2d_poll; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 1a97d2c3d07..d267ac8565c 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -174,14 +174,14 @@ void ED_object_add_generic_props(wmOperatorType *ot, int do_editmode) PropertyRNA *prop; /* note: this property gets hidden for add-camera operator */ - RNA_def_boolean(ot->srna, "view_align", 0, "Align to View", "Align the new object to the view."); + RNA_def_boolean(ot->srna, "view_align", 0, "Align to View", "Align the new object to the view"); if(do_editmode) { - prop= RNA_def_boolean(ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object."); + prop= RNA_def_boolean(ot->srna, "enter_editmode", 0, "Enter Editmode", "Enter editmode when adding this object"); RNA_def_property_flag(prop, PROP_HIDDEN); } - RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location for the newly added object.", -FLT_MAX, FLT_MAX); + RNA_def_float_vector_xyz(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Location for the newly added object", -FLT_MAX, FLT_MAX); RNA_def_float_rotation(ot->srna, "rotation", 3, NULL, -FLT_MAX, FLT_MAX, "Rotation", "Rotation for the newly added object", -FLT_MAX, FLT_MAX); prop = RNA_def_boolean_layer_member(ot->srna, "layers", 20, NULL, "Layer", ""); @@ -641,7 +641,7 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); if(obedit==NULL) { - BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature."); + BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature"); return OPERATOR_CANCELLED; } @@ -1386,7 +1386,7 @@ static int convert_exec(bContext *C, wmOperator *op) void OBJECT_OT_convert(wmOperatorType *ot) { /* identifiers */ - ot->name= "Convert"; + ot->name= "Convert to"; ot->description = "Convert selected objects to another type"; ot->idname= "OBJECT_OT_convert"; @@ -1399,8 +1399,8 @@ void OBJECT_OT_convert(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* properties */ - ot->prop= RNA_def_enum(ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to."); - RNA_def_boolean(ot->srna, "keep_original", 0, "Keep Original", "Keep original objects instead of replacing them."); + ot->prop= RNA_def_enum(ot->srna, "target", convert_target_items, OB_MESH, "Target", "Type of object to convert to"); + RNA_def_boolean(ot->srna, "keep_original", 0, "Keep Original", "Keep original objects instead of replacing them"); } /**************************** Duplicate ************************/ @@ -1720,7 +1720,7 @@ void OBJECT_OT_duplicate(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; /* to give to transform */ - RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data."); + RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data"); prop= RNA_def_enum(ot->srna, "mode", transform_mode_types, TFM_TRANSLATION, "Mode", ""); RNA_def_property_flag(prop, PROP_HIDDEN); } @@ -1790,8 +1790,8 @@ void OBJECT_OT_add_named(wmOperatorType *ot) /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data."); - RNA_def_string(ot->srna, "name", "Cube", 24, "Name", "Object name to add."); + RNA_def_boolean(ot->srna, "linked", 0, "Linked", "Duplicate object but not object data, linking to the original data"); + RNA_def_string(ot->srna, "name", "Cube", 24, "Name", "Object name to add"); } @@ -1816,11 +1816,11 @@ static int join_exec(bContext *C, wmOperator *op) Object *ob= CTX_data_active_object(C); if(scene->obedit) { - BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode."); + BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode"); return OPERATOR_CANCELLED; } else if(object_data_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata."); + BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); return OPERATOR_CANCELLED; } @@ -1869,11 +1869,11 @@ static int join_shapes_exec(bContext *C, wmOperator *op) Object *ob= CTX_data_active_object(C); if(scene->obedit) { - BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode."); + BKE_report(op->reports, RPT_ERROR, "This data does not support joining in editmode"); return OPERATOR_CANCELLED; } else if(object_data_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata."); + BKE_report(op->reports, RPT_ERROR, "Can't edit external libdata"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index b513bab3924..5dc161c6267 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -22,7 +22,8 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Morten Mikkelsen, + * Sergey Sharybin * * ***** END GPL LICENSE BLOCK ***** */ @@ -44,10 +45,15 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_world_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" #include "BLI_blenlib.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_math_geom.h" #include "BKE_blender.h" #include "BKE_context.h" @@ -56,6 +62,10 @@ #include "BKE_main.h" #include "BKE_multires.h" #include "BKE_report.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_modifier.h" +#include "BKE_DerivedMesh.h" +#include "BKE_subsurf.h" #include "RE_pipeline.h" #include "RE_shader_ext.h" @@ -74,6 +84,1178 @@ #include "object_intern.h" +/* ****************** multires BAKING ********************** */ + +/* holder of per-object data needed for bake job + needed to make job totally thread-safe */ +typedef struct MultiresBakerJobData { + struct MultiresBakerJobData *next, *prev; + DerivedMesh *lores_dm, *hires_dm; + int simple, lvl, tot_lvl; +} MultiresBakerJobData; + +/* data passing to multires-baker job */ +typedef struct { + ListBase data; + int bake_clear, bake_filter; + short mode, use_lores_mesh; +} MultiresBakeJob; + +/* data passing to multires baker */ +typedef struct { + DerivedMesh *lores_dm, *hires_dm; + int simple, lvl, tot_lvl, bake_filter; + short mode, use_lores_mesh; + + int tot_obj, tot_image; + ListBase image; + + int baked_objects, baked_faces; + + short *stop; + short *do_update; + float *progress; +} MultiresBakeRender; + +typedef void (*MPassKnownData)(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, + const int face_index, const int lvl, const float st[2], + float tangmat[3][3], const int x, const int y); + +typedef void* (*MInitBakeData)(MultiresBakeRender *bkr, Image* ima); +typedef void (*MApplyBakeData)(void *bake_data); +typedef void (*MFreeBakeData)(void *bake_data); + +typedef struct { + MVert *mvert; + MFace *mface; + MTFace *mtface; + float *pvtangent; + float *precomputed_normals; + int w, h; + int face_index; + int i0, i1, i2; + DerivedMesh *lores_dm, *hires_dm; + int lvl; + void *bake_data; + MPassKnownData pass_data; +} MResolvePixelData; + +typedef void (*MFlushPixel)(const MResolvePixelData *data, const int x, const int y); + +typedef struct { + int w, h; + char *texels; + const MResolvePixelData *data; + MFlushPixel flush_pixel; +} MBakeRast; + +typedef struct { + float *heights; + float height_min, height_max; + Image *ima; + DerivedMesh *ssdm; +} MHeightBakeData; + +static void multiresbake_get_normal(const MResolvePixelData *data, float norm[], const int face_num, const int vert_index) +{ + unsigned int indices[]= {data->mface[face_num].v1, data->mface[face_num].v2, + data->mface[face_num].v3, data->mface[face_num].v4}; + const int smoothnormal= (data->mface[face_num].flag & ME_SMOOTH); + + if(!smoothnormal) { /* flat */ + if(data->precomputed_normals) { + copy_v3_v3(norm, &data->precomputed_normals[3*face_num]); + } else { + float nor[3]; + float *p0, *p1, *p2; + const int iGetNrVerts= data->mface[face_num].v4!=0 ? 4 : 3; + + p0= data->mvert[indices[0]].co; + p1= data->mvert[indices[1]].co; + p2= data->mvert[indices[2]].co; + + if(iGetNrVerts==4) { + float *p3= data->mvert[indices[3]].co; + normal_quad_v3(nor, p0, p1, p2, p3); + } else { + normal_tri_v3(nor, p0, p1, p2); + } + + copy_v3_v3(norm, nor); + } + } else { + short *no= data->mvert[indices[vert_index]].no; + + normal_short_to_float_v3(norm, no); + normalize_v3(norm); + } +} + +static void init_bake_rast(MBakeRast *bake_rast, const ImBuf *ibuf, const MResolvePixelData *data, MFlushPixel flush_pixel) +{ + memset(bake_rast, 0, sizeof(MBakeRast)); + + bake_rast->texels = ibuf->userdata; + bake_rast->w= ibuf->x; + bake_rast->h= ibuf->y; + bake_rast->data= data; + bake_rast->flush_pixel= flush_pixel; +} + +static void flush_pixel(const MResolvePixelData *data, const int x, const int y) +{ + float st[2]= {(x+0.5f)/data->w, (y+0.5f)/data->h}; + float *st0, *st1, *st2; + float *tang0, *tang1, *tang2; + float no0[3], no1[3], no2[3]; + float fUV[2], from_tang[3][3], to_tang[3][3]; + float u, v, w, sign; + int r; + + const int i0= data->i0; + const int i1= data->i1; + const int i2= data->i2; + + st0= data->mtface[data->face_index].uv[i0]; + st1= data->mtface[data->face_index].uv[i1]; + st2= data->mtface[data->face_index].uv[i2]; + + tang0= data->pvtangent + data->face_index*16 + i0*4; + tang1= data->pvtangent + data->face_index*16 + i1*4; + tang2= data->pvtangent + data->face_index*16 + i2*4; + + multiresbake_get_normal(data, no0, data->face_index, i0); /* can optimize these 3 into one call */ + multiresbake_get_normal(data, no1, data->face_index, i1); + multiresbake_get_normal(data, no2, data->face_index, i2); + + resolve_tri_uv(fUV, st, st0, st1, st2); + + u= fUV[0]; + v= fUV[1]; + w= 1-u-v; + + /* the sign is the same at all face vertices for any non degenerate face. + Just in case we clamp the interpolated value though. */ + sign= (tang0[3]*u + tang1[3]*v + tang2[3]*w)<0 ? (-1.0f) : 1.0f; + + /* this sequence of math is designed specifically as is with great care + to be compatible with our shader. Please don't change without good reason. */ + for(r= 0; r<3; r++) { + from_tang[0][r]= tang0[r]*u + tang1[r]*v + tang2[r]*w; + from_tang[2][r]= no0[r]*u + no1[r]*v + no2[r]*w; + } + + cross_v3_v3v3(from_tang[1], from_tang[2], from_tang[0]); /* B = sign * cross(N, T) */ + mul_v3_fl(from_tang[1], sign); + invert_m3_m3(to_tang, from_tang); + /* sequence end */ + + data->pass_data(data->lores_dm, data->hires_dm, data->bake_data, + data->face_index, data->lvl, st, to_tang, x, y); +} + +static void set_rast_triangle(const MBakeRast *bake_rast, const int x, const int y) +{ + const int w= bake_rast->w; + const int h= bake_rast->h; + + if(x>=0 && x<w && y>=0 && y<h) { + if((bake_rast->texels[y*w+x])==0) { + flush_pixel(bake_rast->data, x, y); + bake_rast->texels[y*w+x]= FILTER_MASK_USED; + } + } +} + +static void rasterize_half(const MBakeRast *bake_rast, + const float s0_s, const float t0_s, const float s1_s, const float t1_s, + const float s0_l, const float t0_l, const float s1_l, const float t1_l, + const int y0_in, const int y1_in, const int is_mid_right) +{ + const int s_stable= fabsf(t1_s-t0_s)>FLT_EPSILON ? 1 : 0; + const int l_stable= fabsf(t1_l-t0_l)>FLT_EPSILON ? 1 : 0; + const int w= bake_rast->w; + const int h= bake_rast->h; + int y, y0, y1; + + if(y1_in<=0 || y0_in>=h) + return; + + y0= y0_in<0 ? 0 : y0_in; + y1= y1_in>=h ? h : y1_in; + + for(y= y0; y<y1; y++) { + /*-b(x-x0) + a(y-y0) = 0 */ + int iXl, iXr, x; + float x_l= s_stable!=0 ? (s0_s + (((s1_s-s0_s)*(y-t0_s))/(t1_s-t0_s))) : s0_s; + float x_r= l_stable!=0 ? (s0_l + (((s1_l-s0_l)*(y-t0_l))/(t1_l-t0_l))) : s0_l; + + if(is_mid_right!=0) + SWAP(float, x_l, x_r); + + iXl= (int)ceilf(x_l); + iXr= (int)ceilf(x_r); + + if(iXr>0 && iXl<w) { + iXl= iXl<0?0:iXl; + iXr= iXr>=w?w:iXr; + + for(x= iXl; x<iXr; x++) + set_rast_triangle(bake_rast, x, y); + } + } +} + +static void bake_rasterize(const MBakeRast *bake_rast, const float st0_in[2], const float st1_in[2], const float st2_in[2]) +{ + const int w= bake_rast->w; + const int h= bake_rast->h; + float slo= st0_in[0]*w - 0.5f; + float tlo= st0_in[1]*h - 0.5f; + float smi= st1_in[0]*w - 0.5f; + float tmi= st1_in[1]*h - 0.5f; + float shi= st2_in[0]*w - 0.5f; + float thi= st2_in[1]*h - 0.5f; + int is_mid_right= 0, ylo, yhi, yhi_beg; + + /* skip degenerates */ + if((slo==smi && tlo==tmi) || (slo==shi && tlo==thi) || (smi==shi && tmi==thi)) + return; + + /* sort by T */ + if(tlo>tmi && tlo>thi) { + SWAP(float, shi, slo); + SWAP(float, thi, tlo); + } else if(tmi>thi) { + SWAP(float, shi, smi); + SWAP(float, thi, tmi); + } + + if(tlo>tmi) { + SWAP(float, slo, smi); + SWAP(float, tlo, tmi); + } + + /* check if mid point is to the left or to the right of the lo-hi edge */ + is_mid_right= (-(shi-slo)*(tmi-thi) + (thi-tlo)*(smi-shi))>0 ? 1 : 0; + ylo= (int) ceilf(tlo); + yhi_beg= (int) ceilf(tmi); + yhi= (int) ceilf(thi); + + /*if(fTmi>ceilf(fTlo))*/ + rasterize_half(bake_rast, slo, tlo, smi, tmi, slo, tlo, shi, thi, ylo, yhi_beg, is_mid_right); + rasterize_half(bake_rast, smi, tmi, shi, thi, slo, tlo, shi, thi, yhi_beg, yhi, is_mid_right); +} + +static int multiresbake_test_break(MultiresBakeRender *bkr) +{ + if(!bkr->stop) { + /* this means baker is executed outside from job system */ + return 0; + } + + return G.afbreek; +} + +static void do_multires_bake(MultiresBakeRender *bkr, Image* ima, MPassKnownData passKnownData, + MInitBakeData initBakeData, MApplyBakeData applyBakeData, MFreeBakeData freeBakeData) +{ +#if 1 // BMESH_TODO + (void)bkr; + (void)ima; + (void)passKnownData; + (void)initBakeData; + (void)applyBakeData; + (void)freeBakeData; + + printf("BMESH_TODO" AT "\n"); +#else + DerivedMesh *dm= bkr->lores_dm; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + const int lvl= bkr->lvl; + const int tot_face= dm->getNumFaces(dm); + MVert *mvert= dm->getVertArray(dm); + MFace *mface= dm->getFaceArray(dm); + MTFace *mtface= dm->getFaceDataArray(dm, CD_MTFACE); + float *pvtangent= NULL; + + if(CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) + DM_add_tangent_layer(dm); + + pvtangent= DM_get_face_data_layer(dm, CD_TANGENT); + + if(tot_face > 0) { /* sanity check */ + int f= 0; + MBakeRast bake_rast; + MResolvePixelData data={NULL}; + + data.mface= mface; + data.mvert= mvert; + data.mtface= mtface; + data.pvtangent= pvtangent; + data.precomputed_normals= dm->getFaceDataArray(dm, CD_NORMAL); /* don't strictly need this */ + data.w= ibuf->x; + data.h= ibuf->y; + data.lores_dm= dm; + data.hires_dm= bkr->hires_dm; + data.lvl= lvl; + data.pass_data= passKnownData; + + if(initBakeData) + data.bake_data= initBakeData(bkr, ima); + + init_bake_rast(&bake_rast, ibuf, &data, flush_pixel); + + for(f= 0; f<tot_face; f++) { + MTFace *mtfate= &mtface[f]; + int verts[3][2], nr_tris, t; + + if(multiresbake_test_break(bkr)) + break; + + if(mtfate->tpage!=ima) + continue; + + data.face_index= f; + + /* might support other forms of diagonal splits later on such as + split by shortest diagonal.*/ + verts[0][0]=0; + verts[1][0]=1; + verts[2][0]=2; + + verts[0][1]=0; + verts[1][1]=2; + verts[2][1]=3; + + nr_tris= mface[f].v4!=0 ? 2 : 1; + for(t= 0; t<nr_tris; t++) { + data.i0= verts[0][t]; + data.i1= verts[1][t]; + data.i2 =verts[2][t]; + + bake_rasterize(&bake_rast, mtfate->uv[data.i0], mtfate->uv[data.i1], mtfate->uv[data.i2]); + } + + bkr->baked_faces++; + + if(bkr->do_update) + *bkr->do_update= 1; + + if(bkr->progress) + *bkr->progress= ((float)bkr->baked_objects + (float)bkr->baked_faces / tot_face) / bkr->tot_obj; + } + + if(applyBakeData) + applyBakeData(data.bake_data); + + if(freeBakeData) + freeBakeData(data.bake_data); + } +#endif // BMESH_TODO +} + +static void interp_bilinear_quad_data(float data[4][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, (1-u)*(1-v)); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, u*(1-v)); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, u*v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[3]); + mul_v3_fl(vec, (1-u)*v); add_v3_v3(res, vec); +} + +static void interp_barycentric_tri_data(float data[3][3], float u, float v, float res[3]) +{ + float vec[3]; + + copy_v3_v3(res, data[0]); + mul_v3_fl(res, u); + copy_v3_v3(vec, data[1]); + mul_v3_fl(vec, v); add_v3_v3(res, vec); + copy_v3_v3(vec, data[2]); + mul_v3_fl(vec, 1.0f-u-v); add_v3_v3(res, vec); +} + +/* mode = 0: interpolate normals, + mode = 1: interpolate coord */ +static void interp_bilinear_grid(DMGridData *grid, int grid_size, float crn_x, float crn_y, int mode, float res[3]) +{ + int x0, x1, y0, y1; + float u, v; + float data[4][3]; + + x0= (int) crn_x; + x1= x0>=(grid_size-1) ? (grid_size-1) : (x0+1); + + y0= (int) crn_y; + y1= y0>=(grid_size-1) ? (grid_size-1) : (y0+1); + + u= crn_x-x0; + v= crn_y-y0; + + if(mode == 0) { + copy_v3_v3(data[0], grid[y0 * grid_size + x0].no); + copy_v3_v3(data[1], grid[y0 * grid_size + x1].no); + copy_v3_v3(data[2], grid[y1 * grid_size + x1].no); + copy_v3_v3(data[3], grid[y1 * grid_size + x0].no); + } else { + copy_v3_v3(data[0], grid[y0 * grid_size + x0].co); + copy_v3_v3(data[1], grid[y0 * grid_size + x1].co); + copy_v3_v3(data[2], grid[y1 * grid_size + x1].co); + copy_v3_v3(data[3], grid[y1 * grid_size + x0].co); + } + + interp_bilinear_quad_data(data, u, v, res); +} + +static void get_ccgdm_data(DerivedMesh *lodm, DerivedMesh *hidm, const int lvl, const int face_index, const float u, const float v, float co[3], float n[3]) +{ +#if 1 // BMESH_TODO + (void)lodm; + (void)hidm; + (void)lvl; + (void)face_index; + (void)u; + (void)v; + (void)co; + (void)n; +#else + MFace mface; + DMGridData **grid_data; + float crn_x, crn_y; + int grid_size, S, face_side; + int *grid_offset, g_index; + + lodm->getFace(lodm, face_index, &mface); + + grid_size= hidm->getGridSize(hidm); + grid_data= hidm->getGridData(hidm); + grid_offset= hidm->getGridOffset(hidm); + + face_side= (grid_size<<1)-1; + + if(lvl==0) { + g_index= grid_offset[face_index]; + S= mdisp_rot_face_to_crn(mface.v4 ? 4 : 3, face_side, u*(face_side-1), v*(face_side-1), &crn_x, &crn_y); + } else { + const int *index= lodm->getFaceDataArray(lodm, CD_ORIGINDEX); + int side= (1 << (lvl-1)) + 1; + int grid_index= index[face_index]; + int loc_offs= face_index % (1<<(2*lvl)); + int cell_index= loc_offs % ((side-1)*(side-1)); + int cell_side= grid_size / (side-1); + int row= cell_index / (side-1); + int col= cell_index % (side-1); + + S= face_index / (1<<(2*(lvl-1))) - grid_offset[grid_index]; + g_index= grid_offset[grid_index]; + + crn_y= (row * cell_side) + u * cell_side; + crn_x= (col * cell_side) + v * cell_side; + } + + CLAMP(crn_x, 0.0f, grid_size); + CLAMP(crn_y, 0.0f, grid_size); + + if(n != NULL) + interp_bilinear_grid(grid_data[g_index + S], grid_size, crn_x, crn_y, 0, n); + + if(co != NULL) + interp_bilinear_grid(grid_data[g_index + S], grid_size, crn_x, crn_y, 1, co); +#endif +} + +/* mode = 0: interpolate normals, + mode = 1: interpolate coord */ +static void interp_bilinear_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3]) +{ + float data[4][3]; + + if(mode == 0) { + dm->getVertNo(dm, mface->v1, data[0]); + dm->getVertNo(dm, mface->v2, data[1]); + dm->getVertNo(dm, mface->v3, data[2]); + dm->getVertNo(dm, mface->v4, data[3]); + } else { + dm->getVertCo(dm, mface->v1, data[0]); + dm->getVertCo(dm, mface->v2, data[1]); + dm->getVertCo(dm, mface->v3, data[2]); + dm->getVertCo(dm, mface->v4, data[3]); + } + + interp_bilinear_quad_data(data, u, v, res); +} + +/* mode = 0: interpolate normals, + mode = 1: interpolate coord */ +static void interp_barycentric_mface(DerivedMesh *dm, MFace *mface, const float u, const float v, const int mode, float res[3]) +{ + float data[3][3]; + + if(mode == 0) { + dm->getVertNo(dm, mface->v1, data[0]); + dm->getVertNo(dm, mface->v2, data[1]); + dm->getVertNo(dm, mface->v3, data[2]); + } else { + dm->getVertCo(dm, mface->v1, data[0]); + dm->getVertCo(dm, mface->v2, data[1]); + dm->getVertCo(dm, mface->v3, data[2]); + } + + interp_barycentric_tri_data(data, u, v, res); +} + +static void *init_heights_data(MultiresBakeRender *bkr, Image* ima) +{ + MHeightBakeData *height_data; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + height_data= MEM_callocN(sizeof(MHeightBakeData), "MultiresBake heightData"); + + height_data->ima= ima; + height_data->heights= MEM_callocN(sizeof(float)*ibuf->x*ibuf->y, "MultiresBake heights"); + height_data->height_max= -FLT_MAX; + height_data->height_min= FLT_MAX; + + if(!bkr->use_lores_mesh) { + SubsurfModifierData smd= {{NULL}}; + int ss_lvl= bkr->tot_lvl - bkr->lvl; + + CLAMP(ss_lvl, 0, 6); + + smd.levels= smd.renderLevels= ss_lvl; + smd.flags|= eSubsurfModifierFlag_SubsurfUv; + + if(bkr->simple) + smd.subdivType= ME_SIMPLE_SUBSURF; + + height_data->ssdm= subsurf_make_derived_from_derived(bkr->lores_dm, &smd, 0, NULL, 0, 0, 0); + } + + return (void*)height_data; +} + +static void apply_heights_data(void *bake_data) +{ + MHeightBakeData *height_data= (MHeightBakeData*)bake_data; + ImBuf *ibuf= BKE_image_get_ibuf(height_data->ima, NULL); + int x, y, i; + float height, *heights= height_data->heights; + float min= height_data->height_min, max= height_data->height_max; + + for(x= 0; x<ibuf->x; x++) { + for(y =0; y<ibuf->y; y++) { + i= ibuf->x*y + x; + + if(((char*)ibuf->userdata)[i] != FILTER_MASK_USED) + continue; + + if(ibuf->rect_float) { + float *rrgbf= ibuf->rect_float + i*4; + + if(max-min > 1e-5) height= (heights[i]-min)/(max-min); + else height= 0; + + rrgbf[0]=rrgbf[1]=rrgbf[2]= height; + } else { + char *rrgb= (char*)ibuf->rect + i*4; + + if(max-min > 1e-5) height= (heights[i]-min)/(max-min); + else height= 0; + + rrgb[0]=rrgb[1]=rrgb[2]= FTOCHAR(height); + } + } + } + + ibuf->userflags= IB_RECT_INVALID; +} + +static void free_heights_data(void *bake_data) +{ + MHeightBakeData *height_data= (MHeightBakeData*)bake_data; + + if(height_data->ssdm) + height_data->ssdm->release(height_data->ssdm); + + MEM_freeN(height_data->heights); + MEM_freeN(height_data); +} + +/* MultiresBake callback for heights baking + general idea: + - find coord of point with specified UV in hi-res mesh (let's call it p1) + - find coord of point and normal with specified UV in lo-res mesh (or subdivided lo-res + mesh to make texture smoother) let's call this point p0 and n. + - height wound be dot(n, p1-p0) */ +static void apply_heights_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *bake_data, + const int face_index, const int lvl, const float st[2], + float UNUSED(tangmat[3][3]), const int x, const int y) +{ +#if 1 // BMESH_TODO + (void)lores_dm; + (void)hires_dm; + (void)bake_data; + (void)face_index; + (void)lvl; + (void)st; + (void)x; + (void)y; +#else + MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); + MFace mface; + Image *ima= mtface[face_index].tpage; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + MHeightBakeData *height_data= (MHeightBakeData*)bake_data; + float uv[2], *st0, *st1, *st2, *st3; + int pixel= ibuf->x*y + x; + float vec[3], p0[3], p1[3], n[3], len; + + lores_dm->getFace(lores_dm, face_index, &mface); + + st0= mtface[face_index].uv[0]; + st1= mtface[face_index].uv[1]; + st2= mtface[face_index].uv[2]; + + if(mface.v4) { + st3= mtface[face_index].uv[3]; + resolve_quad_uv(uv, st, st0, st1, st2, st3); + } else + resolve_tri_uv(uv, st, st0, st1, st2); + + CLAMP(uv[0], 0.0f, 1.0f); + CLAMP(uv[1], 0.0f, 1.0f); + + get_ccgdm_data(lores_dm, hires_dm, lvl, face_index, uv[0], uv[1], p1, 0); + + if(height_data->ssdm) { + //get_ccgdm_data_ss(lores_dm, height_data->ssdm, lvl, face_index, uv[0], uv[1], p0, n); + get_ccgdm_data(lores_dm, height_data->ssdm, 0, face_index, uv[0], uv[1], p0, n); + } else { + MFace mface; + lores_dm->getFace(lores_dm, face_index, &mface); + + if(mface.v4) { + interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); + interp_bilinear_mface(lores_dm, &mface, uv[0], uv[1], 0, n); + } else { + interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 1, p0); + interp_barycentric_mface(lores_dm, &mface, uv[0], uv[1], 0, n); + } + } + + sub_v3_v3v3(vec, p1, p0); + //len= len_v3(vec); + len= dot_v3v3(n, vec); + + height_data->heights[pixel]= len; + if(len<height_data->height_min) height_data->height_min= len; + if(len>height_data->height_max) height_data->height_max= len; + + if(ibuf->rect_float) { + float *rrgbf= ibuf->rect_float + pixel*4; + rrgbf[3]= 1.0f; + + ibuf->userflags= IB_RECT_INVALID; + } else { + char *rrgb= (char*)ibuf->rect + pixel*4; + rrgb[3]= 255; + } +#endif // BMESH_TODO +} + +/* MultiresBake callback for normals' baking + general idea: + - find coord and normal of point with specified UV in hi-res mesh + - multiply it by tangmat + - vector in color space would be norm(vec) /2 + (0.5, 0.5, 0.5) */ +static void apply_tangmat_callback(DerivedMesh *lores_dm, DerivedMesh *hires_dm, const void *UNUSED(bake_data), + const int face_index, const int lvl, const float st[2], + float tangmat[3][3], const int x, const int y) +{ +#if 1 // BMESH_TODO + (void)lores_dm; + (void)hires_dm; + (void)face_index; + (void)lvl; + (void)st; + (void)tangmat; + (void)y; + (void)x; +#else + MTFace *mtface= CustomData_get_layer(&lores_dm->faceData, CD_MTFACE); + MFace mface; + Image *ima= mtface[face_index].tpage; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + float uv[2], *st0, *st1, *st2, *st3; + int pixel= ibuf->x*y + x; + float n[3], vec[3], tmp[3]= {0.5, 0.5, 0.5}; + + lores_dm->getFace(lores_dm, face_index, &mface); + + st0= mtface[face_index].uv[0]; + st1= mtface[face_index].uv[1]; + st2= mtface[face_index].uv[2]; + + if(mface.v4) { + st3= mtface[face_index].uv[3]; + resolve_quad_uv(uv, st, st0, st1, st2, st3); + } else + resolve_tri_uv(uv, st, st0, st1, st2); + + CLAMP(uv[0], 0.0f, 1.0f); + CLAMP(uv[1], 0.0f, 1.0f); + + get_ccgdm_data(lores_dm, hires_dm, lvl, face_index, uv[0], uv[1], NULL, n); + + mul_v3_m3v3(vec, tangmat, n); + normalize_v3(vec); + mul_v3_fl(vec, 0.5); + add_v3_v3(vec, tmp); + + if(ibuf->rect_float) { + float *rrgbf= ibuf->rect_float + pixel*4; + rrgbf[0]= vec[0]; + rrgbf[1]= vec[1]; + rrgbf[2]= vec[2]; + rrgbf[3]= 1.0f; + + ibuf->userflags= IB_RECT_INVALID; + } else { + char *rrgb= (char*)ibuf->rect + pixel*4; + rrgb[0]= FTOCHAR(vec[0]); + rrgb[1]= FTOCHAR(vec[1]); + rrgb[2]= FTOCHAR(vec[2]); + rrgb[3]= 255; + } +#endif +} + +static void count_images(MultiresBakeRender *bkr) +{ + int a, totface; + DerivedMesh *dm= bkr->lores_dm; + MTFace *mtface= CustomData_get_layer(&dm->faceData, CD_MTFACE); + + bkr->image.first= bkr->image.last= NULL; + bkr->tot_image= 0; + + totface= dm->getNumFaces(dm); + + for(a= 0; a<totface; a++) + mtface[a].tpage->id.flag&= ~LIB_DOIT; + + for(a= 0; a<totface; a++) { + Image *ima= mtface[a].tpage; + if((ima->id.flag&LIB_DOIT)==0) { + LinkData *data= BLI_genericNodeN(ima); + BLI_addtail(&bkr->image, data); + bkr->tot_image++; + ima->id.flag|= LIB_DOIT; + } + } + + for(a= 0; a<totface; a++) + mtface[a].tpage->id.flag&= ~LIB_DOIT; +} + +static void bake_images(MultiresBakeRender *bkr) +{ + LinkData *link; + + for(link= bkr->image.first; link; link= link->next) { + Image *ima= (Image*)link->data; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf->x>0 && ibuf->y>0) { + ibuf->userdata= MEM_callocN(ibuf->y*ibuf->x, "MultiresBake imbuf mask"); + + switch(bkr->mode) { + case RE_BAKE_NORMALS: + do_multires_bake(bkr, ima, apply_tangmat_callback, NULL, NULL, NULL); + break; + case RE_BAKE_DISPLACEMENT: + do_multires_bake(bkr, ima, apply_heights_callback, init_heights_data, + apply_heights_data, free_heights_data); + break; + } + } + + ima->id.flag|= LIB_DOIT; + } +} + +static void finish_images(MultiresBakeRender *bkr) +{ + LinkData *link; + + for(link= bkr->image.first; link; link= link->next) { + Image *ima= (Image*)link->data; + int i; + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if(ibuf->x<=0 || ibuf->y<=0) + continue; + + /* Margin */ + if(bkr->bake_filter) { + char *temprect; + + /* extend the mask +2 pixels from the image, + * this is so colors dont blend in from outside */ + + for(i=0; i<bkr->bake_filter; i++) + IMB_mask_filter_extend((char *)ibuf->userdata, ibuf->x, ibuf->y); + + temprect = MEM_dupallocN(ibuf->userdata); + + /* expand twice to clear this many pixels, so they blend back in */ + IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y); + IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y); + + /* clear all pixels in the margin */ + IMB_mask_clear(ibuf, temprect, FILTER_MASK_MARGIN); + MEM_freeN(temprect); + + for(i= 0; i<bkr->bake_filter; i++) + IMB_filter_extend(ibuf, (char *)ibuf->userdata); + } + + ibuf->userflags|= IB_BITMAPDIRTY; + if(ibuf->mipmap[0]) { + ibuf->userflags|= IB_MIPMAP_INVALID; + imb_freemipmapImBuf(ibuf); + } + + if(ibuf->userdata) { + MEM_freeN(ibuf->userdata); + ibuf->userdata= NULL; + } + } +} + +static void multiresbake_start(MultiresBakeRender *bkr) +{ + count_images(bkr); + bake_images(bkr); + finish_images(bkr); +} + +static int multiresbake_check(bContext *C, wmOperator *op) { + Scene *scene= CTX_data_scene(C); + Object *ob; + Mesh *me; + MultiresModifierData *mmd; + int ok= 1, a; + + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + ob= base->object; + + if(ob->type != OB_MESH) { + BKE_report(op->reports, RPT_ERROR, "Basking of multires data only works with active object which is a mesh"); + + ok= 0; + break; + } + + me= (Mesh*)ob->data; + mmd= get_multires_modifier(scene, ob, 0); + + /* Multi-resolution should be and be last in the stack */ + if(ok && mmd) { + ModifierData *md; + + ok= mmd->totlvl>0; + + for(md = (ModifierData*)mmd->modifier.next; md && ok; md = md->next) { + if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + ok= 0; + } + } + } else ok= 0; + + if(!ok) { + BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object"); + + break; + } + + if(!me->mtface) { + BKE_report(op->reports, RPT_ERROR, "Mesh should be unwrapped before multires data baking"); + + ok= 0; + } else { + a= me->totface; + while (ok && a--) { + Image *ima= me->mtface[a].tpage; + + if(!ima) { + BKE_report(op->reports, RPT_ERROR, "You should have active texture to use multires baker"); + + ok= 0; + } else { + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + if(!ibuf) { + BKE_report(op->reports, RPT_ERROR, "Baking should happend to image with image buffer"); + + ok= 0; + } else { + if(ibuf->rect==NULL && ibuf->rect_float==NULL) + ok= 0; + + if(ibuf->rect_float && !(ibuf->channels==0 || ibuf->channels==4)) + ok= 0; + + if(!ok) + BKE_report(op->reports, RPT_ERROR, "Baking to unsupported image type"); + } + } + } + } + + if(!ok) + break; + } + CTX_DATA_END; + + return ok; +} + +static DerivedMesh *multiresbake_create_loresdm(Scene *scene, Object *ob, int *lvl) +{ + DerivedMesh *dm; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0); + Mesh *me= (Mesh*)ob->data; + + *lvl= mmd->lvl; + + if(mmd->lvl==0) { + DerivedMesh *tmp_dm= CDDM_from_mesh(me, ob); + dm= CDDM_copy(tmp_dm, 0); + tmp_dm->release(tmp_dm); + } else { + MultiresModifierData tmp_mmd= *mmd; + DerivedMesh *cddm= CDDM_from_mesh(me, ob); + + tmp_mmd.lvl= mmd->lvl; + dm= multires_dm_create_from_derived(&tmp_mmd, 1, cddm, ob, 0, 0); + cddm->release(cddm); + } + + return dm; +} + +static DerivedMesh *multiresbake_create_hiresdm(Scene *scene, Object *ob, int *lvl, int *simple) +{ + Mesh *me= (Mesh*)ob->data; + MultiresModifierData *mmd= get_multires_modifier(scene, ob, 0); + MultiresModifierData tmp_mmd= *mmd; + DerivedMesh *cddm= CDDM_from_mesh(me, ob); + DerivedMesh *dm; + + *lvl= mmd->totlvl; + *simple= mmd->simple; + + tmp_mmd.lvl= mmd->totlvl; + dm= multires_dm_create_from_derived(&tmp_mmd, 1, cddm, ob, 0, 0); + cddm->release(cddm); + + return dm; +} + +static void clear_images(MTFace *mtface, int totface) +{ + int a; + float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f}; + + for(a= 0; a<totface; a++) + mtface[a].tpage->id.flag&= ~LIB_DOIT; + + for(a= 0; a<totface; a++) { + Image *ima= mtface[a].tpage; + + if((ima->id.flag&LIB_DOIT)==0) { + ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL); + + IMB_rectfill(ibuf, vec); + ima->id.flag|= LIB_DOIT; + } + } + + for(a= 0; a<totface; a++) + mtface[a].tpage->id.flag&= ~LIB_DOIT; +} + +static int multiresbake_image_exec_locked(bContext *C, wmOperator *op) +{ + Object *ob; + Scene *scene= CTX_data_scene(C); + + if(!multiresbake_check(C, op)) + return OPERATOR_CANCELLED; + + if(scene->r.bake_flag&R_BAKE_CLEAR) { /* clear images */ + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + Mesh *me; + + ob= base->object; + me= (Mesh*)ob->data; + + clear_images(me->mtface, me->totface); + } + CTX_DATA_END; + } + + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + MultiresBakeRender bkr= {0}; + + ob= base->object; + + /* copy data stored in job descriptor */ + bkr.bake_filter= scene->r.bake_filter; + bkr.mode= scene->r.bake_mode; + bkr.use_lores_mesh= scene->r.bake_flag&R_BAKE_LORES_MESH; + + /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ + bkr.lores_dm= multiresbake_create_loresdm(scene, ob, &bkr.lvl); + bkr.hires_dm= multiresbake_create_hiresdm(scene, ob, &bkr.tot_lvl, &bkr.simple); + + multiresbake_start(&bkr); + + BLI_freelistN(&bkr.image); + + bkr.lores_dm->release(bkr.lores_dm); + bkr.hires_dm->release(bkr.hires_dm); + } + CTX_DATA_END; + + return OPERATOR_FINISHED; +} + +/* Multiresbake adopted for job-system executing */ +static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj) +{ + Scene *scene= CTX_data_scene(C); + Object *ob; + + /* backup scene settings, so their changing in UI would take no effect on baker */ + bkj->bake_filter= scene->r.bake_filter; + bkj->mode= scene->r.bake_mode; + bkj->use_lores_mesh= scene->r.bake_flag&R_BAKE_LORES_MESH; + bkj->bake_clear= scene->r.bake_flag&R_BAKE_CLEAR; + + CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { + MultiresBakerJobData *data; + ob= base->object; + + data= MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data"); + data->lores_dm = multiresbake_create_loresdm(scene, ob, &data->lvl); + data->hires_dm = multiresbake_create_hiresdm(scene, ob, &data->tot_lvl, &data->simple); + BLI_addtail(&bkj->data, data); + } + CTX_DATA_END; +} + +static void multiresbake_startjob(void *bkv, short *stop, short *do_update, float *progress) +{ + MultiresBakerJobData *data; + MultiresBakeJob *bkj= bkv; + int baked_objects= 0, tot_obj; + + tot_obj= BLI_countlist(&bkj->data); + + if(bkj->bake_clear) { /* clear images */ + for(data= bkj->data.first; data; data= data->next) { + DerivedMesh *dm= data->lores_dm; + MTFace *mtface= CustomData_get_layer(&dm->faceData, CD_MTFACE); + + clear_images(mtface, dm->getNumFaces(dm)); + } + } + + for(data= bkj->data.first; data; data= data->next) { + MultiresBakeRender bkr= {0}; + + /* copy data stored in job descriptor */ + bkr.bake_filter= bkj->bake_filter; + bkr.mode= bkj->mode; + bkr.use_lores_mesh= bkj->use_lores_mesh; + + /* create low-resolution DM (to bake to) and hi-resolution DM (to bake from) */ + bkr.lores_dm= data->lores_dm; + bkr.hires_dm= data->hires_dm; + bkr.tot_lvl= data->tot_lvl; + bkr.lvl= data->lvl; + bkr.simple= data->simple; + + /* needed for proper progress bar */ + bkr.tot_obj= tot_obj; + bkr.baked_objects= baked_objects; + + bkr.stop= stop; + bkr.do_update= do_update; + bkr.progress= progress; + + multiresbake_start(&bkr); + + BLI_freelistN(&bkr.image); + + baked_objects++; + } +} + +static void multiresbake_freejob(void *bkv) +{ + MultiresBakeJob *bkj= bkv; + MultiresBakerJobData *data, *next; + + data= bkj->data.first; + while (data) { + next= data->next; + data->lores_dm->release(data->lores_dm); + data->hires_dm->release(data->hires_dm); + MEM_freeN(data); + data= next; + } + + MEM_freeN(bkj); +} + +static int multiresbake_image_exec(bContext *C, wmOperator *op) +{ + Scene *scene= CTX_data_scene(C); + MultiresBakeJob *bkr; + wmJob *steve; + + if(!multiresbake_check(C, op)) + return OPERATOR_CANCELLED; + + bkr= MEM_callocN(sizeof(MultiresBakeJob), "MultiresBakeJob data"); + init_multiresbake_job(C, bkr); + + /* setup job */ + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Multires Bake", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS); + WM_jobs_customdata(steve, bkr, multiresbake_freejob); + WM_jobs_timer(steve, 0.2, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ + WM_jobs_callbacks(steve, multiresbake_startjob, NULL, NULL, NULL); + + G.afbreek= 0; + + WM_jobs_start(CTX_wm_manager(C), steve); + WM_cursor_wait(0); + + /* add modal handler for ESC */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; +} + /* ****************** render BAKING ********************** */ /* threaded break test */ @@ -147,9 +1329,6 @@ static void init_bake_internal(BakeRender *bkr, bContext *C) { Scene *scene= CTX_data_scene(C); - /* flush multires changes (for sculpt) */ - multires_force_render_update(CTX_data_active_object(C)); - /* get editmode results */ ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */ @@ -273,43 +1452,59 @@ static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), wmEven return OPERATOR_PASS_THROUGH; } +static int is_multires_bake(Scene *scene) +{ + if ( ELEM(scene->r.bake_mode, RE_BAKE_NORMALS, RE_BAKE_DISPLACEMENT)) + return scene->r.bake_flag & R_BAKE_MULTIRES; + + return 0; +} + static int objects_bake_render_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(_event)) { Scene *scene= CTX_data_scene(C); + int result= OPERATOR_CANCELLED; - /* only one render job at a time */ - if(WM_jobs_test(CTX_wm_manager(C), scene)) - return OPERATOR_CANCELLED; - - if(test_bake_internal(C, op->reports)==0) { - return OPERATOR_CANCELLED; - } - else { - BakeRender *bkr= MEM_callocN(sizeof(BakeRender), "render bake"); - wmJob *steve; + if(is_multires_bake(scene)) { + result= multiresbake_image_exec(C, op); + } else { + /* only one render job at a time */ + if(WM_jobs_test(CTX_wm_manager(C), scene)) + return OPERATOR_CANCELLED; + + if(test_bake_internal(C, op->reports)==0) { + return OPERATOR_CANCELLED; + } + else { + BakeRender *bkr= MEM_callocN(sizeof(BakeRender), "render bake"); + wmJob *steve; - init_bake_internal(bkr, C); - bkr->reports= op->reports; + init_bake_internal(bkr, C); + bkr->reports= op->reports; - /* setup job */ - steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS); - WM_jobs_customdata(steve, bkr, bake_freejob); - WM_jobs_timer(steve, 0.2, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ - WM_jobs_callbacks(steve, bake_startjob, NULL, bake_update, NULL); + /* setup job */ + steve= WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene, "Texture Bake", WM_JOB_EXCL_RENDER|WM_JOB_PRIORITY|WM_JOB_PROGRESS); + WM_jobs_customdata(steve, bkr, bake_freejob); + WM_jobs_timer(steve, 0.2, NC_IMAGE, 0); /* TODO - only draw bake image, can we enforce this */ + WM_jobs_callbacks(steve, bake_startjob, NULL, bake_update, NULL); - G.afbreek= 0; - G.rendering = 1; + G.afbreek= 0; + G.rendering = 1; - WM_jobs_start(CTX_wm_manager(C), steve); + WM_jobs_start(CTX_wm_manager(C), steve); - WM_cursor_wait(0); - WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); + WM_cursor_wait(0); - /* add modal handler for ESC */ - WM_event_add_modal_handler(C, op); + /* add modal handler for ESC */ + WM_event_add_modal_handler(C, op); + } + + result= OPERATOR_RUNNING_MODAL; } - return OPERATOR_RUNNING_MODAL; + WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); + + return result; } @@ -317,46 +1512,53 @@ static int bake_image_exec(bContext *C, wmOperator *op) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); + int result= OPERATOR_CANCELLED; + if(is_multires_bake(scene)) { + result= multiresbake_image_exec_locked(C, op); + } else { + if(test_bake_internal(C, op->reports)==0) { + return OPERATOR_CANCELLED; + } + else { + ListBase threads; + BakeRender bkr= {NULL}; - if(test_bake_internal(C, op->reports)==0) { - return OPERATOR_CANCELLED; - } - else { - ListBase threads; - BakeRender bkr= {NULL}; + init_bake_internal(&bkr, C); + bkr.reports= op->reports; - init_bake_internal(&bkr, C); - bkr.reports= op->reports; + RE_test_break_cb(bkr.re, NULL, thread_break); + G.afbreek= 0; /* blender_test_break uses this global */ - RE_test_break_cb(bkr.re, NULL, thread_break); - G.afbreek= 0; /* blender_test_break uses this global */ + RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE)? OBACT: NULL); - RE_Database_Baking(bkr.re, bmain, scene, scene->lay, scene->r.bake_mode, (scene->r.bake_flag & R_BAKE_TO_ACTIVE)? OBACT: NULL); + /* baking itself is threaded, cannot use test_break in threads */ + BLI_init_threads(&threads, do_bake_render, 1); + bkr.ready= 0; + BLI_insert_thread(&threads, &bkr); - /* baking itself is threaded, cannot use test_break in threads */ - BLI_init_threads(&threads, do_bake_render, 1); - bkr.ready= 0; - BLI_insert_thread(&threads, &bkr); + while(bkr.ready==0) { + PIL_sleep_ms(50); + if(bkr.ready) + break; - while(bkr.ready==0) { - PIL_sleep_ms(50); - if(bkr.ready) - break; + /* used to redraw in 2.4x but this is just for exec in 2.5 */ + if (!G.background) + blender_test_break(); + } + BLI_end_threads(&threads); - /* used to redraw in 2.4x but this is just for exec in 2.5 */ - if (!G.background) - blender_test_break(); - } - BLI_end_threads(&threads); + if(bkr.tot==0) BKE_report(op->reports, RPT_ERROR, "No valid images found to bake to"); - if(bkr.tot==0) BKE_report(op->reports, RPT_ERROR, "No valid images found to bake to"); + finish_bake_internal(&bkr); - finish_bake_internal(&bkr); + result= OPERATOR_FINISHED; + } } WM_event_add_notifier(C, NC_SCENE|ND_RENDER_RESULT, scene); - return OPERATOR_FINISHED; + + return result; } void OBJECT_OT_bake_image(wmOperatorType *ot) diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 92284f59183..5cc9166e973 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -1326,16 +1326,22 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; if(mmd->bindcagecos) { - if(mmd->bindweights) MEM_freeN(mmd->bindweights); if(mmd->bindcagecos) MEM_freeN(mmd->bindcagecos); if(mmd->dyngrid) MEM_freeN(mmd->dyngrid); if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences); + if(mmd->bindinfluences) MEM_freeN(mmd->bindinfluences); + if(mmd->bindoffsets) MEM_freeN(mmd->bindoffsets); if(mmd->dynverts) MEM_freeN(mmd->dynverts); - mmd->bindweights= NULL; + if(mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */ + if(mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */ + mmd->bindcagecos= NULL; mmd->dyngrid= NULL; mmd->dyninfluences= NULL; + mmd->bindoffsets= NULL; mmd->dynverts= NULL; + mmd->bindweights= NULL; /* deprecated */ + mmd->bindcos= NULL; /* deprecated */ mmd->totvert= 0; mmd->totcagevert= 0; mmd->totinfluence= 0; diff --git a/source/blender/editors/object/object_shapekey.c b/source/blender/editors/object/object_shapekey.c index a277c99c7ed..a7b73b21865 100644 --- a/source/blender/editors/object/object_shapekey.c +++ b/source/blender/editors/object/object_shapekey.c @@ -203,9 +203,9 @@ static int object_shape_key_mirror(bContext *C, Object *ob) fp1= ((float *)kb->data) + i1*3; fp2= ((float *)kb->data) + i2*3; - VECCOPY(tvec, fp1); - VECCOPY(fp1, fp2); - VECCOPY(fp2, tvec); + copy_v3_v3(tvec, fp1); + copy_v3_v3(fp1, fp2); + copy_v3_v3(fp2, tvec); /* flip x axis */ fp1[0] = -fp1[0]; @@ -217,7 +217,46 @@ static int object_shape_key_mirror(bContext *C, Object *ob) //BMESH_TODO mesh_octree_table(ob, NULL, NULL, 'e'); } - /* todo, other types? */ + else if (ob->type == OB_LATTICE) { + Lattice *lt= ob->data; + int i1, i2; + float *fp1, *fp2; + int u, v, w; + /* half but found up odd value */ + const int pntsu_half = (((lt->pntsu / 2) + (lt->pntsu % 2))) ; + + /* currently editmode isnt supported by mesh so + * ignore here for now too */ + + /* if(lt->editlatt) lt= lt->editlatt->latt; */ + + for(w=0; w<lt->pntsw; w++) { + for(v=0; v<lt->pntsv; v++) { + for(u=0; u<pntsu_half; u++) { + int u_inv= (lt->pntsu - 1) - u; + float tvec[3]; + if(u == u_inv) { + i1= LT_INDEX(lt, u, v, w); + fp1= ((float *)kb->data) + i1*3; + fp1[0]= -fp1[0]; + } + else { + i1= LT_INDEX(lt, u, v, w); + i2= LT_INDEX(lt, u_inv, v, w); + + fp1= ((float *)kb->data) + i1*3; + fp2= ((float *)kb->data) + i2*3; + + copy_v3_v3(tvec, fp1); + copy_v3_v3(fp1, fp2); + copy_v3_v3(fp2, tvec); + fp1[0]= -fp1[0]; + fp2[0]= -fp2[0]; + } + } + } + } + } MEM_freeN(tag_elem); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 881643a01ea..92fab159875 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -79,6 +79,7 @@ static void vgroup_remap_update_users(Object *ob, int *map); static void vgroup_delete_edit_mode(Object *ob, bDeformGroup *defgroup); static void vgroup_delete_object_mode(Object *ob, bDeformGroup *dg); +static void vgroup_delete_all(Object *ob); static Lattice *vgroup_edit_lattice(Object *ob) { @@ -140,22 +141,30 @@ void ED_vgroup_delete(Object *ob, bDeformGroup *defgroup) vgroup_delete_object_mode(ob, dg); } -void ED_vgroup_data_create(ID *id) +int ED_vgroup_data_create(ID *id) { /* create deform verts */ if(GS(id->name)==ID_ME) { Mesh *me= (Mesh *)id; me->dvert= CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert); + return TRUE; } else if(GS(id->name)==ID_LT) { Lattice *lt= (Lattice *)id; lt->dvert= MEM_callocN(sizeof(MDeformVert)*lt->pntsu*lt->pntsv*lt->pntsw, "lattice deformVert"); + return TRUE; + } + else { + return FALSE; } } static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_tot) { + *dvert_tot = 0; + *dvert_arr = NULL; + if(id) { switch(GS(id->name)) { case ID_ME: @@ -169,8 +178,6 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to int i; if (!CustomData_has_layer(&em->bm->vdata, CD_MDEFORMVERT)) { - *dvert_tot = 0; - *dvert_arr = NULL; return 0; } @@ -199,8 +206,9 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to return 1; } - else + else { return 0; + } } case ID_LT: { @@ -226,8 +234,6 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to } } - *dvert_arr= NULL; - *dvert_tot= 0; return 0; } @@ -269,13 +275,24 @@ int ED_vgroup_copy_array(Object *ob, Object *ob_from) int i; int totdef_from= BLI_countlist(&ob_from->defbase); int totdef= BLI_countlist(&ob->defbase); + short new_vgroup= FALSE; ED_vgroup_give_parray(ob_from->data, &dvert_array_from, &dvert_tot_from); ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); + if((dvert_array == NULL) && (dvert_array_from != NULL) && ED_vgroup_data_create(ob->data)) { + ED_vgroup_give_parray(ob->data, &dvert_array, &dvert_tot); + new_vgroup= TRUE; + } + if(ob==ob_from || dvert_tot==0 || (dvert_tot != dvert_tot_from) || dvert_array_from==NULL || dvert_array==NULL) { if (dvert_array) MEM_freeN(dvert_array); if (dvert_array_from) MEM_freeN(dvert_array_from); + + if(new_vgroup == TRUE) { + /* free the newly added vgroup since it wasn't compatible */ + vgroup_delete_all(ob); + } return 0; } @@ -1018,64 +1035,83 @@ static void vgroup_clean_all(Object *ob, float eul, int keep_single) if (dvert_array) MEM_freeN(dvert_array); } -void ED_vgroup_mirror(Object *ob, int mirror_weights, int flip_vgroups) + +static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr, + const char sel, const char sel_mirr, + const int *flip_map, + const short mirror_weights, const short flip_vgroups) +{ + BLI_assert(sel || sel_mirr); + + if(sel_mirr && sel) { + /* swap */ + if(mirror_weights) + SWAP(MDeformVert, *dvert, *dvert_mirr); + if(flip_vgroups) { + defvert_flip(dvert, flip_map); + defvert_flip(dvert_mirr, flip_map); + } + } + else { + /* dvert should always be the target */ + if(sel_mirr) { + SWAP(MDeformVert *, dvert, dvert_mirr); + } + + if(mirror_weights) + defvert_copy(dvert, dvert_mirr); + if(flip_vgroups) { + defvert_flip(dvert, flip_map); + } + } +} + +void ED_vgroup_mirror(Object *ob, const short mirror_weights, const short flip_vgroups) { - BMVert *eve, *eve_mirr; +#define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups) + +#if 0 + EditVert *eve, *eve_mirr; +#endif + MDeformVert *dvert, *dvert_mirr; + short sel, sel_mirr; int *flip_map; if(mirror_weights==0 && flip_vgroups==0) return; + flip_map= defgroup_flip_map(ob, 0); + /* only the active group */ if(ob->type == OB_MESH) { - Mesh *me= ob->data; - BMEditMesh *em = me->edit_btmesh; - BMIter iter; #if 1 //BMESH_TODO - (void)eve; - (void)eve_mirr; (void)dvert; (void)dvert_mirr; (void)flip_map; - (void)iter; - (void)em; #else - EM_cache_x_mirror_vert(ob, em); + Mesh *me= ob->data; + EditMesh *em = BKE_mesh_get_editmesh(me); - if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) + + if(!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { + MEM_freeN(flip_map); return; + } - flip_map= defgroup_flip_map(ob, 0); + EM_cache_x_mirror_vert(ob, em); /* Go through the list of editverts and assign them */ for(eve=em->verts.first; eve; eve=eve->next){ if((eve_mirr=eve->tmp.v)) { - if((eve_mirr->f & SELECT || eve->f & SELECT) && (eve != eve_mirr)) { + sel= eve->f & SELECT; + sel_mirr= eve_mirr->f & SELECT; + + if((sel || sel_mirr) && (eve != eve_mirr)) { dvert= CustomData_em_get(&em->vdata, eve->data, CD_MDEFORMVERT); dvert_mirr= CustomData_em_get(&em->vdata, eve_mirr->data, CD_MDEFORMVERT); if(dvert && dvert_mirr) { - if(eve_mirr->f & SELECT && eve->f & SELECT) { - /* swap */ - if(mirror_weights) - SWAP(MDeformVert, *dvert, *dvert_mirr); - if(flip_vgroups) { - defvert_flip(dvert, flip_map); - defvert_flip(dvert_mirr, flip_map); - } - } - else { - /* dvert should always be the target */ - if(eve_mirr->f & SELECT) { - SWAP(MDeformVert *, dvert, dvert_mirr); - } - - if(mirror_weights) - defvert_copy(dvert, dvert_mirr); - if(flip_vgroups) { - defvert_flip(dvert, flip_map); - } - } + VGROUP_MIRR_OP; } } @@ -1083,11 +1119,59 @@ void ED_vgroup_mirror(Object *ob, int mirror_weights, int flip_vgroups) } } - MEM_freeN(flip_map); - BKE_mesh_end_editmesh(me, em); -#endif +#endif // BMESH_TODO } + else if (ob->type == OB_LATTICE) { + Lattice *lt= ob->data; + int i1, i2; + int u, v, w; + int pntsu_half; + /* half but found up odd value */ + + if(lt->editlatt) lt= lt->editlatt->latt; + + if(lt->pntsu == 1 || lt->dvert == NULL) { + MEM_freeN(flip_map); + return; + } + + /* unlike editmesh we know that by only looping over the first hald of + * the 'u' indicies it will cover all points except the middle which is + * ok in this case */ + pntsu_half= lt->pntsu / 2; + + for(w=0; w<lt->pntsw; w++) { + for(v=0; v<lt->pntsv; v++) { + for(u=0; u<pntsu_half; u++) { + int u_inv= (lt->pntsu - 1) - u; + if(u != u_inv) { + BPoint *bp, *bp_mirr; + + i1= LT_INDEX(lt, u, v, w); + i2= LT_INDEX(lt, u_inv, v, w); + + bp= <->def[i1]; + bp_mirr= <->def[i2]; + + sel= bp->f1 & SELECT; + sel_mirr= bp_mirr->f1 & SELECT; + + if(sel || sel_mirr) { + dvert= <->dvert[i1]; + dvert_mirr= <->dvert[i2]; + + VGROUP_MIRR_OP; + } + } + } + } + } + } + + MEM_freeN(flip_map); + +#undef VGROUP_MIRR_OP } static void vgroup_remap_update_users(Object *ob, int *map) @@ -1933,17 +2017,25 @@ void OBJECT_OT_vertex_group_copy_to_linked(wmOperatorType *ot) ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; } -static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *UNUSED(op)) +static int vertex_group_copy_to_selected_exec(bContext *C, wmOperator *op) { Object *obact= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + int change= 0; + int fail= 0; CTX_DATA_BEGIN(C, Object*, ob, selected_editable_objects) { - if(obact != ob) - ED_vgroup_copy_array(ob, obact); + if(obact != ob) { + if(ED_vgroup_copy_array(ob, obact)) change++; + else fail++; + } } CTX_DATA_END; + if((change == 0 && fail == 0) || fail) { + BKE_reportf(op->reports, RPT_ERROR, "Copy to VGroups to Selected warning done %d, failed %d, object data must have matching indicies", change, fail); + } + return OPERATOR_FINISHED; } diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 4fcc989e4a1..b36aa41f755 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3971,18 +3971,6 @@ int PE_undo_valid(Scene *scene) return 0; } -static void PTCacheUndo_number(Scene *scene, PTCacheEdit *edit, int nr) -{ - PTCacheUndo *undo; - int a=1; - - for(undo= edit->undo.first; undo; undo= undo->next, a++) { - if(a==nr) break; - } - edit->curundo= undo; - PE_undo_step(scene, 0); -} - static void PTCacheUndo_clear(PTCacheEdit *edit) { PTCacheUndo *undo; @@ -4008,32 +3996,38 @@ void PE_redo(Scene *scene) PE_undo_step(scene, -1); } -void PE_undo_menu(Scene *scene, Object *ob) +void PE_undo_number(Scene *scene, int nr) { - PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, OBACT); PTCacheUndo *undo; - DynStr *ds; - short event=0; - char *menu; - - if(!edit) return; - - ds= BLI_dynstr_new(); - - BLI_dynstr_append(ds, "Particlemode Undo History %t"); + int a=0; - for(undo= edit->undo.first; undo; undo= undo->next) { - BLI_dynstr_append(ds, "|"); - BLI_dynstr_append(ds, undo->name); + for(undo= edit->undo.first; undo; undo= undo->next, a++) { + if(a==nr) break; } + edit->curundo= undo; + PE_undo_step(scene, 0); +} + + +/* get name of undo item, return null if no item with this index */ +/* if active pointer, set it to 1 if true */ +char *PE_undo_get_name(Scene *scene, int nr, int *active) +{ + PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheUndo *undo; - menu= BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - -// XXX event= pupmenu_col(menu, 20); - MEM_freeN(menu); + if(active) *active= 0; - if(event>0) PTCacheUndo_number(scene, edit, event); + if(edit) { + undo= BLI_findlink(&edit->undo, nr); + if(undo) { + if(active && undo==edit->curundo) + *active= 1; + return undo->name; + } + } + return NULL; } /************************ utilities ******************************/ diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 64a4d47cddc..9dfcde6ed0d 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -184,8 +184,7 @@ void render_view_open(bContext *C, int mx, int my) area_was_image = 1; /* this function returns with changed context */ - ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_IMAGE); - sa= CTX_wm_area(C); + sa= ED_screen_full_newspace(C, CTX_wm_area(C), SPACE_IMAGE); } if(!sa) { diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index a1a4f33d008..4d531e78ec0 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -650,8 +650,12 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int if(ar->next==NULL && alignment!=RGN_ALIGN_QSPLIT) alignment= RGN_ALIGN_NONE; + /* prefsize, for header we stick to exception */ prefsizex= ar->sizex?ar->sizex:ar->type->prefsizex; - prefsizey= ar->sizey?ar->sizey:ar->type->prefsizey; + if(ar->regiontype==RGN_TYPE_HEADER) + prefsizey= ar->type->prefsizey; + else + prefsizey= ar->sizey?ar->sizey:ar->type->prefsizey; /* hidden is user flag */ if(ar->flag & RGN_FLAG_HIDDEN); @@ -811,8 +815,18 @@ static void region_rect_recursive(ScrArea *sa, ARegion *ar, rcti *remainder, int ar->winrct.xmax= ar->winrct.xmin; } /* in end, add azones, where appropriate */ - region_azone_add(sa, ar, alignment); - + if(ar->regiontype == RGN_TYPE_HEADER && ar->winy + 6 > sa->winy) { + /* The logic for this is: when the header takes up the full area, + * disallow hiding it to view the main window. + * + * Without this, uou can drag down the file selectors header and hide it + * by accident very easily (highly annoying!), the value 6 is arbitrary + * but accounts for small common rounding problems when scaling the UI, + * must be minimum '4' */ + } + else { + region_azone_add(sa, ar, alignment); + } region_rect_recursive(sa, ar->next, remainder, quad); } @@ -953,6 +967,9 @@ void ED_area_initialize(wmWindowManager *wm, wmWindow *win, ScrArea *sa) uiFreeBlocks(NULL, &ar->uiblocks); } + /* rechecks 2d matrix for header on dpi changing, do not do for other regions, it resets view && blocks view2d operator polls (ton) */ + if(ar->regiontype==RGN_TYPE_HEADER) + ar->v2d.flag &= ~V2D_IS_INITIALISED; } } @@ -1121,7 +1138,7 @@ void ED_area_newspace(bContext *C, ScrArea *sa, int type) /* tell WM to refresh, cursor types etc */ WM_event_add_mousemove(C); - /*send space change notifyer*/ + /*send space change notifier*/ WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CHANGED, sa); ED_area_tag_refresh(sa); @@ -1148,7 +1165,7 @@ void ED_area_prevspace(bContext *C, ScrArea *sa) } ED_area_tag_redraw(sa); - /*send space change notifyer*/ + /*send space change notifier*/ WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CHANGED, sa); } @@ -1196,7 +1213,7 @@ static void spacefunc(struct bContext *C, void *UNUSED(arg1), void *UNUSED(arg2) ED_area_newspace(C, CTX_wm_area(C), CTX_wm_area(C)->butspacetype); ED_area_tag_redraw(CTX_wm_area(C)); - /*send space change notifyer*/ + /*send space change notifier*/ WM_event_add_notifier(C, NC_SPACE|ND_SPACE_CHANGED, CTX_wm_area(C)); } @@ -1208,13 +1225,13 @@ int ED_area_header_switchbutton(const bContext *C, uiBlock *block, int yco) int xco= 8; but= uiDefIconTextButC(block, ICONTEXTROW, 0, ICON_VIEW3D, - editortype_pup(), xco, yco, XIC+10, YIC, + editortype_pup(), xco, yco, UI_UNIT_X+10, UI_UNIT_Y, &(sa->butspacetype), 1.0, SPACEICONMAX, 0, 0, "Displays current editor type. " "Click for menu of available types"); uiButSetFunc(but, spacefunc, NULL, NULL); - return xco + XIC + 14; + return xco + UI_UNIT_X + 14; } int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco) @@ -1230,21 +1247,21 @@ int ED_area_header_standardbuttons(const bContext *C, uiBlock *block, int yco) if (sa->flag & HEADER_NO_PULLDOWN) { uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0, ICON_DISCLOSURE_TRI_RIGHT, - xco,yco,XIC,YIC-2, + xco,yco,UI_UNIT_X,UI_UNIT_Y-2, &(sa->flag), 0, 0, 0, 0, "Show pulldown menus"); } else { uiDefIconButBitS(block, TOG, HEADER_NO_PULLDOWN, 0, ICON_DISCLOSURE_TRI_DOWN, - xco,yco,XIC,YIC-2, + xco,yco,UI_UNIT_X,UI_UNIT_Y-2, &(sa->flag), 0, 0, 0, 0, "Hide pulldown menus"); } uiBlockSetEmboss(block, UI_EMBOSS); - return xco + XIC; + return xco + UI_UNIT_X; } /************************ standard UI regions ************************/ @@ -1265,11 +1282,11 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char * if(vertical) { w= v2d->cur.xmax - v2d->cur.xmin; - em= (ar->type->prefsizex)? 10: 20; + em= (ar->type->prefsizex)? UI_UNIT_Y/2: UI_UNIT_Y; } else { w= UI_PANEL_WIDTH; - em= (ar->type->prefsizex)? 10: 20; + em= (ar->type->prefsizex)? UI_UNIT_Y/2: UI_UNIT_Y; } x= 0; @@ -1293,8 +1310,8 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char * panel= uiBeginPanel(sa, ar, block, pt, &open); /* bad fixed values */ - header= (pt->flag & PNL_NO_HEADER)? 0: 20; - triangle= 22; + header= (pt->flag & PNL_NO_HEADER)? 0: UI_UNIT_Y; + triangle= (int)(UI_UNIT_Y * 1.1f); if(vertical) y -= header; @@ -1446,6 +1463,7 @@ void ED_region_header(const bContext *C, ARegion *ar) HeaderType *ht; Header header = {NULL}; int maxco, xco, yco; + int headery= ED_area_headersize(); /* clear */ UI_ThemeClearColor((ED_screen_area_active(C))?TH_HEADER:TH_HEADERDESEL); @@ -1455,12 +1473,12 @@ void ED_region_header(const bContext *C, ARegion *ar) UI_view2d_view_ortho(&ar->v2d); xco= maxco= 8; - yco= HEADERY-4; + yco= headery-4; /* draw all headers types */ for(ht= ar->type->headertypes.first; ht; ht= ht->next) { block= uiBeginBlock(C, ar, ht->idname, UI_EMBOSS); - layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, HEADERY-6, 1, style); + layout= uiBlockLayout(block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, xco, yco, UI_UNIT_Y, 1, style); if(ht->draw) { header.type= ht; @@ -1484,7 +1502,7 @@ void ED_region_header(const bContext *C, ARegion *ar) } /* always as last */ - UI_view2d_totRect_set(&ar->v2d, maxco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); + UI_view2d_totRect_set(&ar->v2d, maxco+UI_UNIT_X+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); /* restore view matrix? */ UI_view2d_view_restore(C); @@ -1495,3 +1513,8 @@ void ED_region_header_init(ARegion *ar) UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_HEADER, ar->winx, ar->winy); } +/* UI_UNIT_Y is defined as U variable now, depending dpi */ +int ED_area_headersize(void) +{ + return UI_UNIT_Y+6; +} diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 9bc2b1a402c..721ce823351 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -671,9 +671,9 @@ static void screen_test_scale(bScreen *sc, int winsizex, int winsizey) /* test for collapsed areas. This could happen in some blender version... */ /* ton: removed option now, it needs Context... */ - /* make each window at least HEADERY high */ + /* make each window at least ED_area_headersize() high */ for(sa= sc->areabase.first; sa; sa= sa->next) { - int headery= HEADERY+1; + int headery= ED_area_headersize()+1; if(sa->v1->vec.y+headery > sa->v2->vec.y) { /* lower edge */ @@ -1055,6 +1055,18 @@ void ED_screen_draw(wmWindow *win) win->screen->do_draw= 0; } +/* helper call for below, dpi changes headers */ +static void screen_refresh_headersizes(void) +{ + const ListBase *lb= BKE_spacetypes_list(); + SpaceType *st; + + for(st= lb->first; st; st= st->next) { + ARegionType *art= BKE_regiontype_from_id(st, RGN_TYPE_HEADER); + if(art) art->prefsizey= ED_area_headersize(); + } +} + /* make this screen usable */ /* for file read and first use, for scaling window, area moves */ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) @@ -1076,6 +1088,9 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) else wm_subwindow_position(win, win->screen->mainwin, &winrct); + /* header size depends on DPI, let's verify */ + screen_refresh_headersizes(); + for(sa= win->screen->areabase.first; sa; sa= sa->next) { /* set spacetype and region callbacks, calls init() */ /* sets subwindows for regions, adds handlers */ @@ -1498,7 +1513,7 @@ void ED_screen_delete_scene(bContext *C, Scene *scene) unlink_scene(bmain, scene, newscene); } -int ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) +ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) { wmWindow *win= CTX_wm_window(C); bScreen *screen= CTX_wm_screen(C); @@ -1523,7 +1538,7 @@ int ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) ED_area_newspace(C, newsa, type); - return 1; + return newsa; } void ED_screen_full_prevspace(bContext *C, ScrArea *sa) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 0716a22b8cc..bd1c00e6fdb 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -625,6 +625,13 @@ static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static int actionzone_cancel(bContext *UNUSED(C), wmOperator *op) +{ + actionzone_exit(op); + + return OPERATOR_CANCELLED; +} + static void SCREEN_OT_actionzone(wmOperatorType *ot) { /* identifiers */ @@ -635,6 +642,7 @@ static void SCREEN_OT_actionzone(wmOperatorType *ot) ot->invoke= actionzone_invoke; ot->modal= actionzone_modal; ot->poll= actionzone_area_poll; + ot->cancel= actionzone_cancel; ot->flag= OPTYPE_BLOCKING; @@ -757,6 +765,7 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot) ot->invoke= area_swap_invoke; ot->modal= area_swap_modal; ot->poll= ED_operator_areaactive; + ot->cancel= area_swap_cancel; ot->flag= OPTYPE_BLOCKING; } @@ -866,13 +875,14 @@ typedef struct sAreaMoveData { static void area_move_set_limits(bScreen *sc, int dir, int *bigger, int *smaller) { ScrArea *sa; + int areaminy= ED_area_headersize()+1; /* we check all areas and test for free space with MINSIZE */ *bigger= *smaller= 100000; for(sa= sc->areabase.first; sa; sa= sa->next) { if(dir=='h') { - int y1= sa->v2->vec.y - sa->v1->vec.y-AREAMINY; + int y1= sa->v2->vec.y - sa->v1->vec.y-areaminy; /* if top or down edge selected, test height */ if(sa->v1->flag && sa->v4->flag) @@ -931,6 +941,7 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int bScreen *sc= CTX_wm_screen(C); ScrVert *v1; ScrArea *sa; + int areaminy= ED_area_headersize()+1; delta= CLAMPIS(delta, -smaller, bigger); @@ -948,8 +959,8 @@ static void area_move_apply_do(bContext *C, int origval, int delta, int dir, int v1->vec.y-= (v1->vec.y % AREAGRID); /* prevent too small top header */ - if(v1->vec.y > win->sizey-AREAMINY) - v1->vec.y= win->sizey-AREAMINY; + if(v1->vec.y > win->sizey-areaminy) + v1->vec.y= win->sizey-areaminy; } } } @@ -1163,6 +1174,7 @@ static int area_split_init(bContext *C, wmOperator *op) { ScrArea *sa= CTX_wm_area(C); sAreaSplitData *sd; + int areaminy= ED_area_headersize()+1; int dir; /* required context */ @@ -1173,7 +1185,7 @@ static int area_split_init(bContext *C, wmOperator *op) /* minimal size */ if(dir=='v' && sa->winx < 2*AREAMINX) return 0; - if(dir=='h' && sa->winy < 2*AREAMINY) return 0; + if(dir=='h' && sa->winy < 2*areaminy) return 0; /* custom data */ sd= (sAreaSplitData*)MEM_callocN(sizeof (sAreaSplitData), "op_area_split"); @@ -1489,6 +1501,7 @@ static void SCREEN_OT_area_split(wmOperatorType *ot) ot->exec= area_split_exec; ot->invoke= area_split_invoke; ot->modal= area_split_modal; + ot->cancel= area_split_cancel; ot->poll= screen_active_editable; ot->flag= OPTYPE_BLOCKING; @@ -1626,7 +1639,7 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) rmd->ar->sizex= rmd->origval + delta; CLAMP(rmd->ar->sizex, 0, rmd->maxsize); - if(rmd->ar->sizex < 24) { + if(rmd->ar->sizex < UI_UNIT_X) { rmd->ar->sizex= rmd->origval; if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) ED_region_toggle_hidden(C, rmd->ar); @@ -1641,11 +1654,17 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) rmd->ar->sizey= rmd->origval + delta; CLAMP(rmd->ar->sizey, 0, rmd->maxsize); - - if(rmd->ar->regiontype == RGN_TYPE_TOOL_PROPS) - maxsize = rmd->maxsize - ((rmd->sa->headertype==2)?48:24) - 10; - if(rmd->ar->sizey < 24 || (maxsize > 0 && (rmd->ar->sizey > maxsize)) ) { + if(rmd->ar->regiontype == RGN_TYPE_TOOL_PROPS) { + /* this calculation seems overly verbose + * can someone explain why this method is necessary? - campbell */ + maxsize = rmd->maxsize - ((rmd->sa->headertype==HEADERTOP)?UI_UNIT_Y*2:UI_UNIT_Y) - (UI_UNIT_Y/4); + } + + /* note, 'UI_UNIT_Y/4' means you need to drag the header almost + * all the way down for it to become hidden, this is done + * otherwise its too easy to do this by accident */ + if(rmd->ar->sizey < UI_UNIT_Y/4 || (maxsize > 0 && (rmd->ar->sizey > maxsize)) ) { rmd->ar->sizey= rmd->origval; if(!(rmd->ar->flag & RGN_FLAG_HIDDEN)) ED_region_toggle_hidden(C, rmd->ar); @@ -1682,6 +1701,13 @@ static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int region_scale_cancel(bContext *UNUSED(C), wmOperator *op) +{ + MEM_freeN(op->customdata); + op->customdata = NULL; + + return OPERATOR_CANCELLED; +} static void SCREEN_OT_region_scale(wmOperatorType *ot) { @@ -1692,6 +1718,7 @@ static void SCREEN_OT_region_scale(wmOperatorType *ot) ot->invoke= region_scale_invoke; ot->modal= region_scale_modal; + ot->cancel= region_scale_cancel; ot->poll= ED_operator_areaactive; @@ -2246,8 +2273,9 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) ot->invoke= area_join_invoke; ot->modal= area_join_modal; ot->poll= screen_active_editable; + ot->cancel= area_join_cancel; - ot->flag= OPTYPE_BLOCKING; + ot->flag= OPTYPE_BLOCKING|OPTYPE_INTERNAL; /* rna */ RNA_def_int(ot->srna, "min_x", -100, INT_MIN, INT_MAX, "X 1", "", INT_MIN, INT_MAX); @@ -3042,6 +3070,7 @@ static void SCREEN_OT_border_select(wmOperatorType *ot) ot->exec= border_select_do; ot->invoke= WM_border_select_invoke; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_areaactive; @@ -3312,6 +3341,7 @@ void ED_operatortypes_screen(void) WM_operatortype_append(ED_OT_undo); WM_operatortype_append(ED_OT_undo_push); WM_operatortype_append(ED_OT_redo); + WM_operatortype_append(ED_OT_undo_history); } @@ -3420,9 +3450,11 @@ void ED_keymap_screen(wmKeyConfig *keyconf) #ifdef __APPLE__ WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_OSKEY, 0); WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_OSKEY, 0); + WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT|KM_OSKEY, 0); #endif WM_keymap_add_item(keymap, "ED_OT_undo", ZKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "ED_OT_redo", ZKEY, KM_PRESS, KM_SHIFT|KM_CTRL, 0); + WM_keymap_add_item(keymap, "ED_OT_undo_history", ZKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); /* render */ diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index bfd6ba8ac9d..7b4c75759de 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -3696,14 +3696,26 @@ static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, float } } -static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask) { +static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float *rgba, float alpha, float mask, int use_color_correction) { if (ps->is_texbrush) { - rgba[0] *= ps->brush->rgb[0]; - rgba[1] *= ps->brush->rgb[1]; - rgba[2] *= ps->brush->rgb[2]; + /* rgba already holds a texture result here from higher level function */ + float rgba_br[3]; + if(use_color_correction){ + srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb); + mul_v3_v3(rgba, rgba_br); + } + else{ + mul_v3_v3(rgba, ps->brush->rgb); + } } else { - VECCOPY(rgba, ps->brush->rgb); + if(use_color_correction){ + srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb); + } + else { + VECCOPY(rgba, ps->brush->rgb); + } + rgba[3] = 1.0; } if (ps->is_airbrush==0 && mask < 1.0f) { @@ -3740,6 +3752,7 @@ static void *do_projectpaint_thread(void *ph_v) float falloff; int bucket_index; int is_floatbuf = 0; + int use_color_correction = 0; const short tool = ps->tool; rctf bucket_bounds; @@ -3845,6 +3858,7 @@ static void *do_projectpaint_thread(void *ph_v) last_projIma->touch = 1; is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; + use_color_correction = (last_projIma->ibuf->profile == IB_PROFILE_LINEAR_RGB) ? 1 : 0; } last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index; @@ -3875,7 +3889,7 @@ static void *do_projectpaint_thread(void *ph_v) else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co); break; default: - if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask); + if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask, use_color_correction); else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); break; } @@ -3991,7 +4005,7 @@ static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, c // we may want to use this later // brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0); - if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps)) { + if (brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) { return 1; } else return 0; @@ -4062,7 +4076,6 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) { if(ibuf->rect_float) - /* TODO - should just update a portion from imapaintpartial! */ ibuf->userflags |= IB_RECT_INVALID; /* force recreate of char rect */ if(ibuf->mipmap[0]) @@ -4259,8 +4272,8 @@ static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) static void imapaint_convert_brushco(ImBuf *ibufb, float *pos, int *ipos) { - ipos[0]= (int)(pos[0] - ibufb->x/2); - ipos[1]= (int)(pos[1] - ibufb->y/2); + ipos[0]= (int)floorf((pos[0] - ibufb->x/2) + 1.0f); + ipos[1]= (int)floorf((pos[1] - ibufb->y/2) + 1.0f); } /* dosnt run for projection painting @@ -4413,7 +4426,7 @@ static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, brush_painter_require_imbuf(painter, ((ibuf->rect_float)? 1: 0), 0, 0); - if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s)) { + if (brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, ibuf->profile == IB_PROFILE_LINEAR_RGB)) { if (update) imapaint_image_update(s->sima, image, ibuf, texpaint); return 1; @@ -4887,12 +4900,7 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) PointerRNA itemptr; float pressure, mousef[2]; double time; - int tablet, mouse[2]; - - // XXX +1 matches brush location better but - // still not exact, find out why and fix .. - mouse[0]= event->mval[0] + 1; - mouse[1]= event->mval[1] + 1; + int tablet; time= PIL_check_seconds_timer(); @@ -4912,8 +4920,8 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) pressure= pop->prev_pressure ? pop->prev_pressure : 1.0f; if(pop->first) { - pop->prevmouse[0]= mouse[0]; - pop->prevmouse[1]= mouse[1]; + pop->prevmouse[0]= event->mval[0]; + pop->prevmouse[1]= event->mval[1]; pop->starttime= time; /* special exception here for too high pressure values on first touch in @@ -4932,8 +4940,8 @@ static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) /* fill in stroke */ RNA_collection_add(op->ptr, "stroke", &itemptr); - mousef[0] = (float)(mouse[0]); - mousef[1] = (float)(mouse[1]); + mousef[0] = (float)(event->mval[0]); + mousef[1] = (float)(event->mval[1]); RNA_float_set_array(&itemptr, "mouse", mousef); RNA_float_set(&itemptr, "time", (float)(time - pop->starttime)); RNA_float_set(&itemptr, "pressure", pressure); @@ -5036,31 +5044,45 @@ static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)) { +#define PX_SIZE_FADE_MAX 12.0f +#define PX_SIZE_FADE_MIN 4.0f + Brush *brush= image_paint_brush(C); Paint *paint= paint_get_active(CTX_data_scene(C)); - if(paint && brush) { + if(paint && brush && paint->flags & PAINT_SHOW_BRUSH) { float zoomx, zoomy; + const float size= (float)brush_size(brush); + const short use_zoom= get_imapaint_zoom(C, &zoomx, &zoomy); + const float pixel_size= MAX2(size * zoomx, size * zoomy); + float alpha= 0.5f; - if(!(paint->flags & PAINT_SHOW_BRUSH)) + /* fade out the brush (cheap trick to work around brush interfearing with sampling [#])*/ + if(pixel_size < PX_SIZE_FADE_MIN) { return; + } + else if (pixel_size < PX_SIZE_FADE_MAX) { + alpha *= (pixel_size - PX_SIZE_FADE_MIN) / (PX_SIZE_FADE_MAX - PX_SIZE_FADE_MIN); + } glPushMatrix(); glTranslatef((float)x, (float)y, 0.0f); - if(get_imapaint_zoom(C, &zoomx, &zoomy)) + if(use_zoom) glScalef(zoomx, zoomy, 1.0f); - glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], 0.5f); + glColor4f(brush->add_col[0], brush->add_col[1], brush->add_col[2], alpha); glEnable( GL_LINE_SMOOTH ); glEnable(GL_BLEND); - glutil_draw_lined_arc(0, (float)(M_PI*2.0), (float)brush_size(brush), 40); + glutil_draw_lined_arc(0, (float)(M_PI*2.0), size, 40); glDisable(GL_BLEND); glDisable( GL_LINE_SMOOTH ); glPopMatrix(); } +#undef PX_SIZE_FADE_MAX +#undef PX_SIZE_FADE_MIN } static void toggle_paint_cursor(bContext *C, int enable) diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index bb877e4b1ee..5a0ee19d6c9 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -65,6 +65,7 @@ int paint_space_stroke_enabled(struct Brush *br); int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int paint_stroke_exec(struct bContext *C, struct wmOperator *op); +int paint_stroke_cancel(struct bContext *C, struct wmOperator *op); struct ViewContext *paint_stroke_view_context(struct PaintStroke *stroke); void *paint_stroke_mode_data(struct PaintStroke *stroke); void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 58c3446673c..7ddf5dff000 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -916,6 +916,19 @@ int paint_stroke_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +int paint_stroke_cancel(bContext *C, wmOperator *op) +{ + PaintStroke *stroke = op->customdata; + + if(stroke->done) + stroke->done(C, stroke); + + MEM_freeN(stroke); + op->customdata = NULL; + + return OPERATOR_CANCELLED; +} + ViewContext *paint_stroke_view_context(PaintStroke *stroke) { return &stroke->vc; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 1da87fdc6a7..d1f2f7617ca 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -361,7 +361,7 @@ static void wpaint_mirror_vgroup_ensure(Object *ob, int *vgroup_mirror) flip_side_name(name, defgroup->name, FALSE); if(strcmp(name, defgroup->name) != 0) { - for (curdef= ob->defbase.first, mirrdef; curdef; curdef=curdef->next, mirrdef++) { + for (curdef= ob->defbase.first, mirrdef= 0; curdef; curdef=curdef->next, mirrdef++) { if (!strcmp(curdef->name, name)) { break; } @@ -1659,6 +1659,13 @@ static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static int wpaint_cancel(bContext *C, wmOperator *op) +{ + paint_stroke_cancel(C, op); + + return OPERATOR_CANCELLED; +} + void PAINT_OT_weight_paint(wmOperatorType *ot) { @@ -1671,6 +1678,7 @@ void PAINT_OT_weight_paint(wmOperatorType *ot) ot->modal= paint_stroke_modal; /* ot->exec= vpaint_exec; <-- needs stroke property */ ot->poll= weight_paint_poll; + ot->cancel= wpaint_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; @@ -2101,6 +2109,13 @@ static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static int vpaint_cancel(bContext *C, wmOperator *op) +{ + paint_stroke_cancel(C, op); + + return OPERATOR_CANCELLED; +} + void PAINT_OT_vertex_paint(wmOperatorType *ot) { /* identifiers */ @@ -2112,6 +2127,7 @@ void PAINT_OT_vertex_paint(wmOperatorType *ot) ot->modal= paint_stroke_modal; /* ot->exec= vpaint_exec; <-- needs stroke property */ ot->poll= vertex_paint_poll; + ot->cancel= vpaint_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index d6d6d2f819b..434518c6d7e 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3586,6 +3586,24 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int sculpt_brush_stroke_cacel(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_active_object(C); + SculptSession *ss = ob->sculpt; + Sculpt *sd = CTX_data_tool_settings(C)->sculpt; + + paint_stroke_cancel(C, op); + + if(ss->cache) { + sculpt_cache_free(ss->cache); + ss->cache = NULL; + } + + sculpt_brush_exit_tex(sd); + + return OPERATOR_CANCELLED; +} + static void SCULPT_OT_brush_stroke(wmOperatorType *ot) { static EnumPropertyItem stroke_mode_items[] = { @@ -3604,6 +3622,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot) ot->modal= paint_stroke_modal; ot->exec= sculpt_brush_stroke_exec; ot->poll= sculpt_poll; + ot->cancel= sculpt_brush_stroke_cacel; /* flags (sculpt does own undo? (ton) */ ot->flag= OPTYPE_BLOCKING; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index be8547afa23..4d0043913ab 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -332,6 +332,7 @@ void ACTION_OT_select_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= actkeys_borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_action_active; diff --git a/source/blender/editors/space_action/space_action.c b/source/blender/editors/space_action/space_action.c index 10a1fe62cca..7a824e6bf9d 100644 --- a/source/blender/editors/space_action/space_action.c +++ b/source/blender/editors/space_action/space_action.c @@ -58,6 +58,7 @@ #include "UI_view2d.h" #include "ED_space_api.h" +#include "ED_screen.h" #include "ED_anim_api.h" #include "ED_markers.h" diff --git a/source/blender/editors/space_api/spacetypes.c b/source/blender/editors/space_api/spacetypes.c index 015d8d1dee5..05edf2b167d 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -72,6 +72,9 @@ void ED_spacetypes_init(void) const ListBase *spacetypes; SpaceType *type; + /* UI_UNIT_X is now a variable, is used in some spacetype inits? */ + U.widget_unit= 20; + /* create space types */ ED_spacetype_outliner(); ED_spacetype_time(); diff --git a/source/blender/editors/space_buttons/buttons_header.c b/source/blender/editors/space_buttons/buttons_header.c index 8d48836704e..19c600be937 100644 --- a/source/blender/editors/space_buttons/buttons_header.c +++ b/source/blender/editors/space_buttons/buttons_header.c @@ -104,7 +104,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar) { SpaceButs *sbuts= CTX_wm_space_buts(C); uiBlock *block; - int xco, yco= 1; + int xco, yco= 2; buttons_context_compute(C, sbuts); @@ -115,7 +115,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar) uiBlockSetEmboss(block, UI_EMBOSS); - xco -= XIC; + xco -= UI_UNIT_X; // Default panels uiBlockBeginAlign(block); @@ -150,7 +150,7 @@ void buttons_header_buttons(const bContext *C, ARegion *ar) uiBlockEndAlign(block); /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco+(XIC/2), ar->v2d.tot.ymax-ar->v2d.tot.ymin); + UI_view2d_totRect_set(&ar->v2d, xco+(UI_UNIT_X/2), ar->v2d.tot.ymax-ar->v2d.tot.ymin); uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt index e161e2d4b9b..afa746ea359 100644 --- a/source/blender/editors/space_file/CMakeLists.txt +++ b/source/blender/editors/space_file/CMakeLists.txt @@ -51,6 +51,10 @@ set(SRC fsmenu.h ) +if(WITH_HEADLESS) + add_definitions(-DWITH_HEADLESS) +endif() + if(WITH_IMAGE_OPENEXR) add_definitions(-DWITH_OPENEXR) endif() diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 903af649caa..a6fee359197 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -74,12 +74,6 @@ #include "file_intern.h" // own include -/* ui geometry */ -#define IMASEL_BUTTONS_HEIGHT 40 -#define IMASEL_BUTTONS_MARGIN 6 -#define TILE_BORDER_X 8 -#define TILE_BORDER_Y 8 - /* button events */ enum { B_FS_DIRNAME, @@ -523,8 +517,8 @@ void file_draw_list(const bContext *C, ARegion *ar) file_draw_preview(block, file, sx, sy, imb, layout, !is_icon && (file->flags & IMAGEFILE)); } else { - file_draw_icon(block, file->path, sx, sy-3, get_file_icon(file), ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH); - sx += ICON_DEFAULT_WIDTH + 4; + file_draw_icon(block, file->path, sx, sy-(UI_UNIT_Y / 6), get_file_icon(file), ICON_DEFAULT_WIDTH_SCALE, ICON_DEFAULT_WIDTH_SCALE); + sx += ICON_DEFAULT_WIDTH_SCALE + 4; } UI_ThemeColor4(TH_TEXT); diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index f171c4936fc..1965c661685 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -43,8 +43,12 @@ struct SpaceFile; struct ARegion *file_buttons_region(struct ScrArea *sa); /* file_draw.c */ -#define TILE_BORDER_X 8 -#define TILE_BORDER_Y 8 +#define TILE_BORDER_X (UI_UNIT_X/4) +#define TILE_BORDER_Y (UI_UNIT_Y/4) + +/* ui geometry */ +#define IMASEL_BUTTONS_HEIGHT (UI_UNIT_Y*2) +#define IMASEL_BUTTONS_MARGIN (UI_UNIT_Y/6) void file_draw_buttons(const bContext *C, ARegion *ar); void file_calc_previews(const bContext *C, ARegion *ar); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 9662b4b401f..a5d516a1417 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -301,6 +301,7 @@ void FILE_OT_select_border(wmOperatorType *ot) ot->exec= file_border_select_exec; ot->modal= file_border_select_modal; ot->poll= ED_operator_file_active; + ot->cancel= WM_border_select_cancel; /* rna */ WM_operator_properties_gesture_border(ot, 0); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 9b65589ef4c..32b725e0b1f 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -373,7 +373,11 @@ void filelist_init_icons(void) short x, y, k; ImBuf *bbuf; ImBuf *ibuf; +#ifdef WITH_HEADLESS + bbuf = NULL; +#else bbuf = IMB_ibImageFromMemory((unsigned char*)datatoc_prvicons, datatoc_prvicons_size, IB_rect); +#endif if (bbuf) { for (y=0; y<SPECIAL_IMG_ROWS; y++) { for (x=0; x<SPECIAL_IMG_COLS; x++) { diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 968953abf62..45193a38ef5 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -406,7 +406,7 @@ float file_font_pointsize(void) #else uiStyle *style= U.uistyles.first; uiStyleFontSet(&style->widget); - return style->widget.points; + return style->widget.points * UI_DPI_FAC; #endif } @@ -497,11 +497,11 @@ void ED_fileselect_init_layout(struct SpaceFile *sfile, struct ARegion *ar) column_widths(sfile->files, layout); if (params->display == FILE_SHORTDISPLAY) { - maxlen = ICON_DEFAULT_WIDTH + 4 + + maxlen = ICON_DEFAULT_WIDTH_SCALE + 4 + (int)layout->column_widths[COLUMN_NAME] + 12 + (int)layout->column_widths[COLUMN_SIZE] + 12; } else { - maxlen = ICON_DEFAULT_WIDTH + 4 + + maxlen = ICON_DEFAULT_WIDTH_SCALE + 4 + (int)layout->column_widths[COLUMN_NAME] + 12 + #ifndef WIN32 (int)layout->column_widths[COLUMN_MODE1] + 12 + diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 76883027df1..cb799b85d3a 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -344,6 +344,7 @@ void GRAPH_OT_select_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= graphkeys_borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= graphop_visible_keyframes_poll; diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 7e881e7e62f..adce540cee4 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -556,20 +556,20 @@ static void uiblock_layer_pass_buttons(uiLayout *layout, RenderResult *rr, Image /* menu buts */ if(render_slot) { strp= slot_menu(); - but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu1, 20, render_slot, 0,0,0,0, "Select Slot"); + but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu1, UI_UNIT_Y, render_slot, 0,0,0,0, "Select Slot"); uiButSetFunc(but, image_multi_cb, rr, iuser); MEM_freeN(strp); } if(rr) { strp= layer_menu(rr, &iuser->layer); - but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu2, 20, &iuser->layer, 0,0,0,0, "Select Layer"); + but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu2, UI_UNIT_Y, &iuser->layer, 0,0,0,0, "Select Layer"); uiButSetFunc(but, image_multi_cb, rr, iuser); MEM_freeN(strp); rl= BLI_findlink(&rr->layers, iuser->layer - (rr->rectf?1:0)); /* fake compo layer, return NULL is meant to be */ strp= pass_menu(rl, &iuser->pass); - but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu3, 20, &iuser->pass, 0,0,0,0, "Select Pass"); + but= uiDefButS(block, MENU, 0, strp, 0, 0, wmenu3, UI_UNIT_Y, &iuser->pass, 0,0,0,0, "Select Pass"); uiButSetFunc(but, image_multi_cb, rr, iuser); MEM_freeN(strp); } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index f48daa39c59..10b8cb238aa 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1925,6 +1925,7 @@ void IMAGE_OT_sample_line(wmOperatorType *ot) ot->modal= WM_gesture_straightline_modal; ot->exec= sample_line_exec; ot->poll= space_image_main_area_poll; + ot->cancel= WM_gesture_straightline_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index 937b683e880..c8bda434227 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -302,6 +302,7 @@ void INFO_OT_select_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_info_active; diff --git a/source/blender/editors/space_logic/logic_buttons.c b/source/blender/editors/space_logic/logic_buttons.c index e894fd9cff5..16e916928a9 100644 --- a/source/blender/editors/space_logic/logic_buttons.c +++ b/source/blender/editors/space_logic/logic_buttons.c @@ -206,6 +206,7 @@ void LOGIC_OT_links_cut(wmOperatorType *ot) ot->invoke= WM_gesture_lines_invoke; ot->modal= WM_gesture_lines_modal; ot->exec= cut_links_exec; + ot->cancel= WM_gesture_lines_cancel; ot->poll= ED_operator_logic_active; diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 0f0a4c0ad4c..8ef63b9a83d 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -333,6 +333,7 @@ void NLA_OT_select_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= nlaedit_borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= nlaop_poll_tweakmode_off; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index d967e2240e6..99f2ea99efc 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1086,6 +1086,13 @@ static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +static int snode_bg_viewmove_cancel(bContext *UNUSED(C), wmOperator *op) +{ + MEM_freeN(op->customdata); + op->customdata= NULL; + + return OPERATOR_CANCELLED; +} void NODE_OT_backimage_move(wmOperatorType *ot) { @@ -1098,6 +1105,7 @@ void NODE_OT_backimage_move(wmOperatorType *ot) ot->invoke= snode_bg_viewmove_invoke; ot->modal= snode_bg_viewmove_modal; ot->poll= composite_node_active; + ot->cancel= snode_bg_viewmove_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING; @@ -1384,6 +1392,14 @@ static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_CANCELLED|OPERATOR_PASS_THROUGH; } +static int node_resize_cancel(bContext *UNUSED(C), wmOperator *op) +{ + MEM_freeN(op->customdata); + op->customdata= NULL; + + return OPERATOR_CANCELLED; +} + void NODE_OT_resize(wmOperatorType *ot) { /* identifiers */ @@ -1394,6 +1410,7 @@ void NODE_OT_resize(wmOperatorType *ot) ot->invoke= node_resize_invoke; ot->modal= node_resize_modal; ot->poll= ED_operator_node_active; + ot->cancel= node_resize_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING; @@ -2279,6 +2296,18 @@ static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event) } } +static int node_link_cancel(bContext *C, wmOperator *op) +{ + SpaceNode *snode= CTX_wm_space_node(C); + bNodeLinkDrag *nldrag= op->customdata; + + nodeRemLink(snode->edittree, nldrag->link); + BLI_remlink(&snode->linkdrag, nldrag); + MEM_freeN(nldrag); + + return OPERATOR_CANCELLED; +} + void NODE_OT_link(wmOperatorType *ot) { /* identifiers */ @@ -2290,6 +2319,7 @@ void NODE_OT_link(wmOperatorType *ot) ot->modal= node_link_modal; // ot->exec= node_link_exec; ot->poll= ED_operator_node_active; + ot->cancel= node_link_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; @@ -2402,6 +2432,7 @@ void NODE_OT_links_cut(wmOperatorType *ot) ot->invoke= WM_gesture_lines_invoke; ot->modal= WM_gesture_lines_modal; ot->exec= cut_links_exec; + ot->cancel= WM_gesture_lines_cancel; ot->poll= ED_operator_node_active; diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index a1ef75f3976..1abcaccc939 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -215,6 +215,7 @@ void NODE_OT_select_border(wmOperatorType *ot) ot->invoke= node_border_select_invoke; ot->exec= node_borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_node_active; diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c index 037b1db56d6..43e46d485ee 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -106,21 +106,17 @@ #include "outliner_intern.h" - -#define OL_H 19 -#define OL_X 18 - #define OL_Y_OFFSET 2 -#define OL_TOG_RESTRICT_VIEWX 54 -#define OL_TOG_RESTRICT_SELECTX 36 -#define OL_TOG_RESTRICT_RENDERX 18 +#define OL_TOG_RESTRICT_VIEWX (UI_UNIT_X*3) +#define OL_TOG_RESTRICT_SELECTX (UI_UNIT_X*2) +#define OL_TOG_RESTRICT_RENDERX UI_UNIT_X #define OL_TOGW OL_TOG_RESTRICT_VIEWX -#define OL_RNA_COLX 300 -#define OL_RNA_COL_SIZEX 150 -#define OL_RNA_COL_SPACEX 50 +#define OL_RNA_COLX (UI_UNIT_X*15) +#define OL_RNA_COL_SIZEX (UI_UNIT_X*7.5) +#define OL_RNA_COL_SPACEX (UI_UNIT_X*2.5) #define TS_CHUNK 128 @@ -260,7 +256,7 @@ static void outliner_height(SpaceOops *soops, ListBase *lb, int *h) TreeStoreElem *tselem= TREESTORE(te); if((tselem->flag & TSE_CLOSED)==0) outliner_height(soops, &te->subtree, h); - (*h) += OL_H; + (*h) += UI_UNIT_Y; te= te->next; } } @@ -297,7 +293,7 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start *w = startx+100; if((tselem->flag & TSE_CLOSED)==0) - outliner_rna_width(soops, &te->subtree, w, startx+OL_X); + outliner_rna_width(soops, &te->subtree, w, startx+UI_UNIT_X); te= te->next; } } @@ -2485,13 +2481,13 @@ static int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int extend, const float mval[2]) { - if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) { TreeStoreElem *tselem= TREESTORE(te); int openclose= 0; /* open close icon */ if((te->flag & TE_ICONROW)==0) { // hidden icon, no open/close - if( mval[0]>te->xs && mval[0]<te->xs+OL_X) + if( mval[0]>te->xs && mval[0]<te->xs+UI_UNIT_X) openclose= 1; } @@ -2510,7 +2506,7 @@ static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Spa return 1; } /* name and first icon */ - else if(mval[0]>te->xs+OL_X && mval[0]<te->xend) { + else if(mval[0]>te->xs+UI_UNIT_X && mval[0]<te->xend) { /* always makes active object */ if(tselem->type!=TSE_SEQUENCE && tselem->type!=TSE_SEQ_STRIP && tselem->type!=TSE_SEQUENCE_DUP) @@ -2597,7 +2593,7 @@ static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event) int row; /* get row number - 100 here is just a dummy value since we don't need the column */ - UI_view2d_listview_view_to_cell(&ar->v2d, 1000, OL_H, 0.0f, OL_Y_OFFSET, + UI_view2d_listview_view_to_cell(&ar->v2d, 1000, UI_UNIT_Y, 0.0f, OL_Y_OFFSET, fmval[0], fmval[1], NULL, &row); /* select relevant row */ @@ -2631,7 +2627,7 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) static int do_outliner_item_openclose(bContext *C, SpaceOops *soops, TreeElement *te, int all, const float mval[2]) { - if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) { TreeStoreElem *tselem= TREESTORE(te); /* all below close/open? */ @@ -2696,11 +2692,11 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, TreeElement *te, const float mval[2]) { - if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) { TreeStoreElem *tselem= TREESTORE(te); /* name and first icon */ - if(mval[0]>te->xs+OL_X && mval[0]<te->xend) { + if(mval[0]>te->xs+UI_UNIT_X && mval[0]<te->xend) { /* can't rename rna datablocks entries */ if(ELEM3(tselem->type, TSE_RNA_STRUCT, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) @@ -2861,12 +2857,12 @@ static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, /* store coord and continue, we need coordinates for elements outside view too */ te->xs= (float)startx; te->ys= (float)(*starty); - *starty-= OL_H; + *starty-= UI_UNIT_Y; if((tselem->flag & TSE_CLOSED)==0) { TreeElement *ten; for(ten= te->subtree.first; ten; ten= ten->next) { - outliner_set_coordinates_element(soops, ten, startx+OL_X, starty); + outliner_set_coordinates_element(soops, ten, startx+UI_UNIT_X, starty); } } @@ -2876,7 +2872,7 @@ static void outliner_set_coordinates_element(SpaceOops *soops, TreeElement *te, static void outliner_set_coordinates(ARegion *ar, SpaceOops *soops) { TreeElement *te; - int starty= (int)(ar->v2d.tot.ymax)-OL_H; + int starty= (int)(ar->v2d.tot.ymax)-UI_UNIT_Y; int startx= 0; for(te= soops->tree.first; te; te= te->next) { @@ -3731,7 +3727,7 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot) static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, wmEvent *event, const float mval[2]) { - if(mval[1]>te->ys && mval[1]<te->ys+OL_H) { + if(mval[1]>te->ys && mval[1]<te->ys+UI_UNIT_Y) { int scenelevel=0, objectlevel=0, idlevel=0, datalevel=0; TreeStoreElem *tselem= TREESTORE(te); @@ -4309,7 +4305,10 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon) if(arg->x >= arg->xmax) UI_icon_draw(arg->x, arg->y, icon); else { - uiBut *but= uiDefIconBut(arg->block, LABEL, 0, icon, arg->x-4, arg->y, ICON_DEFAULT_WIDTH, ICON_DEFAULT_WIDTH, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : ""); + /* XXX investigate: button placement of icons is way different than UI_icon_draw? */ + float ufac= UI_UNIT_X/20.0f; + uiBut *but= uiDefIconBut(arg->block, LABEL, 0, icon, arg->x-3.0f*ufac, arg->y, UI_UNIT_X-4.0f*ufac, UI_UNIT_Y-4.0f*ufac, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : ""); + if(arg->id) uiButSetDragID(but, arg->id); } @@ -4572,7 +4571,7 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa for(te= lb->first; te; te= te->next) { /* exit drawing early */ - if((*offsx) - OL_X > xmax) + if((*offsx) - UI_UNIT_X > xmax) break; tselem= TREESTORE(te); @@ -4589,19 +4588,21 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa else active= tree_element_type_active(NULL, scene, soops, te, tselem, 0); if(active) { + float ufac= UI_UNIT_X/20.0f; + uiSetRoundBox(15); glColor4ub(255, 255, 255, 100); - uiRoundBox( (float)*offsx-0.5f, (float)ys-1.0f, (float)*offsx+OL_H-3.0f, (float)ys+OL_H-3.0f, OL_H/2.0f-2.0f); + uiRoundBox( (float)*offsx-0.5f*ufac, (float)ys-1.0f*ufac, (float)*offsx+UI_UNIT_Y-3.0f*ufac, (float)ys+UI_UNIT_Y-3.0f*ufac, UI_UNIT_Y/2.0f-2.0f*ufac); glEnable(GL_BLEND); /* roundbox disables */ } tselem_draw_icon(block, xmax, (float)*offsx, (float)ys, tselem, te, 0.5f); te->xs= (float)*offsx; te->ys= (float)ys; - te->xend= (short)*offsx+OL_X; + te->xend= (short)*offsx+UI_UNIT_X; te->flag |= TE_ICONROW; // for click - (*offsx) += OL_X; + (*offsx) += UI_UNIT_X; } /* this tree element always has same amount of branches, so dont draw */ @@ -4621,7 +4622,7 @@ static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, i te->ys= (float)(*starty); for(ten= te->subtree.first; ten; ten= ten->next) { - outliner_set_coord_tree_element(soops, ten, startx+OL_X, starty); + outliner_set_coord_tree_element(soops, ten, startx+UI_UNIT_X, starty); } } @@ -4630,16 +4631,17 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene { TreeElement *ten; TreeStoreElem *tselem; + float ufac= UI_UNIT_X/20.0f; int offsx= 0, active=0; // active=1 active obj, else active data tselem= TREESTORE(te); - if(*starty+2*OL_H >= ar->v2d.cur.ymin && *starty<= ar->v2d.cur.ymax) { + if(*starty+2*UI_UNIT_Y >= ar->v2d.cur.ymin && *starty<= ar->v2d.cur.ymax) { int xmax= ar->v2d.cur.xmax; /* icons can be ui buts, we dont want it to overlap with restrict */ if((soops->flag & SO_HIDE_RESTRICTCOLS)==0) - xmax-= OL_TOGW+ICON_DEFAULT_WIDTH; + xmax-= OL_TOGW+UI_UNIT_X; glEnable(GL_BLEND); @@ -4708,7 +4710,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene /* active circle */ if(active) { uiSetRoundBox(15); - uiRoundBox( (float)startx+OL_H-1.5f, (float)*starty+2.0f, (float)startx+2.0f*OL_H-4.0f, (float)*starty+OL_H-1.0f, OL_H/2.0f-2.0f); + uiRoundBox( (float)startx+UI_UNIT_Y-1.5f*ufac, (float)*starty+2.0f*ufac, (float)startx+2.0f*UI_UNIT_Y-4.0f*ufac, (float)*starty+UI_UNIT_Y-1.0f*ufac, UI_UNIT_Y/2.0f-2.0f*ufac); glEnable(GL_BLEND); /* roundbox disables it */ te->flag |= TE_ACTIVE; // for lookup in display hierarchies @@ -4720,35 +4722,35 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene if(tselem->type==0 && ELEM(te->idcode, ID_OB, ID_SCE)) icon_x = startx; else - icon_x = startx+5; + icon_x = startx+5*ufac; // icons a bit higher if(tselem->flag & TSE_CLOSED) - UI_icon_draw((float)icon_x, (float)*starty+2, ICON_DISCLOSURE_TRI_RIGHT); + UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_RIGHT); else - UI_icon_draw((float)icon_x, (float)*starty+2, ICON_DISCLOSURE_TRI_DOWN); + UI_icon_draw((float)icon_x, (float)*starty+2*ufac, ICON_DISCLOSURE_TRI_DOWN); } - offsx+= OL_X; + offsx+= UI_UNIT_X; /* datatype icon */ if(!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) { // icons a bit higher - tselem_draw_icon(block, xmax, (float)startx+offsx, (float)*starty+2, tselem, te, 1.0f); + tselem_draw_icon(block, xmax, (float)startx+offsx, (float)*starty+2*ufac, tselem, te, 1.0f); - offsx+= OL_X; + offsx+= UI_UNIT_X; } else - offsx+= 2; + offsx+= 2*ufac; if(tselem->type==0 && tselem->id->lib) { glPixelTransferf(GL_ALPHA_SCALE, 0.5f); if(tselem->id->flag & LIB_INDIRECT) - UI_icon_draw((float)startx+offsx, (float)*starty+2, ICON_LIBRARY_DATA_INDIRECT); + UI_icon_draw((float)startx+offsx, (float)*starty+2*ufac, ICON_LIBRARY_DATA_INDIRECT); else - UI_icon_draw((float)startx+offsx, (float)*starty+2, ICON_LIBRARY_DATA_DIRECT); + UI_icon_draw((float)startx+offsx, (float)*starty+2*ufac, ICON_LIBRARY_DATA_DIRECT); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); - offsx+= OL_X; + offsx+= UI_UNIT_X; } glDisable(GL_BLEND); @@ -4757,9 +4759,9 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene else if(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM)) UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.75f); else UI_ThemeColor(TH_TEXT); - UI_DrawString(startx+offsx, *starty+5, te->name); + UI_DrawString(startx+offsx, *starty+5*ufac, te->name); - offsx+= (int)(OL_X + UI_GetStringWidth(te->name)); + offsx+= (int)(UI_UNIT_X + UI_GetStringWidth(te->name)); /* closed item, we draw the icons, not when it's a scene, or master-server list though */ if(tselem->flag & TSE_CLOSED) { @@ -4770,7 +4772,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene // divider UI_ThemeColorShade(TH_BACK, -40); - glRecti(tempx -10, *starty+4, tempx -8, *starty+OL_H-4); + glRecti(tempx -10, *starty+4, tempx -8, *starty+UI_UNIT_Y-4); glEnable(GL_BLEND); glPixelTransferf(GL_ALPHA_SCALE, 0.5); @@ -4789,16 +4791,16 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene te->xend= startx+offsx; if((tselem->flag & TSE_CLOSED)==0) { - *starty-= OL_H; + *starty-= UI_UNIT_Y; for(ten= te->subtree.first; ten; ten= ten->next) - outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx+OL_X, starty); + outliner_draw_tree_element(C, block, scene, ar, soops, ten, startx+UI_UNIT_X, starty); } else { for(ten= te->subtree.first; ten; ten= ten->next) outliner_set_coord_tree_element(soops, te, startx, starty); - *starty-= OL_H; + *starty-= UI_UNIT_Y; } } @@ -4817,12 +4819,12 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, /* horizontal line? */ if(tselem->type==0 && (te->idcode==ID_OB || te->idcode==ID_SCE)) - glRecti(startx, *starty, startx+OL_X, *starty-1); + glRecti(startx, *starty, startx+UI_UNIT_X, *starty-1); - *starty-= OL_H; + *starty-= UI_UNIT_Y; if((tselem->flag & TSE_CLOSED)==0) - outliner_draw_hierarchy(soops, &te->subtree, startx+OL_X, starty); + outliner_draw_hierarchy(soops, &te->subtree, startx+UI_UNIT_X, starty); } /* vertical line */ @@ -4831,7 +4833,7 @@ static void outliner_draw_hierarchy(SpaceOops *soops, ListBase *lb, int startx, tselem= TREESTORE(te); if(tselem->type==0 && te->idcode==ID_OB) { - glRecti(startx, y1+OL_H, startx+1, y2); + glRecti(startx, y1+UI_UNIT_Y, startx+1, y2); } } } @@ -4847,13 +4849,13 @@ static void outliner_draw_struct_marks(ARegion *ar, SpaceOops *soops, ListBase * /* selection status */ if((tselem->flag & TSE_CLOSED)==0) if(tselem->type == TSE_RNA_STRUCT) - glRecti(0, *starty+1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, *starty+OL_H-1); + glRecti(0, *starty+1, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, *starty+UI_UNIT_Y-1); - *starty-= OL_H; + *starty-= UI_UNIT_Y; if((tselem->flag & TSE_CLOSED)==0) { outliner_draw_struct_marks(ar, soops, &te->subtree, starty); if(tselem->type == TSE_RNA_STRUCT) - fdrawline(0, (float)*starty+OL_H, ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (float)*starty+OL_H); + fdrawline(0, (float)*starty+UI_UNIT_Y, ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, (float)*starty+UI_UNIT_Y); } } } @@ -4868,9 +4870,9 @@ static void outliner_draw_selection(ARegion *ar, SpaceOops *soops, ListBase *lb, /* selection status */ if(tselem->flag & TSE_SELECTED) { - glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+OL_H-1); + glRecti(0, *starty+1, (int)ar->v2d.cur.xmax, *starty+UI_UNIT_Y-1); } - *starty-= OL_H; + *starty-= UI_UNIT_Y; if((tselem->flag & TSE_CLOSED)==0) outliner_draw_selection(ar, soops, &te->subtree, starty); } } @@ -4888,24 +4890,24 @@ static void outliner_draw_tree(bContext *C, uiBlock *block, Scene *scene, ARegio /* struct marks */ UI_ThemeColorShadeAlpha(TH_BACK, -15, -200); //UI_ThemeColorShade(TH_BACK, -20); - starty= (int)ar->v2d.tot.ymax-OL_H-OL_Y_OFFSET; + starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y-OL_Y_OFFSET; outliner_draw_struct_marks(ar, soops, &soops->tree, &starty); } /* always draw selection fill before hierarchy */ UI_GetThemeColor3fv(TH_BACK, col); glColor3f(col[0]+0.06f, col[1]+0.08f, col[2]+0.10f); - starty= (int)ar->v2d.tot.ymax-OL_H-OL_Y_OFFSET; + starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y-OL_Y_OFFSET; outliner_draw_selection(ar, soops, &soops->tree, &starty); // grey hierarchy lines UI_ThemeColorBlend(TH_BACK, TH_TEXT, 0.2f); - starty= (int)ar->v2d.tot.ymax-OL_H/2-OL_Y_OFFSET; + starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y/2-OL_Y_OFFSET; startx= 6; outliner_draw_hierarchy(soops, &soops->tree, startx, &starty); // items themselves - starty= (int)ar->v2d.tot.ymax-OL_H-OL_Y_OFFSET; + starty= (int)ar->v2d.tot.ymax-UI_UNIT_Y-OL_Y_OFFSET; startx= 0; for(te= soops->tree.first; te; te= te->next) { outliner_draw_tree_element(C, block, scene, ar, soops, te, startx, &starty); @@ -4919,11 +4921,11 @@ static void outliner_back(ARegion *ar) UI_ThemeColorShade(TH_BACK, 6); ystart= (int)ar->v2d.tot.ymax; - ystart= OL_H*(ystart/(OL_H))-OL_Y_OFFSET; + ystart= UI_UNIT_Y*(ystart/(UI_UNIT_Y))-OL_Y_OFFSET; - while(ystart+2*OL_H > ar->v2d.cur.ymin) { - glRecti(0, ystart, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, ystart+OL_H); - ystart-= 2*OL_H; + while(ystart+2*UI_UNIT_Y > ar->v2d.cur.ymin) { + glRecti(0, ystart, (int)ar->v2d.cur.xmax+V2D_SCROLL_WIDTH, ystart+UI_UNIT_Y); + ystart-= 2*UI_UNIT_Y; } } @@ -4937,11 +4939,11 @@ static void outliner_draw_restrictcols(ARegion *ar) UI_ThemeColorShade(TH_BACK, 6); ystart= (int)ar->v2d.tot.ymax; - ystart= OL_H*(ystart/(OL_H))-OL_Y_OFFSET; + ystart= UI_UNIT_Y*(ystart/(UI_UNIT_Y))-OL_Y_OFFSET; - while(ystart+2*OL_H > ar->v2d.cur.ymin) { - glRecti((int)ar->v2d.cur.xmax-OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart+OL_H); - ystart-= 2*OL_H; + while(ystart+2*UI_UNIT_Y > ar->v2d.cur.ymin) { + glRecti((int)ar->v2d.cur.xmax-OL_TOGW, ystart, (int)ar->v2d.cur.xmax, ystart+UI_UNIT_Y); + ystart-= 2*UI_UNIT_Y; } UI_ThemeColorShadeAlpha(TH_BACK, -15, -200); @@ -5225,7 +5227,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar for(te= lb->first; te; te= te->next) { tselem= TREESTORE(te); - if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { + if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { /* objects have toggle-able restriction flags */ if(tselem->type==0 && te->idcode==ID_OB) { PointerRNA ptr; @@ -5235,17 +5237,17 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_VIEW_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &ptr, "hide", -1, 0, 0, -1, -1, NULL); uiButSetFunc(bt, restrictbutton_view_cb, scene, ob); bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_SELECT_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, 17, OL_H-1, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &ptr, "hide_select", -1, 0, 0, -1, -1, NULL); uiButSetFunc(bt, restrictbutton_sel_cb, scene, ob); bt= uiDefIconButR(block, ICONTOG, 0, ICON_RESTRICT_RENDER_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, 17, OL_H-1, + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &ptr, "hide_render", -1, 0, 0, -1, -1, NULL); uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob); @@ -5259,15 +5261,15 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar uiBlockSetEmboss(block, UI_EMBOSSN); restrict_bool= group_restrict_flag(gr, OB_RESTRICT_VIEW); - bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); + bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_gr_restrict_view, scene, gr); restrict_bool= group_restrict_flag(gr, OB_RESTRICT_SELECT); - bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, 17, OL_H-1, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_SELECT_ON : ICON_RESTRICT_SELECT_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); uiButSetFunc(bt, restrictbutton_gr_restrict_select, scene, gr); restrict_bool= group_restrict_flag(gr, OB_RESTRICT_RENDER); - bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, 17, OL_H-1, NULL, 0, 0, 0, 0, "Restrict/Allow renderability"); + bt = uiDefIconBut(block, BUT, 0, restrict_bool ? ICON_RESTRICT_RENDER_ON : ICON_RESTRICT_RENDER_OFF, (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, NULL, 0, 0, 0, 0, "Restrict/Allow renderability"); uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr); uiBlockSetEmboss(block, UI_EMBOSS); @@ -5277,7 +5279,7 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOGN, SCE_LAY_DISABLE, 0, ICON_CHECKBOX_HLT-1, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, te->directdata, 0, 0, 0, 0, "Render this RenderLayer"); uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); uiBlockSetEmboss(block, UI_EMBOSS); @@ -5290,13 +5292,13 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar bt= uiDefIconButBitI(block, ICONTOG, passflag, 0, ICON_CHECKBOX_HLT-1, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Render this Pass"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, layflag, 0, 0, 0, 0, "Render this Pass"); uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); layflag++; /* is lay_xor */ if(ELEM8(passflag, SCE_PASS_SPEC, SCE_PASS_SHADOW, SCE_PASS_AO, SCE_PASS_REFLECT, SCE_PASS_REFRACT, SCE_PASS_INDIRECT, SCE_PASS_EMIT, SCE_PASS_ENVIRONMENT)) bt= uiDefIconButBitI(block, TOG, passflag, 0, (*layflag & passflag)?ICON_DOT:ICON_BLANK1, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, 17, OL_H-1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, layflag, 0, 0, 0, 0, "Exclude this Pass from Combined"); uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); uiBlockSetEmboss(block, UI_EMBOSS); @@ -5307,11 +5309,11 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Realtime, 0, ICON_RESTRICT_VIEW_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob); bt= uiDefIconButBitI(block, ICONTOGN, eModifierMode_Render, 0, ICON_RESTRICT_RENDER_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, 17, OL_H-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_RENDERX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability"); uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob); } else if(tselem->type==TSE_POSE_CHANNEL) { @@ -5320,11 +5322,11 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_P, 0, ICON_RESTRICT_VIEW_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone); bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, 17, OL_H-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); } else if(tselem->type==TSE_EBONE) { @@ -5332,11 +5334,11 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar uiBlockSetEmboss(block, UI_EMBOSSN); bt= uiDefIconButBitI(block, ICONTOG, BONE_HIDDEN_A, 0, ICON_RESTRICT_VIEW_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_VIEWX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone); bt= uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, 17, OL_H-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + (int)ar->v2d.cur.xmax-OL_TOG_RESTRICT_SELECTX, (int)te->ys, UI_UNIT_X-1, UI_UNIT_Y-1, &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL); } } @@ -5377,19 +5379,19 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa for(te= lb->first; te; te= te->next) { tselem= TREESTORE(te); - if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { + if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if(tselem->type == TSE_RNA_PROPERTY) { ptr= &te->rnaptr; prop= te->directdata; if(!(RNA_property_type(prop) == PROP_POINTER && (tselem->flag & TSE_CLOSED)==0)) - uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, OL_H-1); + uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1); } else if(tselem->type == TSE_RNA_ARRAY_ELEM) { ptr= &te->rnaptr; prop= te->directdata; - uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, OL_H-1); + uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y-1); } } @@ -5444,7 +5446,7 @@ static uiBlock *operator_search_menu(bContext *C, ARegion *ar, void *arg_kmi) /* fake button, it holds space for search items */ uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, arg_kmi, operator_call_cb, ot); uiBoundsBlock(block, 6); @@ -5583,11 +5585,11 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo for(te= lb->first; te; te= te->next) { tselem= TREESTORE(te); - if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { + if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { uiBut *but; const char *str; int xstart= 240; - int butw1= 20; /* operator */ + int butw1= UI_UNIT_X; /* operator */ int butw2= 90; /* event type, menus */ int butw3= 43; /* modifiers */ @@ -5597,7 +5599,7 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo /* modal map? */ if(kmi->propvalue); else { - uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys+1, butw1, OL_H-1, "Assign new Operator"); + uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys+1, butw1, UI_UNIT_Y-1, "Assign new Operator"); } xstart+= butw1+10; @@ -5605,43 +5607,43 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo kmi->maptype= keymap_menu_type(kmi->type); str= keymap_type_menu(); - but= uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->maptype, 0, 0, 0, 0, "Event type"); + but= uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->maptype, 0, 0, 0, 0, "Event type"); uiButSetFunc(but, keymap_type_cb, kmi, NULL); xstart+= butw2+5; /* edit actual event */ switch(kmi->maptype) { case OL_KM_KEYBOARD: - uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->type, "Key code"); + uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->type, "Key code"); xstart+= butw2+5; break; case OL_KM_MOUSE: str= keymap_mouse_menu(); - uiDefButS(block, MENU, 0, str, xstart,(int)te->ys+1, butw2, OL_H-1, &kmi->type, 0, 0, 0, 0, "Mouse button"); + uiDefButS(block, MENU, 0, str, xstart,(int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->type, 0, 0, 0, 0, "Mouse button"); xstart+= butw2+5; break; case OL_KM_TWEAK: str= keymap_tweak_menu(); - uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->type, 0, 0, 0, 0, "Tweak gesture"); + uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->type, 0, 0, 0, 0, "Tweak gesture"); xstart+= butw2+5; str= keymap_tweak_dir_menu(); - uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->val, 0, 0, 0, 0, "Tweak gesture direction"); + uiDefButS(block, MENU, 0, str, xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->val, 0, 0, 0, 0, "Tweak gesture direction"); xstart+= butw2+5; break; } /* modifiers */ - uiDefButS(block, OPTION, 0, "Shift", xstart, (int)te->ys+1, butw3+5, OL_H-1, &kmi->shift, 0, 0, 0, 0, "Modifier"); xstart+= butw3+5; - uiDefButS(block, OPTION, 0, "Ctrl", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart+= butw3; - uiDefButS(block, OPTION, 0, "Alt", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart+= butw3; - uiDefButS(block, OPTION, 0, "OS", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart+= butw3; + uiDefButS(block, OPTION, 0, "Shift", xstart, (int)te->ys+1, butw3+5, UI_UNIT_Y-1, &kmi->shift, 0, 0, 0, 0, "Modifier"); xstart+= butw3+5; + uiDefButS(block, OPTION, 0, "Ctrl", xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->ctrl, 0, 0, 0, 0, "Modifier"); xstart+= butw3; + uiDefButS(block, OPTION, 0, "Alt", xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->alt, 0, 0, 0, 0, "Modifier"); xstart+= butw3; + uiDefButS(block, OPTION, 0, "OS", xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->oskey, 0, 0, 0, 0, "Modifier"); xstart+= butw3; xstart+= 5; - uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw3, OL_H-1, &kmi->keymodifier, "Key Modifier code"); + uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys+1, butw3, UI_UNIT_Y-1, &kmi->keymodifier, "Key Modifier code"); xstart+= butw3+5; /* rna property */ if(kmi->ptr && kmi->ptr->data) { - uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys+1, butw2, OL_H-1, &kmi->oskey, 0, 0, 0, 0, ""); xstart+= butw2; + uiDefBut(block, LABEL, 0, "(RNA property)", xstart, (int)te->ys+1, butw2, UI_UNIT_Y-1, &kmi->oskey, 0, 0, 0, 0, ""); xstart+= butw2; } (void)xstart; @@ -5662,7 +5664,7 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa for(te= lb->first; te; te= te->next) { tselem= TREESTORE(te); - if(te->ys+2*OL_H >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { + if(te->ys+2*UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if(tselem->flag & TSE_TEXTBUT) { @@ -5679,10 +5681,10 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa dx= (int)UI_GetStringWidth(te->name); if(dx<100) dx= 100; - spx=te->xs+2*OL_X-4; + spx=te->xs+2*UI_UNIT_X-4; if(spx+dx+10>ar->v2d.cur.xmax) dx = ar->v2d.cur.xmax-spx-10; - bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, (int)te->ys, dx+10, OL_H-1, (void *)te->name, 1.0, (float)len, 0, 0, ""); + bt= uiDefBut(block, TEX, OL_NAMEBUTTON, "", spx, (int)te->ys, dx+10, UI_UNIT_Y-1, (void *)te->name, 1.0, (float)len, 0, 0, ""); uiButSetRenameFunc(bt, namebutton_cb, tselem); /* returns false if button got removed */ @@ -5716,7 +5718,7 @@ void draw_outliner(const bContext *C) * (OL_RNA_COL_X), whichever is wider... * - column 2 is fixed at OL_RNA_COL_SIZEX * - * (*) XXX max width for now is a fixed factor of OL_X*(max_indention+100) + * (*) XXX max width for now is a fixed factor of UI_UNIT_X*(max_indention+100) */ /* get actual width of column 1 */ diff --git a/source/blender/editors/space_script/script_header.c b/source/blender/editors/space_script/script_header.c index 57a1d36e3a2..d88d4296008 100644 --- a/source/blender/editors/space_script/script_header.c +++ b/source/blender/editors/space_script/script_header.c @@ -106,14 +106,14 @@ void script_header_buttons(const bContext *C, ARegion *ar) xmax= GetButStringLength("View"); uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C), - "View", xco, yco-2, xmax-3, 24, ""); - xco+=XIC+xmax; + "View", xco, yco-2, xmax-3, UI_UNIT_Y, ""); + xco+=UI_UNIT_X+xmax; } uiBlockSetEmboss(block, UI_EMBOSS); /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); + UI_view2d_totRect_set(&ar->v2d, xco+UI_UNIT_X+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index f351d52db07..119c5da309e 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -550,15 +550,17 @@ static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, floa glShadeModel(GL_SMOOTH); glBegin(GL_QUADS); - if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50); + if(seq->flag & SEQ_INVALID_EFFECT) { col[0]= 255; col[1]= 0; col[2]= 255; } + else if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -50); else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 0); glColor3ubv(col); glVertex2f(x1,y1); glVertex2f(x2,y1); - - if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5); + + if(seq->flag & SEQ_INVALID_EFFECT) { col[0]= 255; col[1]= 0; col[2]= 255; } + else if(seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 5); else UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, -5); glColor3ubv((GLubyte *)col); diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 71ed7928bc8..6900271deea 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2817,6 +2817,7 @@ void SEQUENCER_OT_view_ghost_border(wmOperatorType *ot) ot->exec= view_ghost_border_exec; ot->modal= WM_border_select_modal; ot->poll= sequencer_view_poll; + ot->cancel= WM_border_select_cancel; /* flags */ ot->flag= 0; diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 8b4bfb2e042..8d5f372f55e 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -871,6 +871,7 @@ void SEQUENCER_OT_select_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= sequencer_borderselect_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_sequencer_active; diff --git a/source/blender/editors/space_sound/sound_header.c b/source/blender/editors/space_sound/sound_header.c index 60707e18187..2246eb310b5 100644 --- a/source/blender/editors/space_sound/sound_header.c +++ b/source/blender/editors/space_sound/sound_header.c @@ -113,14 +113,14 @@ void sound_header_buttons(const bContext *C, ARegion *ar) xmax= GetButStringLength("View"); uiDefPulldownBut(block, dummy_viewmenu, CTX_wm_area(C), - "View", xco, yco-2, xmax-3, 24, ""); - xco+=XIC+xmax; + "View", xco, yco-2, xmax-3, UI_UNIT_Y, ""); + xco+=UI_UNIT_X+xmax; } uiBlockSetEmboss(block, UI_EMBOSS); /* always as last */ - UI_view2d_totRect_set(&ar->v2d, xco+XIC+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); + UI_view2d_totRect_set(&ar->v2d, xco+UI_UNIT_X+80, ar->v2d.tot.ymax-ar->v2d.tot.ymin); uiEndBlock(C, block); uiDrawBlock(C, block); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 2df614f5e01..5feeac0e95e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -5886,7 +5886,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag) /* multiply view with object matrix. * local viewmat and persmat, to calculate projections */ - ED_view3d_init_mats_rv3d(ob, rv3d); + ED_view3d_init_mats_rv3d_gl(ob, rv3d); /* which wire color */ if((flag & DRAW_CONSTCOLOR) == 0) { diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 054da3895b5..d9fcb45881c 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -208,13 +208,18 @@ void ED_view3d_init_mats_rv3d(struct Object *ob, struct RegionView3D *rv3d) mul_m4_m4m4(rv3d->viewmatob, ob->obmat, rv3d->viewmat); mul_m4_m4m4(rv3d->persmatob, ob->obmat, rv3d->persmat); + /* initializes object space clipping, speeds up clip tests */ + ED_view3d_local_clipping(rv3d, ob->obmat); +} + +void ED_view3d_init_mats_rv3d_gl(struct Object *ob, struct RegionView3D *rv3d) +{ + ED_view3d_init_mats_rv3d(ob, rv3d); + /* we have to multiply instead of loading viewmatob to make it work with duplis using displists, otherwise it will override the dupli-matrix */ glMultMatrixf(ob->obmat); - - /* initializes object space clipping, speeds up clip tests */ - ED_view3d_local_clipping(rv3d, ob->obmat); } /* ******************** default callbacks for view3d space ***************** */ diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 31aae28dd61..9ff73767b4c 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -904,6 +904,13 @@ static int view3d_camera_active_poll(bContext *C) return 0; } +static int viewrotate_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + void VIEW3D_OT_rotate(wmOperatorType *ot) { @@ -916,6 +923,7 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->invoke= viewrotate_invoke; ot->modal= viewrotate_modal; ot->poll= ED_operator_region_view3d_active; + ot->cancel= viewrotate_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -1058,6 +1066,13 @@ static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) } } +static int viewmove_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + void VIEW3D_OT_move(wmOperatorType *ot) { @@ -1070,6 +1085,7 @@ void VIEW3D_OT_move(wmOperatorType *ot) ot->invoke= viewmove_invoke; ot->modal= viewmove_modal; ot->poll= ED_operator_view3d_active; + ot->cancel= viewmove_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -1414,6 +1430,12 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } +static int viewzoom_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} void VIEW3D_OT_zoom(wmOperatorType *ot) { @@ -1427,6 +1449,7 @@ void VIEW3D_OT_zoom(wmOperatorType *ot) ot->exec= viewzoom_exec; ot->modal= viewzoom_modal; ot->poll= ED_operator_region_view3d_active; + ot->cancel= viewzoom_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -1641,6 +1664,13 @@ static int viewdolly_poll(bContext *C) return 0; } +static int viewdolly_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + void VIEW3D_OT_dolly(wmOperatorType *ot) { /* identifiers */ @@ -1653,6 +1683,7 @@ void VIEW3D_OT_dolly(wmOperatorType *ot) ot->exec= viewdolly_exec; ot->modal= viewdolly_modal; ot->poll= viewdolly_poll; + ot->cancel= viewdolly_cancel; /* flags */ ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; @@ -2046,6 +2077,7 @@ void VIEW3D_OT_render_border(wmOperatorType *ot) ot->invoke= WM_border_select_invoke; ot->exec= render_border_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= view3d_camera_active_poll; @@ -2201,6 +2233,7 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot) ot->invoke= view3d_zoom_border_invoke; ot->exec= view3d_zoom_border_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_region_view3d_active; @@ -2839,6 +2872,7 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot) ot->invoke= view3d_clipping_invoke; ot->exec= view3d_clipping_exec; ot->modal= WM_border_select_modal; + ot->cancel= WM_border_select_cancel; ot->poll= ED_operator_region_view3d_active; diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index 60c863b4be3..1df85192389 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -442,9 +442,9 @@ void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C) row= uiLayoutRow(layout, 1); block= uiLayoutGetBlock(row); - uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0,0,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode"); - uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0,0,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select mode"); - uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0,0,XIC,YIC, &em->selectmode, 1.0, 0.0, 0, 0, "Face select mode"); + uiDefIconButBitS(block, TOG, SCE_SELECT_VERTEX, B_SEL_VERT, ICON_VERTEXSEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Vertex select mode"); + uiDefIconButBitS(block, TOG, SCE_SELECT_EDGE, B_SEL_EDGE, ICON_EDGESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Edge select mode"); + uiDefIconButBitS(block, TOG, SCE_SELECT_FACE, B_SEL_FACE, ICON_FACESEL, 0,0,UI_UNIT_X,UI_UNIT_Y, &em->selectmode, 1.0, 0.0, 0, 0, "Face select mode"); } } @@ -486,7 +486,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) uiBlockBeginAlign(block); uiDefIconTextButS(block, MENU, B_MODESELECT, object_mode_icon(v3d->modeselect), view3d_modeselect_pup(scene) , - 0,0,126 * dpi_fac,20, &(v3d->modeselect), 0, 0, 0, 0, "Mode"); + 0,0,126 * dpi_fac, UI_UNIT_Y, &(v3d->modeselect), 0, 0, 0, 0, "Mode"); uiBlockEndAlign(block); /* Draw type */ @@ -509,10 +509,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) /* NDOF */ /* Not implemented yet if (G.ndofdevice ==0 ) { - uiDefIconTextButC(block, ICONTEXTROW,B_NDOF, ICON_NDOF_TURN, ndof_pup(), 0,0,XIC+10,YIC, &(v3d->ndofmode), 0, 3.0, 0, 0, "Ndof mode"); + uiDefIconTextButC(block, ICONTEXTROW,B_NDOF, ICON_NDOF_TURN, ndof_pup(), 0,0,UI_UNIT_X+10,UI_UNIT_Y, &(v3d->ndofmode), 0, 3.0, 0, 0, "Ndof mode"); uiDefIconButC(block, TOG, B_NDOF, ICON_NDOF_DOM, - 0,0,XIC,YIC, + 0,0,UI_UNIT_X,UI_UNIT_Y, &v3d->ndoffilter, 0, 1, 0, 0, "dominant axis"); } */ @@ -523,9 +523,9 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) block= uiLayoutGetBlock(row); if(v3d->twflag & V3D_USE_MANIPULATOR) { - uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, 0,0,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Translate manipulator mode"); - uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT, 0,0,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Rotate manipulator mode"); - uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, 0,0,XIC,YIC, &v3d->twtype, 1.0, 0.0, 0, 0, "Scale manipulator mode"); + uiDefIconButBitC(block, TOG, V3D_MANIP_TRANSLATE, B_MAN_TRANS, ICON_MAN_TRANS, 0,0,UI_UNIT_X,UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, "Translate manipulator mode"); + uiDefIconButBitC(block, TOG, V3D_MANIP_ROTATE, B_MAN_ROT, ICON_MAN_ROT, 0,0,UI_UNIT_X,UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, "Rotate manipulator mode"); + uiDefIconButBitC(block, TOG, V3D_MANIP_SCALE, B_MAN_SCALE, ICON_MAN_SCALE, 0,0,UI_UNIT_X,UI_UNIT_Y, &v3d->twtype, 1.0, 0.0, 0, 0, "Scale manipulator mode"); } if (v3d->twmode > (BIF_countTransformOrientation(C) - 1) + V3D_MANIP_CUSTOM) { @@ -533,7 +533,7 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C) } str_menu = BIF_menustringTransformOrientation(C, "Orientation"); - uiDefButC(block, MENU, B_MAN_MODE, str_menu,0,0,70 * dpi_fac, YIC, &v3d->twmode, 0, 0, 0, 0, "Transform Orientation"); + uiDefButC(block, MENU, B_MAN_MODE, str_menu,0,0,70 * dpi_fac, UI_UNIT_Y, &v3d->twmode, 0, 0, 0, 0, "Transform Orientation"); MEM_freeN((void *)str_menu); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index da5eff8a31e..32fc7f12359 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -491,11 +491,8 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, if (extend == 0 && select) EDBM_clear_flag_all(vc->em, BM_SELECT); - /* workaround: init mats first, EM_mask_init_backbuf_border can change - view matrix to pixel space, breaking edge select with backbuf. fixes bug [#20936] */ - - /* [#21018] breaks zbuf select. run below. only if bbsel fails */ - /* ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d) */ + /* for non zbuf projections, dont change the GL state */ + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); glLoadMatrixf(vc->rv3d->viewmat); bbsel= EDBM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); @@ -503,15 +500,13 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, if(ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { EDBM_backbuf_checkAndSelectVerts(vc->em, select); - } else { - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + } + else { mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1); } } if(ts->selectmode & SCE_SELECT_EDGE) { - /* Does both bbsel and non-bbsel versions (need screen cos for both) */ - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ - + /* Does both bbsel and non-bbsel versions (need screen cos for both) */ data.pass = 0; mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, 0); @@ -524,8 +519,8 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, if(ts->selectmode & SCE_SELECT_FACE) { if (bbsel) { EDBM_backbuf_checkAndSelectFaces(vc->em, select); - } else { - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */ + } + else { mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data); } } @@ -881,6 +876,7 @@ void VIEW3D_OT_select_lasso(wmOperatorType *ot) ot->modal= WM_gesture_lasso_modal; ot->exec= view3d_lasso_select_exec; ot->poll= view3d_selectable_data; + ot->cancel= WM_gesture_lasso_cancel; /* flags */ ot->flag= OPTYPE_UNDO; @@ -1496,12 +1492,8 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten if (extend == 0 && select) EDBM_clear_flag_all(vc->em, BM_SELECT); - /* workaround: init mats first, EM_mask_init_backbuf_border can change - view matrix to pixel space, breaking edge select with backbuf. fixes bug #20936 */ - /*ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);*/ /* for foreach's screen/vert projection */ - - /* [#21018] breaks zbuf select. run below. only if bbsel fails */ - /* ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d) */ + /* for non zbuf projections, dont change the GL state */ + ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); glLoadMatrixf(vc->rv3d->viewmat); bbsel= EDBM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); @@ -1510,7 +1502,6 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten if (bbsel) { EDBM_backbuf_checkAndSelectVerts(vc->em, select); } else { - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1); } } @@ -1530,7 +1521,6 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten if(bbsel) { EDBM_backbuf_checkAndSelectFaces(vc->em, select); } else { - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data); } } @@ -1835,6 +1825,7 @@ void VIEW3D_OT_select_border(wmOperatorType *ot) ot->exec= view3d_borderselect_exec; ot->modal= WM_border_select_modal; ot->poll= view3d_selectable_data; + ot->cancel= WM_border_select_cancel; /* flags */ ot->flag= OPTYPE_UNDO; @@ -2314,6 +2305,7 @@ void VIEW3D_OT_select_circle(wmOperatorType *ot) ot->modal= WM_gesture_circle_modal; ot->exec= view3d_circle_select_exec; ot->poll= view3d_selectable_data; + ot->cancel= WM_gesture_circle_cancel; /* flags */ ot->flag= OPTYPE_UNDO; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 848083ad043..47ba48521c1 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -391,12 +391,15 @@ static int view3d_setcameratoview_exec(bContext *C, wmOperator *UNUSED(op)) static int view3d_setcameratoview_poll(bContext *C) { - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d= CTX_wm_region_view3d(C); + View3D *v3d= CTX_wm_view3d(C); + if(v3d && v3d->camera && v3d->camera->id.lib==NULL) { + RegionView3D *rv3d= CTX_wm_region_view3d(C); + if(rv3d && !rv3d->viewlock) { + return 1; + } + } - if (v3d==NULL || v3d->camera==NULL) return 0; - if (rv3d && rv3d->viewlock != 0) return 0; - return 1; + return 0; } void VIEW3D_OT_setcameratoview(wmOperatorType *ot) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 8163ccc4cb0..f228653aa79 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4818,8 +4818,8 @@ void initEdgeSlide(TransInfo *t) t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; - t->snap[1] = (float)((5.0/180)*M_PI); - t->snap[2] = t->snap[1] * 0.2f; + t->snap[1] = 0.1f; + t->snap[2] = t->snap[1] * 0.1f; t->num.increment = t->snap[1]; @@ -4862,6 +4862,9 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) snapGrid(t, &final); + /* only do this so out of range values are not displayed */ + CLAMP(final, -1.0f, 1.0f); + if (hasNumInput(&t->num)) { char c[20]; @@ -4869,10 +4872,10 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, "Edge Slide Percent: %s", &c[0]); + sprintf(str, "Edge Slide: %s", &c[0]); } else { - sprintf(str, "Edge Slide Percent: %.2f", final); + sprintf(str, "Edge Slide: %.2f", final); } CLAMP(final, -1.0f, 1.0f); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 381a5e585dd..a514a6a523c 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4149,6 +4149,7 @@ static void freeSeqData(TransInfo *t) } if(overlap) { + int has_effect= 0; for(seq= seqbasep->first; seq; seq= seq->next) seq->tmp= NULL; @@ -4157,12 +4158,47 @@ static void freeSeqData(TransInfo *t) for(a=0; a<t->total; a++, td++) { seq= ((TransDataSeq *)td->extra)->seq; if ((seq != seq_prev)) { - /* Tag seq with a non zero value, used by shuffle_seq_time to identify the ones to shuffle */ - seq->tmp= (void*)1; + /* check effects strips, we cant change their time */ + if((seq->type & SEQ_EFFECT) && seq->seq1) { + has_effect= TRUE; + } + else { + /* Tag seq with a non zero value, used by shuffle_seq_time to identify the ones to shuffle */ + seq->tmp= (void*)1; + } } } shuffle_seq_time(seqbasep, t->scene); + + if(has_effect) { + /* update effects strips based on strips just moved in time */ + td= t->data; + seq_prev= NULL; + for(a=0; a<t->total; a++, td++) { + seq= ((TransDataSeq *)td->extra)->seq; + if ((seq != seq_prev)) { + if((seq->type & SEQ_EFFECT) && seq->seq1) { + calc_sequence(t->scene, seq); + } + } + } + + /* now if any effects _still_ overlap, we need to move them up */ + td= t->data; + seq_prev= NULL; + for(a=0; a<t->total; a++, td++) { + seq= ((TransDataSeq *)td->extra)->seq; + if ((seq != seq_prev)) { + if((seq->type & SEQ_EFFECT) && seq->seq1) { + if(seq_test_overlap(seqbasep, seq)) { + shuffle_seq(seqbasep, seq, t->scene); + } + } + } + } + /* done with effects */ + } } } #endif diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 6f4bbff8a0b..f2ab43c281b 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -296,7 +296,7 @@ void undo_editmode_clear(void) } /* based on index nr it does a restore */ -static void undo_number(bContext *C, int nr) +void undo_editmode_number(bContext *C, int nr) { UndoElem *uel; int a=1; @@ -337,66 +337,28 @@ int undo_editmode_valid(const char *undoname) return undobase.last != undobase.first; } -/* ************** for interaction with menu/pullown */ -void undo_editmode_menu(bContext *C) +/* get name of undo item, return null if no item with this index */ +/* if active pointer, set it to 1 if true */ +char *undo_editmode_get_name(bContext *C, int nr, int *active) { UndoElem *uel; - DynStr *ds= BLI_dynstr_new(); - short event= 0; - char *menu; - - undo_clean_stack(C); // removes other objects from it - - BLI_dynstr_append(ds, "Editmode Undo History %t"); - - for(uel= undobase.first; uel; uel= uel->next) { - BLI_dynstr_append(ds, "|"); - BLI_dynstr_append(ds, uel->name); - } - - menu= BLI_dynstr_get_cstring(ds); - BLI_dynstr_free(ds); - -// XXX event= pupmenu_col(menu, 20); - MEM_freeN(menu); - if(event>0) undo_number(C, event); -} - -static void do_editmode_undohistorymenu(bContext *C, void *UNUSED(arg), int event) -{ - Object *obedit= CTX_data_edit_object(C); - - if(obedit==NULL || event<1) return; - - undo_number(C, event-1); + /* prevent wrong numbers to be returned */ + undo_clean_stack(C); -} - -uiBlock *editmode_undohistorymenu(bContext *C, ARegion *ar, void *UNUSED(arg)) -{ - uiBlock *block; - UndoElem *uel; - short yco = 20, menuwidth = 120; - short item= 1; + if(active) *active= 0; - undo_clean_stack(C); // removes other objects from it - - block= uiBeginBlock(C, ar, "view3d_edit_mesh_undohistorymenu", UI_EMBOSSP); - uiBlockSetButmFunc(block, do_editmode_undohistorymenu, NULL); - - for(uel= undobase.first; uel; uel= uel->next, item++) { - if (uel==curundo) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); - uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, uel->name, 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 1, (float)item, ""); - if (uel==curundo) uiDefBut(block, SEPR, 0, "", 0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); + uel= BLI_findlink(&undobase, nr); + if(uel) { + if(active && uel==curundo) + *active= 1; + return uel->name; } - - uiBlockSetDirection(block, UI_RIGHT); - uiTextBoundsBlock(block, 60); - return block; + return NULL; } + void *undo_editmode_get_prev(Object *ob) { UndoElem *ue= undobase.last; diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index f4e27a5faf9..24a868891de 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -68,6 +68,9 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "UI_interface.h" +#include "UI_resources.h" + #include "util_intern.h" #define MAXUNDONAME 64 /* XXX, make common define */ @@ -111,10 +114,12 @@ void ED_undo_push(bContext *C, const char *str) if(wm->file_saved) { wm->file_saved= 0; + /* notifier that data changed, for save-over warning or header */ WM_event_add_notifier(C, NC_WM|ND_DATACHANGED, NULL); } } +/* note: also check undo_history_exec() in bottom if you change notifiers */ static int ed_undo_step(bContext *C, int step, const char *undoname) { Object *obedit= CTX_data_edit_object(C); @@ -277,32 +282,6 @@ static int ed_redo_exec(bContext *C, wmOperator *UNUSED(op)) return ed_undo_step(C, -1, NULL); } -#if 0 /* UNUSED */ -void ED_undo_menu(bContext *C) -{ - Object *obedit= CTX_data_edit_object(C); - Object *obact= CTX_data_active_object(C); - - if(obedit) { - //if ELEM7(obedit->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE) - // undo_editmode_menu(); - } - else { - if(obact && obact->mode & OB_MODE_PARTICLE_EDIT) - PE_undo_menu(CTX_data_scene(C), CTX_data_active_object(C)); - else if(U.uiflag & USER_GLOBALUNDO) { - char *menu= BKE_undo_menu_string(); - if(menu) { - short event= 0; // XXX pupmenu_col(menu, 20); - MEM_freeN(menu); - if(event>0) { - BKE_undo_number(C, event); - } - } - } - } -} -#endif /* ********************** */ @@ -328,6 +307,8 @@ void ED_OT_undo_push(wmOperatorType *ot) /* api callbacks */ ot->exec= ed_undo_push_exec; + ot->flag= OPTYPE_INTERNAL; + RNA_def_string(ot->srna, "message", "Add an undo step *function may be moved*", MAXUNDONAME, "Undo Message", ""); } @@ -399,3 +380,144 @@ void ED_undo_operator_repeat_cb_evt(bContext *C, void *arg_op, int UNUSED(arg_ev { ED_undo_operator_repeat(C, (wmOperator *)arg_op); } + + +/* ************************** */ + +#define UNDOSYSTEM_GLOBAL 1 +#define UNDOSYSTEM_EDITMODE 2 +#define UNDOSYSTEM_PARTICLE 3 + +static int get_undo_system(bContext *C) +{ + Object *obedit= CTX_data_edit_object(C); + + /* find out which undo system */ + if(obedit) { + if (ELEM7(obedit->type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE)) + return UNDOSYSTEM_EDITMODE; + } + else { + Object *obact= CTX_data_active_object(C); + + if(obact && obact->mode & OB_MODE_PARTICLE_EDIT) + return UNDOSYSTEM_PARTICLE; + else if(U.uiflag & USER_GLOBALUNDO) + return UNDOSYSTEM_GLOBAL; + } + + return 0; +} + +/* create enum based on undo items */ +static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem) +{ + EnumPropertyItem item_tmp= {0}, *item= NULL; + int active, i= 0; + + while(TRUE) { + char *name= NULL; + + if(undosys==UNDOSYSTEM_PARTICLE) { + name= PE_undo_get_name(CTX_data_scene(C), i, &active); + } + else if(undosys==UNDOSYSTEM_EDITMODE) { + name= undo_editmode_get_name(C, i, &active); + } + else { + name= BKE_undo_get_name(i, &active); + } + + if(name) { + item_tmp.identifier= item_tmp.name= name; + if(active) + item_tmp.icon= ICON_RESTRICT_VIEW_OFF; + else + item_tmp.icon= ICON_NONE; + item_tmp.value= i++; + RNA_enum_item_add(&item, totitem, &item_tmp); + } + else + break; + } + + RNA_enum_item_end(&item, totitem); + + return item; +} + + +static int undo_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +{ + int undosys, totitem= 0; + + undosys= get_undo_system(C); + + if(undosys) { + EnumPropertyItem *item= rna_undo_itemf(C, undosys, &totitem); + + if(totitem > 0) { + uiPopupMenu *pup= uiPupMenuBegin(C, op->type->name, ICON_NONE); + uiLayout *layout= uiPupMenuLayout(pup); + uiLayout *split= uiLayoutSplit(layout, 0, 0), *column; + int i, c; + + for(c=0, i=totitem-1; i >= 0; i--, c++) { + if( (c % 20)==0 ) + column= uiLayoutColumn(split, 0); + if(item[i].identifier) + uiItemIntO(column, item[i].name, item[i].icon, op->type->idname, "item", item[i].value); + + } + + MEM_freeN(item); + + uiPupMenuEnd(C, pup); + } + + } + return OPERATOR_CANCELLED; +} + +/* note: also check ed_undo_step() in top if you change notifiers */ +static int undo_history_exec(bContext *C, wmOperator *op) +{ + if(RNA_property_is_set(op->ptr, "item")) { + int undosys= get_undo_system(C); + int item= RNA_int_get(op->ptr, "item"); + + if(undosys==UNDOSYSTEM_PARTICLE) { + PE_undo_number(CTX_data_scene(C), item); + } + else if(undosys==UNDOSYSTEM_EDITMODE) { + undo_editmode_number(C, item+1); + WM_event_add_notifier(C, NC_GEOM|ND_DATA, NULL); + } + else { + BKE_undo_number(C, item); + WM_event_add_notifier(C, NC_SCENE|ND_LAYER_CONTENT, CTX_data_scene(C)); + } + WM_event_add_notifier(C, NC_WINDOW, NULL); + + return OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; +} + +void ED_OT_undo_history(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Undo History"; + ot->description= "Redo specific action in history"; + ot->idname= "ED_OT_undo_history"; + + /* api callbacks */ + ot->invoke= undo_history_invoke; + ot->exec= undo_history_exec; + ot->poll= ED_operator_screenactive; + + RNA_def_int(ot->srna, "item", 0, 0, INT_MAX, "Item", "", 0, INT_MAX); + +} + + diff --git a/source/blender/editors/util/util_intern.h b/source/blender/editors/util/util_intern.h index 1a82668236d..bfa758b3faa 100644 --- a/source/blender/editors/util/util_intern.h +++ b/source/blender/editors/util/util_intern.h @@ -37,8 +37,12 @@ /* internal exports only */ /* editmode_undo.c */ -void undo_editmode_name(bContext *C, const char *undoname); -int undo_editmode_valid(const char *undoname); +void undo_editmode_name (struct bContext *C, const char *undoname); +int undo_editmode_valid (const char *undoname); +char *undo_editmode_get_name (struct bContext *C, int nr, int *active); +void *undo_editmode_get_prev (struct Object *ob); +void undo_editmode_step (struct bContext *C, int step); +void undo_editmode_number (struct bContext *C, int nr); #endif /* ED_UTIL_INTERN_H */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index d17f966363a..c95d4d0636a 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2453,6 +2453,7 @@ static void UV_OT_select_border(wmOperatorType *ot) ot->exec= border_select_exec; ot->modal= WM_border_select_modal; ot->poll= ED_operator_image_active; /* requires space image */; + ot->cancel= WM_border_select_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -2544,6 +2545,7 @@ static void UV_OT_circle_select(wmOperatorType *ot) ot->modal= WM_gesture_circle_modal; ot->exec= circle_select_exec; ot->poll= ED_operator_image_active; /* requires space image */; + ot->cancel= WM_gesture_circle_cancel; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.c b/source/blender/editors/uvedit/uvedit_parametrizer.c index cbc673b9391..83b9752f838 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.c +++ b/source/blender/editors/uvedit/uvedit_parametrizer.c @@ -4142,7 +4142,7 @@ void param_construct_end(ParamHandle *handle, ParamBool fill, ParamBool impl) param_assert(phandle->state == PHANDLE_STATE_ALLOCATED); - phandle->ncharts = p_connect_pairs(phandle, impl); + phandle->ncharts = p_connect_pairs(phandle, (PBool)impl); phandle->charts = p_split_charts(phandle, chart, phandle->ncharts); p_chart_delete(phandle->construction_chart); @@ -4191,7 +4191,7 @@ void param_lscm_begin(ParamHandle *handle, ParamBool live, ParamBool abf) for (i = 0; i < phandle->ncharts; i++) { for (f=phandle->charts[i]->faces; f; f=f->nextlink) p_face_backup_uvs(f); - p_chart_lscm_begin(phandle->charts[i], live, abf); + p_chart_lscm_begin(phandle->charts[i], (PBool)live, (PBool)abf); } } diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 0e7df43bd34..7dfbc52819e 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -687,9 +687,25 @@ void GPU_paint_update_image(Image *ima, int x, int y, int w, int h, int mipmap) glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skip_pixels); glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skip_rows); - if ((ibuf->rect==NULL) && ibuf->rect_float) - IMB_rect_from_float(ibuf); - + if (ibuf->rect_float){ + /*This case needs a whole new buffer*/ + if(ibuf->rect==NULL) { + IMB_rect_from_float(ibuf); + } + else { + /* Do partial drawing. 'buffer' holds only the changed part. Needed for color corrected result */ + float *buffer = (float *)MEM_mallocN(w*h*sizeof(float)*4, "temp_texpaint_float_buf"); + IMB_partial_rect_from_float(ibuf, buffer, x, y, w, h); + glBindTexture(GL_TEXTURE_2D, ima->bindcode); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, GL_RGBA, + GL_FLOAT, buffer); + MEM_freeN(buffer); + if(ima->tpageflag & IMA_MIPMAP_COMPLETE) + ima->tpageflag &= ~IMA_MIPMAP_COMPLETE; + return; + } + } + glBindTexture(GL_TEXTURE_2D, ima->bindcode); glPixelStorei(GL_UNPACK_ROW_LENGTH, ibuf->x); diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index 21249c9e8f7..5d61452e149 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -243,8 +243,15 @@ void IMB_free_anim(struct anim *anim); * * @attention Defined in filter.c */ + +#define FILTER_MASK_NULL 0 +#define FILTER_MASK_MARGIN 1 +#define FILTER_MASK_USED 2 + void IMB_filter(struct ImBuf *ibuf); void IMB_filterN(struct ImBuf *out, struct ImBuf *in); +void IMB_mask_filter_extend(char *mask, int width, int height); +void IMB_mask_clear(struct ImBuf *ibuf, char *mask, int val); void IMB_filter_extend(struct ImBuf *ibuf, char *mask); void IMB_makemipmap(struct ImBuf *ibuf, int use_filter); void IMB_remakemipmap(struct ImBuf *ibuf, int use_filter); @@ -320,7 +327,12 @@ int imb_get_anim_type(const char *name); */ void IMB_de_interlace(struct ImBuf *ibuf); void IMB_interlace(struct ImBuf *ibuf); + +/* create char buffer, color corrected if necessary, for ImBufs that lack one */ void IMB_rect_from_float(struct ImBuf *ibuf); +/* create char buffer for part of the image, color corrected if necessary, + Changed part will be stored in buffer. This is expected to be used for texture painting updates */ +void IMB_partial_rect_from_float(struct ImBuf *ibuf, float *buffer, int x, int y, int w, int h); void IMB_float_from_rect(struct ImBuf *ibuf); void IMB_float_from_rect_simple(struct ImBuf *ibuf); /* no profile conversion */ /* note, check that the conversion exists, only some are supported */ diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 6b35d7df397..90ee2692cf0 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -197,6 +197,135 @@ void IMB_rect_from_float(struct ImBuf *ibuf) ibuf->userflags &= ~IB_RECT_INVALID; } + + +/* converts from linear float to sRGB byte for part of the texture, buffer will hold the changed part */ +void IMB_partial_rect_from_float(struct ImBuf *ibuf,float *buffer, int x, int y, int w, int h) +{ + /* indices to source and destination image pixels */ + float *srcFloatPxl; + unsigned char *dstBytePxl; + /* buffer index will fill buffer */ + float *bufferIndex; + + /* convenience pointers to start of image buffers */ + float *init_srcFloatPxl = (float *)ibuf->rect_float; + unsigned char *init_dstBytePxl = (unsigned char *) ibuf->rect; + + /* Dithering factor */ + float dither= ibuf->dither / 255.0f; + /* respective attributes of image */ + short profile= ibuf->profile; + int channels= ibuf->channels; + + int i, j; + + /* + if called -only- from GPU_paint_update_image this test will never fail + but leaving it here for better or worse + */ + if(init_srcFloatPxl==NULL || (buffer == NULL)){ + return; + } + if(init_dstBytePxl==NULL) { + imb_addrectImBuf(ibuf); + init_dstBytePxl = (unsigned char *) ibuf->rect; + } + if(channels==1) { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x); + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl++, bufferIndex+=4) { + dstBytePxl[1]= dstBytePxl[2]= dstBytePxl[3]= dstBytePxl[0] = FTOCHAR(srcFloatPxl[0]); + bufferIndex[0] = bufferIndex[1] = bufferIndex[2] = bufferIndex[3] = srcFloatPxl[0]; + } + } + } + else if (profile == IB_PROFILE_LINEAR_RGB) { + if(channels == 3) { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3; + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex += 4) { + linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl); + F3TOCHAR4(bufferIndex, dstBytePxl); + bufferIndex[3]= 1.0; + } + } + } + else if (channels == 4) { + if (dither != 0.f) { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { + const float d = (BLI_frand()-0.5f)*dither; + linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl); + bufferIndex[3] = srcFloatPxl[3]; + add_v4_fl(bufferIndex, d); + F4TOCHAR4(bufferIndex, dstBytePxl); + } + } + } else { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { + linearrgb_to_srgb_v3_v3(bufferIndex, srcFloatPxl); + bufferIndex[3]= srcFloatPxl[3]; + F4TOCHAR4(bufferIndex, dstBytePxl); + } + } + } + } + } + else if(ELEM(profile, IB_PROFILE_NONE, IB_PROFILE_SRGB)) { + if(channels==3) { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*3; + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=3, bufferIndex+=4) { + copy_v3_v3(bufferIndex, srcFloatPxl); + F3TOCHAR4(bufferIndex, dstBytePxl); + bufferIndex[3] = 1.0; + } + } + } + else { + if (dither != 0.f) { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { + const float d = (BLI_frand()-0.5f)*dither; + copy_v4_v4(bufferIndex, srcFloatPxl); + add_v4_fl(bufferIndex,d); + F4TOCHAR4(bufferIndex, dstBytePxl); + } + } + } else { + for (j = 0; j < h; j++){ + bufferIndex = buffer + w*j*4; + dstBytePxl = init_dstBytePxl + (ibuf->x*(y + j) + x)*4; + srcFloatPxl = init_srcFloatPxl + (ibuf->x*(y + j) + x)*4; + for(i = 0; i < w; i++, dstBytePxl+=4, srcFloatPxl+=4, bufferIndex+=4) { + copy_v4_v4(bufferIndex, srcFloatPxl); + F4TOCHAR4(bufferIndex, dstBytePxl); + } + } + } + } + } + /* ensure user flag is reset */ + ibuf->userflags &= ~IB_RECT_INVALID; +} + static void imb_float_from_rect_nonlinear(struct ImBuf *ibuf, float *fbuf) { float *tof = fbuf; diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 16fb1fdf4aa..d12360e5a7e 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -262,6 +262,70 @@ void IMB_filter(struct ImBuf *ibuf) imb_filterx(ibuf); } +void IMB_mask_filter_extend(char *mask, int width, int height) +{ + char *row1, *row2, *row3; + int rowlen, x, y; + char *temprect; + + rowlen= width; + + /* make a copy, to prevent flooding */ + temprect= MEM_dupallocN(mask); + + for(y=1; y<=height; y++) { + /* setup rows */ + row1= (char *)(temprect + (y-2)*rowlen); + row2= row1 + rowlen; + row3= row2 + rowlen; + if(y==1) + row1= row2; + else if(y==height) + row3= row2; + + for(x=0; x<rowlen; x++) { + if (mask[((y-1)*rowlen)+x]==0) { + if (*row1 || *row2 || *row3 || *(row1+1) || *(row3+1) ) { + mask[((y-1)*rowlen)+x] = FILTER_MASK_MARGIN; + } else if((x!=rowlen-1) && (*(row1+2) || *(row2+2) || *(row3+2)) ) { + mask[((y-1)*rowlen)+x] = FILTER_MASK_MARGIN; + } + } + + if(x!=0) { + row1++; row2++; row3++; + } + } + } + + MEM_freeN(temprect); +} + +void IMB_mask_clear(ImBuf *ibuf, char *mask, int val) +{ + int x,y; + if (ibuf->rect_float) { + for(x=0; x<ibuf->x; x++) { + for(y=0; y<ibuf->y; y++) { + if (mask[ibuf->x*y + x] == val) { + float *col= ibuf->rect_float + 4*(ibuf->x*y + x); + col[0] = col[1] = col[2] = col[3] = 0.0f; + } + } + } + } else { + /* char buffer */ + for(x=0; x<ibuf->x; x++) { + for(y=0; y<ibuf->y; y++) { + if (mask[ibuf->x*y + x] == val) { + char *col= (char *)(ibuf->rect + ibuf->x*y + x); + col[0] = col[1] = col[2] = col[3] = 0; + } + } + } + } +} + #define EXTEND_PIXEL(color, w) if((color)[3]) {r+= w*(color)[0]; g+= w*(color)[1]; b+= w*(color)[2]; a+= w*(color)[3]; tot+=w;} /* if alpha is zero, it checks surrounding pixels and averages color. sets new alphas to 1.0 diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index 5d9f350be48..ec00b15c079 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -586,7 +586,7 @@ struct ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags) ibuf->depth = size; if (tga.mapbits != 32) { /* set alpha bits */ - cmap[0] &= BIG_LONG(0x00ffffff); + cmap[0] &= BIG_LONG(0x00ffffffl); } } diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h index 662ef9e8a45..a9e745b8148 100644 --- a/source/blender/makesdna/DNA_lattice_types.h +++ b/source/blender/makesdna/DNA_lattice_types.h @@ -83,5 +83,7 @@ typedef struct Lattice { #define LT_DS_EXPAND 4 +#define LT_INDEX(lt, u, v, w) ((w) * ((lt)->pntsu * (lt)->pntsv) + ((v) * (lt)->pntsu) + (u)) + #endif diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 657bfb1c884..70e90cfc713 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1009,13 +1009,14 @@ typedef struct Scene { #define R_JPEG2K_CINE_PRESET 256 #define R_JPEG2K_CINE_48FPS 512 - /* bake_mode: same as RE_BAKE_xxx defines */ /* bake_flag: */ #define R_BAKE_CLEAR 1 #define R_BAKE_OSA 2 #define R_BAKE_TO_ACTIVE 4 #define R_BAKE_NORMALIZE 8 +#define R_BAKE_MULTIRES 16 +#define R_BAKE_LORES_MESH 32 /* bake_normal_space */ #define R_BAKE_SPACE_CAMERA 0 diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index cd19f4cb3de..b52ed35ddce 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -187,7 +187,6 @@ typedef struct ARegion { #define AREA_FLAG_DRAWSPLIT_H 16 #define AREA_FLAG_DRAWSPLIT_V 32 -/* If you change EDGEWIDTH, also do the global arrat edcol[] */ #define EDGEWIDTH 1 #define AREAGRID 4 #define AREAMINX 32 diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index f89cc9d518a..3e7654bcf47 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -253,27 +253,30 @@ typedef struct SpeedControlVars { #define SEQ_NAME_MAXSTR 24 /* seq->flag */ -#define SEQ_LEFTSEL 2 -#define SEQ_RIGHTSEL 4 -#define SEQ_OVERLAP 8 -#define SEQ_FILTERY 16 -#define SEQ_MUTE 32 -#define SEQ_MAKE_PREMUL 64 -#define SEQ_REVERSE_FRAMES 128 -#define SEQ_IPO_FRAME_LOCKED 256 -#define SEQ_EFFECT_NOT_LOADED 512 -#define SEQ_FLAG_DELETE 1024 -#define SEQ_FLIPX 2048 -#define SEQ_FLIPY 4096 -#define SEQ_MAKE_FLOAT 8192 -#define SEQ_LOCK 16384 -#define SEQ_USE_PROXY 32768 -#define SEQ_USE_TRANSFORM 65536 -#define SEQ_USE_CROP 131072 -#define SEQ_USE_COLOR_BALANCE 262144 -#define SEQ_USE_PROXY_CUSTOM_DIR 524288 -#define SEQ_USE_PROXY_CUSTOM_FILE 2097152 -#define SEQ_USE_EFFECT_DEFAULT_FADE 4194304 +#define SEQ_LEFTSEL (1<<1) +#define SEQ_RIGHTSEL (1<<2) +#define SEQ_OVERLAP (1<<3) +#define SEQ_FILTERY (1<<4) +#define SEQ_MUTE (1<<5) +#define SEQ_MAKE_PREMUL (1<<6) +#define SEQ_REVERSE_FRAMES (1<<7) +#define SEQ_IPO_FRAME_LOCKED (1<<8) +#define SEQ_EFFECT_NOT_LOADED (1<<9) +#define SEQ_FLAG_DELETE (1<<10) +#define SEQ_FLIPX (1<<11) +#define SEQ_FLIPY (1<<12) +#define SEQ_MAKE_FLOAT (1<<13) +#define SEQ_LOCK (1<<14) +#define SEQ_USE_PROXY (1<<15) +#define SEQ_USE_TRANSFORM (1<<16) +#define SEQ_USE_CROP (1<<17) +#define SEQ_USE_COLOR_BALANCE (1<<18) +#define SEQ_USE_PROXY_CUSTOM_DIR (1<<19) + +#define SEQ_USE_PROXY_CUSTOM_FILE (1<<21) +#define SEQ_USE_EFFECT_DEFAULT_FADE (1<<22) + +#define SEQ_INVALID_EFFECT (1<<31) /* convenience define for all selection flags */ #define SEQ_ALLSEL (SELECT+SEQ_LEFTSEL+SEQ_RIGHTSEL) diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index eea764b5423..1231f10b81f 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -374,7 +374,8 @@ typedef struct UserDef { short scrcastfps; /* frame rate for screencast to be played back */ short scrcastwait; /* milliseconds between screencast snapshots */ - short pad8, pad[3]; /* Value for Dual/Single Column UI */ + short widget_unit; /* defaults to 20 for 72 DPI setting */ + short pad[3]; char versemaster[160]; char verseuser[160]; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index e0feba3f2fd..ca19a86e42c 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -650,6 +650,7 @@ PropertyType RNA_property_type(PropertyRNA *prop); PropertySubType RNA_property_subtype(PropertyRNA *prop); PropertyUnit RNA_property_unit(PropertyRNA *prop); int RNA_property_flag(PropertyRNA *prop); +void *RNA_property_py_data_get(PropertyRNA *prop); int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_array_check(PointerRNA *ptr, PropertyRNA *prop); diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h index b076393ef3d..ac2a89161d9 100644 --- a/source/blender/makesrna/RNA_define.h +++ b/source/blender/makesrna/RNA_define.h @@ -163,6 +163,8 @@ void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *update void RNA_def_property_editable_func(PropertyRNA *prop, const char *editable); void RNA_def_property_editable_array_func(PropertyRNA *prop, const char *editable); +void RNA_def_property_update_runtime(PropertyRNA *prop, void *func); + void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength); void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const char *set); void RNA_def_property_int_funcs(PropertyRNA *prop, const char *get, const char *set, const char *range); @@ -172,6 +174,7 @@ void RNA_def_property_string_funcs(PropertyRNA *prop, const char *get, const cha void RNA_def_property_pointer_funcs(PropertyRNA *prop, const char *get, const char *set, const char *typef, const char *poll); void RNA_def_property_collection_funcs(PropertyRNA *prop, const char *begin, const char *next, const char *end, const char *get, const char *length, const char *lookupint, const char *lookupstring); void RNA_def_property_srna(PropertyRNA *prop, const char *type); +void RNA_def_py_data(PropertyRNA *prop, void *py_data); /* Function */ diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index b3f2ae01c99..ec213d6a496 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -159,6 +159,8 @@ typedef enum PropertyFlag { /* hidden in the user interface */ PROP_HIDDEN = 1<<19, + /* do not write in presets */ + PROP_SKIP_SAVE = 1<<28, /* function paramater flags */ PROP_REQUIRED = 1<<2, @@ -190,6 +192,7 @@ typedef enum PropertyFlag { /* need context for update function */ PROP_CONTEXT_UPDATE = 1<<22, + PROP_CONTEXT_PROPERTY_UPDATE = (1<<22)|(1<<27), /* Use for arrays or for any data that should not have a referene kept * most common case is functions that return arrays where the array */ diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 9b8db639cbb..ab11f88e0f6 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -755,6 +755,11 @@ int RNA_property_flag(PropertyRNA *prop) return rna_ensure_property(prop)->flag; } +void *RNA_property_py_data_get(PropertyRNA *prop) +{ + return prop->py_data; +} + int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop) { return rna_ensure_property_array_length(ptr, prop); @@ -1344,7 +1349,14 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR /* ideally no context would be needed for update, but there's some parts of the code that need it still, so we have this exception */ if(prop->flag & PROP_CONTEXT_UPDATE) { - if(C) ((ContextUpdateFunc)prop->update)(C, ptr); + if(C) { + if(prop->flag & PROP_CONTEXT_PROPERTY_UPDATE) { + ((ContextPropUpdateFunc)prop->update)(C, ptr, prop); + } + else { + ((ContextUpdateFunc)prop->update)(C, ptr); + } + } } else prop->update(bmain, scene, ptr); diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index 116f5185980..c7cf511d5c7 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -584,7 +584,7 @@ static void rna_def_action_actuator(BlenderRNA *brna) RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "use_continue_last_frame", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "end_reset", 1); + RNA_def_property_boolean_negative_sdna(prop, NULL, "end_reset", 1); RNA_def_property_ui_text(prop, "Continue", "Restore last frame when switching on/off, otherwise play from the start each time"); RNA_def_property_update(prop, NC_LOGIC, NULL); @@ -1383,7 +1383,7 @@ static void rna_def_edit_object_actuator(BlenderRNA *brna) RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "use_replace_display_mesh", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_EDOB_REPLACE_MESH_NOGFX); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ACT_EDOB_REPLACE_MESH_NOGFX); RNA_def_property_ui_text(prop, "Gfx", "Replace the display mesh"); RNA_def_property_update(prop, NC_LOGIC, NULL); @@ -1769,12 +1769,12 @@ static void rna_def_parent_actuator(BlenderRNA *brna) /* booleans */ prop= RNA_def_property(srna, "use_compound", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_PARENT_COMPOUND); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ACT_PARENT_COMPOUND); RNA_def_property_ui_text(prop, "Compound", "Add this object shape to the parent shape (only if the parent shape is already compound)"); RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "use_ghost", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_PARENT_GHOST); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ACT_PARENT_GHOST); RNA_def_property_ui_text(prop, "Ghost", "Make this object ghost while parented"); RNA_def_property_update(prop, NC_LOGIC, NULL); } @@ -1816,7 +1816,7 @@ static void rna_def_shape_action_actuator(BlenderRNA *brna) RNA_def_property_update(prop, NC_LOGIC, NULL); prop= RNA_def_property(srna, "use_continue_last_frame", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "end_reset", 1); + RNA_def_property_boolean_negative_sdna(prop, NULL, "end_reset", 1); RNA_def_property_ui_text(prop, "Continue", "Restore last frame when switching on/off, otherwise play from the start each time"); RNA_def_property_update(prop, NC_LOGIC, NULL); diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 66d1036ec44..8e9c7e287d6 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -1839,6 +1839,11 @@ void RNA_def_property_update(PropertyRNA *prop, int noteflag, const char *func) prop->update= (UpdateFunc)func; } +void RNA_def_property_update_runtime(PropertyRNA *prop, void *func) +{ + prop->update= func; +} + void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getlength) { if(!DefRNA.preprocess) { @@ -2057,6 +2062,11 @@ void RNA_def_property_srna(PropertyRNA *prop, const char *type) prop->srna= (StructRNA*)type; } +void RNA_def_py_data(PropertyRNA *prop, void *py_data) +{ + prop->py_data= py_data; +} + /* Compact definitions */ PropertyRNA *RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, int default_value, const char *ui_name, const char *ui_description) @@ -2822,6 +2832,7 @@ void RNA_def_property_free_pointers(PropertyRNA *prop) if(prop->identifier) MEM_freeN((void*)prop->identifier); if(prop->name) MEM_freeN((void*)prop->name); if(prop->description) MEM_freeN((void*)prop->description); + if(prop->py_data) MEM_freeN(prop->py_data); switch(prop->type) { case PROP_BOOLEAN: { diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 771d2afcd96..249833ae94b 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -62,6 +62,7 @@ struct Scene; /* Function Callbacks */ typedef void (*UpdateFunc)(struct Main *main, struct Scene *scene, struct PointerRNA *ptr); +typedef void (*ContextPropUpdateFunc)(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop); typedef void (*ContextUpdateFunc)(struct bContext *C, struct PointerRNA *ptr); typedef int (*EditableFunc)(struct PointerRNA *ptr); typedef int (*ItemEditableFunc)(struct PointerRNA *ptr, int index); @@ -177,6 +178,10 @@ struct PropertyRNA { * any property can have this but should only be used for collections and arrays * since python will convert int/bool/pointer's */ struct StructRNA *srna; /* attributes attached directly to this collection */ + + /* python handle to hold all callbacks + * (in a pointer array at the moment, may later be a tuple) */ + void *py_data; }; /* Property Types */ diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index d7d72659ab1..e8cea74ef3b 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -45,6 +45,9 @@ #include "WM_types.h" +#include "BLI_math_base.h" +#include "BLI_math_rotation.h" + #ifdef RNA_RUNTIME #include "DNA_scene_types.h" @@ -835,6 +838,20 @@ static void rna_TextureFace_image_set(PointerRNA *ptr, PointerRNA value) tf->tpage= (struct Image*)id; } +static void rna_Mesh_auto_smooth_angle_set(PointerRNA *ptr, float value) +{ + Mesh *me= (Mesh*)ptr->id.data; + value= RAD2DEGF(value); + CLAMP(value, 1.0f, 80.0f); + me->smoothresh= (int)value; +} + +static float rna_Mesh_auto_smooth_angle_get(PointerRNA *ptr) +{ + Mesh *me= (Mesh*)ptr->id.data; + return DEG2RADF((float)me->smoothresh); +} + static int rna_MeshFace_verts_get_length(PointerRNA *ptr, int length[RNA_MAX_ARRAY_DIMENSION]) { MFace *face= (MFace*)ptr->data; @@ -1566,7 +1583,7 @@ static void rna_def_mesh_vertices(BlenderRNA *brna, PropertyRNA *cprop) // PropertyRNA *prop; FunctionRNA *func; - PropertyRNA *parm; +// PropertyRNA *parm; RNA_def_property_srna(cprop, "MeshVertices"); srna= RNA_def_struct(brna, "MeshVertices", NULL); @@ -1799,9 +1816,15 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", ME_AUTOSMOOTH); RNA_def_property_ui_text(prop, "Auto Smooth", "Treats all set-smoothed faces with angles less than the specified angle as 'smooth' during render"); +#if 1 /* expose as radians */ + prop= RNA_def_property(srna, "auto_smooth_angle", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_funcs(prop, "rna_Mesh_auto_smooth_angle_get", "rna_Mesh_auto_smooth_angle_set", NULL); + RNA_def_property_ui_range(prop, DEG2RAD(1.0), DEG2RAD(80), 1.0, 1); +#else prop= RNA_def_property(srna, "auto_smooth_angle", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "smoothresh"); RNA_def_property_range(prop, 1, 80); +#endif RNA_def_property_ui_text(prop, "Auto Smooth Angle", "Defines maximum angle between face normals that 'Auto Smooth' will operate on"); prop= RNA_def_property(srna, "show_double_sided", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 1b7df335e68..5635c04793d 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -581,6 +581,34 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value) md->projectors[a]= NULL; } +static float rna_EdgeSplitModifier_split_angle_get(PointerRNA *ptr) +{ + EdgeSplitModifierData *md= (EdgeSplitModifierData*)ptr->data; + return DEG2RADF(md->split_angle); +} + +static void rna_EdgeSplitModifier_split_angle_set(PointerRNA *ptr, float value) +{ + EdgeSplitModifierData *md= (EdgeSplitModifierData*)ptr->data; + value= RAD2DEGF(value); + CLAMP(value, 0.0f, 180.0f); + md->split_angle= (int)value; +} + +static float rna_BevelModifier_angle_limit_get(PointerRNA *ptr) +{ + BevelModifierData *md= (BevelModifierData*)ptr->data; + return DEG2RADF(md->bevel_angle); +} + +static void rna_BevelModifier_angle_limit_set(PointerRNA *ptr, float value) +{ + BevelModifierData *md= (BevelModifierData*)ptr->data; + value= RAD2DEGF(value); + CLAMP(value, 0.0f, 180.0f); + md->bevel_angle= (int)value; +} + #else static void rna_def_property_subdivision_common(StructRNA *srna, const char type[]) @@ -1368,10 +1396,16 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna) RNA_def_struct_sdna(srna, "EdgeSplitModifierData"); RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT); - // XXX, convert to radians. +#if 1 /* expose as radians */ + prop= RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_funcs(prop, "rna_EdgeSplitModifier_split_angle_get", "rna_EdgeSplitModifier_split_angle_set", NULL); + RNA_def_property_range(prop, 0, DEG2RAD(180)); + RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2); +#else prop= RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 0, 90); RNA_def_property_ui_range(prop, 0, 90, 100, 2); +#endif RNA_def_property_ui_text(prop, "Split Angle", "Angle above which to split edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); @@ -1968,10 +2002,17 @@ static void rna_def_modifier_bevel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Edge Weight Method", "What edge weight to use for weighting a vertex"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); +#if 1 /* expose as radians */ + prop= RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_funcs(prop, "rna_BevelModifier_angle_limit_get", "rna_BevelModifier_angle_limit_set", NULL); + RNA_def_property_range(prop, 0, DEG2RAD(180)); + RNA_def_property_ui_range(prop, 0, DEG2RAD(180), 100, 2); +#else prop= RNA_def_property(srna, "angle_limit", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "bevel_angle"); RNA_def_property_range(prop, 0, 180); RNA_def_property_ui_range(prop, 0, 180, 100, 2); +#endif RNA_def_property_ui_text(prop, "Angle", "Angle above which to bevel edges"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); } diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d0b60c7f153..7fd6a9dacfe 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -2221,6 +2221,7 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "gamma"); RNA_def_property_array(prop, 3); RNA_def_property_float_array_default(prop, default_1); + RNA_def_property_range(prop, 0.f, FLT_MAX); RNA_def_property_ui_range(prop, 0, 2, 0.1, 3); RNA_def_property_ui_text(prop, "Power", "Correction for Midtones"); RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); @@ -2229,6 +2230,7 @@ static void def_cmp_colorbalance(StructRNA *srna) RNA_def_property_float_sdna(prop, NULL, "gain"); RNA_def_property_array(prop, 3); RNA_def_property_float_array_default(prop, default_1); + RNA_def_property_range(prop, 0.f, FLT_MAX); RNA_def_property_ui_range(prop, 0, 2, 0.1, 3); RNA_def_property_ui_text(prop, "Slope", "Correction for Highlights"); RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_Node_update"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index b411ea75d4e..76cc7f4ed80 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -455,6 +455,14 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value) BKE_report(NULL, RPT_ERROR, "Cannot set dupli-group as object belongs in group being instanced thus causing a cycle"); } +void rna_VertexGroup_name_set(PointerRNA *ptr, const char *value) +{ + Object *ob= (Object *)ptr->id.data; + bDeformGroup *dg= (bDeformGroup *)ptr->data; + BLI_strncpy(dg->name, value, sizeof(dg->name)); + defgroup_unique_name(dg, ob); +} + static int rna_VertexGroup_index_get(PointerRNA *ptr) { Object *ob= (Object*)ptr->id.data; @@ -1237,6 +1245,7 @@ static void rna_def_vertex_group(BlenderRNA *brna) prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_ui_text(prop, "Name", "Vertex group name"); RNA_def_struct_name_property(srna, prop); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_VertexGroup_name_set"); RNA_def_property_update(prop, NC_GEOM|ND_DATA|NA_RENAME, "rna_Object_internal_update_data"); /* update data because modifiers may use [#24761] */ prop= RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 84bb624b546..b4da3a02442 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -493,6 +493,13 @@ static int rna_Property_is_hidden_get(PointerRNA *ptr) return prop->flag & PROP_HIDDEN ? 1:0; } +static int rna_Property_is_skip_save_get(PointerRNA *ptr) +{ + PropertyRNA *prop= (PropertyRNA*)ptr->data; + return prop->flag & PROP_SKIP_SAVE ? 1:0; +} + + static int rna_Property_is_enum_flag_get(PointerRNA *ptr) { PropertyRNA *prop= (PropertyRNA*)ptr->data; @@ -1037,6 +1044,11 @@ static void rna_def_property(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Property_is_hidden_get", NULL); RNA_def_property_ui_text(prop, "Hidden", "True when the property is hidden"); + prop= RNA_def_property(srna, "is_skip_save", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_boolean_funcs(prop, "rna_Property_is_skip_save_get", NULL); + RNA_def_property_ui_text(prop, "Skip Save", "True when the property is not saved in presets"); + prop= RNA_def_property(srna, "is_output", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Property_use_output_get", NULL); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b7bd4e251f0..641ac8a9882 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2814,6 +2814,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Bias", "Bias towards faces further away from the object (in blender units)"); + prop= RNA_def_property(srna, "use_bake_multires", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_MULTIRES); + RNA_def_property_ui_text(prop, "Bake from Multires", "Bake directly from multires object"); + + prop= RNA_def_property(srna, "use_bake_lores_mesh", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "bake_flag", R_BAKE_LORES_MESH); + RNA_def_property_ui_text(prop, "Low Resolution Mesh", "Calculate heights against unsubdivided low resolution mesh"); + /* stamp */ prop= RNA_def_property(srna, "use_stamp_time", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 88ff5ebb628..8c4e4d9e736 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -588,11 +588,16 @@ static void rna_Sequence_filepath_update(Main *bmain, Scene *scene, PointerRNA * } /* do_versions? */ -static float rna_Sequence_opacity_get(PointerRNA *ptr) { - return ((Sequence*)(ptr->data))->blend_opacity / 100.0f; +static float rna_Sequence_opacity_get(PointerRNA *ptr) +{ + Sequence *seq= (Sequence*)(ptr->data); + return seq->blend_opacity / 100.0f; } -static void rna_Sequence_opacity_set(PointerRNA *ptr, float value) { - ((Sequence*)(ptr->data))->blend_opacity = value * 100.0f; +static void rna_Sequence_opacity_set(PointerRNA *ptr, float value) +{ + Sequence *seq= (Sequence*)(ptr->data); + CLAMP(value, 0.0f, 1.0f); + seq->blend_opacity = value * 100.0f; } @@ -675,6 +680,23 @@ static void rna_SequenceEditor_overlay_frame_set(PointerRNA *ptr, int value) ed->over_ofs= value; } + +static void rna_WipeSequence_angle_set(PointerRNA *ptr, float value) +{ + Sequence *seq= (Sequence *)(ptr->data); + value= RAD2DEGF(value); + CLAMP(value, -90.0f, 90.0f); + ((WipeVars *)seq->effectdata)->angle= value; +} + +static float rna_WipeSequence_angle_get(PointerRNA *ptr) +{ + Sequence *seq= (Sequence *)(ptr->data); + + return DEG2RADF(((WipeVars *)seq->effectdata)->angle); +} + + #else static void rna_def_strip_element(BlenderRNA *brna) @@ -1455,10 +1477,16 @@ static void rna_def_wipe(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_ui_text(prop, "Blur Width", "Width of the blur edge, in percentage relative to the image size"); RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update"); - + +#if 1 /* expose as radians */ + prop= RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_funcs(prop, "rna_WipeSequence_angle_get", "rna_WipeSequence_angle_set", NULL); + RNA_def_property_range(prop, DEG2RAD(-90.0f), DEG2RAD(90.0f)); +#else prop= RNA_def_property(srna, "angle", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "angle"); RNA_def_property_range(prop, -90.0f, 90.0f); +#endif RNA_def_property_ui_text(prop, "Angle", "Edge angle"); RNA_def_property_update(prop, NC_SCENE|ND_SEQUENCER, "rna_Sequence_update"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 33808446757..b67805c97b9 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -69,6 +69,13 @@ static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), Pointe WM_main_add_notifier(NC_WINDOW, NULL); } +static void rna_userdef_dpi_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + U.widget_unit = (U.dpi * 20 + 36)/72; + WM_main_add_notifier(NC_WINDOW, NULL); /* full redraw */ + WM_main_add_notifier(NC_SCREEN|NA_EDITED, NULL); /* refresh region sizes */ +} + static void rna_userdef_show_manipulator_update(Main *bmain, Scene *scene, PointerRNA *ptr) { UserDef *userdef = (UserDef *)ptr->data; @@ -2444,7 +2451,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "dpi"); RNA_def_property_range(prop, 48, 128); RNA_def_property_ui_text(prop, "DPI", "Font size and resolution for display"); - RNA_def_property_update(prop, 0, "rna_userdef_update"); + RNA_def_property_update(prop, 0, "rna_userdef_dpi_update"); prop= RNA_def_property(srna, "scrollback", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "scrollback"); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 406ee6b3f3e..7ea4701dec3 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -272,10 +272,11 @@ EnumPropertyItem keymap_modifiers_items[] = { EnumPropertyItem operator_flag_items[] = { {OPTYPE_REGISTER, "REGISTER", 0, "Register", ""}, {OPTYPE_UNDO, "UNDO", 0, "Undo", ""}, - {OPTYPE_BLOCKING, "BLOCKING", 0, "Finished", ""}, + {OPTYPE_BLOCKING, "BLOCKING", 0, "Blocking", ""}, {OPTYPE_MACRO, "MACRO", 0, "Macro", ""}, {OPTYPE_GRAB_POINTER, "GRAB_POINTER", 0, "Grab Pointer", ""}, {OPTYPE_PRESET, "PRESET", 0, "Preset", ""}, + {OPTYPE_INTERNAL, "INTERNAL", 0, "Internal", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem operator_return_items[] = { @@ -1047,6 +1048,7 @@ static StructRNA* rna_MacroOperator_refine(PointerRNA *opr) static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, const char *idname, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) { // wmWindowManager *wm = CTX_wm_manager(C); + char idname_bl[OP_MAX_TYPENAME]; int modifier= 0; /* only on non-modal maps */ @@ -1055,6 +1057,8 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, cons return NULL; } + WM_operator_bl_idname(idname_bl, idname); + if(shift) modifier |= KM_SHIFT; if(ctrl) modifier |= KM_CTRL; if(alt) modifier |= KM_ALT; @@ -1062,7 +1066,7 @@ static wmKeyMapItem *rna_KeyMap_item_new(wmKeyMap *km, ReportList *reports, cons if(any) modifier = KM_ANY; - return WM_keymap_add_item(km, idname, type, value, modifier, keymodifier); + return WM_keymap_add_item(km, idname_bl, type, value, modifier, keymodifier); } static wmKeyMapItem *rna_KeyMap_item_new_modal(wmKeyMap *km, bContext *C, ReportList *reports, const char *propvalue_str, int type, int value, int any, int shift, int ctrl, int alt, int oskey, int keymodifier) diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 657c20a06a3..f71fd11877f 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -90,8 +90,12 @@ set(SRC if(WITH_MOD_BOOLEAN) add_definitions(-DWITH_MOD_BOOLEAN) - list(APPEND SRC intern/MOD_boolean_util.c) - list(APPEND INC ../../../intern/bsp/extern) + list(APPEND SRC + intern/MOD_boolean_util.c + ) + list(APPEND INC + ../../../intern/bsp/extern + ) endif() if(WITH_MOD_DECIMATE) diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 30ddb3f7b9c..1d2a6b2f788 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -190,6 +190,19 @@ static void freeData(ModifierData *md) } } +static void foreachIDLink(ModifierData *md, Object *ob, + IDWalkFunc walk, void *userData) +{ + ClothModifierData *clmd = (ClothModifierData*) md; + + if(clmd->coll_parms) { + walk(userData, ob, (ID **)&clmd->coll_parms->group); + } + + if(clmd->sim_parms && clmd->sim_parms->effector_weights) { + walk(userData, ob, (ID **)&clmd->sim_parms->effector_weights->group); + } +} ModifierTypeInfo modifierType_Cloth = { /* name */ "Cloth", @@ -215,5 +228,5 @@ ModifierTypeInfo modifierType_Cloth = { /* dependsOnTime */ dependsOnTime, /* dependsOnNormals */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, }; diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 2fcf352e20b..90faff5c68c 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -58,12 +58,12 @@ DerivedMesh *doEdgeSplit(DerivedMesh *dm, EdgeSplitModifierData *emd, Object *ob { BMesh *bm; BMEditMesh *em; - DerivedMesh *cddm, *bmdm; + DerivedMesh *cddm; BMIter iter, liter; BMFace *f; BMLoop *l; BMEdge *e; - int allocsize[] = {512, 512, 2048, 512}; + /* int allocsize[] = {512, 512, 2048, 512}; */ /* UNUSED */ float threshold = cos((emd->split_angle + 0.00001) * M_PI / 180.0); if (!CDDM_Check(dm)) { diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index 48799510ad9..e6495348a61 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -73,6 +73,8 @@ static void freeData(ModifierData *md) if(mmd->dyngrid) MEM_freeN(mmd->dyngrid); if(mmd->dyninfluences) MEM_freeN(mmd->dyninfluences); if(mmd->dynverts) MEM_freeN(mmd->dynverts); + if(mmd->bindweights) MEM_freeN(mmd->bindweights); /* deprecated */ + if(mmd->bindcos) MEM_freeN(mmd->bindcos); /* deprecated */ } static void copyData(ModifierData *md, ModifierData *target) diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index 489733c8480..48c5b9a4c08 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -57,7 +57,7 @@ ModifierTypeInfo modifierType_None = { /* name */ "None", /* structName */ "ModifierData", /* structSize */ sizeof(ModifierData), - /* type */ eModifierType_None, + /* type */ eModifierTypeType_None, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, diff --git a/source/blender/modifiers/intern/MOD_smoke.c b/source/blender/modifiers/intern/MOD_smoke.c index d8e94e92bfa..b6203bb3c1d 100644 --- a/source/blender/modifiers/intern/MOD_smoke.c +++ b/source/blender/modifiers/intern/MOD_smoke.c @@ -43,6 +43,7 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_smoke_types.h" +#include "DNA_object_force.h" #include "BLI_utildefines.h" @@ -156,6 +157,10 @@ static void foreachIDLink(ModifierData *md, Object *ob, walk(userData, ob, (ID **)&smd->domain->coll_group); walk(userData, ob, (ID **)&smd->domain->fluid_group); walk(userData, ob, (ID **)&smd->domain->eff_group); + + if(smd->domain->effector_weights) { + walk(userData, ob, (ID **)&smd->domain->effector_weights->group); + } } } diff --git a/source/blender/nodes/intern/CMP_nodes/CMP_math.c b/source/blender/nodes/intern/CMP_nodes/CMP_math.c index 4348fd18759..b7a67f3563b 100644 --- a/source/blender/nodes/intern/CMP_nodes/CMP_math.c +++ b/source/blender/nodes/intern/CMP_nodes/CMP_math.c @@ -140,7 +140,12 @@ static void do_math(bNode *node, float *out, float *in, float *in2) break; case 14: /* Round */ { - out[0]= (out[0]<0)?(int)(in[0] - 0.5f):(int)(in[0] + 0.5f); + /* round by the second value */ + if( in2[0] != 0.0f ) + out[0]= floorf(in[0] / in2[0] + 0.5f) * in2[0]; + else + out[0]= floorf(in[0] + 0.5f); + } break; case 15: /* Less Than */ diff --git a/source/blender/nodes/intern/CMP_util.c b/source/blender/nodes/intern/CMP_util.c index 78025f4d964..b73a46c7d7d 100644 --- a/source/blender/nodes/intern/CMP_util.c +++ b/source/blender/nodes/intern/CMP_util.c @@ -1320,6 +1320,12 @@ void IIR_gauss(CompBuf* src, float sigma, int chan, int xy) if ((xy < 1) || (xy > 3)) xy = 3; + // XXX The YVV macro defined below explicitely expects sources of at least 3x3 pixels, + // so just skiping blur along faulty direction if src's def is below that limit! + if (src->x < 3) xy &= ~(int) 1; + if (src->y < 3) xy &= ~(int) 2; + if (xy < 1) return; + // see "Recursive Gabor Filtering" by Young/VanVliet // all factors here in double.prec. Required, because for single.prec it seems to blow up if sigma > ~200 if (sigma >= 3.556) diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index e8796a6f8dd..ae5253d07a0 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -67,14 +67,14 @@ int BPY_is_pyconstraint(struct Text *text); // void BPY_free_pyconstraint_links(struct Text *text); // void BPY_python_start(int argc, const char **argv); -void BPY_python_end( void ); -// void init_syspath( int first_time ); -// void syspath_append( char *dir ); -// void BPY_rebuild_syspath( void ); -// int BPY_path_update( void ); +void BPY_python_end(void); +// void init_syspath(int first_time); +// void syspath_append(char *dir); +// void BPY_rebuild_syspath(void); +// int BPY_path_update(void); // -// int BPY_Err_getLinenumber( void ); -// const char *BPY_Err_getFilename( void ); +// int BPY_Err_getLinenumber(void); +// const char *BPY_Err_getFilename(void); /* 2.5 UI Scripts */ int BPY_filepath_exec(struct bContext *C, const char *filepath, struct ReportList *reports); diff --git a/source/blender/python/generic/bgl.c b/source/blender/python/generic/bgl.c index 4eb6d78bd7b..b5a693c397c 100644 --- a/source/blender/python/generic/bgl.c +++ b/source/blender/python/generic/bgl.c @@ -62,16 +62,16 @@ square buffer. Passing [16, 16, 32] will create a 3 dimensional\n\ buffer which is twice as deep as it is wide or high." ); -static PyObject *Method_Buffer( PyObject * self, PyObject *args ); +static PyObject *Method_Buffer(PyObject *self, PyObject *args); /* Buffer sequence methods */ -static int Buffer_len( PyObject * self ); -static PyObject *Buffer_item( PyObject * self, int i ); -static PyObject *Buffer_slice( PyObject * self, int begin, int end ); -static int Buffer_ass_item( PyObject * self, int i, PyObject * v ); -static int Buffer_ass_slice( PyObject * self, int begin, int end, - PyObject * seq ); +static int Buffer_len(PyObject *self); +static PyObject *Buffer_item(PyObject *self, int i); +static PyObject *Buffer_slice(PyObject *self, int begin, int end); +static int Buffer_ass_item(PyObject *self, int i, PyObject *v); +static int Buffer_ass_slice(PyObject *self, int begin, int end, + PyObject *seq); static PySequenceMethods Buffer_SeqMethods = { ( lenfunc ) Buffer_len, /*sq_length */ @@ -86,11 +86,11 @@ static PySequenceMethods Buffer_SeqMethods = { (ssizeargfunc) NULL, /* sq_inplace_repeat */ }; -static void Buffer_dealloc( PyObject * self ); -static PyObject *Buffer_tolist( PyObject * self ); -static PyObject *Buffer_dimensions( PyObject * self ); -static PyObject *Buffer_getattr( PyObject * self, char *name ); -static PyObject *Buffer_repr( PyObject * self ); +static void Buffer_dealloc(PyObject *self); +static PyObject *Buffer_tolist(PyObject *self); +static PyObject *Buffer_dimensions(PyObject *self); +static PyObject *Buffer_getattr(PyObject *self, char *name); +static PyObject *Buffer_repr(PyObject *self); PyTypeObject BGL_bufferType = { PyVarObject_HEAD_INIT(NULL, 0) diff --git a/source/blender/python/generic/bgl.h b/source/blender/python/generic/bgl.h index a870e82d4fd..81b570c8505 100644 --- a/source/blender/python/generic/bgl.h +++ b/source/blender/python/generic/bgl.h @@ -55,7 +55,7 @@ int BGL_typeSize( int type ); /*@ For Python access to OpenGL functions requiring a pointer. */ typedef struct _Buffer { PyObject_VAR_HEAD - PyObject * parent; + PyObject *parent; int type; /* GL_BYTE, GL_SHORT, GL_INT, GL_FLOAT */ int ndimensions; diff --git a/source/blender/python/generic/bpy_internal_import.c b/source/blender/python/generic/bpy_internal_import.c index cb145cc453b..f0158fe72c3 100644 --- a/source/blender/python/generic/bpy_internal_import.c +++ b/source/blender/python/generic/bpy_internal_import.c @@ -217,7 +217,7 @@ PyObject *bpy_text_reimport(PyObject *module, int *found) } -static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject * kw) +static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject *kw) { PyObject *exception, *err, *tb; char *name; @@ -270,7 +270,7 @@ static PyObject *blender_import(PyObject *UNUSED(self), PyObject *args, PyObject * our reload() module, to handle reloading in-memory scripts */ -static PyObject *blender_reload(PyObject *UNUSED(self), PyObject * module) +static PyObject *blender_reload(PyObject *UNUSED(self), PyObject *module) { PyObject *exception, *err, *tb; PyObject *newmodule= NULL; diff --git a/source/blender/python/generic/mathutils_Color.c b/source/blender/python/generic/mathutils_Color.c index 09e3493cd09..c59cb501d86 100644 --- a/source/blender/python/generic/mathutils_Color.c +++ b/source/blender/python/generic/mathutils_Color.c @@ -186,7 +186,7 @@ static PyObject *Color_item(ColorObject * self, int i) } //----------------------------object[]------------------------- //sequence accessor (set) -static int Color_ass_item(ColorObject * self, int i, PyObject * value) +static int Color_ass_item(ColorObject * self, int i, PyObject *value) { float f = PyFloat_AsDouble(value); @@ -233,7 +233,7 @@ static PyObject *Color_slice(ColorObject * self, int begin, int end) } //----------------------------object[z:y]------------------------ //sequence slice (set) -static int Color_ass_slice(ColorObject * self, int begin, int end, PyObject * seq) +static int Color_ass_slice(ColorObject *self, int begin, int end, PyObject *seq) { int i, size; float col[COLOR_SIZE]; @@ -344,13 +344,279 @@ static PyMappingMethods Color_AsMapping = { (objobjargproc)Color_ass_subscript }; +/* numeric */ + + +/* addition: obj + obj */ +static PyObject *Color_add(PyObject *v1, PyObject *v2) +{ + ColorObject *color1 = NULL, *color2 = NULL; + float col[COLOR_SIZE]; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_SetString(PyExc_AttributeError, "Color addition: arguments not valid for this operation"); + return NULL; + } + color1 = (ColorObject*)v1; + color2 = (ColorObject*)v2; + + if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) + return NULL; + + add_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE); + + return newColorObject(col, Py_NEW, Py_TYPE(v1)); +} + +/* addition in-place: obj += obj */ +static PyObject *Color_iadd(PyObject *v1, PyObject *v2) +{ + ColorObject *color1 = NULL, *color2 = NULL; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_SetString(PyExc_AttributeError, "Color addition: arguments not valid for this operation"); + return NULL; + } + color1 = (ColorObject*)v1; + color2 = (ColorObject*)v2; + + if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) + return NULL; + + add_vn_vn(color1->col, color2->col, COLOR_SIZE); + + (void)BaseMath_WriteCallback(color1); + Py_INCREF(v1); + return v1; +} + +/* subtraction: obj - obj */ +static PyObject *Color_sub(PyObject *v1, PyObject *v2) +{ + ColorObject *color1 = NULL, *color2 = NULL; + float col[COLOR_SIZE]; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_SetString(PyExc_AttributeError, "Color subtraction: arguments not valid for this operation"); + return NULL; + } + color1 = (ColorObject*)v1; + color2 = (ColorObject*)v2; + + if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) + return NULL; + + sub_vn_vnvn(col, color1->col, color2->col, COLOR_SIZE); + + return newColorObject(col, Py_NEW, Py_TYPE(v1)); +} + +/* subtraction in-place: obj -= obj */ +static PyObject *Color_isub(PyObject *v1, PyObject *v2) +{ + ColorObject *color1= NULL, *color2= NULL; + + if (!ColorObject_Check(v1) || !ColorObject_Check(v2)) { + PyErr_SetString(PyExc_AttributeError, "Color subtraction: arguments not valid for this operation"); + return NULL; + } + color1 = (ColorObject*)v1; + color2 = (ColorObject*)v2; + + if(BaseMath_ReadCallback(color1) == -1 || BaseMath_ReadCallback(color2) == -1) + return NULL; + + sub_vn_vn(color1->col, color2->col, COLOR_SIZE); + + (void)BaseMath_WriteCallback(color1); + Py_INCREF(v1); + return v1; +} + +static PyObject *color_mul_float(ColorObject *color, const float scalar) +{ + float tcol[COLOR_SIZE]; + mul_vn_vn_fl(tcol, color->col, COLOR_SIZE, scalar); + return newColorObject(tcol, Py_NEW, Py_TYPE(color)); +} + + +static PyObject *Color_mul(PyObject *v1, PyObject *v2) +{ + ColorObject *color1 = NULL, *color2 = NULL; + float scalar; + + if ColorObject_Check(v1) { + color1= (ColorObject *)v1; + if(BaseMath_ReadCallback(color1) == -1) + return NULL; + } + if ColorObject_Check(v2) { + color2= (ColorObject *)v2; + if(BaseMath_ReadCallback(color2) == -1) + return NULL; + } + + + /* make sure v1 is always the vector */ + if (color1 && color2) { + /* col * col, dont support yet! */ + } + else if (color1) { + if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR * FLOAT */ + return color_mul_float(color1, scalar); + } + } + else if (color2) { + if (((scalar= PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred())==0) { /* FLOAT * COLOR */ + return color_mul_float(color2, scalar); + } + } + else { + BLI_assert(!"internal error"); + } + + PyErr_Format(PyExc_TypeError, "Color multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); + return NULL; +} + +static PyObject *Color_div(PyObject *v1, PyObject *v2) +{ + ColorObject *color1 = NULL; + float scalar; + + if ColorObject_Check(v1) { + color1= (ColorObject *)v1; + if(BaseMath_ReadCallback(color1) == -1) + return NULL; + } + else { + PyErr_SetString(PyExc_TypeError, "Color division not supported in this order"); + return NULL; + } + + /* make sure v1 is always the vector */ + if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR * FLOAT */ + if(scalar==0.0f) { + PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error"); + return NULL; + } + return color_mul_float(color1, 1.0f / scalar); + } + + PyErr_Format(PyExc_TypeError, "Color multiplication: not supported between '%.200s' and '%.200s' types", Py_TYPE(v1)->tp_name, Py_TYPE(v2)->tp_name); + return NULL; +} + +/* mulplication in-place: obj *= obj */ +static PyObject *Color_imul(PyObject *v1, PyObject *v2) +{ + ColorObject *color = (ColorObject *)v1; + float scalar; + + if(BaseMath_ReadCallback(color) == -1) + return NULL; + + /* only support color *= float */ + if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR *= FLOAT */ + mul_vn_fl(color->col, COLOR_SIZE, scalar); + } + else { + PyErr_SetString(PyExc_TypeError, "Color multiplication: arguments not acceptable for this operation"); + return NULL; + } + + (void)BaseMath_WriteCallback(color); + Py_INCREF(v1); + return v1; +} + +/* mulplication in-place: obj *= obj */ +static PyObject *Color_idiv(PyObject *v1, PyObject *v2) +{ + ColorObject *color = (ColorObject *)v1; + float scalar; + + if(BaseMath_ReadCallback(color) == -1) + return NULL; + + /* only support color /= float */ + if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* COLOR /= FLOAT */ + if(scalar==0.0f) { + PyErr_SetString(PyExc_ZeroDivisionError, "Color division: divide by zero error"); + return NULL; + } + + mul_vn_fl(color->col, COLOR_SIZE, 1.0f / scalar); + } + else { + PyErr_SetString(PyExc_TypeError, "Color multiplication: arguments not acceptable for this operation"); + return NULL; + } + + (void)BaseMath_WriteCallback(color); + Py_INCREF(v1); + return v1; +} + +/* -obj + returns the negative of this object*/ +static PyObject *Color_neg(ColorObject *self) +{ + float tcol[COLOR_SIZE]; + + if(BaseMath_ReadCallback(self) == -1) + return NULL; + + negate_vn_vn(tcol, self->col, COLOR_SIZE); + return newColorObject(tcol, Py_NEW, Py_TYPE(self)); +} + + +static PyNumberMethods Color_NumMethods = { + (binaryfunc) Color_add, /*nb_add*/ + (binaryfunc) Color_sub, /*nb_subtract*/ + (binaryfunc) Color_mul, /*nb_multiply*/ + NULL, /*nb_remainder*/ + NULL, /*nb_divmod*/ + NULL, /*nb_power*/ + (unaryfunc) Color_neg, /*nb_negative*/ + (unaryfunc) NULL, /*tp_positive*/ + (unaryfunc) NULL, /*tp_absolute*/ + (inquiry) NULL, /*tp_bool*/ + (unaryfunc) NULL, /*nb_invert*/ + NULL, /*nb_lshift*/ + (binaryfunc)NULL, /*nb_rshift*/ + NULL, /*nb_and*/ + NULL, /*nb_xor*/ + NULL, /*nb_or*/ + NULL, /*nb_int*/ + NULL, /*nb_reserved*/ + NULL, /*nb_float*/ + Color_iadd, /* nb_inplace_add */ + Color_isub, /* nb_inplace_subtract */ + Color_imul, /* nb_inplace_multiply */ + NULL, /* nb_inplace_remainder */ + NULL, /* nb_inplace_power */ + NULL, /* nb_inplace_lshift */ + NULL, /* nb_inplace_rshift */ + NULL, /* nb_inplace_and */ + NULL, /* nb_inplace_xor */ + NULL, /* nb_inplace_or */ + NULL, /* nb_floor_divide */ + Color_div, /* nb_true_divide */ + NULL, /* nb_inplace_floor_divide */ + Color_idiv, /* nb_inplace_true_divide */ + NULL, /* nb_index */ +}; + /* color channel, vector.r/g/b */ static PyObject *Color_getChannel(ColorObject * self, void *type) { return Color_item(self, GET_INT_FROM_POINTER(type)); } -static int Color_setChannel(ColorObject * self, PyObject * value, void * type) +static int Color_setChannel(ColorObject * self, PyObject *value, void * type) { return Color_ass_item(self, GET_INT_FROM_POINTER(type), value); } @@ -369,7 +635,7 @@ static PyObject *Color_getChannelHSV(ColorObject * self, void *type) return PyFloat_FromDouble(hsv[i]); } -static int Color_setChannelHSV(ColorObject * self, PyObject * value, void * type) +static int Color_setChannelHSV(ColorObject * self, PyObject *value, void * type) { float hsv[3]; int i= GET_INT_FROM_POINTER(type); @@ -412,7 +678,7 @@ static PyObject *Color_getHSV(ColorObject * self, void *UNUSED(closure)) return ret; } -static int Color_setHSV(ColorObject * self, PyObject * value, void *UNUSED(closure)) +static int Color_setHSV(ColorObject * self, PyObject *value, void *UNUSED(closure)) { float hsv[3]; @@ -473,7 +739,7 @@ PyTypeObject color_Type = { NULL, //tp_setattr NULL, //tp_compare (reprfunc) Color_repr, //tp_repr - NULL, //tp_as_number + &Color_NumMethods, //tp_as_number &Color_SeqMethods, //tp_as_sequence &Color_AsMapping, //tp_as_mapping NULL, //tp_hash diff --git a/source/blender/python/generic/mathutils_Euler.c b/source/blender/python/generic/mathutils_Euler.c index 9adf0ee905b..4281c7bf6c5 100644 --- a/source/blender/python/generic/mathutils_Euler.c +++ b/source/blender/python/generic/mathutils_Euler.c @@ -419,7 +419,7 @@ static PyObject *Euler_slice(EulerObject * self, int begin, int end) } //----------------------------object[z:y]------------------------ //sequence slice (set) -static int Euler_ass_slice(EulerObject * self, int begin, int end, PyObject * seq) +static int Euler_ass_slice(EulerObject *self, int begin, int end, PyObject *seq) { int i, size; float eul[EULER_SIZE]; diff --git a/source/blender/python/generic/mathutils_Matrix.c b/source/blender/python/generic/mathutils_Matrix.c index 982a8e63282..4b7f9dc0d97 100644 --- a/source/blender/python/generic/mathutils_Matrix.c +++ b/source/blender/python/generic/mathutils_Matrix.c @@ -1485,7 +1485,7 @@ static PyObject *matrix_mul_float(MatrixObject *mat, const float scalar) return newMatrixObject(tmat, mat->row_size, mat->col_size, Py_NEW, Py_TYPE(mat)); } -static PyObject *Matrix_mul(PyObject * m1, PyObject * m2) +static PyObject *Matrix_mul(PyObject *m1, PyObject *m2) { float scalar; diff --git a/source/blender/python/generic/mathutils_Vector.c b/source/blender/python/generic/mathutils_Vector.c index fd8d1b5f481..d0ba94474d4 100644 --- a/source/blender/python/generic/mathutils_Vector.c +++ b/source/blender/python/generic/mathutils_Vector.c @@ -869,8 +869,7 @@ static PyObject *Vector_slice(VectorObject *self, int begin, int end) return tuple; } /* sequence slice (set): vector[a:b] = value */ -static int Vector_ass_slice(VectorObject *self, int begin, int end, - PyObject * seq) +static int Vector_ass_slice(VectorObject *self, int begin, int end, PyObject *seq) { int y, size = 0; float vec[MAX_DIMENSIONS]; @@ -899,7 +898,7 @@ static int Vector_ass_slice(VectorObject *self, int begin, int end, /* Numeric Protocols */ /* addition: obj + obj */ -static PyObject *Vector_add(PyObject * v1, PyObject * v2) +static PyObject *Vector_add(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; float vec[MAX_DIMENSIONS]; @@ -926,7 +925,7 @@ static PyObject *Vector_add(PyObject * v1, PyObject * v2) } /* addition in-place: obj += obj */ -static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) +static PyObject *Vector_iadd(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; @@ -953,7 +952,7 @@ static PyObject *Vector_iadd(PyObject * v1, PyObject * v2) } /* subtraction: obj - obj */ -static PyObject *Vector_sub(PyObject * v1, PyObject * v2) +static PyObject *Vector_sub(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; float vec[MAX_DIMENSIONS]; @@ -979,7 +978,7 @@ static PyObject *Vector_sub(PyObject * v1, PyObject * v2) } /* subtraction in-place: obj -= obj */ -static PyObject *Vector_isub(PyObject * v1, PyObject * v2) +static PyObject *Vector_isub(PyObject *v1, PyObject *v2) { VectorObject *vec1= NULL, *vec2= NULL; @@ -1055,7 +1054,7 @@ static PyObject *vector_mul_float(VectorObject *vec, const float scalar) return newVectorObject(tvec, vec->size, Py_NEW, Py_TYPE(vec)); } -static PyObject *Vector_mul(PyObject * v1, PyObject * v2) +static PyObject *Vector_mul(PyObject *v1, PyObject *v2) { VectorObject *vec1 = NULL, *vec2 = NULL; float scalar; @@ -1116,12 +1115,12 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) mul_qt_v3(quat2->quat, tvec); return newVectorObject(tvec, 3, Py_NEW, Py_TYPE(vec1)); } - else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC*FLOAT */ + else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC * FLOAT */ return vector_mul_float(vec1, scalar); } } else if (vec2) { - if (((scalar= PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred())==0) { /* VEC*FLOAT */ + if (((scalar= PyFloat_AsDouble(v1)) == -1.0f && PyErr_Occurred())==0) { /* FLOAT * VEC */ return vector_mul_float(vec2, scalar); } } @@ -1134,7 +1133,7 @@ static PyObject *Vector_mul(PyObject * v1, PyObject * v2) } /* mulplication in-place: obj *= obj */ -static PyObject *Vector_imul(PyObject * v1, PyObject * v2) +static PyObject *Vector_imul(PyObject *v1, PyObject *v2) { VectorObject *vec = (VectorObject *)v1; float scalar; @@ -1168,7 +1167,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) } mul_qt_v3(quat2->quat, vec->vec); } - else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC*=FLOAT */ + else if (((scalar= PyFloat_AsDouble(v2)) == -1.0f && PyErr_Occurred())==0) { /* VEC *= FLOAT */ mul_vn_fl(vec->vec, vec->size, scalar); } else { @@ -1182,7 +1181,7 @@ static PyObject *Vector_imul(PyObject * v1, PyObject * v2) } /* divid: obj / obj */ -static PyObject *Vector_div(PyObject * v1, PyObject * v2) +static PyObject *Vector_div(PyObject *v1, PyObject *v2) { int i; float vec[4], scalar; @@ -1214,7 +1213,7 @@ static PyObject *Vector_div(PyObject * v1, PyObject * v2) } /* divide in-place: obj /= obj */ -static PyObject *Vector_idiv(PyObject * v1, PyObject * v2) +static PyObject *Vector_idiv(PyObject *v1, PyObject *v2) { int i; float scalar; @@ -1489,7 +1488,7 @@ static PyObject *Vector_getAxis(VectorObject *self, void *type) return vector_item_internal(self, GET_INT_FROM_POINTER(type), TRUE); } -static int Vector_setAxis(VectorObject *self, PyObject * value, void *type) +static int Vector_setAxis(VectorObject *self, PyObject *value, void *type) { return vector_ass_item_internal(self, GET_INT_FROM_POINTER(type), value, TRUE); } @@ -1596,7 +1595,7 @@ static PyObject *Vector_getSwizzle(VectorObject *self, void *closure) Returns 0 on success and -1 on failure. On failure, the vector will be unchanged. */ -static int Vector_setSwizzle(VectorObject *self, PyObject * value, void *closure) +static int Vector_setSwizzle(VectorObject *self, PyObject *value, void *closure) { size_t size_from; float scalarVal; diff --git a/source/blender/python/generic/mathutils_geometry.c b/source/blender/python/generic/mathutils_geometry.c index c4917199e59..53c066d1a85 100644 --- a/source/blender/python/generic/mathutils_geometry.c +++ b/source/blender/python/generic/mathutils_geometry.c @@ -169,7 +169,7 @@ PyDoc_STRVAR(M_Geometry_intersect_line_line_doc, ); static PyObject *M_Geometry_intersect_line_line(PyObject *UNUSED(self), PyObject *args) { - PyObject * tuple; + PyObject *tuple; VectorObject *vec1, *vec2, *vec3, *vec4; float v1[3], v2[3], v3[3], v4[3], i1[3], i2[3]; @@ -720,7 +720,7 @@ static int boxPack_FromPyObject(PyObject *value, boxPack **boxarray) return 0; } -static void boxPack_ToPyObject(PyObject * value, boxPack **boxarray) +static void boxPack_ToPyObject(PyObject *value, boxPack **boxarray) { int len, i; PyObject *list_item; diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 450151ee870..cb11b53c83c 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -231,7 +231,7 @@ static PyObject *bpy_import_test(const char *modname) /***************************************************************************** * Description: Creates the bpy module and adds it to sys.modules for importing *****************************************************************************/ -void BPy_init_modules( void ) +void BPy_init_modules(void) { extern BPy_StructRNA *bpy_context_module; extern int bpy_lib_init(PyObject *); @@ -262,17 +262,17 @@ void BPy_init_modules( void ) /* run first, initializes rna types */ BPY_rna_init(); - PyModule_AddObject( mod, "types", BPY_rna_types() ); /* needs to be first so bpy_types can run */ + PyModule_AddObject(mod, "types", BPY_rna_types()); /* needs to be first so bpy_types can run */ PyModule_AddObject(mod, "StructMetaPropGroup", (PyObject *)&pyrna_struct_meta_idprop_Type); /* metaclass for idprop types, bpy_types.py needs access */ bpy_lib_init(mod); /* adds '_bpy._library_load', must be called before 'bpy_types' which uses it */ bpy_import_test("bpy_types"); - PyModule_AddObject( mod, "data", BPY_rna_module() ); /* imports bpy_types by running this */ + PyModule_AddObject(mod, "data", BPY_rna_module()); /* imports bpy_types by running this */ bpy_import_test("bpy_types"); - PyModule_AddObject( mod, "props", BPY_rna_props() ); - PyModule_AddObject( mod, "ops", BPY_operator_module() ); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ - PyModule_AddObject( mod, "app", BPY_app_struct() ); + PyModule_AddObject(mod, "props", BPY_rna_props()); + PyModule_AddObject(mod, "ops", BPY_operator_module()); /* ops is now a python module that does the conversion from SOME_OT_foo -> some.foo */ + PyModule_AddObject(mod, "app", BPY_app_struct()); /* bpy context */ RNA_pointer_create(NULL, &RNA_Context, (void *)BPy_GetContext(), &ctx_ptr); diff --git a/source/blender/python/intern/bpy.h b/source/blender/python/intern/bpy.h index 0f298c1daf1..0ebc6bb2438 100644 --- a/source/blender/python/intern/bpy.h +++ b/source/blender/python/intern/bpy.h @@ -26,5 +26,5 @@ */ -void BPy_init_modules( void ); +void BPy_init_modules(void); extern PyObject *bpy_package_py; diff --git a/source/blender/python/intern/bpy_app.h b/source/blender/python/intern/bpy_app.h index d57e4688f46..fbc5696875a 100644 --- a/source/blender/python/intern/bpy_app.h +++ b/source/blender/python/intern/bpy_app.h @@ -29,6 +29,6 @@ #ifndef BPY_APP_H #define BPY_APP_H -PyObject *BPY_app_struct( void ); +PyObject *BPY_app_struct(void); #endif // BPY_APP_H diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index df31fab6bde..dec393bd1e4 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -60,7 +60,7 @@ int bpy_pydriver_create_dict(void) else bpy_pydriver_Dict= d; - /* import some modules: builtins, bpy, math, (Blender.noise )*/ + /* import some modules: builtins, bpy, math, (Blender.noise)*/ PyDict_SetItemString(d, "__builtins__", PyEval_GetBuiltins()); mod= PyImport_ImportModule("math"); @@ -185,12 +185,11 @@ float BPY_driver_exec(ChannelDriver *driver) expr_vars= PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 1); Py_XDECREF(expr_vars); - /* intern the arg names so creating the namespace for every run is faster */ expr_vars= PyTuple_New(BLI_countlist(&driver->variables)); PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars); for (dvar= driver->variables.first, i=0; dvar; dvar= dvar->next) { - PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_InternFromString(dvar->name)); + PyTuple_SET_ITEM(expr_vars, i++, PyUnicode_FromString(dvar->name)); } driver->flag &= ~DRIVER_FLAG_RENAMEVAR; @@ -211,7 +210,7 @@ float BPY_driver_exec(ChannelDriver *driver) /* try to add to dictionary */ /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ - if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) { /* use string interning for faster namespace creation */ + if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) { /* this target failed - bad name */ if (targets_ok) { /* first one - print some extra info for easier identification */ diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c index 10e97573447..85bffb5a8cc 100644 --- a/source/blender/python/intern/bpy_library.c +++ b/source/blender/python/intern/bpy_library.c @@ -213,7 +213,7 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) int counter= 0; list= PyList_New(totnames); for(l= names; l; l= l->next) { - PyList_SET_ITEM(list, counter, PyUnicode_FromString((char * )l->link)); + PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 0ee9d7e5bd5..8ed4e41de3e 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -47,15 +47,22 @@ #include "../generic/py_capi_utils.h" +/* initial definition of callback slots we'll probably have more then 1 */ +#define BPY_DATA_CB_SLOT_SIZE 1 + +#define BPY_DATA_CB_SLOT_UPDATE 0 + extern BPy_StructRNA *bpy_context_module; static EnumPropertyItem property_flag_items[]= { {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, + {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""}, {0, NULL, 0, NULL, NULL}}; static EnumPropertyItem property_flag_enum_items[]= { {PROP_HIDDEN, "HIDDEN", 0, "Hidden", ""}, + {PROP_SKIP_SAVE, "SKIP_SAVE", 0, "Skip Save", ""}, {PROP_ANIMATABLE, "ANIMATABLE", 0, "Animateable", ""}, {PROP_ENUM_FLAG, "ENUM_FLAG", 0, "Enum Flag", ""}, {0, NULL, 0, NULL, NULL}}; @@ -110,6 +117,45 @@ static PyObject *pymeth_PointerProperty= NULL; static PyObject *pymeth_CollectionProperty= NULL; static PyObject *pymeth_RemoveProperty= NULL; +PyObject *pyrna_struct_as_instance(PointerRNA *ptr) +{ + PyObject *self= NULL; + /* first get self */ + /* operators can store their own instance for later use */ + if(ptr->data) { + void **instance= RNA_struct_instance(ptr); + + if(instance) { + if(*instance) { + self= *instance; + Py_INCREF(self); + } + } + } + + /* in most cases this will run */ + if(self == NULL) { + self= pyrna_struct_CreatePyObject(ptr); + } + + return self; +} + +/* could be moved into bpy_utils */ +static void printf_func_error(PyObject *py_func) +{ + /* since we return to C code we can't leave the error */ + PyCodeObject *f_code= (PyCodeObject *)PyFunction_GET_CODE(py_func); + PyErr_Print(); + PyErr_Clear(); + + /* use py style error */ + fprintf(stderr, "File \"%s\", line %d, in %s\n", + _PyUnicode_AsString(f_code->co_filename), + f_code->co_firstlineno, + _PyUnicode_AsString(((PyFunctionObject *)py_func)->func_name) + ); +} /* operators and classes use this so it can store the args given but defer * running it until the operator runs where these values are used to setup @@ -130,6 +176,96 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) return ret; } +/* callbacks */ +void bpy_prop_update_cb(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop) +{ + PyGILState_STATE gilstate; + PyObject **py_data= (PyObject **)RNA_property_py_data_get(prop); + PyObject *py_func; + PyObject *args; + PyObject *self; + PyObject *ret; + const int is_write_ok= pyrna_write_check(); + + BLI_assert(py_data != NULL); + + if(!is_write_ok) { + pyrna_write_set(TRUE); + } + + bpy_context_set(C, &gilstate); + + py_func= py_data[BPY_DATA_CB_SLOT_UPDATE]; + + args= PyTuple_New(2); + self= pyrna_struct_as_instance(ptr); + PyTuple_SET_ITEM(args, 0, self); + + PyTuple_SET_ITEM(args, 1, (PyObject *)bpy_context_module); + Py_INCREF(bpy_context_module); + + ret= PyObject_CallObject(py_func, args); + + Py_DECREF(args); + + if(ret == NULL) { + printf_func_error(py_func); + } + else { + if(ret != Py_None) { + PyErr_SetString(PyExc_ValueError, "the return value must be None"); + printf_func_error(py_func); + } + + Py_DECREF(ret); + } + + bpy_context_clear(C, &gilstate); + + if(!is_write_ok) { + pyrna_write_set(FALSE); + } +} + +static int bpy_prop_callback_check(PyObject *py_func, int argcount) +{ + if(py_func) { + if(!PyFunction_Check(py_func)) { + PyErr_Format(PyExc_TypeError, + "update keyword: expected a function type, not a %.200s", + Py_TYPE(py_func)->tp_name); + return -1; + } + else { + PyCodeObject *f_code= (PyCodeObject *)PyFunction_GET_CODE(py_func); + if (f_code->co_argcount != argcount) { + PyErr_Format(PyExc_TypeError, + "update keyword: expected a function taking %d arguments, not %d", + argcount, f_code->co_argcount); + return -1; + } + } + } + + return 0; +} + + +static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_cb) +{ + /* assume this is already checked for type and arg length */ + if(update_cb) { + PyObject **py_data= MEM_callocN(sizeof(PyObject *) * BPY_DATA_CB_SLOT_SIZE, "bpy_prop_callback_assign"); + RNA_def_property_update_runtime(prop, (void *)bpy_prop_update_cb); + py_data[BPY_DATA_CB_SLOT_UPDATE]= update_cb; + RNA_def_py_data(prop, py_data); + + RNA_def_property_flag(prop, PROP_CONTEXT_PROPERTY_UPDATE); + } + + return 0; +} + /* this define runs at the start of each function and deals with * returning a deferred property (to be registered later) */ #define BPY_PROPDEF_HEAD(_func) \ @@ -156,11 +292,15 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) * calls because of static strins passed to pyrna_set_to_enum_bitfield */ #define BPY_PROPDEF_CHECK(_func, _property_flag_items) \ if(id_len >= MAX_IDPROP_NAME) { \ - PyErr_Format(PyExc_TypeError, #_func"(): '%.200s' too long, max length is %d", id, MAX_IDPROP_NAME-1); \ + PyErr_Format(PyExc_TypeError, \ + #_func"(): '%.200s' too long, max length is %d", \ + id, MAX_IDPROP_NAME-1); \ return NULL; \ } \ if(RNA_def_property_free_identifier(srna, id) == -1) { \ - PyErr_Format(PyExc_TypeError, #_func"(): '%s' is defined as a non-dynamic type", id); \ + PyErr_Format(PyExc_TypeError, \ + #_func"(): '%s' is defined as a non-dynamic type", \ + id); \ return NULL; \ } \ if(pyopts && pyrna_set_to_enum_bitfield(_property_flag_items, pyopts, &opts, #_func"(options={...}):")) \ @@ -169,7 +309,9 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) #define BPY_PROPDEF_SUBTYPE_CHECK(_func, _property_flag_items, _subtype) \ BPY_PROPDEF_CHECK(_func, _property_flag_items) \ if(pysubtype && RNA_enum_value_from_id(_subtype, pysubtype, &subtype)==0) { \ - PyErr_Format(PyExc_TypeError, #_func"(subtype='%s'): invalid subtype", pysubtype); \ + PyErr_Format(PyExc_TypeError, \ + #_func"(subtype='%s'): invalid subtype", \ + pysubtype); \ return NULL; \ } \ @@ -184,6 +326,11 @@ static PyObject *bpy_prop_deferred_return(PyObject *func, PyObject *kw) " :type description: string\n" \ +#define BPY_PROPDEF_UPDATE_DOC \ +" :arg update: function to be called when this value is modified,\n" \ +" This function must take 2 values (self, context) and return None.\n" \ +" :type update: function\n" \ + #if 0 static int bpy_struct_id_used(StructRNA *srna, char *identifier) { @@ -197,16 +344,17 @@ static int bpy_struct_id_used(StructRNA *srna, char *identifier) /* Function that sets RNA, NOTE - self is NULL when called from python, but being abused from C so we can pass the srna allong * This isnt incorrect since its a python object - but be careful */ PyDoc_STRVAR(BPy_BoolProperty_doc, -".. function:: BoolProperty(name=\"\", description=\"\", default=False, options={'ANIMATABLE'}, subtype='NONE')\n" +".. function:: BoolProperty(name=\"\", description=\"\", default=False, options={'ANIMATABLE'}, subtype='NONE', update=None)\n" "\n" " Returns a new boolean property definition.\n" "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n" " :type subtype: string\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -215,7 +363,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(BoolProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "options", "subtype", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "options", "subtype", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int def=0; @@ -224,18 +372,24 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssiO!s:BoolProperty", + "s#|ssiO!sO:BoolProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, - &PySet_Type, &pyopts, &pysubtype)) + &PySet_Type, &pyopts, &pysubtype, + &update_cb)) { return NULL; } BPY_PROPDEF_SUBTYPE_CHECK(BoolProperty, property_flag_items, property_subtype_number_items) + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_property(srna, id, PROP_BOOLEAN, subtype); RNA_def_property_boolean_default(prop, def); RNA_def_property_ui_text(prop, name, description); @@ -244,6 +398,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } @@ -251,7 +406,7 @@ static PyObject *BPy_BoolProperty(PyObject *self, PyObject *args, PyObject *kw) } PyDoc_STRVAR(BPy_BoolVectorProperty_doc, -".. function:: BoolVectorProperty(name=\"\", description=\"\", default=(False, False, False), options={'ANIMATABLE'}, subtype='NONE', size=3)\n" +".. function:: BoolVectorProperty(name=\"\", description=\"\", default=(False, False, False), options={'ANIMATABLE'}, subtype='NONE', size=3, update=None)\n" "\n" " Returns a new vector boolean property definition.\n" "\n" @@ -259,12 +414,13 @@ BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC " :arg default: sequence of booleans the length of *size*.\n" " :type default: sequence\n" -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'LAYER', 'NONE'].\n" " :type subtype: string\n" " :arg size: Vector dimensions in [1, and " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" " :type size: int\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -273,7 +429,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject BPY_PROPDEF_HEAD(BoolVectorProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "options", "subtype", "size", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "options", "subtype", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int def[PYRNA_STACK_ARRAY]={0}; @@ -284,12 +440,14 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssOO!si:BoolVectorProperty", + "s#|ssOO!siO:BoolVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, - &PySet_Type, &pyopts, &pysubtype,&size)) + &PySet_Type, &pyopts, &pysubtype, &size, + &update_cb)) { return NULL; } @@ -304,6 +462,10 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject if(pydef && PyC_AsArray(def, pydef, size, &PyBool_Type, "BoolVectorProperty(default=sequence)") < 0) return NULL; + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + // prop= RNA_def_boolean_array(srna, id, size, pydef ? def:NULL, name, description); prop= RNA_def_property(srna, id, PROP_BOOLEAN, subtype); RNA_def_property_array(prop, size); @@ -314,6 +476,7 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } @@ -321,16 +484,17 @@ static PyObject *BPy_BoolVectorProperty(PyObject *self, PyObject *args, PyObject } PyDoc_STRVAR(BPy_IntProperty_doc, -".. function:: IntProperty(name=\"\", description=\"\", default=0, min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, step=1, options={'ANIMATABLE'}, subtype='NONE')\n" +".. function:: IntProperty(name=\"\", description=\"\", default=0, min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, step=1, options={'ANIMATABLE'}, subtype='NONE', update=None)\n" "\n" " Returns a new int property definition.\n" "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n" " :type subtype: string\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -339,7 +503,7 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(IntProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def=0; @@ -348,19 +512,25 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssiiiiiiO!s:IntProperty", + "s#|ssiiiiiiO!sO:IntProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &min, &max, &soft_min, &soft_max, - &step, &PySet_Type, &pyopts, &pysubtype)) + &step, &PySet_Type, &pyopts, &pysubtype, + &update_cb)) { return NULL; } BPY_PROPDEF_SUBTYPE_CHECK(IntProperty, property_flag_items, property_subtype_number_items) + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_property(srna, id, PROP_INT, subtype); RNA_def_property_int_default(prop, def); RNA_def_property_range(prop, min, max); @@ -371,13 +541,14 @@ static PyObject *BPy_IntProperty(PyObject *self, PyObject *args, PyObject *kw) if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; } PyDoc_STRVAR(BPy_IntVectorProperty_doc, -".. function:: IntVectorProperty(name=\"\", description=\"\", default=(0, 0, 0), min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, options={'ANIMATABLE'}, subtype='NONE', size=3)\n" +".. function:: IntVectorProperty(name=\"\", description=\"\", default=(0, 0, 0), min=-sys.maxint, max=sys.maxint, soft_min=-sys.maxint, soft_max=sys.maxint, options={'ANIMATABLE'}, subtype='NONE', size=3, update=None)\n" "\n" " Returns a new vector int property definition.\n" "\n" @@ -385,12 +556,13 @@ BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC " :arg default: sequence of ints the length of *size*.\n" " :type default: sequence\n" -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'LAYER', 'NONE'].\n" " :type subtype: string\n" " :arg size: Vector dimensions in [1, and " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" " :type size: int\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -399,7 +571,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject BPY_PROPDEF_HEAD(IntVectorProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "size", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "options", "subtype", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; int min=INT_MIN, max=INT_MAX, soft_min=INT_MIN, soft_max=INT_MAX, step=1, def[PYRNA_STACK_ARRAY]={0}; @@ -410,14 +582,16 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssOiiiiiO!si:IntVectorProperty", + "s#|ssOiiiiiO!siO:IntVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &PySet_Type, &pyopts, - &pysubtype, &size)) + &pysubtype, &size, + &update_cb)) { return NULL; } @@ -432,6 +606,10 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject if(pydef && PyC_AsArray(def, pydef, size, &PyLong_Type, "IntVectorProperty(default=sequence)") < 0) return NULL; + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_property(srna, id, PROP_INT, subtype); RNA_def_property_array(prop, size); if(pydef) RNA_def_property_int_array_default(prop, def); @@ -443,6 +621,7 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; @@ -450,18 +629,19 @@ static PyObject *BPy_IntVectorProperty(PyObject *self, PyObject *args, PyObject PyDoc_STRVAR(BPy_FloatProperty_doc, -".. function:: FloatProperty(name=\"\", description=\"\", default=0.0, min=sys.float_info.min, max=sys.float_info.max, soft_min=sys.float_info.min, soft_max=sys.float_info.max, step=3, precision=2, options={'ANIMATABLE'}, subtype='NONE', unit='NONE')\n" +".. function:: FloatProperty(name=\"\", description=\"\", default=0.0, min=sys.float_info.min, max=sys.float_info.max, soft_min=sys.float_info.min, soft_max=sys.float_info.max, step=3, precision=2, options={'ANIMATABLE'}, subtype='NONE', unit='NONE', update=None)\n" "\n" " Returns a new float property definition.\n" "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n" " :type subtype: string\n" " :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION'].\n" " :type unit: string\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -470,7 +650,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(FloatProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def=0.0f; @@ -482,14 +662,16 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) int subtype= PROP_NONE; char *pyunit= NULL; int unit= PROP_UNIT_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssffffffiO!ss:FloatProperty", + "s#|ssffffffiO!ssO:FloatProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, - &pyopts, &pysubtype, &pyunit)) + &pyopts, &pysubtype, &pyunit, + &update_cb)) { return NULL; } @@ -501,6 +683,10 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) return NULL; } + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); RNA_def_property_float_default(prop, def); RNA_def_property_range(prop, min, max); @@ -511,13 +697,14 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; } PyDoc_STRVAR(BPy_FloatVectorProperty_doc, -".. function:: FloatVectorProperty(name=\"\", description=\"\", default=(0.0, 0.0, 0.0), min=sys.float_info.min, max=sys.float_info.max, soft_min=sys.float_info.min, soft_max=sys.float_info.max, step=3, precision=2, options={'ANIMATABLE'}, subtype='NONE', size=3)\n" +".. function:: FloatVectorProperty(name=\"\", description=\"\", default=(0.0, 0.0, 0.0), min=sys.float_info.min, max=sys.float_info.max, soft_min=sys.float_info.min, soft_max=sys.float_info.max, step=3, precision=2, options={'ANIMATABLE'}, subtype='NONE', size=3, update=None)\n" "\n" " Returns a new vector float property definition.\n" "\n" @@ -525,12 +712,13 @@ BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC " :arg default: sequence of floats the length of *size*.\n" " :type default: sequence\n" -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'LAYER', 'NONE'].\n" " :type subtype: string\n" " :arg size: Vector dimensions in [1, and " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" " :type size: int\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -539,7 +727,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec BPY_PROPDEF_HEAD(FloatVectorProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "size", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def[PYRNA_STACK_ARRAY]={0.0f}; @@ -550,14 +738,16 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssOfffffiO!si:FloatVectorProperty", + "s#|ssOfffffiO!siO:FloatVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, - &pyopts, &pysubtype, &size)) + &pyopts, &pysubtype, &size, + &update_cb)) { return NULL; } @@ -572,6 +762,10 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec if(pydef && PyC_AsArray(def, pydef, size, &PyFloat_Type, "FloatVectorProperty(default=sequence)") < 0) return NULL; + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_property(srna, id, PROP_FLOAT, subtype); RNA_def_property_array(prop, size); if(pydef) RNA_def_property_float_array_default(prop, def); @@ -583,22 +777,24 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; } PyDoc_STRVAR(BPy_StringProperty_doc, -".. function:: StringProperty(name=\"\", description=\"\", default=\"\", maxlen=0, options={'ANIMATABLE'}, subtype='NONE')\n" +".. function:: StringProperty(name=\"\", description=\"\", default=\"\", maxlen=0, options={'ANIMATABLE'}, subtype='NONE', update=None)\n" "\n" " Returns a new string property definition.\n" "\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" " :arg subtype: Enumerator in ['FILE_PATH', 'DIR_PATH', 'FILENAME', 'NONE'].\n" " :type subtype: string\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -607,7 +803,7 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw BPY_PROPDEF_HEAD(StringProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "maxlen", "options", "subtype", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "maxlen", "options", "subtype", "update", NULL}; const char *id=NULL, *name="", *description="", *def=""; int id_len; int maxlen=0; @@ -616,18 +812,24 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|sssiO!s:StringProperty", + "s#|sssiO!sO:StringProperty", (char **)kwlist, &id, &id_len, &name, &description, &def, - &maxlen, &PySet_Type, &pyopts, &pysubtype)) + &maxlen, &PySet_Type, &pyopts, &pysubtype, + &update_cb)) { return NULL; } BPY_PROPDEF_SUBTYPE_CHECK(StringProperty, property_flag_items, property_subtype_string_items) + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_property(srna, id, PROP_STRING, subtype); if(maxlen != 0) RNA_def_property_string_maxlength(prop, maxlen + 1); /* +1 since it includes null terminator */ if(def) RNA_def_property_string_default(prop, def); @@ -637,21 +839,35 @@ static PyObject *BPy_StringProperty(PyObject *self, PyObject *args, PyObject *kw if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; } +#if 0 +/* copies orig to buf, then sets orig to buf, returns copy length */ +static size_t strswapbufcpy(char *buf, const char **orig) +{ + const char *src= *orig; + char *dst= buf; + size_t i= 0; + *orig= buf; + while((*dst= *src)) { dst++; src++; i++; } + return i + 1; /* include '\0' */ +} +#endif + static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, int *defvalue, const short is_enum_flag) { - EnumPropertyItem *items= NULL; + EnumPropertyItem *items; PyObject *item; - int seq_len, i, totitem= 0; + const Py_ssize_t seq_len= PySequence_Fast_GET_SIZE(seq_fast); + Py_ssize_t totbuf= 0; + int i; short def_used= 0; const char *def_cmp= NULL; - seq_len= PySequence_Fast_GET_SIZE(seq_fast); - if(is_enum_flag) { if(seq_len > RNA_ENUM_BITFLAG_SIZE) { PyErr_SetString(PyExc_TypeError, "EnumProperty(...): maximum " STRINGIFY(RNA_ENUM_BITFLAG_SIZE) " members for a ENUM_FLAG type property"); @@ -681,43 +897,52 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i /* blank value */ *defvalue= 0; + items= MEM_callocN(sizeof(EnumPropertyItem) * (seq_len + 1), "enum_items_from_py1"); + for(i=0; i<seq_len; i++) { EnumPropertyItem tmp= {0, "", 0, "", ""}; + Py_ssize_t id_str_size; + Py_ssize_t name_str_size; + Py_ssize_t desc_str_size; item= PySequence_Fast_GET_ITEM(seq_fast, i); - if(PyTuple_Check(item)==0) { - PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected a sequence of tuples for the enum items"); - if(items) MEM_freeN(items); - return NULL; - } - if(!PyArg_ParseTuple(item, "sss", &tmp.identifier, &tmp.name, &tmp.description)) { - PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected an identifier, name and description in the tuple"); - return NULL; - } - - if(is_enum_flag) { - tmp.value= 1<<i; + if( (PyTuple_CheckExact(item)) && + (PyTuple_GET_SIZE(item) == 3) && + (tmp.identifier= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 0), &id_str_size)) && + (tmp.name= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 1), &name_str_size)) && + (tmp.description= _PyUnicode_AsStringAndSize(PyTuple_GET_ITEM(item, 2), &desc_str_size)) + ) { + if(is_enum_flag) { + tmp.value= 1<<i; + + if(def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) { + *defvalue |= tmp.value; + def_used++; + } + } + else { + tmp.value= i; - if(def && PySet_Contains(def, PyTuple_GET_ITEM(item, 0))) { - *defvalue |= tmp.value; - def_used++; + if(def && def_used == 0 && strcmp(def_cmp, tmp.identifier)==0) { + *defvalue= tmp.value; + def_used++; /* only ever 1 */ + } } + + items[i]= tmp; + + /* calculate combine string length */ + totbuf += id_str_size + name_str_size + desc_str_size + 3; /* 3 is for '\0's */ } else { - tmp.value= i; - - if(def && def_used == 0 && strcmp(def_cmp, tmp.identifier)==0) { - *defvalue= tmp.value; - def_used++; /* only ever 1 */ - } + MEM_freeN(items); + PyErr_SetString(PyExc_TypeError, "EnumProperty(...): expected an tuple containing (identifier, name description)"); + return NULL; } - RNA_enum_item_add(&items, &totitem, &tmp); } - RNA_enum_item_end(&items, &totitem); - if(is_enum_flag) { /* strict check that all set members were used */ if(def && def_used != PySet_GET_SIZE(def)) { @@ -740,6 +965,29 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i } } + /* disabled duplicating strings because the array can still be freed and + * the strings from it referenced, for now we can't support dynamically + * created strings from python. */ +#if 0 + /* this would all work perfectly _but_ the python strings may be freed + * immediately after use, so we need to duplicate them, ugh. + * annoying because it works most of the time without this. */ + { + EnumPropertyItem *items_dup= MEM_mallocN((sizeof(EnumPropertyItem) * (seq_len + 1)) + (sizeof(char) * totbuf), "enum_items_from_py2"); + EnumPropertyItem *items_ptr= items_dup; + char *buf= ((char *)items_dup) + (sizeof(EnumPropertyItem) * (seq_len + 1)); + memcpy(items_dup, items, sizeof(EnumPropertyItem) * (seq_len + 1)); + for(i=0; i<seq_len; i++, items_ptr++) { + buf += strswapbufcpy(buf, &items_ptr->identifier); + buf += strswapbufcpy(buf, &items_ptr->name); + buf += strswapbufcpy(buf, &items_ptr->description); + } + MEM_freeN(items); + items=items_dup; + } + /* end string duplication */ +#endif + return items; } @@ -758,23 +1006,7 @@ static EnumPropertyItem *bpy_props_enum_itemf(struct bContext *C, PointerRNA *pt bpy_context_set(C, &gilstate); args= PyTuple_New(2); - - /* first get self */ - /* operators can store their own instance for later use */ - if(ptr->data) { - void **instance = RNA_struct_instance(ptr); - - if(instance) { - if(*instance) { - self= *instance; - Py_INCREF(self); - } - } - } - if(self == NULL) { - self= pyrna_struct_CreatePyObject(ptr); - } - + self= pyrna_struct_as_instance(ptr); PyTuple_SET_ITEM(args, 0, self); /* now get the context */ @@ -812,17 +1044,7 @@ static EnumPropertyItem *bpy_props_enum_itemf(struct bContext *C, PointerRNA *pt *free= 1; } else { - /* since we return to C code we can't leave the error */ - PyCodeObject *f_code= (PyCodeObject *)PyFunction_GET_CODE(py_func); - PyErr_Print(); - PyErr_Clear(); - - /* use py style error */ - fprintf(stderr, "File \"%s\", line %d, in %s\n", - _PyUnicode_AsString(f_code->co_filename), - f_code->co_firstlineno, - _PyUnicode_AsString(((PyFunctionObject *)py_func)->func_name) - ); + printf_func_error(py_func); eitems= DummyRNA_NULL_items; } @@ -833,7 +1055,7 @@ static EnumPropertyItem *bpy_props_enum_itemf(struct bContext *C, PointerRNA *pt } PyDoc_STRVAR(BPy_EnumProperty_doc, -".. function:: EnumProperty(items, name=\"\", description=\"\", default=\"\", options={'ANIMATABLE'})\n" +".. function:: EnumProperty(items, name=\"\", description=\"\", default=\"\", options={'ANIMATABLE'}, update=None)\n" "\n" " Returns a new enumerator property definition.\n" "\n" @@ -843,7 +1065,7 @@ BPY_PROPDEF_DESC_DOC " is disabled otherwise a set which may only contain string identifiers\n" " used in *items*.\n" " :type default: string or set\n" -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE', 'ENUM_FLAG'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE', 'ENUM_FLAG'].\n" " :type options: set\n" " :arg items: sequence of enum items formatted:\n" " [(identifier, name, description), ...] where the identifier is used\n" @@ -852,6 +1074,7 @@ BPY_PROPDEF_DESC_DOC " the same format as the static list.\n" " This function must take 2 arguments (self, context)\n" " :type items: sequence of string triplets or a function\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -860,7 +1083,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_HEAD(EnumProperty) if(srna) { - static const char *kwlist[]= {"attr", "items", "name", "description", "default", "options", NULL}; + static const char *kwlist[]= {"attr", "items", "name", "description", "default", "options", "update", NULL}; const char *id=NULL, *name="", *description=""; PyObject *def= NULL; int id_len; @@ -871,18 +1094,24 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) PyObject *pyopts= NULL; int opts=0; short is_itemf= FALSE; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#O|ssOO!:EnumProperty", + "s#O|ssOO!O:EnumProperty", (char **)kwlist, &id, &id_len, &items, &name, &description, - &def, &PySet_Type, &pyopts)) + &def, &PySet_Type, &pyopts, + &update_cb)) { return NULL; } BPY_PROPDEF_CHECK(EnumProperty, property_flag_enum_items) + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + /* items can be a list or a callable */ if(PyFunction_Check(items)) { /* dont use PyCallable_Check because we need the function code for errors */ PyCodeObject *f_code= (PyCodeObject *)PyFunction_GET_CODE(items); @@ -930,6 +1159,7 @@ static PyObject *BPy_EnumProperty(PyObject *self, PyObject *args, PyObject *kw) if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); if(is_itemf == FALSE) { @@ -972,7 +1202,7 @@ static StructRNA *pointer_type_from_py(PyObject *value, const char *error_prefix } PyDoc_STRVAR(BPy_PointerProperty_doc, -".. function:: PointerProperty(type=\"\", description=\"\", options={'ANIMATABLE'})\n" +".. function:: PointerProperty(type=\"\", description=\"\", options={'ANIMATABLE'}, update=None)\n" "\n" " Returns a new pointer property definition.\n" "\n" @@ -980,8 +1210,9 @@ PyDoc_STRVAR(BPy_PointerProperty_doc, " :type type: class\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" +BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *kw) { @@ -990,7 +1221,7 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k BPY_PROPDEF_HEAD(PointerProperty) if(srna) { - static const char *kwlist[]= {"attr", "type", "name", "description", "options", NULL}; + static const char *kwlist[]= {"attr", "type", "name", "description", "options", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; PropertyRNA *prop; @@ -998,12 +1229,14 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k PyObject *type= Py_None; PyObject *pyopts= NULL; int opts=0; + PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#O|ssO!:PointerProperty", + "s#O|ssO!O:PointerProperty", (char **)kwlist, &id, &id_len, &type, &name, &description, - &PySet_Type, &pyopts)) + &PySet_Type, &pyopts, + &update_cb)) { return NULL; } @@ -1014,11 +1247,16 @@ static PyObject *BPy_PointerProperty(PyObject *self, PyObject *args, PyObject *k if(!ptype) return NULL; + if (bpy_prop_callback_check(update_cb, 2) == -1) { + return NULL; + } + prop= RNA_def_pointer_runtime(srna, id, ptype, name, description); if(pyopts) { if(opts & PROP_HIDDEN) RNA_def_property_flag(prop, PROP_HIDDEN); if((opts & PROP_ANIMATABLE)==0) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); } + bpy_prop_callback_assign(prop, update_cb); RNA_def_property_duplicate_pointers(srna, prop); } Py_RETURN_NONE; @@ -1033,7 +1271,7 @@ PyDoc_STRVAR(BPy_CollectionProperty_doc, " :type type: class\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC -" :arg options: Enumerator in ['HIDDEN', 'ANIMATABLE'].\n" +" :arg options: Enumerator in ['HIDDEN', 'SKIP_SAVE', 'ANIMATABLE'].\n" " :type options: set\n" ); static PyObject *BPy_CollectionProperty(PyObject *self, PyObject *args, PyObject *kw) @@ -1156,7 +1394,7 @@ static struct PyModuleDef props_module= { NULL, NULL, NULL, NULL }; -PyObject *BPY_rna_props( void ) +PyObject *BPY_rna_props(void) { PyObject *submodule; PyObject *submodule_dict; diff --git a/source/blender/python/intern/bpy_props.h b/source/blender/python/intern/bpy_props.h index f306d6898d1..8b64d04e092 100644 --- a/source/blender/python/intern/bpy_props.h +++ b/source/blender/python/intern/bpy_props.h @@ -30,7 +30,7 @@ #ifndef BPY_PROPS_H #define BPY_PROPS_H -PyObject *BPY_rna_props( void ); +PyObject *BPY_rna_props(void); #define PYRNA_STACK_ARRAY 32 diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 72d391fed32..38cc3edd8f6 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -323,11 +323,20 @@ int pyrna_write_check(void) { return !rna_disallow_writes; } + +void pyrna_write_set(int val) +{ + rna_disallow_writes= !val; +} #else // USE_PEDANTIC_WRITE int pyrna_write_check(void) { return TRUE; } +void pyrna_write_set(int UNUSED(val)) +{ + /* nothing */ +} #endif // USE_PEDANTIC_WRITE static Py_ssize_t pyrna_prop_collection_length(BPy_PropertyRNA *self); @@ -1200,7 +1209,7 @@ static PyObject *pyrna_enum_to_py(PointerRNA *ptr, PropertyRNA *prop, int val) return ret; } -PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) +PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) { PyObject *ret; int type= RNA_property_type(prop); @@ -1334,7 +1343,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha return error_val; } -static PyObject * pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw); +static PyObject *pyrna_func_call(PyObject *self, PyObject *args, PyObject *kw); static PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func) { diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index ea8af61c9bf..5db352af53d 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -148,18 +148,18 @@ typedef struct { StructRNA *srna_from_self(PyObject *self, const char *error_prefix); StructRNA *pyrna_struct_as_srna(PyObject *self, int parent, const char *error_prefix); -void BPY_rna_init( void ); -PyObject *BPY_rna_module( void ); -void BPY_update_rna_module( void ); -/*PyObject *BPY_rna_doc( void );*/ -PyObject *BPY_rna_types( void ); +void BPY_rna_init(void); +PyObject *BPY_rna_module(void); +void BPY_update_rna_module(void); +/*PyObject *BPY_rna_doc(void);*/ +PyObject *BPY_rna_types(void); -PyObject *pyrna_struct_CreatePyObject( PointerRNA *ptr ); -PyObject *pyrna_prop_CreatePyObject( PointerRNA *ptr, PropertyRNA *prop ); +PyObject *pyrna_struct_CreatePyObject(PointerRNA *ptr); +PyObject *pyrna_prop_CreatePyObject(PointerRNA *ptr, PropertyRNA *prop); /* operators also need this to set args */ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix); -PyObject * pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); +PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); PyObject *pyrna_enum_bitfield_to_py(struct EnumPropertyItem *items, int value); int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix); @@ -183,6 +183,7 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop); int pyrna_array_contains_py(PointerRNA *ptr, PropertyRNA *prop, PyObject *value); int pyrna_write_check(void); +void pyrna_write_set(int val); int pyrna_struct_validity_check(BPy_StructRNA *pysrna); int pyrna_prop_validity_check(BPy_PropertyRNA *self); diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index d3d3e4d261c..b45528b96d9 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -362,10 +362,18 @@ static void accum_density(void *userdata, int index, float squared_dist) density = pdr->squared_radius; else if (pdr->falloff_type == TEX_PD_FALLOFF_ROOT) density = sqrt(dist); - else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) - density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f); - else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) - density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale; + else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_AGE) { + if (pdr->point_data_used & POINT_DATA_LIFE) + density = dist*MIN2(pdr->point_data[pdr->offset + index], 1.0f); + else + density = dist; + } + else if (pdr->falloff_type == TEX_PD_FALLOFF_PARTICLE_VEL) { + if (pdr->point_data_used & POINT_DATA_VEL) + density = dist*len_v3(pdr->point_data + index*3)*pdr->velscale; + else + density = dist; + } if (pdr->density_curve && dist != 0.0f) { density = curvemapping_evaluateF(pdr->density_curve, 0, density/dist)*dist; diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index bc6c4795f5c..0087be8cca9 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -2018,74 +2018,6 @@ typedef struct BakeShade { short *do_update; } BakeShade; -/* bake uses a char mask to know what has been baked */ -#define BAKE_MASK_NULL 0 -#define BAKE_MASK_MARGIN 1 -#define BAKE_MASK_BAKED 2 -static void bake_mask_filter_extend( char *mask, int width, int height ) -{ - char *row1, *row2, *row3; - int rowlen, x, y; - char *temprect; - - rowlen= width; - - /* make a copy, to prevent flooding */ - temprect= MEM_dupallocN(mask); - - for(y=1; y<=height; y++) { - /* setup rows */ - row1= (char *)(temprect + (y-2)*rowlen); - row2= row1 + rowlen; - row3= row2 + rowlen; - if(y==1) - row1= row2; - else if(y==height) - row3= row2; - - for(x=0; x<rowlen; x++) { - if (mask[((y-1)*rowlen)+x]==0) { - if (*row1 || *row2 || *row3 || *(row1+1) || *(row3+1) ) { - mask[((y-1)*rowlen)+x] = BAKE_MASK_MARGIN; - } else if((x!=rowlen-1) && (*(row1+2) || *(row2+2) || *(row3+2)) ) { - mask[((y-1)*rowlen)+x] = BAKE_MASK_MARGIN; - } - } - - if(x!=0) { - row1++; row2++; row3++; - } - } - } - MEM_freeN(temprect); -} - -static void bake_mask_clear( ImBuf *ibuf, char *mask, char val ) -{ - int x,y; - if (ibuf->rect_float) { - for(x=0; x<ibuf->x; x++) { - for(y=0; y<ibuf->y; y++) { - if (mask[ibuf->x*y + x] == val) { - float *col= ibuf->rect_float + 4*(ibuf->x*y + x); - col[0] = col[1] = col[2] = col[3] = 0.0f; - } - } - } - - } else { - /* char buffer */ - for(x=0; x<ibuf->x; x++) { - for(y=0; y<ibuf->y; y++) { - if (mask[ibuf->x*y + x] == val) { - char *col= (char *)(ibuf->rect + ibuf->x*y + x); - col[0] = col[1] = col[2] = col[3] = 0; - } - } - } - } -} - static void bake_set_shade_input(ObjectInstanceRen *obi, VlakRen *vlr, ShadeInput *shi, int quad, int isect, int x, int y, float u, float v) { if(quad) @@ -2281,7 +2213,7 @@ static void bake_shade(void *handle, Object *ob, ShadeInput *shi, int quad, int } if (bs->rect_mask) { - bs->rect_mask[bs->rectx*y + x] = BAKE_MASK_BAKED; + bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED; } } @@ -2308,7 +2240,7 @@ static void bake_displacement(void *handle, ShadeInput *shi, float dist, int x, col[3]= 255; } if (bs->rect_mask) { - bs->rect_mask[bs->rectx*y + x] = BAKE_MASK_BAKED; + bs->rect_mask[bs->rectx*y + x] = FILTER_MASK_USED; } } @@ -2750,16 +2682,16 @@ int RE_bake_shade_all_selected(Render *re, int type, Object *actob, short *do_up char *temprect; for(a=0; a<re->r.bake_filter; a++) - bake_mask_filter_extend((char *)ibuf->userdata, ibuf->x, ibuf->y); + IMB_mask_filter_extend((char *)ibuf->userdata, ibuf->x, ibuf->y); temprect = MEM_dupallocN(ibuf->userdata); /* expand twice to clear this many pixels, so they blend back in */ - bake_mask_filter_extend(temprect, ibuf->x, ibuf->y); - bake_mask_filter_extend(temprect, ibuf->x, ibuf->y); + IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y); + IMB_mask_filter_extend(temprect, ibuf->x, ibuf->y); /* clear all pixels in the margin*/ - bake_mask_clear(ibuf, temprect, BAKE_MASK_MARGIN); + IMB_mask_clear(ibuf, temprect, FILTER_MASK_MARGIN); MEM_freeN(temprect); } diff --git a/source/blender/render/intern/source/volumetric.c b/source/blender/render/intern/source/volumetric.c index 09422af7c79..c4e741b6c61 100644 --- a/source/blender/render/intern/source/volumetric.c +++ b/source/blender/render/intern/source/volumetric.c @@ -605,7 +605,7 @@ static void volumeintegrate(struct ShadeInput *shi, float *col, float *co, float for (; t0 < t1; pt0 = t0, t0 += stepsize) { const float density = vol_get_density(shi, p); - if (density > 0.01f) { + if (density > 0.00001f) { float scatter_col[3] = {0.f, 0.f, 0.f}, emit_col[3]; const float stepd = (t0 - pt0) * density; diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 223f2e9b654..2ca11dd34ec 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -102,7 +102,6 @@ endif() if(WITH_PYTHON) list(APPEND INC ../python) - list(APPEND INC_SYS ${PYTHON_INCLUDE_DIRS}) add_definitions(-DWITH_PYTHON) if(WITH_PYTHON_SECURITY) @@ -116,7 +115,9 @@ endif() if(APPLE) if(NOT WITH_COCOA) - list(APPEND SRC intern/wm_apple.c) + list(APPEND SRC + intern/wm_apple.c + ) endif() endif() diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 3f9a3f636d0..67294a8eb53 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -278,14 +278,19 @@ void WM_menutype_free(void); /* default operator callbacks for border/circle/lasso */ int WM_border_select_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_border_select_modal (struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_border_select_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_circle_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_circle_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_circle_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_lines_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_lines_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_lines_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_lasso_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op); int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); int WM_gesture_straightline_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op); /* default operator for arearegions, generates event */ void WM_OT_tweak_gesture(struct wmOperatorType *ot); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index ab68c6ef4d4..49bd3ede37d 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -61,6 +61,10 @@ struct ImBuf; #define OPTYPE_MACRO 8 #define OPTYPE_GRAB_POINTER 16 /* */ #define OPTYPE_PRESET 32 /* show preset menu */ +#define OPTYPE_INTERNAL 64 /* some operators are mainly for internal use + * and don't make sense to be accessed from the + * search menu, even if poll() returns TRUE. + * currently only used for the search toolbox */ /* context to call operator in for WM_operator_name_call */ /* rna_ui.c contains EnumPropertyItem's of these, keep in sync */ diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 615259bda15..2613cb8f14f 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -340,7 +340,7 @@ static int wm_handler_ui_call(bContext *C, wmEventHandler *handler, wmEvent *eve int is_wheel= ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE); int retval; - /* UI is quite agressive with swallowing events, like scrollwheel */ + /* UI is quite aggressive with swallowing events, like scrollwheel */ /* I realize this is not extremely nice code... when UI gets keymaps it can be maybe smarter */ if(do_wheel_ui==0) { if(is_wheel) @@ -1289,16 +1289,23 @@ static int wm_handler_fileselect_call(bContext *C, ListBase *handlers, wmEventHa if (handler->op_area == NULL) { bScreen *screen = CTX_wm_screen(C); sa = (ScrArea *)screen->areabase.first; - } else + } + else { sa = handler->op_area; + } - if(event->val==EVT_FILESELECT_OPEN) - ED_area_newspace(C, sa, SPACE_FILE); - else - ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */ - + if(event->val==EVT_FILESELECT_OPEN) { + ED_area_newspace(C, sa, SPACE_FILE); /* 'sa' is modified in-place */ + } + else { + sa= ED_screen_full_newspace(C, sa, SPACE_FILE); /* sets context */ + } + + /* note, getting the 'sa' back from the context causes a nasty bug where the newly created + * 'sa' != CTX_wm_area(C). removed the line below and set 'sa' in the 'if' above */ + /* sa = CTX_wm_area(C); */ + /* settings for filebrowser, sfile is not operator owner but sends events */ - sa = CTX_wm_area(C); sfile= (SpaceFile*)sa->spacedata.first; sfile->op= handler->op; @@ -1570,7 +1577,7 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) * so check for mouse moves too. * note2: the first click event will be handled but still used to create a * double click event if clicking again quickly. - * If no double click events are found itwill fallback to a single click. + * If no double click events are found it will fallback to a single click. * So a double click event can result in 2 successive single click calls * if its not handled by the keymap - campbell */ if ( (ABS(event->x - win->eventstate->prevclickx)) <= 2 && diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 1f005ba6021..c088d0d2d43 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -485,15 +485,16 @@ int WM_read_homefile(bContext *C, ReportList *reports, short from_memory) /* prevent buggy files that had G_FILE_RELATIVE_REMAP written out by mistake. Screws up autosaves otherwise * can remove this eventually, only in a 2.53 and older, now its not written */ G.fileflags &= ~G_FILE_RELATIVE_REMAP; - + + /* check userdef before open window, keymaps etc */ + wm_init_userdef(C); + /* match the read WM with current WM */ wm_window_match_do(C, &wmbase); WM_check(C); /* opens window(s), checks keymaps */ G.main->name[0]= '\0'; - wm_init_userdef(C); - /* When loading factory settings, the reset solid OpenGL lights need to be applied. */ if (!G.background) GPU_default_lights(); @@ -620,31 +621,6 @@ static void write_history(void) } } -static void do_history(char *name, ReportList *reports) -{ - char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE]; - int hisnr= U.versions; - - if(U.versions==0) return; - if(strlen(name)<2) return; - - while(hisnr > 1) { - BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1); - BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr); - - if(BLI_rename(tempname1, tempname2)) - BKE_report(reports, RPT_ERROR, "Unable to make version backup"); - - hisnr--; - } - - /* is needed when hisnr==1 */ - BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr); - - if(BLI_rename(name, tempname1)) - BKE_report(reports, RPT_ERROR, "Unable to make version backup"); -} - static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt) { /* will be scaled down, but gives some nice oversampling */ @@ -693,9 +669,11 @@ static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt) int write_crash_blend(void) { char path[FILE_MAX]; + int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */ + BLI_strncpy(path, G.main->name, sizeof(path)); BLI_replace_extension(path, sizeof(path), "_crash.blend"); - if(BLO_write_file(G.main, path, G.fileflags, NULL, NULL)) { + if(BLO_write_file(G.main, path, fileflags, NULL, NULL)) { printf("written: %s\n", path); return 1; } @@ -753,8 +731,7 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re /* blend file thumbnail */ ibuf_thumb= blend_file_thumb(CTX_data_scene(C), &thumb); - /* rename to .blend1, do this as last before write */ - do_history(filepath, reports); + fileflags |= G_FILE_HISTORY; /* write file history */ if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) { if(!copy) { @@ -770,7 +747,10 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re if(fileflags & G_FILE_AUTOPLAY) G.fileflags |= G_FILE_AUTOPLAY; else G.fileflags &= ~G_FILE_AUTOPLAY; - write_history(); + /* prevent background mode scripts from clobbering history */ + if(!G.background) { + write_history(); + } /* run this function after because the file cant be written before the blend is */ if (ibuf_thumb) { @@ -809,7 +789,7 @@ int WM_write_homefile(bContext *C, wmOperator *op) printf("trying to save homefile at %s ", filepath); /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN); + fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY); if(BLO_write_file(CTX_data_main(C), filepath, fileflags, op->reports, NULL) == 0) { printf("fail\n"); @@ -883,7 +863,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w wm_autosave_location(filepath); /* force save as regular blend file */ - fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN); + fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN|G_FILE_HISTORY); /* no error reporting to console */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 34702558bc8..1b7333024e7 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -727,14 +727,14 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); - //uiDefBut(block, LABEL, 0, op->type->name, 10, 10, 180, 19, NULL, 0.0, 0.0, 0, 0, ""); // ok, this isnt so easy... - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, 0, 0, ""); + //uiDefBut(block, LABEL, 0, op->type->name, 10, 10, 180, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); // ok, this isnt so easy... + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_enum_search_cb, op->type, operator_enum_call_cb, NULL); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9*UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - uiPopupBoundsBlock(block, 6, 0, -20); /* move it downwards, mouse over button */ + uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ uiEndBlock(C, block); event= *(win->eventstate); /* XXX huh huh? make api call */ @@ -916,7 +916,7 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *ar, void *arg_op) assert(op->type->flag & OPTYPE_REGISTER); uiBlockSetHandleFunc(block, ED_undo_operator_repeat_cb_evt, arg_op); - layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, 20, style); + layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, width, UI_UNIT_Y, style); if(ED_undo_valid(C, op->type->name)==0) uiLayoutSetEnabled(layout, 0); @@ -981,7 +981,7 @@ static uiBlock *wm_block_create_dialog(bContext *C, ARegion *ar, void *userData) col= uiLayoutColumn(layout, FALSE); col_block= uiLayoutGetBlock(col); /* Create OK button, the callback of which will execute op */ - btn= uiDefBut(col_block, BUT, 0, "OK", 0, -30, 0, 20, NULL, 0, 0, 0, 0, ""); + btn= uiDefBut(col_block, BUT, 0, "OK", 0, -30, 0, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); uiButSetFunc(btn, dialog_exec_cb, op, col_block); } @@ -1087,7 +1087,7 @@ static int wm_debug_menu_exec(bContext *C, wmOperator *op) static int wm_debug_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) { RNA_int_set(op->ptr, "debug_value", G.rt); - return WM_operator_props_dialog_popup(C, op, 180, 20); + return WM_operator_props_dialog_popup(C, op, 9*UI_UNIT_X, UI_UNIT_Y); } static void WM_OT_debug_menu(wmOperatorType *ot) @@ -1185,8 +1185,8 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiBlockSetFunc(block, wm_block_splash_refreshmenu, block, NULL); #ifdef NAN_BUILDINFO - uiDefBut(block, LABEL, 0, version_str, 494-ver_width, 282-24, ver_width, 20, NULL, 0, 0, 0, 0, NULL); - uiDefBut(block, LABEL, 0, revision_str, 494-rev_width, 282-36, rev_width, 20, NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, version_str, 494-ver_width, 282-24, ver_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, revision_str, 494-rev_width, 282-36, rev_width, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); #endif //NAN_BUILDINFO layout= uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 10, 2, 480, 110, style); @@ -1277,7 +1277,10 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons wmOperatorType *ot = WM_operatortype_first(); for(; ot; ot= ot->next) { - + + if((ot->flag & OPTYPE_INTERNAL) && (G.f & G_DEBUG) == 0) + continue; + if(BLI_strcasestr(ot->name, str)) { if(WM_operator_poll((bContext*)C, ot)) { char name[256]; @@ -1310,13 +1313,13 @@ static uiBlock *wm_block_search_menu(bContext *C, ARegion *ar, void *UNUSED(arg_ block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_RET_1|UI_BLOCK_MOVEMOUSE_QUIT); - but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 180, 19, 0, 0, ""); + but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 10, 9*UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); /* fake button, it holds space for search items */ - uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 180, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxhHeight(), 9*UI_UNIT_X, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); - uiPopupBoundsBlock(block, 6, 0, -20); /* move it downwards, mouse over button */ + uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ uiEndBlock(C, block); event= *(win->eventstate); /* XXX huh huh? make api call */ @@ -1389,6 +1392,8 @@ static void WM_OT_call_menu(wmOperatorType *ot) ot->exec= wm_call_menu_exec; ot->poll= WM_operator_winactive; + ot->flag= OPTYPE_INTERNAL; + RNA_def_string(ot->srna, "name", "", BKE_ST_MAXNAME, "Name", "Name of the menu"); } @@ -2244,6 +2249,13 @@ int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int WM_border_select_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + /* **************** circle gesture *************** */ /* works now only for selection or modal paint stuff, calls exec while hold mouse, exit on release */ @@ -2340,6 +2352,13 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int WM_gesture_circle_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + #if 0 /* template to copy from */ void WM_OT_circle_gesture(wmOperatorType *ot) @@ -2556,6 +2575,20 @@ int WM_gesture_lines_modal(bContext *C, wmOperator *op, wmEvent *event) return WM_gesture_lasso_modal(C, op, event); } +int WM_gesture_lasso_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + +int WM_gesture_lines_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + #if 0 /* template to copy from */ @@ -2677,6 +2710,13 @@ int WM_gesture_straightline_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } +int WM_gesture_straightline_cancel(bContext *C, wmOperator *op) +{ + wm_gesture_end(C, op); + + return OPERATOR_CANCELLED; +} + #if 0 /* template to copy from */ void WM_OT_straightline_gesture(wmOperatorType *ot) @@ -3060,6 +3100,28 @@ static void radial_control_set_value(RadialControl *rc, float val) } } +static int radial_control_cancel(bContext *C, wmOperator *op) +{ + RadialControl *rc = op->customdata; + wmWindowManager *wm = CTX_wm_manager(C); + + WM_paint_cursor_end(wm, rc->cursor); + + /* restore original paint cursors */ + wm->paintcursors = rc->orig_paintcursors; + + /* not sure if this is a good notifier to use; + intended purpose is to update the UI so that the + new value is displayed in sliders/numfields */ + WM_event_add_notifier(C, NC_WINDOW, NULL); + + glDeleteTextures(1, &rc->gltex); + + MEM_freeN(rc); + + return OPERATOR_CANCELLED; +} + static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event) { RadialControl *rc = op->customdata; @@ -3125,23 +3187,8 @@ static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event) ED_region_tag_redraw(CTX_wm_region(C)); - if(ret != OPERATOR_RUNNING_MODAL) { - wm = CTX_wm_manager(C); - - WM_paint_cursor_end(wm, rc->cursor); - - /* restore original paint cursors */ - wm->paintcursors = rc->orig_paintcursors; - - /* not sure if this is a good notifier to use; - intended purpose is to update the UI so that the - new value is displayed in sliders/numfields */ - WM_event_add_notifier(C, NC_WINDOW, NULL); - - glDeleteTextures(1, &rc->gltex); - - MEM_freeN(rc); - } + if(ret != OPERATOR_RUNNING_MODAL) + radial_control_cancel(C, op); return ret; } @@ -3153,6 +3200,7 @@ static void WM_OT_radial_control(wmOperatorType *ot) ot->invoke= radial_control_invoke; ot->modal= radial_control_modal; + ot->cancel= radial_control_cancel; ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO|OPTYPE_BLOCKING; diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 82fe42f2b42..9ee39132521 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -271,9 +271,11 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win) void wm_window_title(wmWindowManager *wm, wmWindow *win) { - /* handle the 'temp' window */ + /* handle the 'temp' window, only set title when not set before */ if(win->screen && win->screen->temp) { - GHOST_SetTitle(win->ghostwin, "Blender"); + char *title= GHOST_GetTitle(win->ghostwin); + if(title==NULL || title[0]==0) + GHOST_SetTitle(win->ghostwin, "Blender"); } else { |