diff options
Diffstat (limited to 'source/blender')
183 files changed, 4193 insertions, 1321 deletions
diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index a45e9a17dc9..07f0885372a 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); 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_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h index 14251fb1762..f36073ba841 100644 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ b/source/blender/blenkernel/BKE_depsgraph.h @@ -51,22 +51,23 @@ struct GHash; /* **** DAG relation types *** */ /* scene link to object */ -#define DAG_RL_SCENE 1 +#define DAG_RL_SCENE (1<<0) /* object link to data */ -#define DAG_RL_DATA 2 +#define DAG_RL_DATA (1<<1) /* object changes object (parent, track, constraints) */ -#define DAG_RL_OB_OB 4 +#define DAG_RL_OB_OB (1<<2) /* object changes obdata (hooks, constraints) */ -#define DAG_RL_OB_DATA 8 +#define DAG_RL_OB_DATA (1<<3) /* data changes object (vertex parent) */ -#define DAG_RL_DATA_OB 16 +#define DAG_RL_DATA_OB (1<<4) /* data changes data (deformers) */ -#define DAG_RL_DATA_DATA 32 +#define DAG_RL_DATA_DATA (1<<5) -#define DAG_NO_RELATION 64 -#define DAG_RL_ALL 63 -#define DAG_RL_ALL_BUT_DATA 61 +#define DAG_NO_RELATION (1<<6) + +#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE|DAG_RL_OB_OB|DAG_RL_OB_DATA|DAG_RL_DATA_OB|DAG_RL_DATA_DATA) +#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA|DAG_RL_DATA) typedef void (*graph_action_func)(void * ob, void **data); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index ea34ff4aa07..ba23b2d79c0 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -91,6 +91,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/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 4dfc53e1734..feeab98ad78 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -300,6 +300,8 @@ void psys_get_pointcache_start_end(struct Scene *scene, ParticleSystem *psys, in void psys_check_boid_data(struct ParticleSystem *psys); +void psys_get_birth_coordinates(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra); + void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); /* ----------- functions needed only inside particlesystem ------------ */ diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index b852629e49c..5a9432552d2 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -180,7 +180,6 @@ static void clean_paths(Main *main) BLI_bpathIterator_free(bpi); for(scene= main->scene.first; scene; scene= scene->id.next) { - BLI_clean(scene->r.backbuf); BLI_clean(scene->r.pic); } } @@ -620,7 +619,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); } @@ -646,6 +645,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/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c index 5520e4d1d41..cc45abb5998 100644 --- a/source/blender/blenkernel/intern/bvhutils.c +++ b/source/blender/blenkernel/intern/bvhutils.c @@ -493,7 +493,7 @@ static void mesh_edges_nearest_point(void *userdata, int index, const float *co, // NOTE: casts to "float*" here are due to co being "const float*" closest_to_line_segment_v3(nearest_tmp, (float*)co, t0, t1); - dist = len_v3v3(nearest_tmp, (float*)co); + dist = len_squared_v3v3(nearest_tmp, (float*)co); if(dist < nearest->dist) { diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index f5f069767eb..45faba8439c 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -540,7 +540,7 @@ static void layerInterp_mdisps(void **sources, float *UNUSED(weights), 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_crn(src_corners, st, face_u, face_v, &crn_u, &crn_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); diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 0696653d2e4..11a0a5884ee 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -121,7 +121,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; @@ -170,7 +170,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 13ab89200db..d833c184274 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -1020,7 +1020,7 @@ static void old_mdisps_rotate(int S, int UNUSED(newside), int oldside, int x, in static void old_mdisps_convert(MFace *mface, MDisps *mdisp) { - int newlvl = log(sqrt(mdisp->totdisp)-1)/log(2); + int newlvl = log(sqrt(mdisp->totdisp)-1)/M_LN2; int oldlvl = newlvl+1; int oldside = multires_side_tot[oldlvl]; int newside = multires_side_tot[newlvl]; @@ -1997,6 +1997,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; @@ -2022,6 +2023,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}; @@ -2148,7 +2204,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/object.c b/source/blender/blenkernel/intern/object.c index d0fbc6247b5..16fa1605467 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2387,24 +2387,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: @@ -2416,25 +2434,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]); @@ -2444,7 +2464,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_system.c b/source/blender/blenkernel/intern/particle_system.c index fca8d470dc1..4e3840832bb 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -1562,8 +1562,7 @@ static void initialize_all_particles(ParticleSimulationData *sim) } } } -/* sets particle to the emitter surface with initial velocity & rotation */ -void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) +void psys_get_birth_coordinates(ParticleSimulationData *sim, ParticleData *pa, ParticleKey *state, float dtime, float cfra) { Object *ob = sim->ob; ParticleSystem *psys = sim->psys; @@ -1575,17 +1574,6 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float q_phase[4]; int p = pa - psys->particles; part=psys->part; - - /* get precise emitter matrix if particle is born */ - if(part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { - /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ - while(ob) { - BKE_animsys_evaluate_animdata(&ob->id, ob->adt, pa->time, ADT_RECALC_ANIM); - ob = ob->parent; - } - ob = sim->ob; - where_is_object_time(sim->scene, ob, pa->time); - } /* get birth location from object */ if(part->tanfac != 0.f) @@ -1594,7 +1582,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); /* get possible textural influence */ - psys_get_texture(sim, pa, &ptex, PAMAP_IVEL|PAMAP_LIFE, cfra); + psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra); /* particles live in global space so */ /* let's convert: */ @@ -1654,37 +1642,27 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, mat4_to_quat(rot,ob->obmat); mul_qt_qtqt(r_rot,r_rot,rot); } -#if 0 - } -#endif if(part->phystype==PART_PHYS_BOIDS && pa->boid) { - BoidParticle *bpa = pa->boid; float dvec[3], q[4], mat[3][3]; - copy_v3_v3(pa->state.co,loc); + copy_v3_v3(state->co,loc); /* boids don't get any initial velocity */ - zero_v3(pa->state.vel); + zero_v3(state->vel); /* boids store direction in ave */ if(fabsf(nor[2])==1.0f) { - sub_v3_v3v3(pa->state.ave, loc, ob->obmat[3]); - normalize_v3(pa->state.ave); + sub_v3_v3v3(state->ave, loc, ob->obmat[3]); + normalize_v3(state->ave); } else { - VECCOPY(pa->state.ave, nor); + VECCOPY(state->ave, nor); } - /* and gravity in r_ve */ - bpa->gravity[0] = bpa->gravity[1] = 0.0f; - bpa->gravity[2] = -1.0f; - if((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) - && sim->scene->physics_settings.gravity[2]!=0.0f) - bpa->gravity[2] = sim->scene->physics_settings.gravity[2]; /* calculate rotation matrix */ - project_v3_v3v3(dvec, r_vel, pa->state.ave); - sub_v3_v3v3(mat[0], pa->state.ave, dvec); + project_v3_v3v3(dvec, r_vel, state->ave); + sub_v3_v3v3(mat[0], state->ave, dvec); normalize_v3(mat[0]); negate_v3_v3(mat[2], r_vel); normalize_v3(mat[2]); @@ -1692,12 +1670,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* apply rotation */ mat3_to_quat_is_ok( q,mat); - copy_qt_qt(pa->state.rot, q); - - bpa->data.health = part->boids->health; - bpa->data.mode = eBoidMode_InAir; - bpa->data.state_id = ((BoidState*)part->boids->states.first)->id; - bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f; + copy_qt_qt(state->rot, q); } else { /* conversion done so now we apply new: */ @@ -1710,7 +1683,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* *emitter velocity */ if(dtime != 0.f && part->obfac != 0.f){ - sub_v3_v3v3(vel, loc, pa->state.co); + sub_v3_v3v3(vel, loc, state->co); mul_v3_fl(vel, part->obfac/dtime); } @@ -1747,13 +1720,13 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, if(part->partfac != 0.f) madd_v3_v3fl(vel, p_vel, part->partfac); - mul_v3_v3fl(pa->state.vel, vel, ptex.ivel); + mul_v3_v3fl(state->vel, vel, ptex.ivel); /* -location from emitter */ - copy_v3_v3(pa->state.co,loc); + copy_v3_v3(state->co,loc); /* -rotation */ - unit_qt(pa->state.rot); + unit_qt(state->rot); if(part->rotmode){ /* create vector into which rotation is aligned */ @@ -1793,32 +1766,74 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, axis_angle_to_quat( q_phase,x_vec, phasefac*(float)M_PI); /* combine base rotation & phase */ - mul_qt_qtqt(pa->state.rot, rot, q_phase); + mul_qt_qtqt(state->rot, rot, q_phase); } /* -angular velocity */ - zero_v3(pa->state.ave); + zero_v3(state->ave); if(part->avemode){ switch(part->avemode){ case PART_AVE_SPIN: - copy_v3_v3(pa->state.ave, vel); + copy_v3_v3(state->ave, vel); break; case PART_AVE_RAND: - copy_v3_v3(pa->state.ave, r_ave); + copy_v3_v3(state->ave, r_ave); break; } - normalize_v3(pa->state.ave); - mul_v3_fl(pa->state.ave,part->avefac); + normalize_v3(state->ave); + mul_v3_fl(state->ave, part->avefac); } } +} +/* sets particle to the emitter surface with initial velocity & rotation */ +void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, float cfra) +{ + Object *ob = sim->ob; + ParticleSystem *psys = sim->psys; + ParticleSettings *part; + ParticleTexture ptex; + int p = pa - psys->particles; + part=psys->part; + + /* get precise emitter matrix if particle is born */ + if(part->type!=PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { + /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ + while(ob) { + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, pa->time, ADT_RECALC_ANIM); + ob = ob->parent; + } + ob = sim->ob; + where_is_object_time(sim->scene, ob, pa->time); + } + + psys_get_birth_coordinates(sim, pa, &pa->state, dtime, cfra); + + if(part->phystype==PART_PHYS_BOIDS && pa->boid) { + BoidParticle *bpa = pa->boid; + + /* and gravity in r_ve */ + bpa->gravity[0] = bpa->gravity[1] = 0.0f; + bpa->gravity[2] = -1.0f; + if((sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) + && sim->scene->physics_settings.gravity[2]!=0.0f) + bpa->gravity[2] = sim->scene->physics_settings.gravity[2]; + + bpa->data.health = part->boids->health; + bpa->data.mode = eBoidMode_InAir; + bpa->data.state_id = ((BoidState*)part->boids->states.first)->id; + bpa->data.acc[0]=bpa->data.acc[1]=bpa->data.acc[2]=0.0f; + } if(part->type == PART_HAIR){ pa->lifetime = 100.0f; } else{ + /* get possible textural influence */ + psys_get_texture(sim, pa, &ptex, PAMAP_LIFE, cfra); + pa->lifetime = part->lifetime * ptex.life; if(part->randlife != 0.0f) @@ -1904,6 +1919,7 @@ static void set_keyed_keys(ParticleSimulationData *sim) PARTICLE_P; ParticleKey *key; int totpart = psys->totpart, k, totkeys = psys->totkeyed; + int keyed_flag = 0; ksim.scene= sim->scene; @@ -1933,6 +1949,8 @@ static void set_keyed_keys(ParticleSimulationData *sim) for(k=0; k<totkeys; k++) { ksim.ob = pt->ob ? pt->ob : sim->ob; ksim.psys = BLI_findlink(&ksim.ob->particlesystem, pt->psys - 1); + keyed_flag = (ksim.psys->flag & PSYS_KEYED); + ksim.psys->flag &= ~PSYS_KEYED; LOOP_PARTICLES { key = pa->keys + k; @@ -1956,6 +1974,8 @@ static void set_keyed_keys(ParticleSimulationData *sim) if(psys->flag & PSYS_KEYED_TIMING && pt->duration!=0.0f) k++; + ksim.psys->flag |= keyed_flag; + pt = (pt->next && pt->next->flag & PTARGET_VALID)? pt->next : psys->targets.first; } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 16cef67ea6d..0d523599598 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -430,6 +430,7 @@ void init_actuator(bActuator *act) act->data= MEM_callocN(sizeof(bCameraActuator), "camact"); ca = act->data; ca->axis = ACT_CAMERA_X; + ca->damping = 1.0/32.0; break; case ACT_EDIT_OBJECT: act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact"); diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 11cdcddae3a..51eaba3c05b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -476,8 +476,7 @@ Scene *add_scene(const char *name) sce->audio.doppler_factor = 1.0; sce->audio.speed_of_sound = 343.3; - strcpy(sce->r.backbuf, "//backbuf"); - strcpy(sce->r.pic, U.renderdir); + BLI_strncpy(sce->r.pic, U.renderdir, sizeof(sce->r.pic)); BLI_init_rctf(&sce->r.safety, 0.1f, 0.9f, 0.1f, 0.9f); sce->r.osa= 8; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index d2f05a8ca53..fbb5a77fa04 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -1582,7 +1582,7 @@ typedef struct WipeZone { static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo) { wipezone->flip = (wipe->angle < 0); - wipezone->angle = pow(fabsf(wipe->angle)/45.0f, log(xo)/log(2.0f)); + wipezone->angle = pow(fabsf(wipe->angle)/45.0f, log(xo)/M_LN2); wipezone->xo = xo; wipezone->yo = yo; wipezone->width = (int)(wipe->edgeWidth*((xo+yo)/2.0f)); @@ -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 634634f02e5..b34b9c4b70f 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -162,6 +162,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 5f26bff0ad9..decfa22c3e6 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -58,6 +58,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 a376d048412..9af55601ff7 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_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index d37f1d6c5f0..2a2b1100fd9 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -114,7 +114,7 @@ MINLINE float shell_angle_to_dist(const float angle) /* used for zoom values*/ MINLINE float power_of_2(float val) { - return (float)pow(2.0, ceil(log((double)val) / log(2.0))); + return (float)pow(2.0, ceil(log((double)val) / M_LN2)); } MINLINE float minf(float a, float b) diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 5979a24c807..96ed788a49f 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 9f6a8afe2d5..e2b7c770356 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 c15acb4f5ca..1e604c45772 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -1723,7 +1723,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 */ @@ -1739,6 +1738,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]); } @@ -3843,26 +3843,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); @@ -5658,11 +5642,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 @@ -6280,7 +6263,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; @@ -11664,6 +11647,21 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + + { + /* add default value for behind strength of camera actuator */ + Object *ob; + bActuator *act; + for(ob = main->object.first; ob; ob= ob->id.next) { + for(act= ob->actuators.first; act; act= act->next) { + if (act->type == ACT_CAMERA) { + bCameraActuator *ba= act->data; + + ba->damping = 1.0/32.0; + } + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -12723,7 +12721,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; @@ -12758,8 +12755,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; + } } } } @@ -12780,7 +12783,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/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index 72341e1caa2..10e6d611cc5 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -959,12 +959,12 @@ bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) if(IS_EQ(linatt, 0.0f) && quadatt > 0.0f) { att2 = quadatt; - d = (1.0f/quadatt) * 2; + d = sqrt(1.0f/quadatt); } // linear light else if(IS_EQ(quadatt, 0.0f) && linatt > 0.0f) { att1 = linatt; - d = (1.0f/linatt) * 2; + d = (1.0f/linatt); } else if (IS_EQ(constatt, 1.0f)) { att1 = 1.0f; } else { @@ -987,9 +987,12 @@ bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) case COLLADAFW::Light::SPOT_LIGHT: { lamp->type = LA_SPOT; - lamp->falloff_type = LA_FALLOFF_INVSQUARE; lamp->att1 = att1; lamp->att2 = att2; + if(IS_EQ(att1, 0.0f) && att2 > 0) + lamp->falloff_type = LA_FALLOFF_INVSQUARE; + if(IS_EQ(att2, 0.0f) && att1 > 0) + lamp->falloff_type = LA_FALLOFF_INVLINEAR; lamp->spotsize = light->getFallOffAngle().getValue(); lamp->spotblend = light->getFallOffExponent().getValue(); } @@ -1004,9 +1007,12 @@ bool DocumentImporter::writeLight( const COLLADAFW::Light* light ) case COLLADAFW::Light::POINT_LIGHT: { lamp->type = LA_LOCAL; - lamp->falloff_type = LA_FALLOFF_INVSQUARE; lamp->att1 = att1; lamp->att2 = att2; + if(IS_EQ(att1, 0.0f) && att2 > 0) + lamp->falloff_type = LA_FALLOFF_INVSQUARE; + if(IS_EQ(att2, 0.0f) && att1 > 0) + lamp->falloff_type = LA_FALLOFF_INVLINEAR; } break; case COLLADAFW::Light::UNDEFINED: 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/collada/LightExporter.cpp b/source/blender/collada/LightExporter.cpp index 89599c62768..12ccf77f6ad 100644 --- a/source/blender/collada/LightExporter.cpp +++ b/source/blender/collada/LightExporter.cpp @@ -68,20 +68,18 @@ void LightsExporter::operator()(Object *ob) std::string la_name(id_name(la)); COLLADASW::Color col(la->r * la->energy, la->g * la->energy, la->b * la->energy); float e, d, constatt, linatt, quadatt; - float r; d = la->dist; - r = d/2.0f; constatt = 1.0f; if(la->falloff_type==LA_FALLOFF_INVLINEAR) { - linatt = 1.0f / r; + linatt = 1.0f / d; quadatt = 0.0f; } else { linatt = 0.0f; - quadatt = 1.0f / r; + quadatt = 1.0f / (d * d); } // sun diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 438c6e7e95e..9eb9e3ecd9a 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -1903,6 +1903,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 f61c1ff7962..1fb2317cdbb 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 5c4dfc6ba3d..8bb77ad43a0 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -206,10 +206,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 50dd2308b6b..5e004fd8d47 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 0adf6633b05..dfe0a304748 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -265,6 +265,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 d139eafc09d..37e4cc7616b 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); } } @@ -1681,7 +1733,7 @@ void ui_set_but_default(bContext *C, short all) static double soft_range_round_up(double value, double max) { /* round up to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax= pow(10.0, ceil(log(value)/log(10.0))); + double newmax= pow(10.0, ceil(log(value)/M_LN10)); if(newmax*0.2 >= max && newmax*0.2 >= value) return newmax*0.2; @@ -1694,7 +1746,7 @@ static double soft_range_round_up(double value, double max) static double soft_range_round_down(double value, double max) { /* round down to .., 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, .. */ - double newmax= pow(10.0, floor(log(value)/log(10.0))); + double newmax= pow(10.0, floor(log(value)/M_LN10)); if(newmax*5.0 <= max && newmax*5.0 <= value) return newmax*5.0; @@ -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 { 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 531c9dbf799..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 @@ -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 e95b544d0c0..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 @@ -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 8b20406e036..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 @@ -675,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 */ @@ -972,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 @@ -1229,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 */ @@ -1305,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) } } @@ -1320,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); @@ -1402,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); @@ -1472,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 */ @@ -1479,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; @@ -1491,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); @@ -1511,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); } @@ -2171,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 @@ -2180,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; @@ -2284,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..b6e255b6758 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) { @@ -2326,39 +2326,43 @@ static void widget_numslider(uiBut *but, uiWidgetColors *wcol, rcti *rect, int s wtb.outline= 0; widgetbase_draw(&wtb, wcol); - /* slider part */ - VECCOPY(outline, wcol->outline); - VECCOPY(wcol->outline, wcol->item); - VECCOPY(wcol->inner, wcol->item); + /* draw left/right parts only when not in text editing */ + if(!(state & UI_TEXTINPUT)) { + + /* slider part */ + VECCOPY(outline, wcol->outline); + VECCOPY(wcol->outline, wcol->item); + VECCOPY(wcol->inner, wcol->item); - if(!(state & UI_SELECT)) - SWAP(short, wcol->shadetop, wcol->shadedown); - - rect1= *rect; - - value= ui_get_but_val(but); - fac= ((float)value-but->softmin)*(rect1.xmax - rect1.xmin - offs)/(but->softmax - but->softmin); - - /* left part of slider, always rounded */ - rect1.xmax= rect1.xmin + ceil(offs+1.0f); - round_box_edges(&wtb1, roundboxalign & ~6, &rect1, offs); - wtb1.outline= 0; - widgetbase_draw(&wtb1, wcol); - - /* right part of slider, interpolate roundness */ - rect1.xmax= rect1.xmin + fac + offs; - rect1.xmin+= floor(offs-1.0f); - if(rect1.xmax + offs > rect->xmax) - offs*= (rect1.xmax + offs - rect->xmax)/offs; - else - offs= 0.0f; - round_box_edges(&wtb1, roundboxalign & ~9, &rect1, offs); - - widgetbase_draw(&wtb1, wcol); - VECCOPY(wcol->outline, outline); - - if(!(state & UI_SELECT)) - SWAP(short, wcol->shadetop, wcol->shadedown); + if(!(state & UI_SELECT)) + SWAP(short, wcol->shadetop, wcol->shadedown); + + rect1= *rect; + + value= ui_get_but_val(but); + fac= ((float)value-but->softmin)*(rect1.xmax - rect1.xmin - offs)/(but->softmax - but->softmin); + + /* left part of slider, always rounded */ + rect1.xmax= rect1.xmin + ceil(offs+1.0f); + round_box_edges(&wtb1, roundboxalign & ~6, &rect1, offs); + wtb1.outline= 0; + widgetbase_draw(&wtb1, wcol); + + /* right part of slider, interpolate roundness */ + rect1.xmax= rect1.xmin + fac + offs; + rect1.xmin+= floor(offs-1.0f); + if(rect1.xmax + offs > rect->xmax) + offs*= (rect1.xmax + offs - rect->xmax)/offs; + else + offs= 0.0f; + round_box_edges(&wtb1, roundboxalign & ~9, &rect1, offs); + + widgetbase_draw(&wtb1, wcol); + VECCOPY(wcol->outline, outline); + + if(!(state & UI_SELECT)) + SWAP(short, wcol->shadetop, wcol->shadedown); + } /* outline */ wtb.outline= 1; @@ -2597,6 +2601,7 @@ static void widget_box(uiBut *but, uiWidgetColors *wcol, rcti *rect, int UNUSED( /* store the box bg as gl clearcolor, to retrieve later when drawing semi-transparent rects * over the top to indicate disabled buttons */ + /* XXX, this doesnt work right since the color applies to buttons outside the box too. */ glClearColor(wcol->inner[0]/255.0, wcol->inner[1]/255.0, wcol->inner[2]/255.0, 1.0); VECCOPY(wcol->inner, old_col); @@ -2872,7 +2877,7 @@ void ui_draw_but(const bContext *C, ARegion *ar, uiStyle *style, uiBut *but, rct ThemeUI *tui= &btheme->tui; uiFontStyle *fstyle= &style->widget; uiWidgetType *wt= NULL; - + /* handle menus separately */ if(but->dt==UI_EMBOSSP) { switch (but->type) { @@ -3081,6 +3086,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 3564dad474a..bbabe968bb2 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/mesh/editmesh_loop.c b/source/blender/editors/mesh/editmesh_loop.c index d7e59e0a68f..32971ca77ed 100644 --- a/source/blender/editors/mesh/editmesh_loop.c +++ b/source/blender/editors/mesh/editmesh_loop.c @@ -716,6 +716,7 @@ void MESH_OT_knife_cut(wmOperatorType *ot) ot->invoke= WM_gesture_lines_invoke; ot->modal= WM_gesture_lines_modal; ot->exec= knife_cut_exec; + ot->cancel= WM_gesture_lines_cancel; ot->poll= EM_view3d_poll; diff --git a/source/blender/editors/mesh/editmesh_mods.c b/source/blender/editors/mesh/editmesh_mods.c index b5da36756b5..741cfd7078c 100644 --- a/source/blender/editors/mesh/editmesh_mods.c +++ b/source/blender/editors/mesh/editmesh_mods.c @@ -2339,7 +2339,7 @@ int mouse_mesh(bContext *C, const int mval[2], short extend) if (efa && efa->mat_nr != vc.obedit->actcol-1) { vc.obedit->actcol= efa->mat_nr+1; vc.em->mat_nr= efa->mat_nr; -// BIF_preview_changed(ID_MA); + WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, NULL); } WM_event_add_notifier(C, NC_GEOM|ND_SELECT, vc.obedit->data); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 424d3dd5a38..bfae101d38e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -3967,6 +3967,7 @@ short sharesFace(EditMesh *em, EditEdge* e1, EditEdge* e2) return 0; } +#if 0 typedef struct SlideUv { float origuv[2]; @@ -3980,7 +3981,6 @@ typedef struct SlideVert { EditVert origvert; } SlideVert; -#if 0 int EdgeSlide(EditMesh *em, wmOperator *op, short immediate, float imperc) { return 0; diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index c425ef5a36a..c5236a38970 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", ""); @@ -637,7 +637,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; } @@ -1382,7 +1382,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"; @@ -1395,8 +1395,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 ************************/ @@ -1716,7 +1716,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); } @@ -1786,8 +1786,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"); } @@ -1812,11 +1812,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; } @@ -1865,11 +1865,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..565c5810cff 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,1134 @@ #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) +{ + 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); + } +} + +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]) +{ + 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); +} + +/* 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) +{ + 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; + } +} + +/* 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) +{ + 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; + } +} + +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); + 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 +1285,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 +1408,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 +1468,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 5996037cd2d..fca35683c6f 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -399,6 +399,13 @@ int ED_object_modifier_convert(ReportList *UNUSED(reports), Main *bmain, Scene * static int modifier_apply_shape(ReportList *reports, Scene *scene, Object *ob, ModifierData *md) { + ModifierTypeInfo *mti= modifierType_getInfo(md->type); + + if (mti->isDisabled && mti->isDisabled(md, 0)) { + BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); + return 0; + } + if (ob->type==OB_MESH) { DerivedMesh *dm; Mesh *me= ob->data; @@ -442,7 +449,7 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, { ModifierTypeInfo *mti= modifierType_getInfo(md->type); - if (!(md->mode&eModifierMode_Realtime) || (mti->isDisabled && mti->isDisabled(md, 0))) { + if (mti->isDisabled && mti->isDisabled(md, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); return 0; } @@ -484,7 +491,7 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, CustomData_free_layer_active(&me->fdata, CD_MDISPS, me->totface); } } - } + } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu; int numVerts; @@ -530,6 +537,8 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, ModifierData *md, int mode) { + int prev_mode; + if (scene->obedit) { BKE_report(reports, RPT_ERROR, "Modifiers cannot be applied in editmode"); return 0; @@ -541,12 +550,20 @@ int ED_object_modifier_apply(ReportList *reports, Scene *scene, Object *ob, Modi if (md!=ob->modifiers.first) BKE_report(reports, RPT_INFO, "Applied modifier was not first, result may not be as expected."); + /* allow apply of a not-realtime modifier, by first re-enabling realtime. */ + prev_mode= md->mode; + md->mode |= eModifierMode_Realtime; + if (mode == MODIFIER_APPLY_SHAPE) { - if (!modifier_apply_shape(reports, scene, ob, md)) + if (!modifier_apply_shape(reports, scene, ob, md)) { + md->mode= prev_mode; return 0; + } } else { - if (!modifier_apply_obdata(reports, scene, ob, md)) + if (!modifier_apply_obdata(reports, scene, ob, md)) { + md->mode= prev_mode; return 0; + } } BLI_remlink(&ob->modifiers, md); @@ -1259,16 +1276,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 7c59278dcf5..fd2e7fd7c99 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) 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 43448198ae1..52ba9460818 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -77,6 +77,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) { @@ -138,22 +139,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: @@ -166,8 +175,6 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to int i; if (!CustomData_has_layer(&em->vdata, CD_MDEFORMVERT)) { - *dvert_tot = 0; - *dvert_arr = NULL; return 0; } @@ -195,8 +202,9 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to return 1; } - else + else { return 0; + } } case ID_LT: { @@ -222,8 +230,6 @@ static int ED_vgroup_give_parray(ID *id, MDeformVert ***dvert_arr, int *dvert_to } } - *dvert_arr= NULL; - *dvert_tot= 0; return 0; } @@ -265,13 +271,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; } @@ -1015,55 +1032,75 @@ 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) { +#define VGROUP_MIRR_OP dvert_mirror_op(dvert, dvert_mirr, sel, sel_mirr, flip_map, mirror_weights, flip_vgroups) + EditVert *eve, *eve_mirr; 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; EditMesh *em = BKE_mesh_get_editmesh(me); - EM_cache_x_mirror_vert(ob, em); - 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; } } @@ -1071,10 +1108,58 @@ void ED_vgroup_mirror(Object *ob, int mirror_weights, int flip_vgroups) } } - MEM_freeN(flip_map); - BKE_mesh_end_editmesh(me, em); } + 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) @@ -1920,17 +2005,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 c5ab840914e..6155929243b 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -3970,18 +3970,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; @@ -4007,32 +3995,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/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index 4aa9b942cf3..b573c77c7f3 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -56,6 +56,7 @@ #include "DNA_object_fluidsim.h" #include "BLI_blenlib.h" +#include "BLI_fileops.h" #include "BLI_threads.h" #include "BLI_math.h" #include "BLI_utildefines.h" @@ -125,7 +126,7 @@ static void get_fluid_gravity(float *gravity, Scene *scene, FluidsimSettings *fs if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { copy_v3_v3(gravity, scene->physics_settings.gravity); } else { - copy_v3_v3(gravity, &fss->gravx); + copy_v3_v3(gravity, fss->grav); } } @@ -443,7 +444,7 @@ static void fluid_init_all_channels(bContext *C, Object *UNUSED(fsDomain), Fluid Object *ob = fobj->object; FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType(ob, eModifierType_Fluidsim); float active= (float)(fluidmd->fss->flag & OB_FLUIDSIM_ACTIVE); - float rot_d[3], old_rot[3] = {0.f, 0.f, 0.f}; + float rot_d[3] = {0.f, 0.f, 0.f}, old_rot[3] = {0.f, 0.f, 0.f}; if (ELEM(fluidmd->fss->type, OB_FLUIDSIM_DOMAIN, OB_FLUIDSIM_PARTICLE)) continue; @@ -809,6 +810,44 @@ static void fluidbake_free_data(FluidAnimChannels *channels, ListBase *fobjects, } } +/* copied from rna_fluidsim.c: fluidsim_find_lastframe() */ +static void fluidsim_delete_until_lastframe(FluidsimSettings *fss) +{ + char targetDir[FILE_MAXFILE+FILE_MAXDIR], targetFile[FILE_MAXFILE+FILE_MAXDIR]; + char targetDirVel[FILE_MAXFILE+FILE_MAXDIR], targetFileVel[FILE_MAXFILE+FILE_MAXDIR]; + char previewDir[FILE_MAXFILE+FILE_MAXDIR], previewFile[FILE_MAXFILE+FILE_MAXDIR]; + int curFrame = 1, exists = 0; + + BLI_snprintf(targetDir, sizeof(targetDir), "%sfluidsurface_final_####.bobj.gz", fss->surfdataPath); + BLI_snprintf(targetDirVel, sizeof(targetDir), "%sfluidsurface_final_####.bvel.gz", fss->surfdataPath); + BLI_snprintf(previewDir, sizeof(targetDir), "%sfluidsurface_preview_####.bobj.gz", fss->surfdataPath); + + BLI_path_abs(targetDir, G.main->name); + BLI_path_abs(targetDirVel, G.main->name); + BLI_path_abs(previewDir, G.main->name); + + do { + BLI_strncpy(targetFile, targetDir, sizeof(targetFile)); + BLI_strncpy(targetFileVel, targetDirVel, sizeof(targetFileVel)); + BLI_strncpy(previewFile, previewDir, sizeof(previewFile)); + + BLI_path_frame(targetFile, curFrame, 0); + BLI_path_frame(targetFileVel, curFrame, 0); + BLI_path_frame(previewFile, curFrame, 0); + + curFrame++; + + if((exists = BLI_exist(targetFile))) + { + BLI_delete(targetFile, 0, 0); + BLI_delete(targetFileVel, 0, 0); + BLI_delete(previewFile, 0, 0); + } + } while(exists); + + return; +} + static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain) { Scene *scene= CTX_data_scene(C); @@ -878,6 +917,9 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain) // reset last valid frame domainSettings->lastgoodframe = -1; + + /* delete old baked files */ + fluidsim_delete_until_lastframe(domainSettings); /* rough check of settings... */ if(domainSettings->previewresxyz > domainSettings->resolutionxyz) { @@ -1018,6 +1060,13 @@ static int fluidsimBake(bContext *C, ReportList *reports, Object *fsDomain) else if (domainSettings->typeFlags&OB_FSBND_PARTSLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_PARTSLIP; else if (domainSettings->typeFlags&OB_FSBND_FREESLIP) fsset->domainobsType = FLUIDSIM_OBSTACLE_FREESLIP; fsset->domainobsPartslip = domainSettings->partSlipValue; + + /* use domainobsType also for surface generation flag (bit: >=64) */ + if(domainSettings->typeFlags & OB_FSSG_NOOBS) + fsset->mFsSurfGenSetting = FLUIDSIM_FSSG_NOOBS; + else + fsset->mFsSurfGenSetting = 0; // "normal" mode + fsset->generateVertexVectors = (domainSettings->domainNovecgen==0); // init blender domain transform matrix diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 6191ec9c035..d4de1386871 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -302,6 +302,9 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str) BLI_timestr(rs->lastframetime, info_time_str); spos+= sprintf(spos, "Time:%s ", info_time_str); + if(rs->curfsa) + spos+= sprintf(spos, "| Full Sample %d ", rs->curfsa); + if(rs->infostr && rs->infostr[0]) spos+= sprintf(spos, "| %s ", rs->infostr); 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 f454dd9ce02..68326edfb11 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -627,6 +627,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 */ @@ -637,6 +644,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; @@ -759,6 +767,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; } @@ -868,13 +877,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) @@ -933,6 +943,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); @@ -950,8 +961,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; } } } @@ -1165,6 +1176,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 */ @@ -1175,7 +1187,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"); @@ -1491,6 +1503,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; @@ -1628,7 +1641,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); @@ -1643,11 +1656,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); @@ -1684,6 +1703,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) { @@ -1694,6 +1720,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; @@ -2248,8 +2275,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); @@ -2433,13 +2461,7 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot) static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) { - wmWindowManager *wm= CTX_wm_manager(C); - wmOperator *lastop; - - /* only for operators that are registered and did an undo push */ - for(lastop= wm->operators.last; lastop; lastop= lastop->prev) - if((lastop->type->flag & OPTYPE_REGISTER) && (lastop->type->flag & OPTYPE_UNDO)) - break; + wmOperator *lastop= WM_operator_last_redo(C); if(lastop) WM_operator_redo_popup(C, lastop); @@ -3044,6 +3066,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; @@ -3314,6 +3337,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); } @@ -3422,9 +3446,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 db0d2314ad0..cae5c14aa97 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -3692,14 +3692,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) { @@ -3736,6 +3748,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; @@ -3841,6 +3854,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; @@ -3871,7 +3885,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; } @@ -3987,7 +4001,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; @@ -4058,7 +4072,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]) @@ -4255,8 +4268,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 @@ -4409,7 +4422,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; @@ -4863,12 +4876,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(); @@ -4888,8 +4896,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 @@ -4908,8 +4916,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); @@ -5012,31 +5020,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 c35b742eb9e..3da19ba7346 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1600,6 +1600,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) { @@ -1612,6 +1619,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; @@ -1892,6 +1900,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 */ @@ -1903,6 +1918,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 20e74702067..be985342ea8 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -3559,6 +3559,24 @@ static int sculpt_brush_stroke_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int sculpt_brush_stroke_cancel(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[] = { @@ -3577,6 +3595,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_cancel; /* 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 8d8cdcc7183..4f8cb8a57b2 100644 --- a/source/blender/editors/space_api/spacetypes.c +++ b/source/blender/editors/space_api/spacetypes.c @@ -70,6 +70,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_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index bf5df87610c..905fed4f30b 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -83,11 +83,13 @@ typedef struct ConsoleDrawContext { int console_width; int winx; int ymin, ymax; +#if 0 /* used by textview, may use later */ int *xy; // [2] int *sel; // [2] int *pos_pick; // bottom of view == 0, top of file == combine chars, end of line is lower then start. int *mval; // [2] int draw; +#endif } ConsoleDrawContext; void console_scrollback_prompt_begin(struct SpaceConsole *sc, ConsoleLine *cl_dummy) 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..0210b0dd78d 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); } @@ -662,7 +662,6 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char block= uiLayoutGetBlock(layout); - imaptr= RNA_property_pointer_get(ptr, prop); ima= imaptr.data; iuser= userptr->data; @@ -719,21 +718,17 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char } } else { - row= uiLayoutRow(layout, 0); - uiItemR(row, &imaptr, "source", 0, NULL, ICON_NONE); + uiItemR(layout, &imaptr, "source", 0, NULL, ICON_NONE); if(ima->source != IMA_SRC_GENERATED) { row= uiLayoutRow(layout, 1); - split = uiLayoutSplit(row, 0.0, 0); if (ima->packedfile) - uiItemO(split, "", ICON_PACKAGE, "image.unpack"); + uiItemO(row, "", ICON_PACKAGE, "image.unpack"); else - uiItemO(split, "", ICON_UGLYPACKAGE, "image.pack"); + uiItemO(row, "", ICON_UGLYPACKAGE, "image.pack"); - split = uiLayoutSplit(row, 0.0, 0); - row= uiLayoutRow(split, 1); + row= uiLayoutRow(row, 0); uiLayoutSetEnabled(row, ima->packedfile==NULL); - uiItemR(row, &imaptr, "filepath", 0, "", ICON_NONE); uiItemO(row, "", ICON_FILE_REFRESH, "image.reload"); } @@ -771,11 +766,10 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char col= uiLayoutColumn(split, 0); uiItemR(col, &imaptr, "use_fields", 0, NULL, ICON_NONE); row= uiLayoutRow(col, 0); - uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE); uiLayoutSetActive(row, RNA_boolean_get(&imaptr, "use_fields")); - - col= uiLayoutColumn(split, 0); - uiItemR(col, &imaptr, "use_premultiply", 0, NULL, ICON_NONE); + uiItemR(row, &imaptr, "field_order", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + + uiItemR(split, &imaptr, "use_premultiply", 0, NULL, ICON_NONE); } } @@ -787,10 +781,9 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char col= uiLayoutColumn(split, 0); sprintf(str, "(%d) Frames", iuser->framenr); - row= uiLayoutRow(col, 1); uiItemR(col, userptr, "frame_duration", 0, str, ICON_NONE); if(ima->anim) { - block= uiLayoutGetBlock(row); + block= uiLayoutGetBlock(col); but= uiDefBut(block, BUT, 0, "Match Movie Length", 0, 0, UI_UNIT_X*2, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Set the number of frames to match the movie or sequence."); uiButSetFunc(but, set_frames_cb, ima, iuser); } @@ -810,8 +803,7 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiItemR(col, &imaptr, "generated_width", 0, "X", ICON_NONE); uiItemR(col, &imaptr, "generated_height", 0, "Y", ICON_NONE); - col= uiLayoutColumn(split, 0); - uiItemR(col, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(split, &imaptr, "generated_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); } } 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_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index 0cbc67a3504..a45e7d39c76 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -3785,6 +3785,8 @@ static void draw_actuator_camera(uiLayout *layout, PointerRNA *ptr) row = uiLayoutRow(layout, 1); uiItemR(row, ptr, "min", 0, NULL, ICON_NONE); uiItemR(row, ptr, "max", 0, NULL, ICON_NONE); + + uiItemR(layout, ptr, "damping", 0, NULL, ICON_NONE); } static void draw_actuator_constraint(uiLayout *layout, PointerRNA *ptr, bContext *C) 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..e539334c282 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; @@ -1358,10 +1366,17 @@ static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event) UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->mx, &snode->my); - /* rect we're interested in is just the bottom right corner */ totr= node->totr; - totr.xmin= totr.xmax-10.0f; - totr.ymax= totr.ymin+10.0f; + + if(node->flag & NODE_HIDDEN) { + /* right part of node */ + totr.xmin= node->totr.xmax-20.0f; + } + else { + /* bottom right corner */ + totr.xmin= totr.xmax-10.0f; + totr.ymax= totr.ymin+10.0f; + } if(BLI_in_rctf(&totr, snode->mx, snode->my)) { NodeSizeWidget *nsw= MEM_callocN(sizeof(NodeSizeWidget), "size widget op data"); @@ -1384,6 +1399,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 +1417,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 +2303,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 +2326,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 +2439,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..bd2d591a8c8 100644 --- a/source/blender/editors/space_outliner/outliner.c +++ b/source/blender/editors/space_outliner/outliner.c @@ -57,6 +57,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_math_base.h" #if defined WIN32 && !defined _LIBC # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ @@ -106,21 +107,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 +257,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 +294,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; } } @@ -440,7 +437,7 @@ static void outliner_sort(SpaceOops *soops, ListBase *lb) static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *idv, TreeElement *parent, short type, short index); -#define LOG2I(x) (int)(log(x)/log(2.0)) +#define LOG2I(x) (int)(log(x)/M_LN2) static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, SceneRenderLayer *srl) { @@ -2485,13 +2482,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 +2507,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 +2594,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 +2628,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 +2693,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 +2858,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 +2873,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 +3728,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 +4306,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 +4572,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 +4589,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 +4623,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 +4632,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 +4711,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 +4723,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 +4760,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 +4773,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 +4792,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 +4820,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 +4834,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 +4850,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 +4871,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 +4891,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 +4922,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 +4940,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 +5228,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 +5238,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 +5262,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 +5280,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 +5293,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 +5310,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 +5323,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 +5335,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 +5380,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 +5447,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 +5586,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 +5600,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 +5608,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 +5665,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 +5682,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 +5719,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..c8965c4d3db 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -124,7 +124,7 @@ typedef struct TransSeq { int startstill, endstill; int startdisp, enddisp; int startofs, endofs; - int final_left, final_right; + /* int final_left, final_right; */ /* UNUSED */ int len; } TransSeq; @@ -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 391eecbbbae..35edd961b1e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -5812,7 +5812,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 fb67e38cbf7..6833dec2e43 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 fce23df3810..75c8d5cae73 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -445,9 +445,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"); BKE_mesh_end_editmesh(obedit->data, em); } @@ -485,7 +485,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 */ @@ -508,10 +508,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"); } */ @@ -522,9 +522,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) { @@ -532,7 +532,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 fb3c0a63b7d..9290e1fc631 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -485,11 +485,8 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, if (extend == 0 && select) EM_deselect_all(vc->em); - /* 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= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax); @@ -497,15 +494,13 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, if(ts->selectmode & SCE_SELECT_VERTEX) { if (bbsel) { EM_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); @@ -518,8 +513,8 @@ static void do_lasso_select_mesh(ViewContext *vc, int mcords[][2], short moves, if(ts->selectmode & SCE_SELECT_FACE) { if (bbsel) { EM_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); } } @@ -875,6 +870,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; @@ -1490,12 +1486,8 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten if (extend == 0 && select) EM_deselect_all(vc->em); - /* 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= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax); @@ -1504,7 +1496,6 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten if (bbsel) { EM_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); } } @@ -1524,7 +1515,6 @@ static int do_mesh_box_select(ViewContext *vc, rcti *rect, int select, int exten if(bbsel) { EM_backbuf_checkAndSelectFaces(vc->em, select); } else { - ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data); } } @@ -1829,6 +1819,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; @@ -2308,6 +2299,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 0c4ab161e71..aadb355f743 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1560,7 +1560,7 @@ static void restore_localviewdata(ScrArea *sa, int free) } } -static void endlocalview(Scene *scene, ScrArea *sa) +static void endlocalview(Main *bmain, Scene *scene, ScrArea *sa) { View3D *v3d= sa->spacedata.first; struct Base *base; @@ -1586,6 +1586,8 @@ static void endlocalview(Scene *scene, ScrArea *sa) base->object->lay= base->lay; } } + + DAG_on_visible_update(bmain, FALSE); } } @@ -1594,7 +1596,7 @@ static int localview_exec(bContext *C, wmOperator *UNUSED(unused)) View3D *v3d= CTX_wm_view3d(C); if(v3d->localvd) - endlocalview(CTX_data_scene(C), CTX_wm_area(C)); + endlocalview(CTX_data_main(C), CTX_data_scene(C), CTX_wm_area(C)); else initlocalview(CTX_data_main(C), CTX_data_scene(C), CTX_wm_area(C)); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 0ce21c2efee..b8369d8cbff 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -4879,8 +4879,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]; @@ -5006,6 +5006,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]; @@ -5013,10 +5016,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 29fc514f01f..e0250829a66 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -4022,6 +4022,7 @@ static void freeSeqData(TransInfo *t) } if(overlap) { + int has_effect= 0; for(seq= seqbasep->first; seq; seq= seq->next) seq->tmp= NULL; @@ -4030,12 +4031,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/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 8699eb1cc2d..71ebe5e051c 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -675,8 +675,9 @@ void recalcData(TransInfo *t) EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh; /* mirror modifier clipping? */ if(t->state != TRANS_CANCEL) { - clipMirrorModifier(t, t->obedit); + /* apply clipping after so we never project past the clip plane [#25423] */ applyProject(t); + clipMirrorModifier(t, t->obedit); } if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR)) editmesh_apply_to_mirror(t); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 705fb83264c..3dd7514429e 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -106,10 +106,6 @@ void ED_editors_exit(bContext *C) if(sce->obedit) { Object *ob= sce->obedit; - /* global in meshtools... */ - mesh_octree_table(NULL, NULL, NULL, 'e'); - mesh_mirrtopo_table(NULL, 'e'); - if(ob) { if(ob->type==OB_MESH) { Mesh *me= ob->data; @@ -122,26 +118,13 @@ void ED_editors_exit(bContext *C) else if(ob->type==OB_ARMATURE) { ED_armature_edit_free(ob); } - else if(ob->type==OB_FONT) { - // free_editText(); - } - // else if(ob->type==OB_MBALL) - // BLI_freelistN(&editelems); - // free_editLatt(); - // free_posebuf(); // XXX this is still a global... - } - } - else if(sce->basact && sce->basact->object) { - Object *ob= sce->basact->object; - - /* if weight-painting is on, free mesh octree data */ - if(ob->mode & OB_MODE_WEIGHT_PAINT) { - mesh_octree_table(NULL, NULL, NULL, 'e'); - mesh_mirrtopo_table(NULL, 'e'); } } } - + + /* global in meshtools... */ + mesh_octree_table(NULL, NULL, NULL, 'e'); + mesh_mirrtopo_table(NULL, 'e'); } diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index 732e5087af2..bcbc134d06d 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..8a6ec7f75db 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); @@ -151,11 +156,11 @@ static int ed_undo_step(bContext *C, int step, const char *undoname) int do_glob_undo= 0; if(obact && obact->mode & OB_MODE_TEXTURE_PAINT) { - if(!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname) && undoname) + if(!ED_undo_paint_step(C, UNDO_PAINT_IMAGE, step, undoname)) do_glob_undo= 1; } else if(obact && obact->mode & OB_MODE_SCULPT) { - if(!ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname) && undoname) + if(!ED_undo_paint_step(C, UNDO_PAINT_MESH, step, undoname)) do_glob_undo= 1; } else if(obact && obact->mode & OB_MODE_PARTICLE_EDIT) { @@ -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 66b1e7d412b..c09f8cff02d 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2221,6 +2221,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; @@ -2310,6 +2311,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/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_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h index 7951ebc8c99..b368aadf4c2 100644 --- a/source/blender/makesdna/DNA_actuator_types.h +++ b/source/blender/makesdna/DNA_actuator_types.h @@ -135,7 +135,7 @@ typedef struct bIpoActuator { typedef struct bCameraActuator { struct Object *ob; float height, min, max; - float pad; + float damping; short pad1, axis; float pad2; } bCameraActuator ; 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_object_fluidsim.h b/source/blender/makesdna/DNA_object_fluidsim.h index 6f4c16cb7f3..578bf8dd415 100644 --- a/source/blender/makesdna/DNA_object_fluidsim.h +++ b/source/blender/makesdna/DNA_object_fluidsim.h @@ -69,7 +69,7 @@ typedef struct FluidsimSettings { short viscosityMode; short viscosityExponent; /* gravity strength */ - float gravx,gravy,gravz; + float grav[3]; /* anim start end time (in seconds) */ float animStart, animEnd; /* bake start end time (in blender frames) */ @@ -161,6 +161,9 @@ typedef struct FluidsimSettings { #define OB_FSBND_FREESLIP (1<<(OB_TYPEFLAG_START+4)) #define OB_FSINFLOW_LOCALCOORD (1<<(OB_TYPEFLAG_START+5)) +/* surface generation flag (part of enabling chapter 6 of "Free Surface Flows with Moving and Deforming Objects for LBM") */ +#define OB_FSSG_NOOBS (1<<(OB_TYPEFLAG_START+6)) + // guiDisplayMode particle flags #define OB_FSDOM_GEOM 1 #define OB_FSDOM_PREVIEW 2 diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 657bfb1c884..c6fa07482c5 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -253,19 +253,12 @@ typedef struct RenderData { */ short yparts; - short winpos, planes, imtype, subimtype; - - /** Mode bits: */ - /* 0: Enable backbuffering for images */ - short bufflag; - short quality; + short planes, imtype, subimtype, quality; /** * Render to image editor, fullscreen or to new window. */ short displaymode; - - short rpad1, rpad2; /** * Flags for render settings. Use bit-masking to access the settings. @@ -322,11 +315,7 @@ typedef struct RenderData { /** * Adjustment factors for the aspect ratio in the x direction, was a short in 2.45 */ - float xasp; - /** - * Adjustment factors for the aspect ratio in the x direction, was a short in 2.45 - */ - float yasp; + float xasp, yasp; float frs_sec_base; @@ -349,8 +338,8 @@ typedef struct RenderData { short bake_normal_space, bake_quad_split; float bake_maxdist, bake_biasdist, bake_pad; - /* paths to backbufffer, output */ - char backbuf[160], pic[160]; + /* path to render output */ + char pic[240]; /* stamps flags. */ int stamp; @@ -1009,13 +998,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 a7a04384d3c..cf416bf9d5b 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -305,7 +305,7 @@ typedef struct UserDef { int savetime; char tempdir[160]; // FILE_MAXDIR length char fontdir[160]; - char renderdir[160]; + char renderdir[240]; // FILE_MAX length char textudir[160]; char plugtexdir[160]; char plugseqdir[160]; @@ -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 cc18d8d9d0d..91f88a26987 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 656dbc53656..75c884a5fbb 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -927,6 +927,13 @@ static void rna_def_camera_actuator(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Max", ""); RNA_def_property_update(prop, NC_LOGIC, NULL); + prop= RNA_def_property(srna, "damping", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "damping"); + RNA_def_property_range(prop, 0, 10.0); + RNA_def_property_ui_range(prop, 0, 5.0, 1, 2); + RNA_def_property_ui_text(prop, "Damping", "Specify the strength of the constraint that drive the camera behind the target"); + RNA_def_property_update(prop, NC_LOGIC, NULL); + /* x/y */ prop= RNA_def_property(srna, "axis", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "axis"); diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 1705e2e5376..37912f810fc 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -133,7 +133,7 @@ void RNA_def_camera(BlenderRNA *brna) prop= RNA_def_property(srna, "ortho_scale", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "ortho_scale"); - RNA_def_property_range(prop, 0.01f, 1000.0f); + RNA_def_property_range(prop, 0.01f, 4000.0f); RNA_def_property_ui_text(prop, "Orthographic Scale", "Orthographic Camera scale (similar to zoom)"); RNA_def_property_update(prop, NC_OBJECT|ND_DRAW, NULL); diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c index 92c762098c7..db5409bf7ef 100644 --- a/source/blender/makesrna/intern/rna_controller.c +++ b/source/blender/makesrna/intern/rna_controller.c @@ -87,6 +87,20 @@ static void rna_Controller_type_set(struct PointerRNA *ptr, int value) } } +static void rna_Controller_mode_set(struct PointerRNA *ptr, int value) +{ + bController *cont= (bController *)ptr->data; + bPythonCont *pycon= (bPythonCont *)cont->data; + + // if mode changed and previous mode were Script + if (value != pycon->mode && pycon->mode == CONT_PY_SCRIPT) + { + // clear script to avoid it to get linked with the controller + pycon->text = NULL; + } + pycon->mode = value; +} + static int rna_Controller_state_number_get(struct PointerRNA *ptr) { bController *cont= (bController *)ptr->data; @@ -222,6 +236,7 @@ void RNA_def_controller(BlenderRNA *brna) prop= RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, python_controller_modes); + RNA_def_property_enum_funcs(prop, NULL, "rna_Controller_mode_set", NULL); RNA_def_property_ui_text(prop, "Execution Method", "Python script type (textblock or module - faster)"); 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_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 7c93ae4168b..1ba2e32502f 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -312,7 +312,7 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna) /* advanced settings */ prop= RNA_def_property(srna, "gravity", PROP_FLOAT, PROP_ACCELERATION); - RNA_def_property_float_sdna(prop, NULL, "gravx"); + RNA_def_property_float_sdna(prop, NULL, "grav"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1000.1, 1000.1); RNA_def_property_ui_text(prop, "Gravity", "Gravity in X, Y and Z direction"); @@ -384,6 +384,12 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Generate Speed Vectors", "Generate speed vectors for vector blur"); + /* no collision object surface */ + prop= RNA_def_property(srna, "surface_noobs", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "typeFlags", OB_FSSG_NOOBS); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_text(prop, "Hide fluid surface", ""); + /* particles */ prop= RNA_def_property(srna, "tracer_particles", PROP_INT, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index a5097cc8b41..5d71d204a72 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -95,7 +95,7 @@ static void rna_def_group_objects(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_ui_description(func, "Add this object to a group"); /* object to add */ parm= RNA_def_pointer(func, "object", "Object", "", "Object to add."); - RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL); /* remove object */ func= RNA_def_function(srna, "unlink", "rna_Group_objects_unlink"); 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 2d3c3fe7a3a..479e449958b 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -40,6 +40,9 @@ #include "WM_types.h" +#include "BLI_math_base.h" +#include "BLI_math_rotation.h" + #ifdef RNA_RUNTIME #include "DNA_scene_types.h" @@ -912,6 +915,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; @@ -1913,9 +1930,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 75f3f1ef238..ff277b6d9b0 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -578,6 +578,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[]) @@ -1365,10 +1393,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, 180); RNA_def_property_ui_range(prop, 0, 180, 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"); @@ -1965,10 +1999,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 9305380d06c..8ee8652e2e5 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -454,6 +454,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; @@ -1236,6 +1244,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 72ec09a61fe..145a58ecf0f 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -2812,6 +2812,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 4171189d928..8c4e4d9e736 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -680,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) @@ -1460,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_texture.c b/source/blender/makesrna/intern/rna_texture.c index 3a80207ba15..9e3a31ddb2e 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -135,6 +135,7 @@ static void rna_Texture_update(Main *bmain, Scene *scene, PointerRNA *ptr) DAG_id_tag_update(&tex->id, 0); WM_main_add_notifier(NC_TEXTURE, tex); + WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, NULL); } static void rna_Texture_voxeldata_update(Main *bmain, Scene *scene, PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 12df0b5dbd7..cb50b99c05d 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; @@ -238,6 +245,13 @@ static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRN static void rna_UserDef_viewport_lights_update(Main *bmain, Scene *scene, PointerRNA *ptr) { + /* if all lights are off gpu_draw resets them all, [#27627] + * so disallow them all to be disabled */ + if(U.light[0].flag==0 && U.light[1].flag==0 && U.light[2].flag==0) { + SolidLight *light= ptr->data; + light->flag |= 1; + } + WM_main_add_notifier(NC_SPACE|ND_SPACE_VIEW3D|NS_VIEW3D_GPU, NULL); rna_userdef_update(bmain, scene, ptr); } @@ -2444,7 +2458,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 cf66a27bda2..348e2a0ec1d 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -88,8 +88,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_explode.c b/source/blender/modifiers/intern/MOD_explode.c index f1bc0d33fd8..10bcbee6661 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -779,11 +779,11 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd, ParticleSettings *part=psmd->psys->part; ParticleSimulationData sim= {NULL}; ParticleData *pa=NULL, *pars=psmd->psys->particles; - ParticleKey state; + ParticleKey state, birth; EdgeHash *vertpahash; EdgeHashIterator *ehi; float *vertco= NULL, imat[4][4]; - float loc0[3], nor[3]; + float rot[4]; float cfra; /* float timestep; */ int *facepa=emd->facepa; @@ -814,7 +814,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd, for (i=0; i<totface; i++) { /* do mindex + totvert to ensure the vertex index to be the first * with BLI_edgehashIterator_getKey */ - if(facepa[i]==totpart || cfra <= (pars+facepa[i])->time) + if(facepa[i]==totpart || cfra < (pars+facepa[i])->time) mindex = totvert+totpart; else mindex = totvert+facepa[i]; @@ -868,26 +868,26 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd, /* get particle */ pa= pars+i; - /* get particle state */ - psys_particle_on_emitter(psmd,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,loc0,nor,NULL,NULL,NULL,NULL); - mul_m4_v3(ob->obmat,loc0); + psys_get_birth_coordinates(&sim, pa, &birth, 0, 0); state.time=cfra; psys_get_particle_state(&sim, i, &state, 1); vertco=CDDM_get_vert(explode,v)->co; - mul_m4_v3(ob->obmat,vertco); - VECSUB(vertco,vertco,loc0); + sub_v3_v3(vertco, birth.co); /* apply rotation, size & location */ - mul_qt_v3(state.rot,vertco); + sub_qt_qtqt(rot, state.rot, birth.rot); + mul_qt_v3(rot, vertco); + if(emd->flag & eExplodeFlag_PaSize) mul_v3_fl(vertco,pa->size); - VECADD(vertco,vertco,state.co); - mul_m4_v3(imat,vertco); + add_v3_v3(vertco, state.co); + + mul_m4_v3(imat, vertco); } } BLI_edgehashIterator_free(ehi); @@ -911,7 +911,7 @@ static DerivedMesh * explodeMesh(ExplodeModifierData *emd, orig_v4 = source.v4; - if(facepa[i]!=totpart && cfra <= pa->time) + if(facepa[i]!=totpart && cfra < pa->time) mindex = totvert+totpart; else mindex = totvert+facepa[i]; diff --git a/source/blender/modifiers/intern/MOD_fluidsim_util.c b/source/blender/modifiers/intern/MOD_fluidsim_util.c index 61345427d1c..277f0852f90 100644 --- a/source/blender/modifiers/intern/MOD_fluidsim_util.c +++ b/source/blender/modifiers/intern/MOD_fluidsim_util.c @@ -90,10 +90,10 @@ void fluidsim_init(FluidsimModifierData *fluidmd) fss->viscosityValue = 1.0; fss->viscosityExponent = 6; - // dg TODO: change this to [] - fss->gravx = 0.0; - fss->gravy = 0.0; - fss->gravz = -9.81; + fss->grav[0] = 0.0; + fss->grav[1] = 0.0; + fss->grav[2] = -9.81; + fss->animStart = 0.0; fss->animEnd = 4.0; fss->gstar = 0.005; // used as normgstar @@ -111,7 +111,7 @@ void fluidsim_init(FluidsimModifierData *fluidmd) // no bounding box needed // todo - reuse default init from elbeem! - fss->typeFlags = OB_FSBND_PARTSLIP; + fss->typeFlags = OB_FSBND_PARTSLIP | OB_FSSG_NOOBS; fss->domainNovecgen = 0; fss->volumeInitType = 1; // volume fss->partSlipValue = 0.2; diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index b36d6848533..94442d96367 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -45,6 +45,7 @@ #include "DNA_modifier_types.h" #include "DNA_object_types.h" +#include "BKE_action.h" /* get_pose_channel */ #include "BKE_cdderivedmesh.h" #include "BKE_mesh.h" #include "BKE_modifier.h" @@ -102,7 +103,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *dm= derivedData, *result= NULL; GHash *vertHash=NULL, *edgeHash, *faceHash; GHashIterator *hashIter; - MDeformVert *dvert= NULL; + MDeformVert *dvert= NULL, *dv; int numFaces=0, numEdges=0, numVerts=0; int maxVerts, maxEdges, maxFaces; int i; @@ -130,50 +131,46 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* if mode is to use selected armature bones, aggregate the bone groups */ if (mmd->mode == MOD_MASK_MODE_ARM) /* --- using selected bones --- */ { - GHash *vgroupHash, *boneHash; + GHash *vgroupHash; Object *oba= mmd->ob_arm; bPoseChannel *pchan; bDeformGroup *def; + char *bone_select_array; + int bone_select_tot= 0; /* check that there is armature object with bones to use, otherwise return original mesh */ - if (ELEM(NULL, mmd->ob_arm, mmd->ob_arm->pose)) - return derivedData; - + if (ELEM3(NULL, mmd->ob_arm, mmd->ob_arm->pose, ob->defbase.first)) + return derivedData; + + bone_select_array= MEM_mallocN(BLI_countlist(&ob->defbase) * sizeof(char), "mask array"); + + for (i = 0, def = ob->defbase.first; def; def = def->next, i++) + { + if (((pchan= get_pose_channel(oba->pose, def->name)) && pchan->bone && (pchan->bone->flag & BONE_SELECTED))) + { + bone_select_array[i]= TRUE; + bone_select_tot++; + } + else { + bone_select_array[i]= FALSE; + } + } + /* hashes for finding mapping of: * - vgroups to indices -> vgroupHash (string, int) * - bones to vgroup indices -> boneHash (index of vgroup, dummy) */ vgroupHash= BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, "mask vgroup gh"); - boneHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask bone gh"); /* build mapping of names of vertex groups to indices */ for (i = 0, def = ob->defbase.first; def; def = def->next, i++) BLI_ghash_insert(vgroupHash, def->name, SET_INT_IN_POINTER(i)); - /* get selected-posechannel <-> vertexgroup index mapping */ - for (pchan= oba->pose->chanbase.first; pchan; pchan= pchan->next) - { - /* check if bone is selected */ - // TODO: include checks for visibility too? - // FIXME: the depsgraph needs extensions to make this work in realtime... - if ( (pchan->bone) && (pchan->bone->flag & BONE_SELECTED) ) - { - /* check if hash has group for this bone */ - if (BLI_ghash_haskey(vgroupHash, pchan->name)) - { - int defgrp_index= GET_INT_FROM_POINTER(BLI_ghash_lookup(vgroupHash, pchan->name)); - - /* add index to hash (store under key only) */ - BLI_ghash_insert(boneHash, SET_INT_IN_POINTER(defgrp_index), pchan); - } - } - } - /* if no bones selected, free hashes and return original mesh */ - if (BLI_ghash_size(boneHash) == 0) + if (bone_select_tot == 0) { BLI_ghash_free(vgroupHash, NULL, NULL); - BLI_ghash_free(boneHash, NULL, NULL); + MEM_freeN(bone_select_array); return derivedData; } @@ -183,7 +180,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (dvert == NULL) { BLI_ghash_free(vgroupHash, NULL, NULL); - BLI_ghash_free(boneHash, NULL, NULL); + MEM_freeN(bone_select_array); return derivedData; } @@ -192,28 +189,29 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert gh"); /* add vertices which exist in vertexgroups into vertHash for filtering */ - for (i = 0; i < maxVerts; i++) + for (i= 0, dv= dvert; i < maxVerts; i++, dv++) { - MDeformWeight *def_weight = NULL; + MDeformWeight *dw= dv->dw; int j; - - for (j= 0; j < dvert[i].totweight; j++) + + for (j= dv->totweight; j > 0; j--, dw++) { - if (BLI_ghash_haskey(boneHash, SET_INT_IN_POINTER(dvert[i].dw[j].def_nr))) + if (bone_select_array[dw->def_nr]) { - def_weight = &dvert[i].dw[j]; - break; + if(dw->weight != 0.0f) { + break; + } } } /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ - if (def_weight) continue; + if (dw) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ - if (!def_weight) continue; + if (!dw) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ @@ -223,7 +221,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* free temp hashes */ BLI_ghash_free(vgroupHash, NULL, NULL); - BLI_ghash_free(boneHash, NULL, NULL); + MEM_freeN(bone_select_array); } else /* --- Using Nominated VertexGroup only --- */ { @@ -241,28 +239,18 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, vertHash= BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, "mask vert2 bh"); /* add vertices which exist in vertexgroup into ghash for filtering */ - for (i = 0; i < maxVerts; i++) + for (i= 0, dv= dvert; i < maxVerts; i++, dv++) { - MDeformWeight *def_weight = NULL; - int j; - - for (j= 0; j < dvert[i].totweight; j++) - { - if (dvert[i].dw[j].def_nr == defgrp_index) - { - def_weight = &dvert[i].dw[j]; - break; - } - } + const int weight_set= defvert_find_weight(dv, defgrp_index) != 0.0f; /* check if include vert in vertHash */ if (mmd->flag & MOD_MASK_INV) { /* if this vert is in the vgroup, don't include it in vertHash */ - if (def_weight) continue; + if (weight_set) continue; } else { /* if this vert isn't in the vgroup, don't include it in vertHash */ - if (!def_weight) continue; + if (!weight_set) continue; } /* add to ghash for verts (numVerts acts as counter for mapping) */ diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index ba73f3fa0d1..5021f3a6d2e 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -72,6 +72,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/nodes/intern/SHD_nodes/SHD_material.c b/source/blender/nodes/intern/SHD_nodes/SHD_material.c index 8b477af0689..f66df9bba90 100644 --- a/source/blender/nodes/intern/SHD_nodes/SHD_material.c +++ b/source/blender/nodes/intern/SHD_nodes/SHD_material.c @@ -209,6 +209,17 @@ static void node_shader_init_material(bNode* node) node->custom1= SH_NODE_MAT_DIFF|SH_NODE_MAT_SPEC; } +/* XXX this is also done as a local static function in gpu_codegen.c, + * but we need this to hack around the crappy material node. + */ +static GPUNodeLink *gpu_get_input_link(GPUNodeStack *in) +{ + if (in->link) + return in->link; + else + return GPU_uniform(in->vec); +} + static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *out) { if(node->id) { @@ -229,18 +240,18 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, /* write values */ if(hasinput[MAT_IN_COLOR]) - shi.rgb = in[MAT_IN_COLOR].link; + shi.rgb = gpu_get_input_link(&in[MAT_IN_COLOR]); if(hasinput[MAT_IN_SPEC]) - shi.specrgb = in[MAT_IN_SPEC].link; + shi.specrgb = gpu_get_input_link(&in[MAT_IN_SPEC]); if(hasinput[MAT_IN_REFL]) - shi.refl = in[MAT_IN_REFL].link; + shi.refl = gpu_get_input_link(&in[MAT_IN_REFL]); /* retrieve normal */ if(hasinput[MAT_IN_NORMAL]) { GPUNodeLink *tmp; - shi.vn = in[MAT_IN_NORMAL].link; + shi.vn = gpu_get_input_link(&in[MAT_IN_NORMAL]); GPU_link(mat, "vec_math_normalize", shi.vn, &shi.vn, &tmp); } @@ -250,11 +261,11 @@ static int gpu_shader_material(GPUMaterial *mat, bNode *node, GPUNodeStack *in, if (node->type == SH_NODE_MATERIAL_EXT) { if(hasinput[MAT_IN_AMB]) - shi.amb= in[MAT_IN_AMB].link; + shi.amb= gpu_get_input_link(&in[MAT_IN_AMB]); if(hasinput[MAT_IN_EMIT]) - shi.emit= in[MAT_IN_EMIT].link; + shi.emit= gpu_get_input_link(&in[MAT_IN_EMIT]); if(hasinput[MAT_IN_ALPHA]) - shi.alpha= in[MAT_IN_ALPHA].link; + shi.alpha= gpu_get_input_link(&in[MAT_IN_ALPHA]); } GPU_shaderesult_set(&shi, &shr); /* clears shr */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 6f124d959cb..dec393bd1e4 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -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_props.c b/source/blender/python/intern/bpy_props.c index 4fef084f093..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,6 +839,7 @@ 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; @@ -803,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 */ @@ -857,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; } @@ -878,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" @@ -888,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" @@ -897,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) { @@ -905,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; @@ -916,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); @@ -975,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) { @@ -1017,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" @@ -1025,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) { @@ -1035,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; @@ -1043,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; } @@ -1059,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; @@ -1078,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) diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 4fe13bc6818..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); diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index dbb5fc2feb7..5db352af53d 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -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/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 47230ab3089..23f301249ba 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -146,7 +146,7 @@ typedef struct RenderResult { typedef struct RenderStats { int cfra; int totface, totvert, totstrand, tothalo, totlamp, totpart; - short curfield, curblur, curpart, partsdone, convertdone; + short curfield, curblur, curpart, partsdone, convertdone, curfsa; double starttime, lastframetime; const char *infostr, *statstr; char scenename[32]; diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index cf16211b6d1..b2535ebc9ea 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -214,7 +214,7 @@ struct Render ListBase instancetable; int totinstance; - struct Image *backbuf, *bakebuf; + struct Image *bakebuf; struct GHash *orco_hash; diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c1c2fb60abd..15fc9d38c01 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4665,7 +4665,6 @@ void RE_Database_Free(Render *re) re->totvlak=re->totvert=re->totstrand=re->totlamp=re->tothalo= 0; re->i.convertdone= 0; - re->backbuf= NULL; re->bakebuf= NULL; if(re->scene) diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 1e40ab886ae..e2ab21ef877 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -149,7 +149,6 @@ static Render *envmap_render_copy(Render *re, EnvMap *env) envre->r.layers.first= envre->r.layers.last= NULL; envre->r.filtertype= 0; envre->r.xparts= envre->r.yparts= 2; - envre->r.bufflag= 0; envre->r.size= 100; envre->r.yasp= envre->r.xasp= 1; diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 7d2c7b35247..cb08ae96bf7 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -76,6 +76,8 @@ extern struct Render R; /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +static void boxsample(ImBuf *ibuf, float minx, float miny, float maxx, float maxy, TexResult *texres, int imaprepeat, int imapextend); + /* *********** IMAGEWRAPPING ****************** */ @@ -201,7 +203,16 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, float *texvec, TexResult *texre ibuf->rect+= (ibuf->x*ibuf->y); } - ibuf_get_color(&texres->tr, ibuf, x, y); + /* interpolate */ + if (tex->imaflag & TEX_INTERPOL) { + float filterx, filtery; + filterx = (0.5f * tex->filtersize) / ibuf->x; + filtery = (0.5f * tex->filtersize) / ibuf->y; + + boxsample(ibuf, fx-filterx, fy-filtery, fx+filterx, fy+filtery, texres, (tex->extend==TEX_REPEAT), (tex->extend==TEX_EXTEND)); + } + else /* no filtering */ + ibuf_get_color(&texres->tr, ibuf, x, y); if( (R.flag & R_SEC_FIELD) && (ibuf->flags & IB_fields) ) { ibuf->rect-= (ibuf->x*ibuf->y); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 436f0ecd997..90f07586786 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2065,36 +2065,6 @@ static void do_render_fields_3d(Render *re) re->display_draw(re->ddh, re->result, NULL); } -static void load_backbuffer(Render *re) -{ - if(re->r.alphamode == R_ADDSKY) { - ImBuf *ibuf; - char name[256]; - - BLI_strncpy(name, re->r.backbuf, sizeof(name)); - BLI_path_abs(name, re->main->name); - BLI_path_frame(name, re->r.cfra, 0); - - if(re->backbuf) { - re->backbuf->id.us--; - if(re->backbuf->id.us<1) - BKE_image_signal(re->backbuf, NULL, IMA_SIGNAL_RELOAD); - } - - re->backbuf= BKE_add_image_file(name); - ibuf= BKE_image_get_ibuf(re->backbuf, NULL); - if(ibuf==NULL) { - // error() doesnt work with render window open - //error("No backbuf there!"); - printf("Error: No backbuf %s\n", name); - } - else { - if (re->r.mode & R_FIELDS) - image_de_interlace(re->backbuf, re->r.mode & R_ODDFIELD); - } - } -} - /* main render routine, no compositing */ static void do_render_fields_blur_3d(Render *re) { @@ -2105,10 +2075,6 @@ static void do_render_fields_blur_3d(Render *re) G.afbreek= 1; return; } - - /* backbuffer initialize */ - if(re->r.bufflag & 1) - load_backbuffer(re); /* now use renderdata and camera to set viewplane */ RE_SetCamera(re, camera); @@ -2203,6 +2169,24 @@ static void render_scene(Render *re, Scene *sce, int cfra) do_render_fields_blur_3d(resc); } +/* helper call to detect if this scene needs a render, or if there's a any render layer to render */ +static int composite_needs_render(Scene *sce, int this_scene) +{ + bNodeTree *ntree= sce->nodetree; + bNode *node; + + if(ntree==NULL) return 1; + if(sce->use_nodes==0) return 1; + if((sce->r.scemode & R_DOCOMP)==0) return 1; + + for(node= ntree->nodes.first; node; node= node->next) { + if(node->type==CMP_NODE_R_LAYERS) + if(this_scene==0 || node->id==NULL || node->id==&sce->id) + return 1; + } + return 0; +} + static void tag_scenes_for_render(Render *re) { bNode *node; @@ -2211,7 +2195,8 @@ static void tag_scenes_for_render(Render *re) for(sce= re->main->scene.first; sce; sce= sce->id.next) sce->id.flag &= ~LIB_DOIT; - re->scene->id.flag |= LIB_DOIT; + if(RE_GetCamera(re) && composite_needs_render(re->scene, 1)) + re->scene->id.flag |= LIB_DOIT; if(re->scene->nodetree==NULL) return; @@ -2258,24 +2243,6 @@ static void ntree_render_scenes(Render *re) set_scene_bg(re->main, re->scene); } -/* helper call to detect if theres a composite with render-result node */ -static int composite_needs_render(Scene *sce) -{ - bNodeTree *ntree= sce->nodetree; - bNode *node; - - if(ntree==NULL) return 1; - if(sce->use_nodes==0) return 1; - if((sce->r.scemode & R_DOCOMP)==0) return 1; - - for(node= ntree->nodes.first; node; node= node->next) { - if(node->type==CMP_NODE_R_LAYERS) - if(node->id==NULL || node->id==&sce->id) - return 1; - } - return 0; -} - /* bad call... need to think over proper method still */ static void render_composit_stats(void *UNUSED(arg), char *str) { @@ -2291,6 +2258,16 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) float *rectf, filt[3][3]; int sample; + /* interaction callbacks */ + if(ntree) { + ntree->stats_draw= render_composit_stats; + ntree->test_break= re->test_break; + ntree->progress= re->progress; + ntree->sdh= re->sdh; + ntree->tbh= re->tbh; + ntree->prh= re->prh; + } + /* filtmask needs it */ R= *re; @@ -2298,25 +2275,27 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) rectf= MEM_mapallocN(re->rectx*re->recty*sizeof(float)*4, "fullsample rgba"); for(sample=0; sample<re->r.osa; sample++) { + Render *re1; RenderResult rres; int x, y, mask; - /* set all involved renders on the samplebuffers (first was done by render itself) */ + /* enable full sample print */ + R.i.curfsa= sample+1; + + /* set all involved renders on the samplebuffers (first was done by render itself, but needs tagged) */ /* also function below assumes this */ - if(sample) { - Render *re1; - tag_scenes_for_render(re); - for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) { - if(re1->scene->id.flag & LIB_DOIT) { - if(re1->r.scemode & R_FULL_SAMPLE) { + tag_scenes_for_render(re); + for(re1= RenderGlobal.renderlist.first; re1; re1= re1->next) { + if(re1->scene->id.flag & LIB_DOIT) { + if(re1->r.scemode & R_FULL_SAMPLE) { + if(sample) read_render_result(re1, sample); - ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */ - } + ntreeCompositTagRender(re1->scene); /* ensure node gets exec to put buffers on stack */ } } } - + /* composite */ if(ntree) { ntreeCompositTagRender(re->scene); @@ -2359,6 +2338,17 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) break; } + /* clear interaction callbacks */ + if(ntree) { + ntree->stats_draw= NULL; + ntree->test_break= NULL; + ntree->progress= NULL; + ntree->tbh= ntree->sdh= ntree->prh= NULL; + } + + /* disable full sample print */ + R.i.curfsa= 0; + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); if(re->result->rectf) MEM_freeN(re->result->rectf); @@ -2398,8 +2388,10 @@ void RE_MergeFullSample(Render *re, Main *bmain, Scene *sce, bNodeTree *ntree) } /* own render result should be read/allocated */ - if(re->scene->id.flag & LIB_DOIT) + if(re->scene->id.flag & LIB_DOIT) { RE_ReadRenderResult(re->scene, re->scene); + re->scene->id.flag &= ~LIB_DOIT; + } /* and now we can draw (result is there) */ re->display_init(re->dih, re->result); @@ -2417,12 +2409,21 @@ static void do_render_composite_fields_blur_3d(Render *re) /* INIT seeding, compositor can use random texture */ BLI_srandom(re->r.cfra); - if(composite_needs_render(re->scene)) { + if(composite_needs_render(re->scene, 1)) { /* save memory... free all cached images */ ntreeFreeCache(ntree); do_render_fields_blur_3d(re); - } else { + } + else { + /* ensure new result gets added, like for regular renders */ + BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); + + RE_FreeRenderResult(re->result); + re->result= new_render_result(re, &re->disprect, 0, RR_USEMEM); + + BLI_rw_mutex_unlock(&re->resultmutex); + /* scene render process already updates animsys */ update_newframe = 1; } @@ -2758,7 +2759,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, void *erh, vo } if(scene->r.scemode & R_FULL_SAMPLE) { - if(composite_needs_render(scene)==0) { + if(composite_needs_render(scene, 0)==0) { error(erh, "Full Sample AA not supported without 3d rendering"); return 0; } diff --git a/source/blender/render/intern/source/pixelshading.c b/source/blender/render/intern/source/pixelshading.c index 2d42938f6ac..56a1c870904 100644 --- a/source/blender/render/intern/source/pixelshading.c +++ b/source/blender/render/intern/source/pixelshading.c @@ -502,21 +502,6 @@ int shadeHaloFloat(HaloRen *har, float *col, int zz, /* ------------------------------------------------------------------------- */ -static void fillBackgroundImage(float *collector, float fx, float fy) -{ - collector[0] = 0.0; - collector[1] = 0.0; - collector[2] = 0.0; - collector[3] = 0.0; - - if(R.backbuf) { - float dx= 1.0f/(float)R.winx; - float dy= 1.0f/(float)R.winy; - - image_sample(R.backbuf, fx*dx, fy*dy, dx, dy, collector); - } -} - /* Only view vector is important here. Result goes to colf[3] */ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short thread) { @@ -626,18 +611,14 @@ void shadeSkyPixel(float *collector, float fx, float fy, short thread) float fac; - /* 1. Do a backbuffer image: */ - if(R.r.bufflag & 1) { - fillBackgroundImage(collector, fx, fy); - } - else if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { - /* 2. solid color */ + if((R.wrld.skytype & (WO_SKYBLEND+WO_SKYTEX))==0) { + /* 1. solid color */ VECCOPY(collector, &R.wrld.horr); collector[3] = 0.0f; } else { - /* 3. */ + /* 2. */ /* This one true because of the context of this routine */ if(R.wrld.skytype & WO_SKYPAPER) { diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 5f5dab94ba3..c4587b83fcd 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -2192,6 +2192,7 @@ void do_material_tex(ShadeInput *shi) } } else if(mtex->texco==TEXCO_REFL) { + calc_R_ref(shi); co= shi->ref; dx= shi->dxref; dy= shi->dyref; } else if(mtex->texco==TEXCO_NORM) { @@ -2509,9 +2510,6 @@ void do_material_tex(ShadeInput *shi) shi->orn[0]= -shi->vn[0]; shi->orn[1]= -shi->vn[1]; shi->orn[2]= -shi->vn[2]; - - /* reflection vector */ - calc_R_ref(shi); } } 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/shadeinput.c b/source/blender/render/intern/source/shadeinput.c index 77141d9b445..e22ddd28dda 100644 --- a/source/blender/render/intern/source/shadeinput.c +++ b/source/blender/render/intern/source/shadeinput.c @@ -543,11 +543,6 @@ void shade_input_set_strand_texco(ShadeInput *shi, StrandRen *strand, StrandVert shi->orn[2]= -shi->vn[2]; } - if(texco & TEXCO_REFL) { - /* mirror reflection color textures (and envmap) */ - calc_R_ref(shi); /* wrong location for normal maps! XXXXXXXXXXXXXX */ - } - if(texco & TEXCO_STRESS) { /* not supported */ } @@ -1205,11 +1200,6 @@ void shade_input_set_shade_texco(ShadeInput *shi) shi->orn[2]= -shi->vn[2]; } - if(texco & TEXCO_REFL) { - /* mirror reflection color textures (and envmap) */ - calc_R_ref(shi); /* wrong location for normal maps! XXXXXXXXXXXXXX */ - } - if(texco & TEXCO_STRESS) { float *s1, *s2, *s3; diff --git a/source/blender/render/intern/source/sunsky.c b/source/blender/render/intern/source/sunsky.c index f645c29a7a5..5877fa42292 100644 --- a/source/blender/render/intern/source/sunsky.c +++ b/source/blender/render/intern/source/sunsky.c @@ -460,7 +460,7 @@ void AtmospherePixleShader( struct SunSky* sunSky, float view[3], float s, float vec3opv(sunSky->atm_BetaRM, sunSky->atm_BetaRay, +, sunSky->atm_BetaMie); //e^(-(beta_1 + beta_2) * s) = E1 - vec3opf(E1, sunSky->atm_BetaRM, *, -s/log(2)); + vec3opf(E1, sunSky->atm_BetaRM, *, -s/M_LN2); E1[0] = exp(E1[0]); E1[1] = exp(E1[1]); E1[2] = exp(E1[2]); 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 76ba298cd5f..0cf59a9b598 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -101,7 +101,6 @@ endif() if(WITH_PYTHON) list(APPEND INC ../python) - list(APPEND INC_SYS ${PYTHON_INCLUDE_DIRS}) add_definitions(-DWITH_PYTHON) if(WITH_PYTHON_SECURITY) @@ -115,7 +114,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 313e9357094..79ec0360ac6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -490,15 +490,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(); @@ -751,7 +752,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) { diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 2e4148ca51d..d57c94a5826 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -328,7 +328,6 @@ static void free_openrecent(void) /* bad stuff*/ -extern ListBase editelems; extern wchar_t *copybuf; extern wchar_t *copybufinfo; @@ -394,10 +393,6 @@ void WM_exit(bContext *C) free_anim_drivers_copybuf(); free_fmodifiers_copybuf(); free_posebuf(); -// free_vertexpaint(); -// free_imagepaint(); - -// fsmenu_free(); BLF_exit(); @@ -420,10 +415,6 @@ void WM_exit(bContext *C) BPY_python_end(); #endif - if (!G.background) { -// XXX UI_filelist_free_icons(); - } - GPU_buffer_pool_free(NULL); GPU_free_unused_buffers(); GPU_extensions_exit(); diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 34702558bc8..06d049d2cb5 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,12 +916,21 @@ 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); - uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + if(op->type->flag & OPTYPE_MACRO) { + for(op= op->macro.first; op; op= op->next) { + uiItemL(layout, op->type->name, ICON_NONE); + uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + } + } + else { + uiLayoutOperatorButs(C, layout, op, NULL, 'H', UI_LAYOUT_OP_SHOW_TITLE); + } + uiPopupBoundsBlock(block, 4, 0, 0); uiEndBlock(C, block); @@ -981,7 +990,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 +1096,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 +1194,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 +1286,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 +1322,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 +1401,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"); } @@ -1471,6 +1485,14 @@ static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED( { const char *openname= G.main->name; + if(CTX_wm_window(C) == NULL) { + /* in rare cases this could happen, when trying to invoke in background + * mode on load for example. Don't use poll for this because exec() + * can still run without a window */ + BKE_report(op->reports, RPT_ERROR, "Context window not set"); + return OPERATOR_CANCELLED; + } + /* if possible, get the name of the most recently used .blend file */ if (G.recent_files.first) { struct RecentFile *recent = G.recent_files.first; @@ -1521,7 +1543,7 @@ static void WM_OT_open_mainfile(wmOperatorType *ot) ot->invoke= wm_open_mainfile_invoke; ot->exec= wm_open_mainfile_exec; - ot->poll= WM_operator_winactive; + /* ommit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER, FILE_OPENFILE, WM_FILESEL_FILEPATH); @@ -1940,7 +1962,7 @@ static void WM_OT_save_mainfile(wmOperatorType *ot) ot->invoke= wm_save_mainfile_invoke; ot->exec= wm_save_as_mainfile_exec; ot->check= blend_save_check; - ot->poll= NULL; + /* ommit window poll so this can work in background mode */ WM_operator_properties_filesel(ot, FOLDERFILE|BLENDERFILE, FILE_BLENDER, FILE_SAVE, WM_FILESEL_FILEPATH); RNA_def_boolean(ot->srna, "compress", 0, "Compress", "Write compressed .blend file"); @@ -2244,6 +2266,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 +2369,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 +2592,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 +2727,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,10 +3117,31 @@ 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; - wmWindowManager *wm; float new_value, dist, zoom[2]; float delta[2], snap, ret = OPERATOR_RUNNING_MODAL; @@ -3125,23 +3203,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 +3216,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 { |