diff options
Diffstat (limited to 'source')
639 files changed, 17751 insertions, 12131 deletions
diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index fcc9526b58a..1b1ec1c08af 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -38,12 +38,15 @@ #include <stdio.h> #include <ctype.h> +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + #include "MEM_guardedalloc.h" #include "MEM_sys_types.h" -#ifdef WIN32 -# include "BLI_winstuff.h" -#endif +#include "BLI_utildefines.h" +#include "BLI_fileops.h" #include "AVI_avi.h" #include "avi_intern.h" @@ -208,7 +211,7 @@ int AVI_is_avi(char *name) FILE *fp; int ret; - fp = fopen(name, "rb"); + fp = BLI_fopen(name, "rb"); if (fp == NULL) return 0; @@ -238,7 +241,7 @@ int AVI_is_avi(const char *name) DEBUG_PRINT("opening movie\n"); movie.type = AVI_MOVIE_READ; - movie.fp = fopen(name, "rb"); + movie.fp = BLI_fopen(name, "rb"); movie.offset_table = NULL; if (movie.fp == NULL) @@ -404,7 +407,9 @@ int AVI_is_avi(const char *name) } if (j > 0) fseek(movie.fp, j, SEEK_CUR); } - else fseek(movie.fp, movie.streams[temp].sf_size, SEEK_CUR); + else { + fseek(movie.fp, movie.streams[temp].sf_size, SEEK_CUR); + } /* Walk to the next LIST */ while (GET_FCC(movie.fp) != FCC("LIST")) { @@ -439,7 +444,7 @@ AviError AVI_open_movie(const char *name, AviMovie *movie) memset(movie, 0, sizeof(AviMovie)); movie->type = AVI_MOVIE_READ; - movie->fp = fopen(name, "rb"); + movie->fp = BLI_fopen(name, "rb"); movie->offset_table = NULL; if (movie->fp == NULL) @@ -595,8 +600,10 @@ AviError AVI_open_movie(const char *name, AviMovie *movie) } if (j > 0) fseek(movie->fp, j, SEEK_CUR); } - else fseek(movie->fp, movie->streams[temp].sf_size, SEEK_CUR); - + else { + fseek(movie->fp, movie->streams[temp].sf_size, SEEK_CUR); + } + /* Walk to the next LIST */ while (GET_FCC(movie->fp) != FCC("LIST")) { temp = GET_FCC(movie->fp); @@ -761,7 +768,7 @@ AviError AVI_open_compress(char *name, AviMovie *movie, int streams, ...) int64_t junk_pos; movie->type = AVI_MOVIE_WRITE; - movie->fp = fopen(name, "wb"); + movie->fp = BLI_fopen(name, "wb"); movie->index_entries = 0; diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 0ca97975d87..fd8bd196717 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -77,6 +77,7 @@ void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t l /* Draw the string using the current font. */ void BLF_draw(int fontid, const char *str, size_t len); void BLF_draw_ascii(int fontid, const char *str, size_t len); +int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth); /* This function return the bounding box of the string * and are not multiplied by the aspect. diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index 197809426ae..c8d46503e26 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -68,6 +68,8 @@ struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void); unsigned char *BLF_get_unifont(int *unifont_size); void BLF_free_unifont(void); +unsigned char *BLF_get_unifont_mono(int *unifont_size); +void BLF_free_unifont_mono(void); const char *BLF_pgettext(const char *msgctxt, const char *msgid); @@ -108,12 +110,14 @@ const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); * All i18n contexts must be defined here. * This is a nice way to be sure not to use a context twice for different * things, and limit the number of existing contexts! + * WARNING! Contexts should not be longer than BKE_ST_MAXNAME - 1! */ /* Default, void context. * WARNING! The "" context is not the same as no (NULL) context at mo/boost::locale level! * NOTE: We translate BLF_I18NCONTEXT_DEFAULT as BLF_I18NCONTEXT_DEFAULT_BPY in Python, as we can't use "natural" * None value in rna string properties... :/ + * The void string "" is also interpreted as BLF_I18NCONTEXT_DEFAULT. * For perf reason, we only use the first char to detect this context, so other contexts should never start * with the same char! */ diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 061e8e28607..e7e277b7b34 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -576,6 +576,21 @@ void BLF_draw_ascii(int fontid, const char *str, size_t len) } } +int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) +{ + FontBLF *font = blf_get(fontid); + GLint mode, param; + int columns = 0; + + if (font && font->glyph_cache) { + blf_draw__start(font, &mode, ¶m); + columns = blf_font_draw_mono(font, str, len, cwidth); + blf_draw__end(mode, param); + } + + return columns; +} + void BLF_boundbox(int fontid, const char *str, rctf *box) { FontBLF *font = blf_get(fontid); diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c index b6a98faa48c..116a55c0579 100644 --- a/source/blender/blenfont/intern/blf_dir.c +++ b/source/blender/blenfont/intern/blf_dir.c @@ -41,6 +41,7 @@ #include "DNA_vec_types.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_path_util.h" diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 1900efa2dbc..f2c36475870 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -219,6 +219,40 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len) } } +/* use fixed column width, but an utf8 character may occupy multiple columns */ +int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth) +{ + unsigned int c; + GlyphBLF *g; + int col, columns = 0; + int pen_x = 0, pen_y = 0; + size_t i = 0; + GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + + blf_font_ensure_ascii_table(font); + + while ((i < len) && str[i]) { + BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + + if (c == BLI_UTF8_ERR) + break; + if (g == NULL) + continue; + + /* do not return this loop if clipped, we want every character tested */ + blf_glyph_render(font, g, (float)pen_x, (float)pen_y); + + col = BLI_wcwidth((wchar_t)c); + if (col < 0) + col = 1; + + columns += col; + pen_x += cwidth * col; + } + + return columns; +} + /* Sanity checks are done by BLF_draw_buffer() */ void blf_font_buffer(FontBLF *font, const char *str) { diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 65a54783978..b1301be46fd 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -53,6 +53,7 @@ void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, in void blf_font_size(struct FontBLF *font, int size, int dpi); void blf_font_draw(struct FontBLF *font, const char *str, size_t len); void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len); +int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int cwidth); void blf_font_buffer(struct FontBLF *font, const char *str); void blf_font_boundbox(struct FontBLF *font, const char *str, struct rctf *box); void blf_font_width_and_height(struct FontBLF *font, const char *str, float *width, float *height); diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 73294f1aed6..d1c037b0358 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -78,15 +78,16 @@ static void free_locales(void) static void fill_locales(void) { - char *languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale"); + const char * const languages_path = BLI_get_folder(BLENDER_DATAFILES, "locale"); + char languages[FILE_MAX]; LinkNode *lines = NULL, *line; char *str; int idx = 0; free_locales(); - BLI_join_dirfile(languages_path, FILE_MAX, languages_path, "languages"); - line = lines = BLI_file_read_as_lines(languages_path); + BLI_join_dirfile(languages, FILE_MAX, languages_path, "languages"); + line = lines = BLI_file_read_as_lines(languages); /* This whole "parsing" code is a bit weak, in that it expects strictly formated input file... * Should not be a problem, though, as this file is script-generated! */ @@ -185,7 +186,7 @@ EnumPropertyItem *BLF_RNA_lang_enum_properties(void) void BLF_lang_init(void) { #ifdef WITH_INTERNATIONAL - char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); + const char * const messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); if (messagepath) { bl_locale_init(messagepath, TEXT_DOMAIN_NAME); diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index b5b72b68677..4e9408c512a 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -50,13 +50,16 @@ static const char unifont_filename[] = "droidsans.ttf.gz"; static unsigned char *unifont_ttf = NULL; static int unifont_size = 0; +static const char unifont_mono_filename[] = "bmonofont-i18n.ttf.gz"; +static unsigned char *unifont_mono_ttf = NULL; +static int unifont_mono_size = 0; #endif /* WITH_INTERNATIONAL */ unsigned char *BLF_get_unifont(int *unifont_size_r) { #ifdef WITH_INTERNATIONAL if (unifont_ttf == NULL) { - char *fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts"); + const char * const fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts"); if (fontpath) { char unifont_path[1024]; @@ -87,14 +90,49 @@ void BLF_free_unifont(void) #endif } +unsigned char *BLF_get_unifont_mono(int *unifont_size_r) +{ +#ifdef WITH_INTERNATIONAL + if (unifont_mono_ttf == NULL) { + const char *fontpath = BLI_get_folder(BLENDER_DATAFILES, "fonts"); + if (fontpath) { + char unifont_path[1024]; + + BLI_snprintf(unifont_path, sizeof(unifont_path), "%s/%s", fontpath, unifont_mono_filename); + + unifont_mono_ttf = (unsigned char *)BLI_file_ungzip_to_mem(unifont_path, &unifont_mono_size); + } + else { + printf("%s: 'fonts' data path not found for international monospace font, continuing\n", __func__); + } + } + + *unifont_size_r = unifont_mono_size; + + return unifont_mono_ttf; +#else + (void)unifont_size_r; + return NULL; +#endif +} + +void BLF_free_unifont_mono(void) +{ +#ifdef WITH_INTERNATIONAL + if (unifont_mono_ttf) + MEM_freeN(unifont_mono_ttf); +#else +#endif +} + const char *BLF_pgettext(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL - if (msgid && msgid[0]) { - const char *ret; + const char *ret = msgid; + if (msgid && msgid[0]) { /*if (msgctxt && !strcmp(msgctxt, BLF_I18NCONTEXT_DEFAULT_BPY_INTERN)) { */ - if (msgctxt && msgctxt[0] == BLF_I18NCONTEXT_DEFAULT_BPY[0]) { + if (msgctxt && (!msgctxt[0] || msgctxt[0] == BLF_I18NCONTEXT_DEFAULT_BPY[0])) { /* BLF_I18NCONTEXT_DEFAULT_BPY context is reserved and considered the same as default NULL one. */ msgctxt = BLF_I18NCONTEXT_DEFAULT; } @@ -105,10 +143,9 @@ const char *BLF_pgettext(const char *msgctxt, const char *msgid) if (ret == msgid) { ret = BPY_app_translations_py_pgettext(msgctxt, msgid); } - - return ret; } - return ""; + + return ret; #else (void)msgctxt; return msgid; diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 486834f9540..51c46bcc235 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -608,7 +608,7 @@ void DM_interp_poly_data(struct DerivedMesh *source, struct DerivedMesh *dest, float *weights, int count, int dest_index); /* Temporary? A function to give a colorband to derivedmesh for vertexcolor ranges */ -void vDM_ColorBand_store(struct ColorBand *coba); +void vDM_ColorBand_store(const struct ColorBand *coba, const char alert_color[4]); /** Simple function to get me->totvert amount of vertices/normals, * correctly deformed and subsurfered. Needed especially when vertexgroups are involved. diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index e648523aec3..dd150ba6a63 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -63,10 +63,10 @@ short BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct void BKE_free_animdata(struct ID *id); /* Copy AnimData */ -struct AnimData *BKE_copy_animdata(struct AnimData *adt, const short do_action); +struct AnimData *BKE_copy_animdata(struct AnimData *adt, const bool do_action); /* Copy AnimData */ -int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const short do_action); +int BKE_copy_animdata_id(struct ID *id_to, struct ID *id_from, const bool do_action); /* Copy AnimData Actions */ void BKE_copy_animdata_id_action(struct ID *id); diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index d66909449e4..d3671516248 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 266 -#define BLENDER_SUBVERSION 0 +#define BLENDER_SUBVERSION 1 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 @@ -50,7 +50,7 @@ extern "C" { /* used by packaging tools */ /* can be left blank, otherwise a,b,c... etc with no quotes */ -#define BLENDER_VERSION_CHAR +#define BLENDER_VERSION_CHAR a /* alpha/beta/rc/release, docs use this */ #define BLENDER_VERSION_CYCLE alpha diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index cfae15961d7..3a4684257f6 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -69,24 +69,13 @@ float BKE_brush_curve_strength_clamp(struct Brush *br, float p, const float len) float BKE_brush_curve_strength(struct Brush *br, float p, const float len); /* used for sculpt */ /* sampling */ -void BKE_brush_sample_tex(const struct Scene *scene, struct Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool); -void BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], float rgba[4], const int thread); +float BKE_brush_sample_tex_3D(const Scene *scene, struct Brush *br, const float point[3], + float rgba[4], const int thread, struct ImagePool *pool); +float BKE_brush_sample_tex_2D(const struct Scene *scene, struct Brush *brush, const float xy[2], + float rgba[4], struct ImagePool *pool); void BKE_brush_imbuf_new(const struct Scene *scene, struct Brush *brush, short flt, short texfalloff, int size, struct ImBuf **imbuf, int use_color_correction); -/* painting */ -struct BrushPainter; -typedef struct BrushPainter BrushPainter; -typedef int (*BrushFunc)(void *user, struct ImBuf *ibuf, const float lastpos[2], const float pos[2]); - -BrushPainter *BKE_brush_painter_new(struct Scene *scene, struct Brush *brush); -void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, - short texonly, int size); -int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], - double time, float pressure, void *user, int use_color_correction); -void BKE_brush_painter_break_stroke(BrushPainter *painter); -void BKE_brush_painter_free(BrushPainter *painter); - /* texture */ unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side); diff --git a/source/blender/blenkernel/BKE_ccg.h b/source/blender/blenkernel/BKE_ccg.h index 6d39d42bde5..fb6211504ae 100644 --- a/source/blender/blenkernel/BKE_ccg.h +++ b/source/blender/blenkernel/BKE_ccg.h @@ -126,7 +126,7 @@ BLI_INLINE CCGElem *CCG_elem_offset(const CCGKey *key, CCGElem *elem, int offset BLI_INLINE CCGElem *CCG_grid_elem(const CCGKey *key, CCGElem *elem, int x, int y) { - BLI_assert(x < key->grid_size && y < key->grid_size); +// BLI_assert(x < key->grid_size && y < key->grid_size); return CCG_elem_offset(key, elem, (y * key->grid_size + x)); } diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 358f884f74e..88d9cbb9b35 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -38,7 +38,6 @@ struct BezTriple; struct Curve; struct EditNurb; struct ListBase; -struct ListBase; struct Main; struct Nurb; struct Object; @@ -66,9 +65,9 @@ void BKE_curve_type_test(struct Object *ob); void BKE_curve_curve_dimension_update(struct Curve *cu); void BKE_curve_texspace_calc(struct Curve *cu); -int BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]); -int BKE_curve_center_median(struct Curve *cu, float cent[3]); -int BKE_curve_center_bounds(struct Curve *cu, float cent[3]); +bool BKE_curve_minmax(struct Curve *cu, float min[3], float max[3]); +bool BKE_curve_center_median(struct Curve *cu, float cent[3]); +bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]); void BKE_curve_translate(struct Curve *cu, float offset[3], int do_keys); void BKE_curve_delete_material_index(struct Curve *cu, int index); @@ -118,11 +117,11 @@ void BKE_nurb_knot_calc_u(struct Nurb *nu); void BKE_nurb_knot_calc_v(struct Nurb *nu); /* nurb checks if they can be drawn, also clamp order func */ -int BKE_nurb_check_valid_u(struct Nurb *nu); -int BKE_nurb_check_valid_v(struct Nurb *nu); +bool BKE_nurb_check_valid_u(struct Nurb *nu); +bool BKE_nurb_check_valid_v(struct Nurb *nu); -int BKE_nurb_order_clamp_u(struct Nurb *nu); -int BKE_nurb_order_clamp_v(struct Nurb *nu); +bool BKE_nurb_order_clamp_u(struct Nurb *nu); +bool BKE_nurb_order_clamp_v(struct Nurb *nu); void BKE_nurb_direction_switch(struct Nurb *nu); @@ -135,4 +134,4 @@ void BKE_nurb_handles_calc(struct Nurb *nu); void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag); void BKE_nurb_handles_test(struct Nurb *nu); -#endif +#endif /* __BKE_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index cd52dd75f26..028ff0f93d6 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -71,7 +71,7 @@ typedef struct EditFont { } EditFont; -int BKE_vfont_is_builtin(struct VFont *vfont); +bool BKE_vfont_is_builtin(struct VFont *vfont); void BKE_vfont_builtin_register(void *mem, int size); void BKE_vfont_free_data(struct VFont *vfont); diff --git a/source/blender/blenkernel/BKE_idcode.h b/source/blender/blenkernel/BKE_idcode.h index 2a01ef3afdb..74dc8de753e 100644 --- a/source/blender/blenkernel/BKE_idcode.h +++ b/source/blender/blenkernel/BKE_idcode.h @@ -64,7 +64,7 @@ int BKE_idcode_from_name(const char *name); * \param code The code to check. * \return Boolean, 0 when non linkable. */ -int BKE_idcode_is_linkable(int code); +bool BKE_idcode_is_linkable(int code); /** * Return if the ID code is a valid ID code. @@ -72,7 +72,7 @@ int BKE_idcode_is_linkable(int code); * \param code The code to check. * \return Boolean, 0 when invalid. */ -int BKE_idcode_is_valid(int code); +bool BKE_idcode_is_valid(int code); /** * Return an ID code and steps the index forward 1. diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index dd7e06259bd..26ac2cc8bb4 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -68,7 +68,7 @@ int BKE_add_image_extension_from_type(char *string, const char imtype); char BKE_ftype_to_imtype(const int ftype); int BKE_imtype_to_ftype(const char imtype); -int BKE_imtype_is_movie(const char imtype); +bool BKE_imtype_is_movie(const char imtype); int BKE_imtype_supports_zbuf(const char imtype); int BKE_imtype_supports_compress(const char imtype); int BKE_imtype_supports_quality(const char imtype); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 5aa82be0541..816fb2d1b35 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -63,7 +63,7 @@ __attribute__((warn_unused_result)) __attribute__((nonnull)) #endif ; -void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const short do_action); +void BKE_libblock_copy_data(struct ID *id, const struct ID *id_from, const bool do_action); void BKE_id_lib_local_paths(struct Main *bmain, struct Library *lib, struct ID *id); void id_lib_extern(struct ID *id); @@ -72,13 +72,13 @@ void id_us_ensure_real(struct ID *id); void id_us_plus(struct ID *id); void id_us_min(struct ID *id); -int id_make_local(struct ID *id, int test); -int id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); -int id_copy(struct ID *id, struct ID **newid, int test); -int id_unlink(struct ID *id, int test); +bool id_make_local(struct ID *id, bool test); +bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); +bool id_copy(struct ID *id, struct ID **newid, bool test); +bool id_unlink(struct ID *id, int test); void id_sort_by_name(struct ListBase *lb, struct ID *id); -int new_id(struct ListBase *lb, struct ID *id, const char *name); +bool new_id(struct ListBase *lb, struct ID *id, const char *name); void id_clear_lib_data(struct Main *bmain, struct ID *id); struct ListBase *which_libbase(struct Main *mainlib, short type); @@ -96,10 +96,9 @@ void tag_main_lb(struct ListBase *lb, const short tag); void tag_main(struct Main *mainvar, const short tag); void rename_id(struct ID *id, const char *name); -void name_uiprefix_id(char *name, struct ID *id); +void name_uiprefix_id(char *name, const struct ID *id); void test_idbutton(char *name); -void text_idbutton(struct ID *id, char *text); -void BKE_library_make_local(struct Main *bmain, struct Library *lib, int untagged_only); +void BKE_library_make_local(struct Main *bmain, struct Library *lib, bool untagged_only); struct ID *BKE_libblock_find_name(const short type, const char *name) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -128,4 +127,4 @@ void set_free_windowmanager_cb(void (*func)(struct bContext *, struct wmWindowMa } #endif -#endif +#endif /* __BKE_LIBRARY_H__ */ diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index 7c36ff07da5..fec163e2d17 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -98,6 +98,10 @@ typedef struct Main { #define MAIN_VERSION_ATLEAST(main, ver, subver) \ ((main)->versionfile > (ver) || (main->versionfile == (ver) && (main)->subversionfile >= (subver))) +#define MAIN_VERSION_OLDER(main, ver, subver) \ + ((main)->versionfile < (ver) || (main->versionfile == (ver) && (main)->subversionfile < (subver))) + + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 662bfab10a1..9bbff515983 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -48,8 +48,8 @@ void BKE_mball_make_local(struct MetaBall *mb); void BKE_mball_cubeTable_free(void); void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase); -int BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); -int BKE_mball_is_basis(struct Object *ob); +bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); +bool BKE_mball_is_basis(struct Object *ob); struct Object *BKE_mball_basis_find(struct Scene *scene, struct Object *ob); void BKE_mball_texspace_calc(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 24535eb1fd6..398d1fe8545 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -169,7 +169,8 @@ int BKE_mesh_nurbs_displist_to_mdata(struct Object *ob, struct ListBase *dispbas struct MLoopUV **alluv, int *_totloop, int *_totpoly); void BKE_mesh_from_nurbs_displist(struct Object *ob, struct ListBase *dispbase, int use_orco_uv); void BKE_mesh_from_nurbs(struct Object *ob); -void BKE_mesh_from_curve(struct Scene *scene, struct Object *ob); +void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test); +void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob); void BKE_mesh_delete_material_index(struct Mesh *me, short index); void BKE_mesh_smooth_flag_set(struct Object *meshOb, int enableSmooth); void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh); @@ -325,7 +326,7 @@ int BKE_mesh_validate_arrays( int BKE_mesh_validate(struct Mesh *me, int do_verbose); int BKE_mesh_validate_dm(struct DerivedMesh *dm); -void BKE_mesh_calc_edges(struct Mesh *mesh, int update); +void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select); void BKE_mesh_ensure_navmesh(struct Mesh *me); diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 5777a4094bc..c8c94b2898b 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -64,9 +64,14 @@ void BKE_movieclip_get_cache_segments(struct MovieClip *clip, struct MovieClipUs void BKE_movieclip_build_proxy_frame(struct MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, int undistorted); +void BKE_movieclip_build_proxy_frame_for_ibuf(struct MovieClip *clip, struct ImBuf *ibuf, struct MovieDistortion *distortion, + int cfra, int *build_sizes, int build_count, int undistorted); + float BKE_movieclip_remap_scene_to_clip_frame(struct MovieClip *clip, float framenr); float BKE_movieclip_remap_clip_to_scene_frame(struct MovieClip *clip, float framenr); +void BKE_movieclip_filename_for_frame(struct MovieClip *clip, int framenr, char *name); + /* cacheing flags */ #define MOVIECLIP_CACHE_SKIP (1 << 0) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 19fe621ade9..80955729326 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -48,6 +48,7 @@ struct GPUMaterial; struct GPUNode; struct GPUNodeStack; struct ID; +struct ImBuf; struct ImageFormatData; struct ListBase; struct Main; diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 89860cd0da9..5caa484caa0 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -68,7 +68,7 @@ void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob); void BKE_object_free(struct Object *ob); void BKE_object_free_display(struct Object *ob); -int BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type); +bool BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type); void BKE_object_link_modifiers(struct Object *ob, struct Object *from); void BKE_object_free_modifiers(struct Object *ob); @@ -77,8 +77,8 @@ void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Obje void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target); void BKE_object_unlink(struct Object *ob); -int BKE_object_exists_check(struct Object *obtest); -int BKE_object_is_in_editmode(struct Object *ob); +bool BKE_object_exists_check(struct Object *obtest); +bool BKE_object_is_in_editmode(struct Object *ob); struct Object *BKE_object_add_only_object(struct Main *bmain, int type, const char *name); struct Object *BKE_object_add(struct Scene *scene, int type); @@ -87,8 +87,8 @@ void *BKE_object_obdata_add_from_type(int type); struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, int copy_caches); struct Object *BKE_object_copy(struct Object *ob); void BKE_object_make_local(struct Object *ob); -int BKE_object_is_libdata(struct Object *ob); -int BKE_object_obdata_is_libdata(struct Object *ob); +bool BKE_object_is_libdata(struct Object *ob); +bool BKE_object_obdata_is_libdata(struct Object *ob); void BKE_object_scale_to_mat3(struct Object *ob, float mat[3][3]); void BKE_object_rot_to_mat3(struct Object *ob, float mat[3][3], short use_drot); @@ -128,7 +128,7 @@ void BKE_scene_foreach_display_point(struct Scene *scene, const short flag, void (*func_cb)(const float[3], void *), void *user_data); -int BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob); +bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob); void *BKE_object_tfm_backup(struct Object *ob); void BKE_object_tfm_restore(struct Object *ob, void *obtfm_pt); @@ -160,9 +160,12 @@ int BKE_object_insert_ptcache(struct Object *ob); // void object_delete_ptcache(struct Object *ob, int index); struct KeyBlock *BKE_object_insert_shape_key(struct Scene *scene, struct Object *ob, const char *name, int from_mix); +bool BKE_object_is_child_recursive(struct Object *ob_parent, struct Object *ob_child); +bool BKE_object_is_animated(struct Scene *scene, struct Object *ob); + +/* return ModifierMode flag */ int BKE_object_is_modified(struct Scene *scene, struct Object *ob); int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob); -int BKE_object_is_animated(struct Scene *scene, struct Object *ob); void BKE_object_relink(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h index b19a2092206..8fab44121de 100644 --- a/source/blender/blenkernel/BKE_packedFile.h +++ b/source/blender/blenkernel/BKE_packedFile.h @@ -74,7 +74,7 @@ void rewindPackedFile(struct PackedFile *pf); int readPackedFile(struct PackedFile *pf, void *data, int size); /* ID should be not NULL, return 1 if there's a packed file */ -int BKE_pack_check(struct ID *id); +bool BKE_pack_check(struct ID *id); /* ID should be not NULL, throws error when ID is Library */ void BKE_unpack_id(struct Main *bmain, struct ID *id, struct ReportList *reports, int how); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index 211b6189fa8..35941d0a05a 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -48,12 +48,23 @@ struct PBVH; struct Scene; struct StrokeCache; struct ImagePool; +struct UnifiedPaintSettings; extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; extern const char PAINT_CURSOR_WEIGHT_PAINT[3]; extern const char PAINT_CURSOR_TEXTURE_PAINT[3]; +typedef enum PaintMode { + PAINT_SCULPT = 0, + PAINT_VERTEX = 1, + PAINT_WEIGHT = 2, + PAINT_TEXTURE_PROJECTIVE = 3, + PAINT_TEXTURE_2D = 4, + PAINT_SCULPT_UV = 5, + PAINT_INVALID = 6 +} PaintMode; + void BKE_paint_init(struct Paint *p, const char col[3]); void BKE_paint_free(struct Paint *p); void BKE_paint_copy(struct Paint *src, struct Paint *tar); @@ -61,6 +72,7 @@ void BKE_paint_copy(struct Paint *src, struct Paint *tar); /* TODO, give these BKE_ prefix too */ struct Paint *paint_get_active(struct Scene *sce); struct Paint *paint_get_active_from_context(const struct bContext *C); +PaintMode paintmode_get_active_from_context(const struct bContext *C); struct Brush *paint_brush(struct Paint *paint); void paint_brush_set(struct Paint *paint, struct Brush *br); @@ -79,7 +91,7 @@ int paint_is_bmesh_face_hidden(struct BMFace *f); /* paint masks */ float paint_grid_paint_mask(const struct GridPaintMask *gpm, unsigned level, unsigned x, unsigned y); - +void paint_calculate_rake_rotation(struct UnifiedPaintSettings *ups, const float mouse_pos[2]); /* Session data (mode-specific) */ typedef struct SculptSession { diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 99ed978561e..cdc8ef0bdf4 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -295,7 +295,7 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \ } \ else { \ - if (!BLI_ghashIterator_isDone(&vi.bm_unique_verts)) {\ + if (BLI_ghashIterator_notDone(&vi.bm_unique_verts)) {\ vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \ BLI_ghashIterator_step(&vi.bm_unique_verts); \ } \ diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 629acab9e34..5407e22e49e 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -75,6 +75,8 @@ typedef struct SpaceType { /* init is to cope with file load, screen (size) changes, check handlers */ void (*init)(struct wmWindowManager *, struct ScrArea *); + /* exit is called when the area is hidden or removed */ + void (*exit)(struct wmWindowManager *, struct ScrArea *); /* Listeners can react to bContext changes */ void (*listener)(struct ScrArea *, struct wmNotifier *); @@ -116,6 +118,8 @@ typedef struct ARegionType { /* add handlers, stuff you only do once or on area/region type/size changes */ void (*init)(struct wmWindowManager *, struct ARegion *); + /* exit is called when the region is hidden or removed */ + void (*exit)(struct wmWindowManager *, struct ARegion *); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct ARegion *); /* contextual changes should be handled here */ @@ -163,9 +167,10 @@ typedef struct ARegionType { typedef struct PanelType { struct PanelType *next, *prev; - char idname[BKE_ST_MAXNAME]; /* unique name */ - char label[BKE_ST_MAXNAME]; /* for panel header */ - char context[BKE_ST_MAXNAME]; /* for buttons window */ + char idname[BKE_ST_MAXNAME]; /* unique name */ + char label[BKE_ST_MAXNAME]; /* for panel header */ + char translation_context[BKE_ST_MAXNAME]; + char context[BKE_ST_MAXNAME]; /* for buttons window */ int space_type; int region_type; @@ -227,7 +232,8 @@ typedef struct MenuType { char idname[BKE_ST_MAXNAME]; /* unique name */ char label[BKE_ST_MAXNAME]; /* for button text */ - char *description; + char translation_context[BKE_ST_MAXNAME]; + char *description; /* verify if the menu should draw or not */ int (*poll)(const struct bContext *, struct MenuType *); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index c0ff634671d..a46d947b9d9 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -192,7 +192,7 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe /* ********************************************************************** * sequencer scene functions * ********************************************************************** */ -struct Editing *BKE_sequencer_editing_get(struct Scene *scene, int alloc); +struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc); struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene); void BKE_sequencer_editing_free(struct Scene *scene); @@ -289,10 +289,10 @@ int BKE_sequence_tx_get_final_right(struct Sequence *seq, int metaclip); void BKE_sequence_tx_set_final_left(struct Sequence *seq, int val); void BKE_sequence_tx_set_final_right(struct Sequence *seq, int val); void BKE_sequence_tx_handle_xlimits(struct Sequence *seq, int leftflag, int rightflag); -int BKE_sequence_tx_test(struct Sequence *seq); -int BKE_sequence_single_check(struct Sequence *seq); +bool BKE_sequence_tx_test(struct Sequence *seq); +bool BKE_sequence_single_check(struct Sequence *seq); void BKE_sequence_single_fix(struct Sequence *seq); -int BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test); +bool BKE_sequence_test_overlap(struct ListBase *seqbasep, struct Sequence *test); void BKE_sequence_translate(struct Scene *scene, struct Sequence *seq, int delta); void BKE_sequence_sound_init(struct Scene *scene, struct Sequence *seq); struct Sequence *BKE_sequencer_foreground_frame_get(struct Scene *scene, int frame); @@ -301,14 +301,14 @@ struct Sequence *BKE_sequence_metastrip(ListBase *seqbase /* = ed->seqbase */, s void BKE_sequencer_offset_animdata(struct Scene *scene, struct Sequence *seq, int ofs); void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst); -int BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene); -int BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene); -int BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase); +bool BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene); +bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene); +bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase); void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, int for_render); struct Sequence *BKE_sequence_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence *seq, int dupe_flag); int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); -int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); +bool BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur); void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq); void BKE_sequence_invalidate_dependent(struct Scene *scene, struct Sequence *seq); void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq); @@ -320,7 +320,7 @@ void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound); void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag); -int BKE_sequence_is_valid_check(struct Sequence *seq); +bool BKE_sequence_is_valid_check(struct Sequence *seq); void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); void BKE_sequencer_clear_movieclip_in_clipboard(struct MovieClip *clip); @@ -419,4 +419,4 @@ int BKE_sequence_supports_modifiers(struct Sequence *seq); struct ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, int cfra, int make_float); void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, short make_float, struct ImBuf *mask_input); -#endif /* __BKE_SEQUENCER_H__ */ +#endif /* __BKE_SEQUENCER_H__ */ diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 3d7b5d1c8e4..5e81fb85d76 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -45,16 +45,16 @@ struct SpaceText; void BKE_text_free (struct Text *text); void txt_set_undostate (int u); int txt_get_undostate (void); -struct Text* BKE_text_add (struct Main *bmain, const char *name); +struct Text *BKE_text_add (struct Main *bmain, const char *name); int txt_extended_ascii_as_utf8(char **str); int BKE_text_reload (struct Text *text); -struct Text* BKE_text_load (struct Main *bmain, const char *file, const char *relpath); -struct Text* BKE_text_copy (struct Text *ta); +struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath); +struct Text *BKE_text_copy (struct Text *ta); void BKE_text_unlink (struct Main *bmain, struct Text *text); void BKE_text_clear (struct Text *text); void BKE_text_write (struct Text *text, const char *str); -char* txt_to_buf (struct Text *text); +char *txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); void txt_order_cursors (struct Text *text); int txt_find_string (struct Text *text, const char *findstr, int wrap, int match_case); @@ -62,6 +62,8 @@ int txt_has_sel (struct Text *text); int txt_get_span (struct TextLine *from, struct TextLine *to); int txt_utf8_offset_to_index(const char *str, int offset); int txt_utf8_index_to_offset(const char *str, int index); +int txt_utf8_offset_to_column(const char *str, int offset); +int txt_utf8_column_to_offset(const char *str, int column); void txt_move_up (struct Text *text, short sel); void txt_move_down (struct Text *text, short sel); void txt_move_left (struct Text *text, short sel); @@ -80,7 +82,7 @@ void txt_delete_word (struct Text *text); void txt_delete_selected (struct Text *text); void txt_sel_all (struct Text *text); void txt_sel_line (struct Text *text); -char* txt_sel_to_buf (struct Text *text); +char *txt_sel_to_buf (struct Text *text); void txt_insert_buf (struct Text *text, const char *in_buffer); void txt_print_undo (struct Text *text); void txt_undo_add_op (struct Text *text, int op); @@ -98,7 +100,7 @@ void txt_indent (struct Text *text); void txt_uncomment (struct Text *text); void txt_move_lines (struct Text *text, const int direction); void txt_duplicate_line (struct Text *text); -int setcurr_tab_spaces (struct Text *text, int space); +int txt_setcurr_tab_spaces(struct Text *text, int space); /* utility functions, could be moved somewhere more generic but are python/text related */ int text_check_bracket(const char ch); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 9bdc96e187d..c8ad708f832 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -144,6 +144,7 @@ void BKE_tracking_camera_get_reconstructed_interpolate(struct MovieTracking *tra struct MovieDistortion *BKE_tracking_distortion_new(void); void BKE_tracking_distortion_update(struct MovieDistortion *distortion, struct MovieTracking *tracking, int calibration_width, int calibration_height); +void BKE_tracking_distortion_set_threads(struct MovieDistortion *distortion, int threads); struct MovieDistortion *BKE_tracking_distortion_copy(struct MovieDistortion *distortion); struct ImBuf *BKE_tracking_distortion_exec(struct MovieDistortion *distortion, struct MovieTracking *tracking, struct ImBuf *ibuf, int width, int height, float overscan, int undistort); @@ -162,7 +163,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(struct MovieTracking *trac /* **** Image sampling **** */ struct ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, struct ImBuf *struct_ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int use_mask, + struct MovieTrackingMarker *marker, int from_anchor, int use_mask, int num_samples_x, int num_samples_y, float pos[2]); struct ImBuf *BKE_tracking_get_pattern_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int anchored, int disable_channels); diff --git a/source/blender/blenkernel/BKE_unit.h b/source/blender/blenkernel/BKE_unit.h index 86f46820c97..6b5ce5e1d21 100644 --- a/source/blender/blenkernel/BKE_unit.h +++ b/source/blender/blenkernel/BKE_unit.h @@ -70,7 +70,8 @@ double bUnit_GetScaler(void *usys_pt, int index); #define B_UNIT_TIME 6 #define B_UNIT_VELOCITY 7 #define B_UNIT_ACCELERATION 8 -#define B_UNIT_TYPE_TOT 9 +#define B_UNIT_CAMERA 9 +#define B_UNIT_TYPE_TOT 10 #ifdef __cplusplus } diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index ad5369c0820..14e7d220449 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -137,8 +137,6 @@ DagNode *dag_get_node(DagForest *forest, void *fob); DagNode *dag_get_sub_node(DagForest *forest, void *fob); void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name); -void graph_bfs(void); - DagNodeQueue *graph_dfs(void); void set_node_xy(DagNode *node, float x, float y); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index ffd86ea9ce0..f09de138428 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1025,12 +1025,18 @@ enum { CALC_WP_AUTO_NORMALIZE = (1 << 4) }; -static void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const float input) +typedef struct DMWeightColorInfo { + const ColorBand *coba; + const char *alert_color; +} DMWeightColorInfo; + + +static void weightpaint_color(unsigned char r_col[4], DMWeightColorInfo *dm_wcinfo, const float input) { float colf[4]; - if (coba) { - do_colorband(coba, input, colf); + if (dm_wcinfo && dm_wcinfo->coba) { + do_colorband(dm_wcinfo->coba, input, colf); } else { weight_to_rgb(colf, input); @@ -1047,17 +1053,19 @@ static void weightpaint_color(unsigned char r_col[4], ColorBand *coba, const flo static void calc_weightpaint_vert_color( unsigned char r_col[4], - MDeformVert *dv, ColorBand *coba, + MDeformVert *dv, + DMWeightColorInfo *dm_wcinfo, const int defbase_tot, const int defbase_act, const char *defbase_sel, const int defbase_sel_tot, const int draw_flag) { float input = 0.0f; - bool make_black = false; + bool show_alert_color = false; if ((defbase_sel_tot > 1) && (draw_flag & CALC_WP_MULTIPAINT)) { - int was_a_nonzero = FALSE; + /* Multi-Paint feature */ + bool was_a_nonzero = false; unsigned int i; MDeformWeight *dw = dv->dw; @@ -1068,15 +1076,15 @@ static void calc_weightpaint_vert_color( if (defbase_sel[dw->def_nr]) { if (dw->weight) { input += dw->weight; - was_a_nonzero = TRUE; + was_a_nonzero = true; } } } } /* make it black if the selected groups have no weight on a vertex */ - if (was_a_nonzero == FALSE) { - make_black = true; + if (was_a_nonzero == false) { + show_alert_color = true; } else if ((draw_flag & CALC_WP_AUTO_NORMALIZE) == FALSE) { input /= defbase_sel_tot; /* get the average */ @@ -1088,33 +1096,32 @@ static void calc_weightpaint_vert_color( if (draw_flag & CALC_WP_GROUP_USER_ACTIVE) { if (input == 0.0f) { - make_black = true; + show_alert_color = true; } } else if (draw_flag & CALC_WP_GROUP_USER_ALL) { if (input == 0.0f) { - make_black = defvert_is_weight_zero(dv, defbase_tot); + show_alert_color = defvert_is_weight_zero(dv, defbase_tot); } } } - if (make_black) { /* TODO, theme color */ - r_col[3] = 255; - r_col[2] = 0; - r_col[1] = 0; - r_col[0] = 0; + if (show_alert_color == false) { + CLAMP(input, 0.0f, 1.0f); + weightpaint_color(r_col, dm_wcinfo, input); } else { - CLAMP(input, 0.0f, 1.0f); - weightpaint_color(r_col, coba, input); + copy_v3_v3_char((char *)r_col, dm_wcinfo->alert_color); + r_col[3] = 255; } } -static ColorBand *stored_cb = NULL; +static DMWeightColorInfo G_dm_wcinfo; -void vDM_ColorBand_store(ColorBand *coba) +void vDM_ColorBand_store(const ColorBand *coba, const char alert_color[4]) { - stored_cb = coba; + G_dm_wcinfo.coba = coba; + G_dm_wcinfo.alert_color = alert_color; } /* return an array of vertex weight colors, caller must free. @@ -1122,7 +1129,7 @@ void vDM_ColorBand_store(ColorBand *coba) * note that we could save some memory and allocate RGB only but then we'd need to * re-arrange the colors when copying to the face since MCol has odd ordering, * so leave this as is - campbell */ -static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, ColorBand *coba) +static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const draw_flag, DMWeightColorInfo *dm_wcinfo) { MDeformVert *dv = DM_get_vert_data_layer(dm, CD_MDEFORMVERT); int numVerts = dm->getNumVerts(dm); @@ -1144,7 +1151,7 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i } for (i = numVerts; i != 0; i--, wc += 4, dv++) { - calc_weightpaint_vert_color(wc, dv, coba, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag); + calc_weightpaint_vert_color(wc, dv, dm_wcinfo, defbase_tot, defbase_act, defbase_sel, defbase_sel_tot, draw_flag); } if (defbase_sel) { @@ -1157,7 +1164,7 @@ static unsigned char *calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, i col_i = 0; } else { - weightpaint_color((unsigned char *)&col_i, coba, 0.0f); + weightpaint_color((unsigned char *)&col_i, dm_wcinfo, 0.0f); } fill_vn_i((int *)wtcol_v, numVerts, col_i); } @@ -1185,7 +1192,6 @@ static unsigned char *calc_colors_from_weights_array(const int num, float *weigh void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, float *weights, int num, const int *indices) { - ColorBand *coba = stored_cb; /* warning, not a local var */ unsigned char *wtcol_v; unsigned char(*wtcol_l)[4] = CustomData_get_layer(dm->getLoopDataLayout(dm), CD_PREVIEW_MLOOPCOL); @@ -1213,10 +1219,10 @@ void DM_update_weight_mcol(Object *ob, DerivedMesh *dm, int const draw_flag, if (indices) MEM_freeN(w); } - - /* No weights given, take them from active vgroup(s). */ - else - wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, coba); + else { + /* No weights given, take them from active vgroup(s). */ + wtcol_v = calc_weightpaint_vert_array(ob, dm, draw_flag, &G_dm_wcinfo); + } /* now add to loops, so the data can be passed through the modifier stack */ /* If no CD_PREVIEW_MLOOPCOL existed yet, we have to add a new one! */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4eb26e81ae2..ddb4cc4391a 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -1154,10 +1154,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ for (a = 0, mp = mpoly; a < totface; a++, mp++) { - int mv1; - int mv2; - int mv3; - /* int mv4; */ /* UNUSED */ float *v1; float *v2; float *v3; @@ -1171,9 +1167,9 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa } else { BKE_mesh_calc_poly_normal(mp, mloop + mp->loopstart, mvert, f_no); - v1 = mvert[(mv1 = loopstart[0].v)].co; - v2 = mvert[(mv2 = loopstart[1].v)].co; - v3 = mvert[(mv3 = loopstart[2].v)].co; + v1 = mvert[loopstart[0].v].co; + v2 = mvert[loopstart[1].v].co; + v3 = mvert[loopstart[2].v].co; } /* translation */ diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index bd13c406fa5..738d4c5b089 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -245,7 +245,7 @@ void BKE_free_animdata(ID *id) /* Freeing -------------------------------------------- */ /* Make a copy of the given AnimData - to be used when copying datablocks */ -AnimData *BKE_copy_animdata(AnimData *adt, const short do_action) +AnimData *BKE_copy_animdata(AnimData *adt, const bool do_action) { AnimData *dadt; @@ -277,7 +277,7 @@ AnimData *BKE_copy_animdata(AnimData *adt, const short do_action) return dadt; } -int BKE_copy_animdata_id(ID *id_to, ID *id_from, const short do_action) +int BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action) { AnimData *adt; diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 480814a28c3..ffe6a312ef8 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1596,7 +1596,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected } else if (pchan->bone->layer & layer_protected) { ListBase proxylocal_constraints = {NULL, NULL}; - bPoseChannel pchanw = {NULL}; + bPoseChannel pchanw; /* copy posechannel to temp, but restore important pointers */ pchanw = *pchanp; diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index be316197078..82b3b4f5618 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -899,7 +899,9 @@ static void copybuffer_doit(void *UNUSED(handle), Main *UNUSED(bmain), void *vid { if (vid) { ID *id = vid; - id->flag |= LIB_NEED_EXPAND | LIB_DOIT; + /* only tag for need-expand if not done, prevents eternal loops */ + if ((id->flag & LIB_DOIT) == 0) + id->flag |= LIB_NEED_EXPAND | LIB_DOIT; } } @@ -993,7 +995,7 @@ int BKE_copybuffer_paste(bContext *C, char *libname, ReportList *reports) /* append, rather than linking */ lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath)); - BKE_library_make_local(bmain, lib, 1); + BKE_library_make_local(bmain, lib, true); /* important we unset, otherwise these object wont * link into other scenes from this blend file */ diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index fc83b24da5b..78da4f5b1c2 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -56,7 +56,7 @@ #include "BKE_bmfont.h" #include "BKE_bmfont_types.h" -void printfGlyph(bmGlyph * glyph) +void printfGlyph(bmGlyph *glyph) { printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode); printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy); @@ -68,7 +68,7 @@ void printfGlyph(bmGlyph * glyph) #define MAX2(x, y) ((x) > (y) ? (x) : (y)) #define MAX3(x, y, z) (MAX2(MAX2((x), (y)), (z))) -void calcAlpha(ImBuf * ibuf) +void calcAlpha(ImBuf *ibuf) { int i; char * rect; @@ -82,7 +82,7 @@ void calcAlpha(ImBuf * ibuf) } } -void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step) +void readBitmapFontVersion0(ImBuf *ibuf, unsigned char *rect, int step) { int glyphcount, bytes, i, index, linelength, ysize; unsigned char * buffer; @@ -198,7 +198,7 @@ void detectBitmapFont(ImBuf *ibuf) readBitmapFontVersion0(ibuf, rect, 4); } else { - printf("detectBitmapFont :Unsupported version %d\n", version); + printf("detectBitmapFont :Unsupported version %d\n", (int)version); } /* on succes ibuf->userdata points to the bitmapfont */ diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index ba69fa4336e..6adcdbd2c3e 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -53,6 +53,7 @@ #include "IMB_imbuf_types.h" #include "RE_render_ext.h" /* externtex */ +#include "RE_shader_ext.h" static void brush_defaults(Brush *brush) { @@ -471,62 +472,133 @@ int BKE_brush_clone_image_delete(Brush *brush) return 0; } -/* Brush Sampling for 3d brushes. Currently used for texture painting only, but should be generalized */ -void BKE_brush_sample_tex(const Scene *scene, Brush *brush, const float sampleco[3], float rgba[4], const int thread, struct ImagePool *pool) +/* Generic texture sampler for 3D painting systems. point has to be either in + * region space mouse coordinates, or 3d world coordinates for 3D mapping */ +float BKE_brush_sample_tex_3D(const Scene *scene, Brush *br, + const float point[3], + float rgba[4], const int thread, + struct ImagePool *pool) { - MTex *mtex = &brush->mtex; + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + MTex *mtex = &br->mtex; + float intensity = 1.0; + bool hasrgb = false; - if (mtex && mtex->tex) { - float tin, tr, tg, tb, ta; - int hasrgb; - const int radius = BKE_brush_size_get(scene, brush); + if (!mtex->tex) { + intensity = 1; + } + else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { + /* Get strength by feeding the vertex + * location directly into a texture */ + hasrgb = externtex(mtex, point, &intensity, + rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); + } + else { + float rotation = -mtex->rot; + float point_2d[2] = {point[0], point[1]}; + float x = 0.0f, y = 0.0f; /* Quite warnings */ + float radius = 1.0f; /* Quite warnings */ + float co[3]; - if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { - hasrgb = externtex(mtex, sampleco, &tin, &tr, &tg, &tb, &ta, thread, pool); - } - else { - float co[3]; + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + /* keep coordinates relative to mouse */ + + rotation += ups->brush_rotation; - co[0] = sampleco[0] / radius; - co[1] = sampleco[1] / radius; - co[2] = 0.0f; + point_2d[0] -= ups->tex_mouse[0]; + point_2d[1] -= ups->tex_mouse[1]; - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, pool); + /* use pressure adjusted size for fixed mode */ + radius = ups->pixel_radius; + + x = point_2d[0]; + y = point_2d[1]; } + else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { + /* leave the coordinates relative to the screen */ - if (hasrgb) { - rgba[0] = tr; - rgba[1] = tg; - rgba[2] = tb; - rgba[3] = ta; + /* use unadjusted size for tiled mode */ + radius = BKE_brush_size_get(scene, br); + + x = point_2d[0]; + y = point_2d[1]; } - else { - rgba[0] = tin; - rgba[1] = tin; - rgba[2] = tin; - rgba[3] = 1.0f; + + x /= radius; + y /= radius; + + /* it is probably worth optimizing for those cases where + * the texture is not rotated by skipping the calls to + * atan2, sqrtf, sin, and cos. */ + if (rotation > 0.001f || rotation < -0.001f) { + const float angle = atan2f(y, x) + rotation; + const float flen = sqrtf(x * x + y * y); + + x = flen * cosf(angle); + y = flen * sinf(angle); } + + x *= br->mtex.size[0]; + y *= br->mtex.size[1]; + + co[0] = x + br->mtex.ofs[0]; + co[1] = y + br->mtex.ofs[1]; + co[2] = 0.0f; + + hasrgb = externtex(mtex, co, &intensity, + rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool); } - else { - rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; + + intensity += br->texture_sample_bias; + + if (!hasrgb) { + rgba[0] = intensity; + rgba[1] = intensity; + rgba[2] = intensity; + rgba[3] = 1.0f; } + + return intensity; } + /* Brush Sampling for 2D brushes. when we unify the brush systems this will be necessarily a separate function */ -void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], const int thread) +float BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2], float rgba[4], struct ImagePool *pool) { + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; MTex *mtex = &brush->mtex; if (mtex && mtex->tex) { float co[3], tin, tr, tg, tb, ta; + float x = xy[0], y = xy[1]; int hasrgb; - const int radius = BKE_brush_size_get(scene, brush); + int radius = BKE_brush_size_get(scene, brush); + float rotation = -mtex->rot; + + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + rotation += ups->brush_rotation; + radius = ups->pixel_radius; + } + + x /= radius; + y /= radius; + + if (rotation > 0.001f || rotation < -0.001f) { + const float angle = atan2f(y, x) + rotation; + const float flen = sqrtf(x * x + y * y); - co[0] = xy[0] / radius; - co[1] = xy[1] / radius; + x = flen * cosf(angle); + y = flen * sinf(angle); + } + + x *= brush->mtex.size[0]; + y *= brush->mtex.size[1]; + + co[0] = x + brush->mtex.ofs[0]; + co[1] = y + brush->mtex.ofs[1]; co[2] = 0.0f; - hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, thread, NULL); + hasrgb = externtex(mtex, co, &tin, &tr, &tg, &tb, &ta, 0, pool); if (hasrgb) { rgba[0] = tr; @@ -540,9 +612,11 @@ void BKE_brush_sample_tex_2D(const Scene *scene, Brush *brush, const float xy[2] rgba[2] = tin; rgba[3] = 1.0f; } + return tin; } else { rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1.0f; + return 1.0; } } @@ -790,7 +864,8 @@ void BKE_brush_scale_size(int *r_brush_size, void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], float jitterpos[2]) { - int use_jitter = brush->jitter != 0; + int use_jitter = (brush->flag & BRUSH_ABSOLUTE_JITTER) ? + (brush->jitter_absolute != 0) : (brush->jitter != 0); /* jitter-ed brush gives weird and unpredictable result for this * kinds of stroke, so manually disable jitter usage (sergey) */ @@ -798,17 +873,26 @@ void BKE_brush_jitter_pos(const Scene *scene, Brush *brush, const float pos[2], if (use_jitter) { float rand_pos[2]; - const int radius = BKE_brush_size_get(scene, brush); - const int diameter = 2 * radius; + float spread; + int diameter; - /* find random position within a circle of diameter 1 */ do { rand_pos[0] = BLI_frand() - 0.5f; rand_pos[1] = BLI_frand() - 0.5f; } while (len_v2(rand_pos) > 0.5f); - jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * brush->jitter; - jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * brush->jitter; + + if (brush->flag & BRUSH_ABSOLUTE_JITTER) { + diameter = 2 * brush->jitter_absolute; + spread = 1.0; + } + else { + diameter = 2 * BKE_brush_size_get(scene, brush); + spread = brush->jitter; + } + /* find random position within a circle of diameter 1 */ + jitterpos[0] = pos[0] + 2 * rand_pos[0] * diameter * spread; + jitterpos[1] = pos[1] + 2 * rand_pos[1] * diameter * spread; } else { copy_v2_v2(jitterpos, pos); @@ -841,6 +925,49 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len) return curvemapping_evaluateF(br->curve, 0, p); } +/* TODO: should probably be unified with BrushPainter stuff? */ +unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) +{ + unsigned int *texcache = NULL; + MTex *mtex = &br->mtex; + TexResult texres = {0}; + int hasrgb, ix, iy; + int side = half_side * 2; + + if (mtex->tex) { + float x, y, step = 2.0 / side, co[3]; + + texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); + + /*do normalized cannonical view coords for texture*/ + for (y = -1.0, iy = 0; iy < side; iy++, y += step) { + for (x = -1.0, ix = 0; ix < side; ix++, x += step) { + co[0] = x; + co[1] = y; + co[2] = 0.0f; + + /* This is copied from displace modifier code */ + hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL); + + /* if the texture gave an RGB value, we assume it didn't give a valid + * intensity, so calculate one (formula from do_material_tex). + * if the texture didn't give an RGB value, copy the intensity across + */ + if (hasrgb & TEX_RGB) + texres.tin = rgb_to_grayscale(&texres.tr); + + ((char *)texcache)[(iy * side + ix) * 4] = + ((char *)texcache)[(iy * side + ix) * 4 + 1] = + ((char *)texcache)[(iy * side + ix) * 4 + 2] = + ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f); + } + } + } + + return texcache; +} + + /**** Radial Control ****/ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br) { diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index c1293542963..a7311d5efc7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -783,14 +783,12 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) /* goalfac= 1.0f; */ /* UNUSED */ - /* // Kicking goal factor to simplify things...who uses that anyway? // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); - */ verts->goal = powf(verts->goal, 4.0f); if ( verts->goal >= SOFTGOALSNAP ) - verts->flags |= CLOTH_VERT_FLAG_PINNED; + verts->flags |= CLOTH_VERT_FLAG_PINNED; } if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_SCALING ) { diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 061657c8f2d..ed72a0fb37b 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -116,7 +116,7 @@ BVHTree *bvhtree_build_from_mvert ( MFace *mfaces, unsigned int numfaces, MVert return tree; } -void bvhtree_update_from_mvert(BVHTree * bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int UNUSED(numverts), int moving ) +void bvhtree_update_from_mvert(BVHTree *bvhtree, MFace *faces, int numfaces, MVert *x, MVert *xnew, int UNUSED(numverts), int moving ) { int i; MFace *mfaces = faces; @@ -654,7 +654,7 @@ static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, Collis { int i; - *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 64, "collision array" ); //*4 since cloth_collision_static can return more than 1 collision + *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 64, "collision array" ); // * 4 since cloth_collision_static can return more than 1 collision *collisions_index = *collisions; for ( i = 0; i < numresult; i++ ) { @@ -706,7 +706,7 @@ static int cloth_bvh_objcollisions_resolve ( ClothModifierData * clmd, Collision } // cloth - object collisions -int cloth_bvh_objcollision(Object *ob, ClothModifierData * clmd, float step, float dt ) +int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, float dt ) { Cloth *cloth= clmd->clothObject; BVHTree *cloth_bvh= cloth->bvhtree; diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index d08c16eac9e..5176f93f4f3 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -199,7 +199,9 @@ int curvemap_remove_point(CurveMap *cuma, CurveMapPoint *point) cmp[b] = cuma->curve[a]; b++; } - else removed++; + else { + removed++; + } } MEM_freeN(cuma->curve); @@ -221,7 +223,9 @@ void curvemap_remove(CurveMap *cuma, const short flag) cmp[b] = cuma->curve[a]; b++; } - else removed++; + else { + removed++; + } } cmp[b] = cuma->curve[a]; diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 48ad3f51389..3430c2ea7a1 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -817,7 +817,7 @@ static void childof_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar static bConstraintTypeInfo CTI_CHILDOF = { CONSTRAINT_TYPE_CHILDOF, /* type */ sizeof(bChildOfConstraint), /* size */ - "ChildOf", /* name */ + "Child Of", /* name */ "bChildOfConstraint", /* struct name */ NULL, /* free data */ childof_id_looper, /* id looper */ @@ -992,7 +992,7 @@ static void trackto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar static bConstraintTypeInfo CTI_TRACKTO = { CONSTRAINT_TYPE_TRACKTO, /* type */ sizeof(bTrackToConstraint), /* size */ - "TrackTo", /* name */ + "Track To", /* name */ "bTrackToConstraint", /* struct name */ NULL, /* free data */ trackto_id_looper, /* id looper */ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index a9e3d52f223..d899990a66a 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -27,7 +27,6 @@ * \ingroup bke */ - #include <string.h> #include <stdlib.h> #include <stddef.h> @@ -41,8 +40,6 @@ #include "DNA_windowmanager_types.h" #include "DNA_object_types.h" -#include "RNA_access.h" - #include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_threads.h" @@ -54,8 +51,10 @@ #include "BKE_main.h" #include "BKE_screen.h" +#include "RNA_access.h" + #ifdef WITH_PYTHON -#include "BPY_extern.h" +# include "BPY_extern.h" #endif /* struct */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 2da75ec64be..5d2c85e5825 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -793,7 +793,9 @@ static void makeknots(Nurb *nu, short uv) calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv); } } - else nu->knotsv = NULL; + else { + nu->knotsv = NULL; + } } } } @@ -3317,76 +3319,76 @@ void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key) } } -int BKE_nurb_check_valid_u(struct Nurb *nu) +bool BKE_nurb_check_valid_u(struct Nurb *nu) { if (nu == NULL) - return 0; + return false; if (nu->pntsu <= 1) - return 0; + return false; if (nu->type != CU_NURBS) - return 1; /* not a nurb, lets assume its valid */ + return true; /* not a nurb, lets assume its valid */ - if (nu->pntsu < nu->orderu) return 0; + if (nu->pntsu < nu->orderu) return false; if (((nu->flag & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { /* Bezier U Endpoints */ if (nu->orderu == 4) { if (nu->pntsu < 5) - return 0; /* bezier with 4 orderu needs 5 points */ + return false; /* bezier with 4 orderu needs 5 points */ } else { if (nu->orderu != 3) - return 0; /* order must be 3 or 4 */ + return false; /* order must be 3 or 4 */ } } - return 1; + return true; } -int BKE_nurb_check_valid_v(struct Nurb *nu) +bool BKE_nurb_check_valid_v(struct Nurb *nu) { if (nu == NULL) - return 0; + return false; if (nu->pntsv <= 1) - return 0; + return false; if (nu->type != CU_NURBS) - return 1; /* not a nurb, lets assume its valid */ + return true; /* not a nurb, lets assume its valid */ if (nu->pntsv < nu->orderv) - return 0; + return false; if (((nu->flag & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { /* Bezier V Endpoints */ if (nu->orderv == 4) { if (nu->pntsv < 5) - return 0; /* bezier with 4 orderu needs 5 points */ + return false; /* bezier with 4 orderu needs 5 points */ } else { if (nu->orderv != 3) - return 0; /* order must be 3 or 4 */ + return false; /* order must be 3 or 4 */ } } - return 1; + return true; } -int BKE_nurb_order_clamp_u(struct Nurb *nu) +bool BKE_nurb_order_clamp_u(struct Nurb *nu) { - int change = 0; + bool change = false; if (nu->pntsu < nu->orderu) { nu->orderu = nu->pntsu; - change = 1; + change = true; } if (((nu->flagu & CU_NURB_CYCLIC) == 0) && (nu->flagu & CU_NURB_BEZIER)) { CLAMP(nu->orderu, 3, 4); - change = 1; + change = true; } return change; } -int BKE_nurb_order_clamp_v(struct Nurb *nu) +bool BKE_nurb_order_clamp_v(struct Nurb *nu) { - int change = 0; + bool change = false; if (nu->pntsv < nu->orderv) { nu->orderv = nu->pntsv; - change = 1; + change = true; } if (((nu->flagv & CU_NURB_CYCLIC) == 0) && (nu->flagv & CU_NURB_BEZIER)) { CLAMP(nu->orderv, 3, 4); - change = 1; + change = true; } return change; } @@ -3403,7 +3405,7 @@ ListBase *BKE_curve_nurbs_get(Curve *cu) /* basic vertex data functions */ -int BKE_curve_minmax(Curve *cu, float min[3], float max[3]) +bool BKE_curve_minmax(Curve *cu, float min[3], float max[3]) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -3414,7 +3416,7 @@ int BKE_curve_minmax(Curve *cu, float min[3], float max[3]) return (nurb_lb->first != NULL); } -int BKE_curve_center_median(Curve *cu, float cent[3]) +bool BKE_curve_center_median(Curve *cu, float cent[3]) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; @@ -3452,16 +3454,16 @@ int BKE_curve_center_median(Curve *cu, float cent[3]) return (total != 0); } -int BKE_curve_center_bounds(Curve *cu, float cent[3]) +bool BKE_curve_center_bounds(Curve *cu, float cent[3]) { float min[3], max[3]; INIT_MINMAX(min, max); if (BKE_curve_minmax(cu, min, max)) { mid_v3_v3v3(cent, min, max); - return 1; + return true; } - return 0; + return false; } void BKE_curve_translate(Curve *cu, float offset[3], int do_keys) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 48d7ae1de86..e91fd0cc929 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -195,7 +195,7 @@ static void layerCopy_bmesh_elem_py_ptr(const void *UNUSED(source), void *dest, } #ifndef WITH_PYTHON -void bpy_bm_generic_invalidate(void *UNUSED(self)) +void bpy_bm_generic_invalidate(struct BPy_BMGeneric *UNUSED(self)) { /* dummy */ } @@ -203,8 +203,6 @@ void bpy_bm_generic_invalidate(void *UNUSED(self)) static void layerFree_bmesh_elem_py_ptr(void *data, int count, int size) { - extern void bpy_bm_generic_invalidate(void *self); - int i; for (i = 0; i < count; ++i) { @@ -1174,7 +1172,7 @@ const CustomDataMask CD_MASK_MESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP | - CD_MASK_MTEXPOLY | CD_MASK_NORMAL | CD_MASK_RECAST | CD_MASK_PAINT_MASK | + CD_MASK_MTEXPOLY | CD_MASK_RECAST | CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MSTICKY | CD_MASK_MDEFORMVERT | CD_MASK_MTFACE | CD_MASK_MLOOPUV | @@ -2866,7 +2864,7 @@ static int CustomData_is_property_layer(int type) return 0; } -static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int index) +static bool cd_layer_find_dupe(CustomData *data, const char *name, int type, int index) { int i; /* see if there is a duplicate */ @@ -2876,21 +2874,21 @@ static int cd_layer_find_dupe(CustomData *data, const char *name, int type, int if (CustomData_is_property_layer(type)) { if (CustomData_is_property_layer(layer->type) && strcmp(layer->name, name) == 0) { - return 1; + return true; } } else { if (i != index && layer->type == type && strcmp(layer->name, name) == 0) { - return 1; + return true; } } } } - return 0; + return false; } -static int customdata_unique_check(void *arg, const char *name) +static bool customdata_unique_check(void *arg, const char *name) { struct {CustomData *data; int type; int index; } *data_arg = arg; return cd_layer_find_dupe(data_arg->data, name, data_arg->type, data_arg->index); diff --git a/source/blender/blenkernel/intern/customdata_file.c b/source/blender/blenkernel/intern/customdata_file.c index 78449879f72..c72eea50e40 100644 --- a/source/blender/blenkernel/intern/customdata_file.c +++ b/source/blender/blenkernel/intern/customdata_file.c @@ -29,9 +29,9 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_string.h" -#include "BLI_utildefines.h" #include "BLI_endian_switch.h" #include "BKE_customdata_file.h" @@ -404,7 +404,7 @@ void cdf_write_close(CDataFile *cdf) void cdf_remove(const char *filename) { - BLI_delete(filename, 0, 0); + BLI_delete(filename, false, false); } /********************************** Layers ***********************************/ diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 439180e8d76..2ba71ecd9b5 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -432,22 +432,22 @@ int defgroup_flip_index(Object *ob, int index, int use_default) return (flip_index == -1 && use_default) ? index : flip_index; } -static int defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob) +static bool defgroup_find_name_dupe(const char *name, bDeformGroup *dg, Object *ob) { bDeformGroup *curdef; for (curdef = ob->defbase.first; curdef; curdef = curdef->next) { if (dg != curdef) { if (!strcmp(curdef->name, name)) { - return 1; + return true; } } } - return 0; + return false; } -static int defgroup_unique_check(void *arg, const char *name) +static bool defgroup_unique_check(void *arg, const char *name) { struct {Object *ob; void *dg; } *data = arg; return defgroup_find_name_dupe(name, data->dg, data->ob); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index b919b9ffd8f..3a531cf32ae 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -1555,7 +1555,9 @@ static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) if (itA->node->lasttime != curtime) { itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */ } - else itA->lay = itA->node->lay; + else { + itA->lay = itA->node->lay; + } node->lay |= itA->lay; } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 685d66195c7..4b05f1c1050 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -340,7 +340,7 @@ int dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object * return 0; } -static int surface_duplicateOutputExists(void *arg, const char *name) +static bool surface_duplicateOutputExists(void *arg, const char *name) { DynamicPaintSurface *t_surface = (DynamicPaintSurface *)arg; DynamicPaintSurface *surface = t_surface->canvas->surfaces.first; @@ -349,11 +349,11 @@ static int surface_duplicateOutputExists(void *arg, const char *name) if (surface != t_surface && surface->type == t_surface->type && surface->format == t_surface->format) { - if (surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) return 1; - if (surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2)) return 1; + if (surface->output_name[0] != '\0' && !BLI_path_cmp(name, surface->output_name)) return true; + if (surface->output_name2[0] != '\0' && !BLI_path_cmp(name, surface->output_name2)) return true; } } - return 0; + return false; } static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *basename, int output) @@ -367,15 +367,15 @@ static void surface_setUniqueOutputName(DynamicPaintSurface *surface, char *base } -static int surface_duplicateNameExists(void *arg, const char *name) +static bool surface_duplicateNameExists(void *arg, const char *name) { DynamicPaintSurface *t_surface = (DynamicPaintSurface *)arg; DynamicPaintSurface *surface = t_surface->canvas->surfaces.first; for (; surface; surface = surface->next) { - if (surface != t_surface && !strcmp(name, surface->name)) return 1; + if (surface != t_surface && !strcmp(name, surface->name)) return true; } - return 0; + return false; } void dynamicPaintSurface_setUniqueName(DynamicPaintSurface *surface, const char *basename) @@ -473,7 +473,9 @@ static float mixColors(float a_color[3], float a_weight, float b_color[3], float } weight_ratio = b_weight / (a_weight + b_weight); } - else return a_weight * (1.0f - ratio); + else { + return a_weight * (1.0f - ratio); + } /* calculate final interpolation factor */ if (ratio <= 0.5f) { @@ -2606,7 +2608,9 @@ int dynamicPaint_createUVSurface(DynamicPaintSurface *surface) if (!f_data->uv_p || !f_data->barycentricWeights) error = 1; } - else error = 1; + else { + error = 1; + } sData->total_points = active_points; @@ -2859,7 +2863,9 @@ static void dynamicPaint_doMaterialTex(BrushMaterials *bMats, float color[3], fl mat = bMats->ob_mats[mat_nr]; if (mat == NULL) return; /* No material assigned */ } - else return; + else { + return; + } } RE_sample_material_color(mat, color, alpha, volume_co, surface_co, faceIndex, isQuad, orcoDm, brushOb); @@ -3924,7 +3930,9 @@ static int dynamicPaint_paintSinglePoint(DynamicPaintSurface *surface, float *po strength = 1.0f - distance / brush_radius; CLAMP(strength, 0.0f, 1.0f); } - else strength = 1.0f; + else { + strength = 1.0f; + } if (strength >= 0.001f) { float paintColor[3] = {0.0f}; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 3e1e55132d8..b3edeb67928 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -101,9 +101,9 @@ void BKE_vfont_free(struct VFont *vf) static void *builtin_font_data = NULL; static int builtin_font_size = 0; -int BKE_vfont_is_builtin(struct VFont *vfont) +bool BKE_vfont_is_builtin(struct VFont *vfont) { - return (strcmp(vfont->name, FO_BUILTIN_NAME) == 0); + return STREQ(vfont->name, FO_BUILTIN_NAME); } void BKE_vfont_builtin_register(void *mem, int size) @@ -188,18 +188,14 @@ VFont *BKE_vfont_load(Main *bmain, const char *name) PackedFile *temp_pf = NULL; int is_builtin; - if (strcmp(name, FO_BUILTIN_NAME) == 0) { + if (STREQ(name, FO_BUILTIN_NAME)) { BLI_strncpy(filename, name, sizeof(filename)); pf = get_builtin_packedfile(); is_builtin = TRUE; } else { - char dir[FILE_MAXDIR]; - - BLI_strncpy(dir, name, sizeof(dir)); - BLI_splitdirstring(dir, filename); - + BLI_split_file_part(name, filename, sizeof(filename)); pf = newPackedFile(NULL, name, bmain->name); temp_pf = newPackedFile(NULL, name, bmain->name); @@ -947,10 +943,13 @@ makebreak: ct = chartransdata; for (i = 0; i < slen; i++) { if (ct->linenr == lnr) { - if (ct->charnr == cnr) break; - if ( (ct + 1)->charnr == 0) break; + if ((ct->charnr == cnr) || ((ct + 1)->charnr == 0)) { + break; + } + } + else if (ct->linenr > lnr) { + break; } - else if (ct->linenr > lnr) break; cu->pos++; ct++; } diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 8fab0f2d4df..11d3e69120d 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -30,12 +30,13 @@ * \ingroup bke */ - #include <stdlib.h> #include <string.h> #include "DNA_ID.h" +#include "BLI_utildefines.h" + #include "BKE_idcode.h" typedef struct { @@ -91,9 +92,11 @@ static IDType *idtype_from_name(const char *str) { int i = nidtypes; - while (i--) - if (strcmp(str, idtypes[i].name) == 0) + while (i--) { + if (STREQ(str, idtypes[i].name)) { return &idtypes[i]; + } + } return NULL; } @@ -108,15 +111,15 @@ static IDType *idtype_from_code(int code) return NULL; } -int BKE_idcode_is_valid(int code) +bool BKE_idcode_is_valid(int code) { - return idtype_from_code(code) ? 1 : 0; + return idtype_from_code(code) ? true : false; } -int BKE_idcode_is_linkable(int code) +bool BKE_idcode_is_linkable(int code) { IDType *idt = idtype_from_code(code); - return idt ? (idt->flags & IDTYPE_FLAGS_ISLINKABLE) : 0; + return idt ? ((idt->flags & IDTYPE_FLAGS_ISLINKABLE) != 0) : false; } const char *BKE_idcode_to_name(int code) diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 19ef1e3971d..8dc284e0a3e 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -451,7 +451,7 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, IDProperty *src) IDProperty *loop, *prop; for (prop = src->data.group.first; prop; prop = prop->next) { for (loop = dest->data.group.first; loop; loop = loop->next) { - if (strcmp(loop->name, prop->name) == 0) { + if (STREQ(loop->name, prop->name)) { IDProperty *copy = IDP_CopyProperty(prop); BLI_insertlinkafter(&dest->data.group, loop, copy); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 3655afdf088..c27f5e62520 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1042,7 +1042,7 @@ char BKE_ftype_to_imtype(const int ftype) } -int BKE_imtype_is_movie(const char imtype) +bool BKE_imtype_is_movie(const char imtype) { switch (imtype) { case R_IMF_IMTYPE_AVIRAW: @@ -1053,9 +1053,9 @@ int BKE_imtype_is_movie(const char imtype) case R_IMF_IMTYPE_THEORA: case R_IMF_IMTYPE_XVID: case R_IMF_IMTYPE_FRAMESERVER: - return 1; + return true; } - return 0; + return false; } int BKE_imtype_supports_zbuf(const char imtype) @@ -1567,7 +1567,9 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d if (camera && camera->type == OB_CAMERA) { BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)camera->data)->lens); } - else BLI_strncpy(text, "<none>", sizeof(text)); + else { + BLI_strncpy(text, "<none>", sizeof(text)); + } BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s" : "%s", text); } @@ -1944,7 +1946,7 @@ int BKE_imbuf_write(ImBuf *ibuf, const char *name, ImageFormatData *imf) else if (imtype == R_IMF_IMTYPE_DPX) { ibuf->ftype = DPX; if (imf->cineon_flag & R_IMF_CINEON_FLAG_LOG) { - ibuf->ftype |= CINEON_LOG; + ibuf->ftype |= CINEON_LOG; } if (imf->depth == R_IMF_CHAN_DEPTH_16) { ibuf->ftype |= CINEON_16BIT; diff --git a/source/blender/blenkernel/intern/image_gen.c b/source/blender/blenkernel/intern/image_gen.c index 468a88775c6..415f0a87431 100644 --- a/source/blender/blenkernel/intern/image_gen.c +++ b/source/blender/blenkernel/intern/image_gen.c @@ -24,13 +24,14 @@ * \ingroup bke */ - #include <math.h> #include <stdlib.h> -#include "BKE_image.h" #include "BLI_math_color.h" #include "BLI_math_base.h" + +#include "BKE_image.h" + #include "BLF_api.h" void BKE_image_buf_fill_color(unsigned char *rect, float *rect_float, int width, int height, const float color[4]) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 90cd7bc2df5..b9064fe8ba3 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -1716,7 +1716,7 @@ static void simulate_implicit_euler(lfVector *Vnew, lfVector *UNUSED(lX), lfVect * (edge distance constraints) in a lagrangian solver. then add forces to help * guide the implicit solver to that state. this function is called after * collisions*/ -static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData * clmd, float (*initial_cos)[3], float UNUSED(step), float dt) +static int UNUSED_FUNCTION(cloth_calc_helper_forces)(Object *UNUSED(ob), ClothModifierData *clmd, float (*initial_cos)[3], float UNUSED(step), float dt) { Cloth *cloth= clmd->clothObject; float (*cos)[3] = MEM_callocN(sizeof(float)*3*cloth->numverts, "cos cloth_calc_helper_forces"); diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index f3dc391738e..d123de224e9 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -405,9 +405,13 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float t[4], int cycl) k1 = firstkey; ofs += dpos; } - else if (t[2] == t[3]) break; + else if (t[2] == t[3]) { + break; + } + } + else { + k1 = k1->next; } - else k1 = k1->next; t[0] = t[1]; k[0] = k[1]; @@ -595,7 +599,9 @@ static void cp_key(const int start, int end, const int tot, char *poin, Key *key k1 += a * key->elemsize; } } - else k1 += start * key->elemsize; + else { + k1 += start * key->elemsize; + } } if (mode == KEY_MODE_BEZTRIPLE) { @@ -828,7 +834,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key if (k[0]->totelem) { k1d = k[0]->totelem / (float)tot; } - else flagdo -= 1; + else { + flagdo -= 1; + } } if (tot != k[1]->totelem) { k2tot = 0.0; @@ -836,7 +844,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key if (k[0]->totelem) { k2d = k[1]->totelem / (float)tot; } - else flagdo -= 2; + else { + flagdo -= 2; + } } if (tot != k[2]->totelem) { k3tot = 0.0; @@ -844,7 +854,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key if (k[0]->totelem) { k3d = k[2]->totelem / (float)tot; } - else flagdo -= 4; + else { + flagdo -= 4; + } } if (tot != k[3]->totelem) { k4tot = 0.0; @@ -852,7 +864,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key if (k[0]->totelem) { k4d = k[3]->totelem / (float)tot; } - else flagdo -= 8; + else { + flagdo -= 8; + } } /* this exception needed for slurphing */ @@ -869,7 +883,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k1 += a * key->elemsize; } } - else k1 += start * key->elemsize; + else { + k1 += start * key->elemsize; + } } if (flagdo & 2) { if (flagflo & 2) { @@ -880,7 +896,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k2 += a * key->elemsize; } } - else k2 += start * key->elemsize; + else { + k2 += start * key->elemsize; + } } if (flagdo & 4) { if (flagflo & 4) { @@ -891,7 +909,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k3 += a * key->elemsize; } } - else k3 += start * key->elemsize; + else { + k3 += start * key->elemsize; + } } if (flagdo & 8) { if (flagflo & 8) { @@ -902,7 +922,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k4 += a * key->elemsize; } } - else k4 += start * key->elemsize; + else { + k4 += start * key->elemsize; + } } } @@ -968,7 +990,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k2 += elemsize; } } - else k2 += elemsize; + else { + k2 += elemsize; + } } if (flagdo & 4) { if (flagflo & 4) { @@ -978,7 +1002,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k3 += elemsize; } } - else k3 += elemsize; + else { + k3 += elemsize; + } } if (flagdo & 8) { if (flagflo & 8) { @@ -988,7 +1014,9 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key k4 += elemsize; } } - else k4 += elemsize; + else { + k4 += elemsize; + } } if (mode == KEY_MODE_BEZTRIPLE) a += 2; diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index c3e7a963c04..c881209b109 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -404,9 +404,11 @@ void calc_latt_deform(Object *ob, float co[3], float weight) if (w != 0.0f) { if (ww > 0) { if (ww < lt->pntsw) idx_w = ww * lt->pntsu * lt->pntsv; - else idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv; + else idx_w = (lt->pntsw - 1) * lt->pntsu * lt->pntsv; + } + else { + idx_w = 0; } - else idx_w = 0; for (vv = vi - 1; vv <= vi + 2; vv++) { v = w * tv[vv - vi + 1]; @@ -414,9 +416,11 @@ void calc_latt_deform(Object *ob, float co[3], float weight) if (v != 0.0f) { if (vv > 0) { if (vv < lt->pntsv) idx_v = idx_w + vv * lt->pntsu; - else idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu; + else idx_v = idx_w + (lt->pntsv - 1) * lt->pntsu; + } + else { + idx_v = idx_w; } - else idx_v = idx_w; for (uu = ui - 1; uu <= ui + 2; uu++) { u = weight * v * tu[uu - ui + 1]; @@ -424,9 +428,11 @@ void calc_latt_deform(Object *ob, float co[3], float weight) if (u != 0.0f) { if (uu > 0) { if (uu < lt->pntsu) idx_u = idx_v + uu; - else idx_u = idx_v + (lt->pntsu - 1); + else idx_u = idx_v + (lt->pntsu - 1); + } + else { + idx_u = idx_v; } - else idx_u = idx_v; madd_v3_v3fl(co, <->latticedata[idx_u * 3], u); @@ -492,7 +498,9 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir if (cycl == 0) { ctime1 = CLAMPIS(ctime, 0.0f, 1.0f); } - else ctime1 = ctime; + else { + ctime1 = ctime; + } /* vec needs 4 items */ if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index b4c1d681ddc..67fc5bd5dca 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -174,6 +174,7 @@ void id_us_plus(ID *id) } } +/* decrements the user count for *id. */ void id_us_min(ID *id) { if (id) { @@ -189,106 +190,112 @@ void id_us_min(ID *id) } } -int id_make_local(ID *id, int test) +/* calls the appropriate make_local method for the block, unless test. Returns true + * if the block can be made local. */ +bool id_make_local(ID *id, bool test) { if (id->flag & LIB_INDIRECT) - return 0; + return false; switch (GS(id->name)) { case ID_SCE: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_LI: - return 0; /* can't be linked */ + return false; /* can't be linked */ case ID_OB: if (!test) BKE_object_make_local((Object *)id); - return 1; + return true; case ID_ME: if (!test) { BKE_mesh_make_local((Mesh *)id); BKE_key_make_local(((Mesh *)id)->key); } - return 1; + return true; case ID_CU: if (!test) { BKE_curve_make_local((Curve *)id); BKE_key_make_local(((Curve *)id)->key); } - return 1; + return true; case ID_MB: if (!test) BKE_mball_make_local((MetaBall *)id); - return 1; + return true; case ID_MA: if (!test) BKE_material_make_local((Material *)id); - return 1; + return true; case ID_TE: if (!test) BKE_texture_make_local((Tex *)id); - return 1; + return true; case ID_IM: if (!test) BKE_image_make_local((Image *)id); - return 1; + return true; case ID_LT: if (!test) { BKE_lattice_make_local((Lattice *)id); BKE_key_make_local(((Lattice *)id)->key); } - return 1; + return true; case ID_LA: if (!test) BKE_lamp_make_local((Lamp *)id); - return 1; + return true; case ID_CA: if (!test) BKE_camera_make_local((Camera *)id); - return 1; + return true; case ID_SPK: if (!test) BKE_speaker_make_local((Speaker *)id); - return 1; + return true; case ID_IP: - return 0; /* deprecated */ + return false; /* deprecated */ case ID_KE: if (!test) BKE_key_make_local((Key *)id); - return 1; + return true; case ID_WO: if (!test) BKE_world_make_local((World *)id); - return 1; + return true; case ID_SCR: - return 0; /* can't be linked */ + return false; /* can't be linked */ case ID_VF: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_TXT: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_SCRIPT: - return 0; /* deprecated */ + return false; /* deprecated */ case ID_SO: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_GR: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_AR: if (!test) BKE_armature_make_local((bArmature *)id); - return 1; + return true; case ID_AC: if (!test) BKE_action_make_local((bAction *)id); - return 1; + return true; case ID_NT: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_BR: if (!test) BKE_brush_make_local((Brush *)id); - return 1; + return true; case ID_PA: if (!test) BKE_particlesettings_make_local((ParticleSettings *)id); - return 1; + return true; case ID_WM: - return 0; /* can't be linked */ + return false; /* can't be linked */ case ID_GD: - return 0; /* not implemented */ + return false; /* not implemented */ #ifdef WITH_FREESTYLE case ID_LS: return 0; /* not implemented */ #endif } - return 0; + return false; } -int id_copy(ID *id, ID **newid, int test) +/** + * Invokes the appropriate copy method for the block and returns the result in + * newid, unless test. Returns true iff the block can be copied. + */ +bool id_copy(ID *id, ID **newid, bool test) { if (!test) *newid = NULL; @@ -297,86 +304,86 @@ int id_copy(ID *id, ID **newid, int test) * - id.us of the new ID is set to 1 */ switch (GS(id->name)) { case ID_SCE: - return 0; /* can't be copied from here */ + return false; /* can't be copied from here */ case ID_LI: - return 0; /* can't be copied from here */ + return false; /* can't be copied from here */ case ID_OB: if (!test) *newid = (ID *)BKE_object_copy((Object *)id); - return 1; + return true; case ID_ME: if (!test) *newid = (ID *)BKE_mesh_copy((Mesh *)id); - return 1; + return true; case ID_CU: if (!test) *newid = (ID *)BKE_curve_copy((Curve *)id); - return 1; + return true; case ID_MB: if (!test) *newid = (ID *)BKE_mball_copy((MetaBall *)id); - return 1; + return true; case ID_MA: if (!test) *newid = (ID *)BKE_material_copy((Material *)id); - return 1; + return true; case ID_TE: if (!test) *newid = (ID *)BKE_texture_copy((Tex *)id); - return 1; + return true; case ID_IM: if (!test) *newid = (ID *)BKE_image_copy(G.main, (Image *)id); - return 1; + return true; case ID_LT: if (!test) *newid = (ID *)BKE_lattice_copy((Lattice *)id); - return 1; + return true; case ID_LA: if (!test) *newid = (ID *)BKE_lamp_copy((Lamp *)id); - return 1; + return true; case ID_SPK: if (!test) *newid = (ID *)BKE_speaker_copy((Speaker *)id); - return 1; + return true; case ID_CA: if (!test) *newid = (ID *)BKE_camera_copy((Camera *)id); - return 1; + return true; case ID_IP: - return 0; /* deprecated */ + return false; /* deprecated */ case ID_KE: if (!test) *newid = (ID *)BKE_key_copy((Key *)id); - return 1; + return true; case ID_WO: if (!test) *newid = (ID *)BKE_world_copy((World *)id); - return 1; + return true; case ID_SCR: - return 0; /* can't be copied from here */ + return false; /* can't be copied from here */ case ID_VF: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_TXT: if (!test) *newid = (ID *)BKE_text_copy((Text *)id); - return 1; + return true; case ID_SCRIPT: - return 0; /* deprecated */ + return false; /* deprecated */ case ID_SO: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_GR: if (!test) *newid = (ID *)BKE_group_copy((Group *)id); - return 1; + return true; case ID_AR: if (!test) *newid = (ID *)BKE_armature_copy((bArmature *)id); - return 1; + return true; case ID_AC: if (!test) *newid = (ID *)BKE_action_copy((bAction *)id); - return 1; + return true; case ID_NT: if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id); - return 1; + return true; case ID_BR: if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id); - return 1; + return true; case ID_PA: if (!test) *newid = (ID *)BKE_particlesettings_copy((ParticleSettings *)id); - return 1; + return true; case ID_WM: - return 0; /* can't be copied from here */ + return false; /* can't be copied from here */ case ID_GD: - return 0; /* not implemented */ + return false; /* not implemented */ case ID_MSK: if (!test) *newid = (ID *)BKE_mask_copy((Mask *)id); - return 1; + return true; #ifdef WITH_FREESTYLE case ID_LS: if(!test) *newid= (ID*)FRS_copy_linestyle((FreestyleLineStyle*)id); @@ -384,42 +391,42 @@ int id_copy(ID *id, ID **newid, int test) #endif } - return 0; + return false; } -int id_unlink(ID *id, int test) +bool id_unlink(ID *id, int test) { Main *mainlib = G.main; ListBase *lb; switch (GS(id->name)) { case ID_TXT: - if (test) return 1; + if (test) return true; BKE_text_unlink(mainlib, (Text *)id); break; case ID_GR: - if (test) return 1; + if (test) return true; BKE_group_unlink((Group *)id); break; case ID_OB: - if (test) return 1; + if (test) return true; BKE_object_unlink((Object *)id); break; } if (id->us == 0) { - if (test) return 1; + if (test) return true; lb = which_libbase(mainlib, GS(id->name)); BKE_libblock_free(lb, id); - return 1; + return true; } - return 0; + return false; } -int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) +bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) { ID *newid = NULL; PointerRNA idptr; @@ -427,7 +434,7 @@ int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) if (id) { /* if property isn't editable, we're going to have an extra block hanging around until we save */ if (RNA_property_editable(ptr, prop)) { - if (id_copy(id, &newid, 0) && newid) { + if (id_copy(id, &newid, false) && newid) { /* copy animation actions too */ BKE_copy_animdata_id_action(id); /* us is 1 by convention, but RNA_property_pointer_set @@ -439,12 +446,12 @@ int id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) RNA_property_pointer_set(ptr, prop, idptr); RNA_property_update(C, ptr, prop); - return 1; + return true; } } } - return 0; + return false; } ListBase *which_libbase(Main *mainlib, short type) @@ -552,7 +559,13 @@ void recalc_all_library_objects(Main *main) ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; } -/* note: MAX_LIBARRAY define should match this code */ +/** + * puts into array *lb pointers to all the ListBase structs in main, + * and returns the number of them as the function result. This is useful for + * generic traversal of all the blocks in a Main (by traversing all the + * lists in turn), without worrying about block types. + * + * \note MAX_LIBARRAY define should match this code */ int set_listbasepointers(Main *main, ListBase **lb) { int a = 0; @@ -619,6 +632,10 @@ int set_listbasepointers(Main *main, ListBase **lb) * * **************************** */ +/** + * Allocates and returns memory of the right size for the specified block type, + * initialized to zero. + */ static ID *alloc_libblock_notest(short type) { ID *id = NULL; @@ -726,7 +743,12 @@ static ID *alloc_libblock_notest(short type) return id; } -/* used everywhere in blenkernel and text.c */ +/** + * Allocates and returns a block of the specified type, with the specified name + * (adjusted as necessary to ensure uniqueness), and appended to the specified list. + * The user count is set to 1, all other content (apart from name and links) being + * initialized to zero. + */ void *BKE_libblock_alloc(ListBase *lb, short type, const char *name) { ID *id = NULL; @@ -738,25 +760,25 @@ void *BKE_libblock_alloc(ListBase *lb, short type, const char *name) id->icon_id = 0; *( (short *)id->name) = type; new_id(lb, id, name); - /* alphabetic insterion: is in new_id */ + /* alphabetic insertion: is in new_id */ } return id; } /* by spec, animdata is first item after ID */ /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ -static void id_copy_animdata(ID *id, const short do_action) +static void id_copy_animdata(ID *id, const bool do_action) { AnimData *adt = BKE_animdata_from_id(id); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id; - iat->adt = BKE_copy_animdata(iat->adt, do_action); /* could be set to FALSE, need to investigate */ + iat->adt = BKE_copy_animdata(iat->adt, do_action); /* could be set to false, need to investigate */ } } /* material nodes use this since they are not treated as libdata */ -void BKE_libblock_copy_data(ID *id, const ID *id_from, const short do_action) +void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action) { if (id_from->properties) id->properties = IDP_CopyProperty(id_from->properties); @@ -788,7 +810,7 @@ void *BKE_libblock_copy_ex(Main *bmain, ID *id) id->newid = idn; idn->flag |= LIB_NEW; - BKE_libblock_copy_data(idn, id, FALSE); + BKE_libblock_copy_data(idn, id, false); return idn; } @@ -1207,7 +1229,7 @@ void id_sort_by_name(ListBase *lb, ID *id) } -/* +/** * Check to see if there is an ID with the same name as 'name'. * Returns the ID if so, if not, returns NULL */ @@ -1229,9 +1251,9 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name) return idtest; } -/* +/** * Check to see if an ID name is already used, and find a new one if so. - * Return 1 if created a new name (returned in name). + * Return true if created a new name (returned in name). * * Normally the ID that's being check is already in the ListBase, so ID *id * points at the new entry. The Python Library module needs to know what @@ -1239,11 +1261,13 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name) * id is NULL */ -static int check_for_dupid(ListBase *lb, ID *id, char *name) +static bool check_for_dupid(ListBase *lb, ID *id, char *name) { ID *idtest; int nr = 0, nrtest, a, left_len; - char in_use[64]; /* use as a boolean array, unrelated to name length */ +#define MAX_IN_USE 64 + bool in_use[MAX_IN_USE]; + /* to speed up finding unused numbers within [1 .. MAX_IN_USE - 1] */ char left[MAX_ID_NAME + 8], leftest[MAX_ID_NAME + 8]; @@ -1251,23 +1275,23 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) /* if ( strlen(name) > MAX_ID_NAME-3 ) name[MAX_ID_NAME-3] = 0; */ /* removed since this is only ever called from one place - campbell */ - while (1) { + while (true) { /* phase 1: id already exists? */ idtest = is_dupid(lb, id, name); /* if there is no double, done */ - if (idtest == NULL) return 0; + if (idtest == NULL) return false; /* we have a dup; need to make a new name */ - /* quick check so we can reuse one of first 64 ids if vacant */ - memset(in_use, 0, sizeof(in_use)); + /* quick check so we can reuse one of first MAX_IN_USE - 1 ids if vacant */ + memset(in_use, false, sizeof(in_use)); /* get name portion, number portion ("name.number") */ left_len = BLI_split_name_num(left, &nr, name, '.'); /* if new name will be too long, truncate it */ - if (nr > 999 && left_len > (MAX_ID_NAME - 8)) { + if (nr > 999 && left_len > (MAX_ID_NAME - 8)) { /* assumption: won't go beyond 9999 */ left[MAX_ID_NAME - 8] = 0; left_len = MAX_ID_NAME - 8; } @@ -1284,35 +1308,50 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) (BLI_split_name_num(leftest, &nrtest, idtest->name + 2, '.') == left_len) ) { - if (nrtest < sizeof(in_use)) - in_use[nrtest] = 1; /* mark as used */ + /* will get here at least once, otherwise is_dupid call above would have returned NULL */ + if (nrtest < MAX_IN_USE) + in_use[nrtest] = true; /* mark as used */ if (nr <= nrtest) nr = nrtest + 1; /* track largest unused */ } } + /* At this point, nr will be at least 1. */ + BLI_assert(nr >= 1); /* decide which value of nr to use */ - for (a = 0; a < sizeof(in_use); a++) { - if (a >= nr) break; /* stop when we've check up to biggest */ - if (in_use[a] == 0) { /* found an unused value */ + for (a = 0; a < MAX_IN_USE; a++) { + if (a >= nr) break; /* stop when we've checked up to biggest */ /* redundant check */ + if (!in_use[a]) { /* found an unused value */ nr = a; + /* can only be zero if all potential duplicate names had + * nonzero numeric suffixes, which means name itself has + * nonzero numeric suffix (else no name conflict and wouldn't + * have got here), which means name[left_len] is not a null */ break; } } + /* At this point, nr is either the lowest unused number within [0 .. MAX_IN_USE - 1], + * or 1 greater than the largest used number if all those low ones are taken. + * We can't be bothered to look for the lowest unused number beyond (MAX_IN_USE - 1). */ /* If the original name has no numeric suffix, * rather than just chopping and adding numbers, * shave off the end chars until we have a unique name. * Check the null terminators match as well so we don't get Cube.000 -> Cube.00 */ if (nr == 0 && name[left_len] == '\0') { - int len = left_len - 1; + int len; + /* FIXME: this code will never be executed, because either nr will be + * at least 1, or name will not end at left_len! */ + BLI_assert(0); + + len = left_len - 1; idtest = is_dupid(lb, id, name); while (idtest && len > 1) { name[len--] = '\0'; idtest = is_dupid(lb, id, name); } - if (idtest == NULL) return 1; + if (idtest == NULL) return true; /* otherwise just continue and use a number suffix */ } @@ -1326,24 +1365,26 @@ static int check_for_dupid(ListBase *lb, ID *id, char *name) /* this format specifier is from hell... */ BLI_snprintf(name, sizeof(id->name) - 2, "%s.%.3d", left, nr); - return 1; + return true; } + +#undef MAX_IN_USE } /* * Only for local blocks: external en indirect blocks already have a * unique ID. * - * return 1: created a new name + * return true: created a new name */ -int new_id(ListBase *lb, ID *id, const char *tname) +bool new_id(ListBase *lb, ID *id, const char *tname) { - int result; + bool result; char name[MAX_ID_NAME - 2]; /* if library, don't rename */ - if (id->lib) return 0; + if (id->lib) return false; /* if no libdata given, look up based on ID */ if (lb == NULL) lb = which_libbase(G.main, GS(id->name)); @@ -1415,10 +1456,9 @@ void clear_id_newpoins(void) } } -#define LIBTAG(a) if (a && a->id.lib) { a->id.flag &= ~LIB_INDIRECT; a->id.flag |= LIB_EXTERN; } (void)0 - static void lib_indirect_test_id(ID *id, Library *lib) { +#define LIBTAG(a) if (a && a->id.lib) { a->id.flag &= ~LIB_INDIRECT; a->id.flag |= LIB_EXTERN; } (void)0 if (id->lib) { /* datablocks that were indirectly related are now direct links @@ -1458,6 +1498,8 @@ static void lib_indirect_test_id(ID *id, Library *lib) me = ob->data; LIBTAG(me); } + +#undef LIBTAG } void tag_main_lb(ListBase *lb, const short tag) @@ -1495,9 +1537,9 @@ void tag_main(struct Main *mainvar, const short tag) /* if lib!=NULL, only all from lib local * bmain is almost certainly G.main */ -void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only) +void BKE_library_make_local(Main *bmain, Library *lib, bool untagged_only) { - ListBase *lbarray[MAX_LIBARRAY], tempbase = {NULL, NULL}; + ListBase *lbarray[MAX_LIBARRAY]; ID *id, *idn; int a; @@ -1515,7 +1557,7 @@ void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only) * (very nasty to discover all your links are lost after appending) * */ if (id->flag & (LIB_EXTERN | LIB_INDIRECT | LIB_NEW) && - (untagged_only == 0 || !(id->flag & LIB_PRE_EXISTING))) + ((untagged_only == false) || !(id->flag & LIB_PRE_EXISTING))) { if (lib == NULL || id->lib == lib) { if (id->lib) { @@ -1532,16 +1574,8 @@ void BKE_library_make_local(Main *bmain, Library *lib, int untagged_only) } id = idn; } - - /* patch2: make it aphabetically */ - while ( (id = tempbase.first) ) { - BLI_remlink(&tempbase, id); - BLI_addtail(lbarray[a], id); - new_id(lbarray[a], id, NULL); - } } - /* patch 3: make sure library data isn't indirect falsely... */ a = set_listbasepointers(bmain, lbarray); while (a--) { for (id = lbarray[a]->first; id; id = id->next) @@ -1557,39 +1591,20 @@ void test_idbutton(char *name) ID *idtest; - lb = which_libbase(G.main, GS(name - 2) ); + lb = which_libbase(G.main, GS(name) ); if (lb == NULL) return; /* search for id */ - idtest = BLI_findstring(lb, name, offsetof(ID, name) + 2); + idtest = BLI_findstring(lb, name + 2, offsetof(ID, name) + 2); - if (idtest && (new_id(lb, idtest, name) == 0)) { + if (idtest && !new_id(lb, idtest, name + 2)) { id_sort_by_name(lb, idtest); } } -void text_idbutton(struct ID *id, char *text) -{ - if (id) { - if (GS(id->name) == ID_SCE) - strcpy(text, "SCE: "); - else if (GS(id->name) == ID_SCR) - strcpy(text, "SCR: "); - else if (GS(id->name) == ID_MA && ((Material *)id)->use_nodes) - strcpy(text, "NT: "); - else { - text[0] = id->name[0]; - text[1] = id->name[1]; - text[2] = ':'; - text[3] = ' '; - text[4] = 0; - } - } - else { - text[0] = '\0'; - } -} - +/** + * Sets the name of a block to name, suitably adjusted for uniqueness. + */ void rename_id(ID *id, const char *name) { ListBase *lb; @@ -1600,7 +1615,11 @@ void rename_id(ID *id, const char *name) new_id(lb, id, name); } -void name_uiprefix_id(char *name, ID *id) +/** + * Returns in name the name of the block, with a 3-character prefix prepended + * indicating whether it comes from a library, has a fake user, or no users. + */ +void name_uiprefix_id(char *name, const ID *id) { name[0] = id->lib ? 'L' : ' '; name[1] = id->flag & LIB_FAKEUSER ? 'F' : (id->us == 0) ? '0' : ' '; diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index aa9200adef4..ca3a910f403 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -39,6 +39,10 @@ #include "DNA_material_types.h" /* for ramp blend */ #include "DNA_texture_types.h" +#include "BLI_blenlib.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + #include "BKE_global.h" #include "BKE_library.h" #include "BKE_linestyle.h" @@ -47,9 +51,6 @@ #include "BKE_colortools.h" #include "BKE_animsys.h" -#include "BLI_blenlib.h" -#include "BLI_math.h" - static const char *modifier_name[LS_MODIFIER_NUM] = { NULL, "Along Stroke", diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 50e00161db3..6f6686150ae 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1797,7 +1797,9 @@ static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag) ma->game.flag = -flag; id_us_min((ID *)ma); } - else printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2); + else { + printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2); + } } /* set as converted, no need to go bad to this face */ diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 5cc3145213c..72284130869 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -439,18 +439,15 @@ float *BKE_mball_make_orco(Object *ob, ListBase *dispbase) * It test last character of Object ID name. If last character * is digit it return 0, else it return 1. */ -int BKE_mball_is_basis(Object *ob) +bool BKE_mball_is_basis(Object *ob) { - int len; - /* just a quick test */ - len = strlen(ob->id.name); - if (isdigit(ob->id.name[len - 1]) ) return 0; - return 1; + const int len = strlen(ob->id.name); + return (!isdigit(ob->id.name[len - 1])); } /* return nonzero if ob1 is a basis mball for ob */ -int BKE_mball_is_basis_for(Object *ob1, Object *ob2) +bool BKE_mball_is_basis_for(Object *ob1, Object *ob2) { int basis1nr, basis2nr; char basis1name[MAX_ID_NAME], basis2name[MAX_ID_NAME]; @@ -458,8 +455,12 @@ int BKE_mball_is_basis_for(Object *ob1, Object *ob2) BLI_split_name_num(basis1name, &basis1nr, ob1->id.name + 2, '.'); BLI_split_name_num(basis2name, &basis2nr, ob2->id.name + 2, '.'); - if (!strcmp(basis1name, basis2name)) return BKE_mball_is_basis(ob1); - else return 0; + if (!strcmp(basis1name, basis2name)) { + return BKE_mball_is_basis(ob1); + } + else { + return false; + } } /* \brief copy some properties from object to other metaball object with same base name @@ -1500,7 +1501,7 @@ static void add_cube(PROCESS *mbproc, int i, int j, int k, int count) static void find_first_points(PROCESS *mbproc, MetaBall *mb, int a) { MetaElem *ml; - float f = 0.0f; + float f; ml = G_mb.mainb[a]; f = 1.0f - (mb->thresh / ml->s); @@ -2293,7 +2294,9 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) } /* width is size per polygonize cube */ - if (G.is_rendering) width = mb->rendersize; + if (G.is_rendering) { + width = mb->rendersize; + } else { width = mb->wiresize; if (G.moving && mb->flag == MB_UPDATE_HALFRES) width *= 2; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index f6f60d03cf7..b4833cdb53b 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1198,7 +1198,7 @@ void BKE_mesh_from_metaball(ListBase *lb, Mesh *me) BKE_mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL); - BKE_mesh_calc_edges(me, TRUE); + BKE_mesh_calc_edges(me, true, false); } } @@ -1523,7 +1523,7 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, int use_orco_u BKE_mesh_calc_normals(me->mvert, me->totvert, me->mloop, me->mpoly, me->totloop, me->totpoly, NULL); - BKE_mesh_calc_edges(me, TRUE); + BKE_mesh_calc_edges(me, true, false); } else { me = BKE_mesh_add(G.main, "Mesh"); @@ -1586,65 +1586,46 @@ static void appendPolyLineVert(ListBase *lb, unsigned int index) BLI_addtail(lb, vl); } -void BKE_mesh_from_curve(Scene *scene, Object *ob) +void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int edge_users_test) { - /* make new mesh data from the original copy */ - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH); - - MVert *mverts = dm->getVertArray(dm); + MVert *mvert = dm->getVertArray(dm); MEdge *med, *medge = dm->getEdgeArray(dm); - MFace *mf, *mface = dm->getTessFaceArray(dm); + MPoly *mp, *mpoly = dm->getPolyArray(dm); + MLoop *mloop = dm->getLoopArray(dm); - int totedge = dm->getNumEdges(dm); - int totface = dm->getNumTessFaces(dm); + int dm_totedge = dm->getNumEdges(dm); + int dm_totpoly = dm->getNumPolys(dm); int totedges = 0; - int i, needsFree = 0; + int i; /* only to detect edge polylines */ - EdgeHash *eh = BLI_edgehash_new(); - EdgeHash *eh_edge = BLI_edgehash_new(); - + int *edge_users; ListBase edges = {NULL, NULL}; - /* create edges from all faces (so as to find edges not in any faces) */ - mf = mface; - for (i = 0; i < totface; i++, mf++) { - if (!BLI_edgehash_haskey(eh, mf->v1, mf->v2)) - BLI_edgehash_insert(eh, mf->v1, mf->v2, NULL); - if (!BLI_edgehash_haskey(eh, mf->v2, mf->v3)) - BLI_edgehash_insert(eh, mf->v2, mf->v3, NULL); - - if (mf->v4) { - if (!BLI_edgehash_haskey(eh, mf->v3, mf->v4)) - BLI_edgehash_insert(eh, mf->v3, mf->v4, NULL); - if (!BLI_edgehash_haskey(eh, mf->v4, mf->v1)) - BLI_edgehash_insert(eh, mf->v4, mf->v1, NULL); - } - else { - if (!BLI_edgehash_haskey(eh, mf->v3, mf->v1)) - BLI_edgehash_insert(eh, mf->v3, mf->v1, NULL); + /* get boundary edges */ + edge_users = MEM_callocN(sizeof(int) * dm_totedge, __func__); + for (i = 0, mp = mpoly; i < dm_totpoly; i++, mp++) { + MLoop *ml = &mloop[mp->loopstart]; + int j; + for (j = 0; j < mp->totloop; j++, ml++) { + edge_users[ml->e]++; } } + /* create edges from all faces (so as to find edges not in any faces) */ med = medge; - for (i = 0; i < totedge; i++, med++) { - if (!BLI_edgehash_haskey(eh, med->v1, med->v2)) { + for (i = 0; i < dm_totedge; i++, med++) { + if (edge_users[i] == edge_users_test) { EdgeLink *edl = MEM_callocN(sizeof(EdgeLink), "EdgeLink"); - - BLI_edgehash_insert(eh_edge, med->v1, med->v2, NULL); edl->edge = med; BLI_addtail(&edges, edl); totedges++; } } - BLI_edgehash_free(eh_edge, NULL); - BLI_edgehash_free(eh, NULL); + MEM_freeN(edge_users); if (edges.first) { - Curve *cu = BKE_curve_add(G.main, ob->id.name + 2, OB_CURVE); - cu->flag |= CU_3D; - while (edges.first) { /* each iteration find a polyline and add this as a nurbs poly spline */ @@ -1724,24 +1705,41 @@ void BKE_mesh_from_curve(Scene *scene, Object *ob) /* add points */ vl = polyline.first; for (i = 0, bp = nu->bp; i < totpoly; i++, bp++, vl = (VertLink *)vl->next) { - copy_v3_v3(bp->vec, mverts[vl->index].co); + copy_v3_v3(bp->vec, mvert[vl->index].co); bp->f1 = SELECT; bp->radius = bp->weight = 1.0; } BLI_freelistN(&polyline); /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + BLI_addtail(nurblist, nu); } /* --- done with nurbs --- */ } + } +} + +void BKE_mesh_to_curve(Scene *scene, Object *ob) +{ + /* make new mesh data from the original copy */ + DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH); + ListBase nurblist = {NULL, NULL}; + bool needsFree = false; + + BKE_mesh_to_curve_nurblist(dm, &nurblist, 0); + + if (nurblist.first) { + Curve *cu = BKE_curve_add(G.main, ob->id.name + 2, OB_CURVE); + cu->flag |= CU_3D; + + cu->nurb = nurblist; ((Mesh *)ob->data)->id.us--; ob->data = cu; ob->type = OB_CURVE; /* curve objects can't contain DM in usual cases, we could free memory */ - needsFree = 1; + needsFree = true; } dm->needsFree = needsFree; diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 74d3645ea66..9d16d38220a 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -774,7 +774,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } if (do_edge_recalc) { - BKE_mesh_calc_edges(mesh, TRUE); + BKE_mesh_calc_edges(mesh, true, false); } } @@ -914,7 +914,7 @@ int BKE_mesh_validate_dm(DerivedMesh *dm) * \param mesh The mesh to add edges into * \param update When true create new edges co-exist */ -void BKE_mesh_calc_edges(Mesh *mesh, int update) +void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select) { CustomData edata; EdgeHashIterator *ehi; @@ -923,9 +923,11 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) EdgeHash *eh = BLI_edgehash_new(); int i, totedge, totpoly = mesh->totpoly; int med_index; + /* select for newly created meshes which are selected [#25595] */ + const short ed_flag = (ME_EDGEDRAW | ME_EDGERENDER) | (select ? SELECT : 0); if (mesh->totedge == 0) - update = FALSE; + update = false; if (update) { /* assume existing edges are valid @@ -963,7 +965,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, int update) } else { BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); - med->flag = ME_EDGEDRAW | ME_EDGERENDER | SELECT; /* select for newly created meshes which are selected [#25595] */ + med->flag = ed_flag; } /* store the new edge index in the hash value */ diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 5519edca7ff..e79754ca203 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1230,7 +1230,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->ok = TRUE; } -static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted) +static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, int proxy_render_size, int undistorted, bool threaded) { char name[FILE_MAX]; int quality, rectx, recty; @@ -1244,7 +1244,10 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i scaleibuf = IMB_dupImBuf(ibuf); - IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty); + if (threaded) + IMB_scaleImBuf_threaded(scaleibuf, (short)rectx, (short)recty); + else + IMB_scaleImBuf(scaleibuf, (short)rectx, (short)recty); quality = clip->proxy.quality; scaleibuf->ftype = JPG | quality; @@ -1253,6 +1256,10 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i if (scaleibuf->planes == 32) scaleibuf->planes = 24; + /* TODO: currently the most weak part of multithreaded proxies, + * could be solved in a way that thread only prepares memory + * buffer and write to disk happens separately + */ BLI_lock_thread(LOCK_MOVIECLIP); BLI_make_existing_file(name); @@ -1264,12 +1271,18 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i IMB_freeImBuf(scaleibuf); } +/* note: currently used by proxy job for movies, threading happens within single frame + * (meaning scaling shall be threaded) + */ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct MovieDistortion *distortion, int cfra, int *build_sizes, int build_count, int undistorted) { ImBuf *ibuf; MovieClipUser user; + if (!build_count) + return; + user.framenr = cfra; user.render_flag = 0; user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; @@ -1284,7 +1297,7 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf); for (i = 0; i < build_count; i++) - movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted); + movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, true); IMB_freeImBuf(ibuf); @@ -1293,6 +1306,30 @@ void BKE_movieclip_build_proxy_frame(MovieClip *clip, int clip_flag, struct Movi } } +/* note: currently used by proxy job for sequences, threading happens within sequence + * (different threads handles different frames, no threading within frame is needed) + */ +void BKE_movieclip_build_proxy_frame_for_ibuf(MovieClip *clip, ImBuf *ibuf, struct MovieDistortion *distortion, + int cfra, int *build_sizes, int build_count, int undistorted) +{ + if (!build_count) + return; + + if (ibuf) { + ImBuf *tmpibuf = ibuf; + int i; + + if (undistorted) + tmpibuf = get_undistorted_ibuf(clip, distortion, ibuf); + + for (i = 0; i < build_count; i++) + movieclip_build_proxy_ibuf(clip, tmpibuf, cfra, build_sizes[i], undistorted, false); + + if (tmpibuf != ibuf) + IMB_freeImBuf(tmpibuf); + } +} + void BKE_movieclip_free(MovieClip *clip) { BKE_sequencer_clear_movieclip_in_clipboard(clip); @@ -1381,3 +1418,14 @@ float BKE_movieclip_remap_clip_to_scene_frame(MovieClip *clip, float framenr) { return framenr + (float) clip->start_frame - 1.0f; } + +void BKE_movieclip_filename_for_frame(MovieClip *clip, int framenr, char *name) +{ + if (clip->source != MCLIP_SRC_MOVIE) { + get_sequence_fname(clip, framenr, name); + } + else { + BLI_strncpy(name, clip->name, FILE_MAX); + BLI_path_abs(name, ID_BLEND_PATH(G.main, &clip->id)); + } +} diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index 3bf5f863557..1d662ae3116 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -436,7 +436,7 @@ int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly, unsigned short **polys, int **dtrisToPolysMap, int **dtrisToTrisMap, int **trisToFacesMap) { - int res = 1; + int res; int ntris = 0, *recastData = NULL; unsigned short *tris = NULL; diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 143f2186020..ccae1f606fc 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -1262,7 +1262,7 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip) /* Sanity Validation ------------------------------------ */ -static int nla_editbone_name_check(void *arg, const char *name) +static bool nla_editbone_name_check(void *arg, const char *name) { return BLI_ghash_haskey((GHash *)arg, (void *)name); } @@ -1660,7 +1660,7 @@ void BKE_nla_tweakmode_exit(AnimData *adt) /* Baking Tools ------------------------------------------- */ -static void UNUSED_FUNCTION(BKE_nla_bake) (Scene * scene, ID *UNUSED(id), AnimData * adt, int UNUSED(flag)) +static void UNUSED_FUNCTION(BKE_nla_bake) (Scene *scene, ID *UNUSED(id), AnimData *adt, int UNUSED(flag)) { /* verify that data is valid diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 3dbaab008f8..974a564b9da 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -571,6 +571,12 @@ void nodeInternalRelink(bNodeTree *ntree, bNode *node) link->fromnode = fromlink->fromnode; link->fromsock = fromlink->fromsock; + /* if the up- or downstream link is invalid, + * the replacement link will be invalid too. + */ + if (!(fromlink->flag & NODE_LINK_VALID)) + link->flag &= ~NODE_LINK_VALID; + ntree->update |= NTREE_UPDATE_LINKS; } else @@ -710,7 +716,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, const short do_id_use } else { newtree = MEM_dupallocN(ntree); - BKE_libblock_copy_data(&newtree->id, &ntree->id, TRUE); /* copy animdata and ID props */ + BKE_libblock_copy_data(&newtree->id, &ntree->id, true); /* copy animdata and ID props */ } id_us_plus((ID *)newtree->gpd); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 5cea2c9fe0e..0c6e0f72523 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -189,7 +189,7 @@ void BKE_object_free_modifiers(Object *ob) BKE_object_free_softbody(ob); } -int BKE_object_support_modifier_type_check(Object *ob, int modifier_type) +bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type) { ModifierTypeInfo *mti; @@ -198,10 +198,10 @@ int BKE_object_support_modifier_type_check(Object *ob, int modifier_type) if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) || (ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh)))) { - return FALSE; + return false; } - return TRUE; + return true; } void BKE_object_link_modifiers(struct Object *ob_dst, struct Object *ob_src) @@ -291,6 +291,9 @@ void sculptsession_bm_to_me(struct Object *ob, int reorder) BM_mesh_bm_to_me(ss->bm, ob->data, FALSE); } } + + /* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */ + DAG_id_tag_update(&ob->id, OB_RECALC_DATA); } } @@ -784,61 +787,61 @@ void BKE_object_unlink(Object *ob) } /* actual check for internal data, not context or flags */ -int BKE_object_is_in_editmode(Object *ob) +bool BKE_object_is_in_editmode(Object *ob) { if (ob->data == NULL) - return 0; + return false; if (ob->type == OB_MESH) { Mesh *me = ob->data; if (me->edit_btmesh) - return 1; + return true; } else if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; if (arm->edbo) - return 1; + return true; } else if (ob->type == OB_FONT) { Curve *cu = ob->data; if (cu->editfont) - return 1; + return true; } else if (ob->type == OB_MBALL) { MetaBall *mb = ob->data; if (mb->editelems) - return 1; + return true; } else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; if (lt->editlatt) - return 1; + return true; } else if (ob->type == OB_SURF || ob->type == OB_CURVE) { Curve *cu = ob->data; if (cu->editnurb) - return 1; + return true; } - return 0; + return false; } -int BKE_object_exists_check(Object *obtest) +bool BKE_object_exists_check(Object *obtest) { Object *ob; - if (obtest == NULL) return 0; + if (obtest == NULL) return false; ob = G.main->object.first; while (ob) { - if (ob == obtest) return 1; + if (ob == obtest) return true; ob = ob->id.next; } - return 0; + return false; } /* *************************************************** */ @@ -1405,24 +1408,24 @@ void BKE_object_make_local(Object *ob) /* * Returns true if the Object is a from an external blend file (libdata) */ -int BKE_object_is_libdata(Object *ob) +bool BKE_object_is_libdata(Object *ob) { - if (!ob) return 0; - if (ob->proxy) return 0; - if (ob->id.lib) return 1; - return 0; + if (!ob) return false; + if (ob->proxy) return false; + if (ob->id.lib) return true; + return false; } /* Returns true if the Object data is a from an external blend file (libdata) */ -int BKE_object_obdata_is_libdata(Object *ob) +bool BKE_object_obdata_is_libdata(Object *ob) { - if (!ob) return 0; - if (ob->proxy && (ob->data == NULL || ((ID *)ob->data)->lib == NULL)) return 0; - if (ob->id.lib) return 1; - if (ob->data == NULL) return 0; - if (((ID *)ob->data)->lib) return 1; + if (!ob) return false; + if (ob->proxy && (ob->data == NULL || ((ID *)ob->data)->lib == NULL)) return false; + if (ob->id.lib) return true; + if (ob->data == NULL) return false; + if (((ID *)ob->data)->lib) return true; - return 0; + return false; } /* *************** PROXY **************** */ @@ -2634,11 +2637,11 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt) copy_m4_m4(ob->imat, obtfm->imat); } -int BKE_object_parent_loop_check(const Object *par, const Object *ob) +bool BKE_object_parent_loop_check(const Object *par, const Object *ob) { /* test if 'ob' is a parent somewhere in par's parents */ - if (par == NULL) return 0; - if (ob == par) return 1; + if (par == NULL) return false; + if (ob == par) return true; return BKE_object_parent_loop_check(par->parent, ob); } @@ -3137,6 +3140,16 @@ KeyBlock *BKE_object_insert_shape_key(Scene *scene, Object *ob, const char *name } +bool BKE_object_is_child_recursive(Object *ob_parent, Object *ob_child) +{ + for (ob_child = ob_child->parent; ob_child; ob_child = ob_child->parent) { + if (ob_child == ob_parent) { + return true; + } + } + return false; +} + /* most important if this is modified it should _always_ return True, in certain * cases false positives are hard to avoid (shape keys for example) */ int BKE_object_is_modified(Scene *scene, Object *ob) @@ -3192,7 +3205,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) } /* See if an object is using an animated modifier */ -int BKE_object_is_animated(Scene *scene, Object *ob) +bool BKE_object_is_animated(Scene *scene, Object *ob) { ModifierData *md; @@ -3201,9 +3214,9 @@ int BKE_object_is_animated(Scene *scene, Object *ob) (modifier_isEnabled(scene, md, eModifierMode_Realtime) || modifier_isEnabled(scene, md, eModifierMode_Render))) { - return 1; + return true; } - return 0; + return false; } static void copy_object__forwardModifierLinks(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin) @@ -3286,18 +3299,6 @@ static Object *obrel_armature_find(Object *ob) return ob_arm; } -static int obrel_is_recursive_child(Object *ob, Object *child) -{ - Object *par; - for (par = child->parent; par; par = par->parent) { - if (par == ob) { - return TRUE; - } - } - return FALSE; -} - - static int obrel_list_test(Object *ob) { return ob && !(ob->id.flag & LIB_DOIT); @@ -3370,7 +3371,7 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS Object *child = local_base->object; if (obrel_list_test(child)) { - if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && obrel_is_recursive_child(ob, child)) || + if ((includeFilter & OB_REL_CHILDREN_RECURSIVE && BKE_object_is_child_recursive(ob, child)) || (includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob)) { obrel_list_add(&links, child); diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 288e4ccde5d..5a02d929b76 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -348,7 +348,7 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i } } else { - if (BLI_delete(tempname, 0, 0) != 0) { + if (BLI_delete(tempname, false, false) != 0) { BKE_reportf(reports, RPT_ERROR, "Error deleting '%s' (ignored)", tempname); } } @@ -488,11 +488,8 @@ int unpackVFont(ReportList *reports, VFont *vfont, int how) int ret_value = RET_ERROR; if (vfont != NULL) { - BLI_strncpy(localname, vfont->name, sizeof(localname)); - BLI_splitdirstring(localname, fi); - + BLI_split_file_part(vfont->name, fi, sizeof(fi)); BLI_snprintf(localname, sizeof(localname), "//fonts/%s", fi); - newname = unpackFile(reports, vfont->name, localname, vfont->packedfile, how); if (newname != NULL) { ret_value = RET_OK; @@ -513,10 +510,8 @@ int unpackSound(Main *bmain, ReportList *reports, bSound *sound, int how) int ret_value = RET_ERROR; if (sound != NULL) { - BLI_strncpy(localname, sound->name, sizeof(localname)); - BLI_splitdirstring(localname, fi); + BLI_split_file_part(sound->name, fi, sizeof(fi)); BLI_snprintf(localname, sizeof(localname), "//sounds/%s", fi); - newname = unpackFile(reports, sound->name, localname, sound->packedfile, how); if (newname != NULL) { BLI_strncpy(sound->name, newname, sizeof(sound->name)); @@ -541,10 +536,8 @@ int unpackImage(ReportList *reports, Image *ima, int how) int ret_value = RET_ERROR; if (ima != NULL && ima->name[0]) { - BLI_strncpy(localname, ima->name, sizeof(localname)); - BLI_splitdirstring(localname, fi); + BLI_split_file_part(ima->name, fi, sizeof(fi)); BLI_snprintf(localname, sizeof(localname), "//textures/%s", fi); - newname = unpackFile(reports, ima->name, localname, ima->packedfile, how); if (newname != NULL) { ret_value = RET_OK; @@ -591,7 +584,7 @@ void packLibraries(Main *bmain, ReportList *reports) /* test for relativenss */ for (lib = bmain->library.first; lib; lib = lib->id.next) - if (0 == BLI_path_is_rel(lib->name)) + if (!BLI_path_is_rel(lib->name)) break; if (lib) { @@ -624,7 +617,7 @@ void unpackAll(Main *bmain, ReportList *reports, int how) } /* ID should be not NULL, return 1 if there's a packed file */ -int BKE_pack_check(ID *id) +bool BKE_pack_check(ID *id) { if (GS(id->name) == ID_IM) { Image *ima = (Image *)id; @@ -642,7 +635,7 @@ int BKE_pack_check(ID *id) Library *li = (Library *)id; return li->packedfile != NULL; } - return 0; + return false; } /* ID should be not NULL */ diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index d34d5eaa250..cc647a90c8f 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -40,6 +40,7 @@ #include "BLI_bitmap.h" #include "BLI_utildefines.h" +#include "BLI_math_vector.h" #include "BKE_brush.h" #include "BKE_context.h" @@ -137,6 +138,55 @@ Paint *paint_get_active_from_context(const bContext *C) return NULL; } +PaintMode paintmode_get_active_from_context(const bContext *C) +{ + Scene *sce = CTX_data_scene(C); + SpaceImage *sima; + + if (sce) { + ToolSettings *ts = sce->toolsettings; + Object *obact = NULL; + + if (sce->basact && sce->basact->object) + obact = sce->basact->object; + + if ((sima = CTX_wm_space_image(C)) != NULL) { + if (obact && obact->mode == OB_MODE_EDIT) { + if (sima->mode == SI_MODE_PAINT) + return PAINT_TEXTURE_2D; + else if (ts->use_uv_sculpt) + return PAINT_SCULPT_UV; + } + else { + return PAINT_TEXTURE_2D; + } + } + else if (obact) { + switch (obact->mode) { + case OB_MODE_SCULPT: + return PAINT_SCULPT; + case OB_MODE_VERTEX_PAINT: + return PAINT_VERTEX; + case OB_MODE_WEIGHT_PAINT: + return PAINT_WEIGHT; + case OB_MODE_TEXTURE_PAINT: + return PAINT_TEXTURE_PROJECTIVE; + case OB_MODE_EDIT: + if (ts->use_uv_sculpt) + return PAINT_SCULPT_UV; + else + return PAINT_TEXTURE_2D; + } + } + else { + /* default to image paint */ + return PAINT_TEXTURE_2D; + } + } + + return PAINT_INVALID; +} + Brush *paint_brush(Paint *p) { return p ? p->brush : NULL; @@ -251,3 +301,22 @@ float paint_grid_paint_mask(const GridPaintMask *gpm, unsigned level, return gpm->data[(y * factor) * gridsize + (x * factor)]; } + +/* threshhold to move before updating the brush rotation */ +#define RAKE_THRESHHOLD 20 + +void paint_calculate_rake_rotation(UnifiedPaintSettings *ups, const float mouse_pos[2]) +{ + const float u = 0.5f; + const float r = RAKE_THRESHHOLD; + + float dpos[2]; + sub_v2_v2v2(dpos, ups->last_rake, mouse_pos); + + if (len_squared_v2(dpos) >= r * r) { + ups->brush_rotation = atan2(dpos[0], dpos[1]); + + interp_v2_v2v2(ups->last_rake, ups->last_rake, + mouse_pos, u); + } +} diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 477ae27394f..5efeeaeedaa 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -294,7 +294,7 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) /* Build the vertex list, unique verts first */ for (iter = BLI_ghashIterator_new(map), i = 0; - BLI_ghashIterator_isDone(iter) == FALSE; + BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter), ++i) { void *value = BLI_ghashIterator_getValue(iter); @@ -1217,7 +1217,7 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *tot faces = MEM_callocN(sizeof(void *) * tot, "PBVH Grid Faces"); for (hiter = BLI_ghashIterator_new(map), i = 0; - !BLI_ghashIterator_isDone(hiter); + BLI_ghashIterator_notDone(hiter); BLI_ghashIterator_step(hiter), ++i) { faces[i] = BLI_ghashIterator_getKey(hiter); diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 386a8b27870..0ca73b92071 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -20,6 +20,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_buffer.h" #include "BLI_ghash.h" #include "BLI_heap.h" @@ -82,8 +83,8 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) } BLI_assert(n->vb.bmin[0] <= n->vb.bmax[0] && - n->vb.bmin[1] <= n->vb.bmax[1] && - n->vb.bmin[2] <= n->vb.bmax[2]); + n->vb.bmin[1] <= n->vb.bmax[1] && + n->vb.bmin[2] <= n->vb.bmax[2]); n->orig_vb = n->vb; @@ -274,8 +275,8 @@ static PBVHNode *pbvh_bmesh_node_lookup(PBVH *bvh, GHash *map, void *key) } static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, - const float co[3], - const BMVert *example) + const float co[3], + const BMVert *example) { BMVert *v = BM_vert_create(bvh->bm, co, example, 0); void *val = SET_INT_IN_POINTER(node_index); @@ -354,7 +355,7 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v) } static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, - BMVert *v) + BMVert *v) { PBVHNode *current_owner; @@ -367,7 +368,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, /* Set new ownership */ BLI_ghash_insert(bvh->bm_vert_to_node, v, - SET_INT_IN_POINTER(new_owner - bvh->nodes)); + SET_INT_IN_POINTER(new_owner - bvh->nodes)); BLI_ghash_insert(new_owner->bm_unique_verts, v, NULL); BLI_ghash_remove(new_owner->bm_other_verts, v, NULL, NULL); BLI_assert(!BLI_ghash_haskey(new_owner->bm_other_verts, v)); @@ -489,35 +490,50 @@ static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) return ((len_squared_v3v3(q->center, c) <= q->radius_squared)); } +/* Return true if the vertex mask is less than 0.5, false otherwise */ +static int check_mask_half(BMesh *bm, BMVert *v) +{ + const float *mask; + + mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK); + return ((*mask) < 0.5f); +} + static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e, - float priority) + float priority, BMesh *bm) { BMVert **pair; - pair = BLI_mempool_alloc(pool); - pair[0] = e->v1; - pair[1] = e->v2; - BLI_heap_insert(q->heap, priority, pair); + /* Don't let topology update affect masked vertices. Unlike with + * displacements, can't do 50% topology update, so instead set + * (arbitrary) cutoff: if both vertices' masks are less than 50%, + * topology update can happen. */ + if (check_mask_half(bm, e->v1) && check_mask_half(bm, e->v2)) { + pair = BLI_mempool_alloc(pool); + pair[0] = e->v1; + pair[1] = e->v2; + BLI_heap_insert(q->heap, priority, pair); + } } static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, - BMEdge *e) + BMEdge *e, BMesh *bm) { const float len_sq = BM_edge_calc_length_squared(e); if (len_sq > q->limit_len_squared) - edge_queue_insert(q, pool, e, 1.0f / len_sq); + edge_queue_insert(q, pool, e, 1.0f / len_sq, bm); } static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, - BMEdge *e) + BMEdge *e, BMesh *bm) { const float len_sq = BM_edge_calc_length_squared(e); if (len_sq < q->limit_len_squared) - edge_queue_insert(q, pool, e, len_sq); + edge_queue_insert(q, pool, e, len_sq, bm); } static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f) + BMFace *f, BMesh *bm) { if (edge_queue_tri_in_sphere(q, f)) { BMLoop *l_iter; @@ -526,13 +542,13 @@ static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, /* Check each edge of the face */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - long_edge_queue_edge_add(q, pool, l_iter->e); + long_edge_queue_edge_add(q, pool, l_iter->e, bm); } while ((l_iter = l_iter->next) != l_first); } } static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f) + BMFace *f, BMesh *bm) { if (edge_queue_tri_in_sphere(q, f)) { BMLoop *l_iter; @@ -541,7 +557,7 @@ static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, /* Check each edge of the face */ l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - short_edge_queue_edge_add(q, pool, l_iter->e); + short_edge_queue_edge_add(q, pool, l_iter->e, bm); } while ((l_iter = l_iter->next) != l_first); } } @@ -556,8 +572,8 @@ static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, * The highest priority (lowest number) is given to the longest edge. */ static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, - PBVH *bvh, const float center[3], - float radius) + PBVH *bvh, const float center[3], + float radius) { int n; @@ -579,7 +595,7 @@ static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, GHASH_ITER (gh_iter, node->bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - long_edge_queue_face_add(q, pool, f); + long_edge_queue_face_add(q, pool, f, bvh->bm); } } } @@ -595,8 +611,8 @@ static void long_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, * The highest priority (lowest number) is given to the shortest edge. */ static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, - PBVH *bvh, const float center[3], - float radius) + PBVH *bvh, const float center[3], + float radius) { int n; @@ -618,7 +634,7 @@ static void short_edge_queue_create(EdgeQueue *q, BLI_mempool *pool, GHASH_ITER (gh_iter, node->bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - short_edge_queue_face_add(q, pool, f); + short_edge_queue_face_add(q, pool, f, bvh->bm); } } } @@ -673,9 +689,9 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, /* Create two new faces */ f_new = pbvh_bmesh_face_create(bvh, ni, v1, v_new, opp, f_adj); - long_edge_queue_face_add(q, pool, f_new); + long_edge_queue_face_add(q, pool, f_new, bvh->bm); f_new = pbvh_bmesh_face_create(bvh, ni, v_new, v2, opp, f_adj); - long_edge_queue_face_add(q, pool, f_new); + long_edge_queue_face_add(q, pool, f_new, bvh->bm); /* Delete original */ pbvh_bmesh_face_remove(bvh, f_adj); @@ -693,7 +709,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, BMEdge *e2; BM_ITER_ELEM (e2, &bm_iter, opp, BM_EDGES_OF_VERT) { - long_edge_queue_edge_add(q, pool, e2); + long_edge_queue_edge_add(q, pool, e2, bvh->bm); } } } @@ -929,8 +945,8 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, /************************* Called from pbvh.c *************************/ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], - const float ray_normal[3], float *dist, - int use_original) + const float ray_normal[3], float *dist, + int use_original) { GHashIterator gh_iter; int hit = 0; @@ -940,10 +956,10 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], for (i = 0; i < node->bm_tot_ortri; i++) { const int *t = node->bm_ortri[i]; hit |= ray_face_intersection(ray_start, ray_normal, - node->bm_orco[t[0]], - node->bm_orco[t[1]], - node->bm_orco[t[2]], - NULL, dist); + node->bm_orco[t[0]], + node->bm_orco[t[1]], + node->bm_orco[t[2]], + NULL, dist); } } else { @@ -988,7 +1004,7 @@ void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode) /* Build a PBVH from a BMesh */ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading, - BMLog *log) + BMLog *log) { BMIter iter; BMFace *f; @@ -1098,7 +1114,7 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) return; totvert = (BLI_ghash_size(node->bm_unique_verts) + - BLI_ghash_size(node->bm_other_verts)); + BLI_ghash_size(node->bm_other_verts)); tottri = BLI_ghash_size(node->bm_faces); @@ -1214,31 +1230,31 @@ void bmesh_print(BMesh *bm) BMLoop *l; fprintf(stderr, "\nbm=%p, totvert=%d, totedge=%d, " - "totloop=%d, totface=%d\n", - bm, bm->totvert, bm->totedge, - bm->totloop, bm->totface); + "totloop=%d, totface=%d\n", + bm, bm->totvert, bm->totedge, + bm->totloop, bm->totface); fprintf(stderr, "vertices:\n"); BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) { fprintf(stderr, " %d co=(%.3f %.3f %.3f) oflag=%x\n", - BM_elem_index_get(v), v->co[0], v->co[1], v->co[2], - v->oflags[bm->stackdepth - 1].f); + BM_elem_index_get(v), v->co[0], v->co[1], v->co[2], + v->oflags[bm->stackdepth - 1].f); } fprintf(stderr, "edges:\n"); BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) { fprintf(stderr, " %d v1=%d, v2=%d, oflag=%x\n", - BM_elem_index_get(e), - BM_elem_index_get(e->v1), - BM_elem_index_get(e->v2), - e->oflags[bm->stackdepth - 1].f); + BM_elem_index_get(e), + BM_elem_index_get(e->v1), + BM_elem_index_get(e->v2), + e->oflags[bm->stackdepth - 1].f); } fprintf(stderr, "faces:\n"); BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) { fprintf(stderr, " %d len=%d, oflag=%x\n", - BM_elem_index_get(f), f->len, - f->oflags[bm->stackdepth - 1].f); + BM_elem_index_get(f), f->len, + f->oflags[bm->stackdepth - 1].f); fprintf(stderr, " v: "); BM_ITER_ELEM(v, &siter, f, BM_VERTS_OF_FACE) { @@ -1255,9 +1271,9 @@ void bmesh_print(BMesh *bm) fprintf(stderr, " l: "); BM_ITER_ELEM(l, &siter, f, BM_LOOPS_OF_FACE) { fprintf(stderr, "%d(v=%d, e=%d) ", - BM_elem_index_get(l), - BM_elem_index_get(l->v), - BM_elem_index_get(l->e)); + BM_elem_index_get(l), + BM_elem_index_get(l->v), + BM_elem_index_get(l->e)); } fprintf(stderr, "\n"); } @@ -1272,15 +1288,15 @@ void pbvh_bmesh_print(PBVH *bvh) fprintf(stderr, "bm_face_to_node:\n"); GHASH_ITER (gh_iter, bvh->bm_face_to_node) { fprintf(stderr, " %d -> %d\n", - BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter)), - GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); + BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter)), + GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); } fprintf(stderr, "bm_vert_to_node:\n"); GHASH_ITER (gh_iter, bvh->bm_vert_to_node) { fprintf(stderr, " %d -> %d\n", - BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter)), - GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); + BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter)), + GET_INT_FROM_POINTER(BLI_ghashIterator_getValue(&gh_iter))); } for (n = 0; n < bvh->totnode; n++) { @@ -1291,15 +1307,15 @@ void pbvh_bmesh_print(PBVH *bvh) fprintf(stderr, "node %d\n faces:\n", n); GHASH_ITER (gh_iter, node->bm_faces) fprintf(stderr, " %d\n", - BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter))); + BM_elem_index_get((BMFace*)BLI_ghashIterator_getKey(&gh_iter))); fprintf(stderr, " unique verts:\n"); GHASH_ITER (gh_iter, node->bm_unique_verts) fprintf(stderr, " %d\n", - BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter))); + BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter))); fprintf(stderr, " other verts:\n"); GHASH_ITER (gh_iter, node->bm_other_verts) fprintf(stderr, " %d\n", - BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter))); + BM_elem_index_get((BMVert*)BLI_ghashIterator_getKey(&gh_iter))); } } @@ -1341,7 +1357,7 @@ void pbvh_bmesh_verify(PBVH *bvh) /* Check that the vertex is in the node */ BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v) ^ - BLI_ghash_haskey(n->bm_other_verts, v)); + BLI_ghash_haskey(n->bm_other_verts, v)); /* Check that the vertex has a node owner */ nv = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index c8947730ea8..c900d08e4e9 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -840,7 +840,10 @@ static int ptcache_dynamicpaint_read(PTCacheFile *pf, void *dp_v) /* version header */ ptcache_file_read(pf, version, 1, sizeof(char) * 4); - if (strncmp(version, DPAINT_CACHE_VERSION, 4)) {printf("Dynamic Paint: Invalid cache version: %s!\n", version); return 0;} + if (strncmp(version, DPAINT_CACHE_VERSION, 4)) { + printf("Dynamic Paint: Invalid cache version: %s!\n", version); + return 0; + } if (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ && surface->data) { unsigned int data_len; @@ -1516,7 +1519,7 @@ static int ptcache_file_compressed_write(PTCacheFile *pf, unsigned char *in, uns if (mode == 2) { r = LzmaCompress(out, &out_len, in, in_len, //assume sizeof(char)==1.... - props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); + props, &sizeOfIt, 5, 1 << 24, 3, 0, 2, 32, 2); if (!(r == SZ_OK) || (out_len >= in_len)) compressed = 0; @@ -2432,7 +2435,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) if (mode == PTCACHE_CLEAR_ALL) { pid->cache->last_exact = MIN2(pid->cache->startframe, 0); BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); - BLI_delete(path_full, 0, 0); + BLI_delete(path_full, false, false); } else { /* read the number of the file */ @@ -2448,7 +2451,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) { BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); - BLI_delete(path_full, 0, 0); + BLI_delete(path_full, false, false); if (pid->cache->cached_frames && frame >=sta && frame <= end) pid->cache->cached_frames[frame-sta] = 0; } @@ -2502,7 +2505,7 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) if (pid->cache->flag & PTCACHE_DISK_CACHE) { if (BKE_ptcache_id_exist(pid, cfra)) { ptcache_filename(pid, filename, cfra, 1, 1); /* no path */ - BLI_delete(filename, 0, 0); + BLI_delete(filename, false, false); } } else { @@ -2820,7 +2823,7 @@ void BKE_ptcache_remove(void) } else if (strstr(de->d_name, PTCACHE_EXT)) { /* do we have the right extension?*/ BLI_join_dirfile(path_full, sizeof(path_full), path, de->d_name); - BLI_delete(path_full, 0, 0); + BLI_delete(path_full, false, false); } else { rmdir = 0; /* unknown file, don't remove the dir */ @@ -2834,7 +2837,7 @@ void BKE_ptcache_remove(void) } if (rmdir) { - BLI_delete(path, 1, 0); + BLI_delete(path, true, false); } } @@ -3039,7 +3042,7 @@ static void *ptcache_bake_thread(void *ptr) } /* if bake is not given run simulations to current frame */ -void BKE_ptcache_bake(PTCacheBaker* baker) +void BKE_ptcache_bake(PTCacheBaker *baker) { Main *bmain = baker->main; Scene *scene = baker->scene; @@ -3511,7 +3514,7 @@ void BKE_ptcache_update_info(PTCacheID *pid) else if (totframes && cache->totpoint) BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("%i points found!"), cache->totpoint); else - BLI_snprintf(cache->info, sizeof(cache->info), IFACE_("No valid data to read!")); + BLI_strncpy(cache->info, IFACE_("No valid data to read!"), sizeof(cache->info)); return; } diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index c4658712ecb..ec23a7db8a1 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -74,8 +74,10 @@ bProperty *BKE_bproperty_copy(bProperty *prop) if (prop->poin && prop->poin != &prop->data) { propn->poin = MEM_dupallocN(prop->poin); } - else propn->poin = &propn->data; - + else { + propn->poin = &propn->data; + } + return propn; } diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index d144ac927a6..bccc6f9a93b 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -637,12 +637,12 @@ void BKE_rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, shor RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f); break; case RBC_TYPE_MOTOR: - rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2); + rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2); - RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG); + RB_constraint_set_enable_motor(rbc->physics_constraint, rbc->flag & RBC_FLAG_USE_MOTOR_LIN, rbc->flag & RBC_FLAG_USE_MOTOR_ANG); RB_constraint_set_max_impulse_motor(rbc->physics_constraint, rbc->motor_lin_max_impulse, rbc->motor_ang_max_impulse); RB_constraint_set_target_velocity_motor(rbc->physics_constraint, rbc->motor_lin_target_velocity, rbc->motor_ang_target_velocity); - break; + break; } } else { /* can't create constraint without both rigid bodies */ @@ -1338,6 +1338,7 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) {} void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) {} void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} +void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {} void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} #ifdef __GNUC__ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 19eea279f79..a942e694f2e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -461,7 +461,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.postsat = 1.0; sce->r.bake_mode = 1; /* prevent to include render stuff here */ - sce->r.bake_filter = 2; + sce->r.bake_filter = 16; sce->r.bake_osa = 5; sce->r.bake_flag = R_BAKE_CLEAR; sce->r.bake_normal_space = R_BAKE_SPACE_TANGENT; @@ -786,7 +786,9 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob) else { if (*base && fase != F_DUPLI) { *base = (*base)->next; - if (*base) *ob = (*base)->object; + if (*base) { + *ob = (*base)->object; + } else { if (fase == F_SCENE) { /* (*scene) is finished, now do the set */ @@ -803,7 +805,9 @@ int BKE_scene_base_iter_next(Scene **scene, int val, Base **base, Object **ob) } } - if (*base == NULL) fase = F_START; + if (*base == NULL) { + fase = F_START; + } else { if (fase != F_DUPLI) { if ( (*base)->object->transflag & OB_DUPLI) { diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c index e3f0226c863..978c1a7c9b0 100644 --- a/source/blender/blenkernel/intern/seqcache.c +++ b/source/blender/blenkernel/intern/seqcache.c @@ -26,7 +26,6 @@ * \ingroup bke */ - #include <stddef.h> #include "BLO_sys_types.h" /* for intptr_t */ @@ -34,7 +33,6 @@ #include "MEM_guardedalloc.h" #include "DNA_sequence_types.h" -#include "BKE_sequencer.h" #include "IMB_moviecache.h" #include "IMB_imbuf.h" @@ -42,6 +40,8 @@ #include "BLI_listbase.h" +#include "BKE_sequencer.h" + typedef struct SeqCacheKey { struct Sequence *seq; SeqRenderData context; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index c0e85352217..a1dc19e1ff7 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -182,8 +182,8 @@ static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, un fac = fac2; mfac = 1.0f - fac2 * rt1[3]; - if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2); - else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1); + if (fac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp2); + else if (mfac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp1); else { tempc[0] = fac * rt1[0] + mfac * rt2[0]; tempc[1] = fac * rt1[1] + mfac * rt2[1]; @@ -206,8 +206,8 @@ static void do_alphaover_effect_byte(float facf0, float facf1, int x, int y, un fac = fac4; mfac = 1.0f - (fac4 * rt1[3]); - if (fac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp2); - else if (mfac <= 0.0f) *( (unsigned int *) rt) = *( (unsigned int *) cp1); + if (fac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp2); + else if (mfac <= 0.0f) *((unsigned int *) rt) = *((unsigned int *) cp1); else { tempc[0] = fac * rt1[0] + mfac * rt2[0]; tempc[1] = fac * rt1[1] + mfac * rt2[1]; @@ -328,13 +328,13 @@ static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, un /* this complex optimization is because the * 'skybuf' can be crossed in */ - if (rt2[3] == 0 && fac2 == 256) *( (unsigned int *) rt) = *( (unsigned int *) rt1); - else if (rt2[3] == 255) *( (unsigned int *) rt) = *( (unsigned int *) rt2); + if (rt2[3] == 0 && fac2 == 256) *((unsigned int *) rt) = *((unsigned int *) rt1); + else if (rt2[3] == 255) *((unsigned int *) rt) = *((unsigned int *) rt2); else { mfac = rt2[3]; fac = (fac2 * (256 - mfac)) >> 8; - if (fac == 0) *( (unsigned int *) rt) = *( (unsigned int *) rt2); + if (fac == 0) *((unsigned int *) rt) = *((unsigned int *) rt2); else { rt[0] = (fac * rt1[0] + mfac * rt2[0]) >> 8; rt[1] = (fac * rt1[1] + mfac * rt2[1]) >> 8; @@ -351,13 +351,13 @@ static void do_alphaunder_effect_byte(float facf0, float facf1, int x, int y, un x = xo; while (x--) { - if (rt2[3] == 0 && fac4 == 256) *( (unsigned int *) rt) = *( (unsigned int *) rt1); - else if (rt2[3] == 255) *( (unsigned int *) rt) = *( (unsigned int *) rt2); + if (rt2[3] == 0 && fac4 == 256) *((unsigned int *) rt) = *((unsigned int *) rt1); + else if (rt2[3] == 255) *((unsigned int *) rt) = *((unsigned int *) rt2); else { mfac = rt2[3]; fac = (fac4 * (256 - mfac)) >> 8; - if (fac == 0) *( (unsigned int *)rt) = *( (unsigned int *)rt2); + if (fac == 0) *((unsigned int *)rt) = *((unsigned int *)rt2); else { rt[0] = (fac * rt1[0] + mfac * rt2[0]) >> 8; rt[1] = (fac * rt1[1] + mfac * rt2[1]) >> 8; @@ -682,7 +682,7 @@ static void gamtabs(float gamma) } /* inverse gamtab1 : in byte, out short */ for (a = 1; a <= 256; a++) { - if (gamma == 2.0f) igamtab1[a - 1] = a * a - 1; + if (gamma == 2.0f) igamtab1[a - 1] = a * a - 1; else if (gamma == 1.0f) igamtab1[a - 1] = 256 * a - 1; else { val = a / 256.0f; diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 613c02c173b..9b276912087 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -245,7 +245,7 @@ static void seq_free_sequence_recurse(Scene *scene, Sequence *seq) } -Editing *BKE_sequencer_editing_get(Scene *scene, int alloc) +Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc) { if (alloc) { BKE_sequencer_editing_ensure(scene); @@ -856,7 +856,7 @@ static void seqbase_unique_name(ListBase *seqbasep, SeqUniqueInfo *sui) { Sequence *seq; for (seq = seqbasep->first; seq; seq = seq->next) { - if (sui->seq != seq && strcmp(sui->name_dest, seq->name + 2) == 0) { + if ((sui->seq != seq) && STREQ(sui->name_dest, seq->name + 2)) { /* SEQ_NAME_MAXSTR - 2 for prefix, -1 for \0, -4 for the number */ BLI_snprintf(sui->name_dest, sizeof(sui->name_dest), "%.59s.%03d", sui->name_src, sui->count++); sui->match = 1; /* be sure to re-scan */ @@ -3062,30 +3062,30 @@ static void free_anim_seq(Sequence *seq) } /* check whether sequence cur depends on seq */ -int BKE_sequence_check_depend(Sequence *seq, Sequence *cur) +bool BKE_sequence_check_depend(Sequence *seq, Sequence *cur) { if (cur->seq1 == seq || cur->seq2 == seq || cur->seq3 == seq) - return TRUE; + return true; /* sequences are not intersecting in time, assume no dependency exists between them */ if (cur->enddisp < seq->startdisp || cur->startdisp > seq->enddisp) - return FALSE; + return false; /* checking sequence is below reference one, not dependent on it */ if (cur->machine < seq->machine) - return FALSE; + return false; /* sequence is not blending with lower machines, no dependency here occurs * check for non-effects only since effect could use lower machines as input */ if ((cur->type & SEQ_TYPE_EFFECT) == 0 && - ((cur->blend_mode == SEQ_BLEND_REPLACE) || - (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f))) + ((cur->blend_mode == SEQ_BLEND_REPLACE) || + (cur->blend_mode == SEQ_TYPE_CROSS && cur->blend_opacity == 100.0f))) { - return FALSE; + return false; } - return TRUE; + return true; } static void sequence_do_invalidate_dependent(Sequence *seq, ListBase *seqbase) @@ -3291,7 +3291,7 @@ void BKE_sequence_tx_set_final_right(Sequence *seq, int val) /* used so we can do a quick check for single image seq * since they work a bit differently to normal image seq's (during transform) */ -int BKE_sequence_single_check(Sequence *seq) +bool BKE_sequence_single_check(Sequence *seq) { return ((seq->len == 1) && (seq->type == SEQ_TYPE_IMAGE || @@ -3300,21 +3300,21 @@ int BKE_sequence_single_check(Sequence *seq) } /* check if the selected seq's reference unselected seq's */ -int BKE_sequence_base_isolated_sel_check(ListBase *seqbase) +bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) { Sequence *seq; /* is there more than 1 select */ - int ok = FALSE; + bool ok = false; for (seq = seqbase->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - ok = TRUE; + ok = true; break; } } - if (ok == FALSE) - return FALSE; + if (ok == false) + return false; /* test relationships */ for (seq = seqbase->first; seq; seq = seq->next) { @@ -3322,24 +3322,24 @@ int BKE_sequence_base_isolated_sel_check(ListBase *seqbase) continue; if (seq->flag & SELECT) { - if ( (seq->seq1 && (seq->seq1->flag & SELECT) == 0) || - (seq->seq2 && (seq->seq2->flag & SELECT) == 0) || - (seq->seq3 && (seq->seq3->flag & SELECT) == 0) ) + if ((seq->seq1 && (seq->seq1->flag & SELECT) == 0) || + (seq->seq2 && (seq->seq2->flag & SELECT) == 0) || + (seq->seq3 && (seq->seq3->flag & SELECT) == 0) ) { - return FALSE; + return false; } } else { - if ( (seq->seq1 && (seq->seq1->flag & SELECT)) || - (seq->seq2 && (seq->seq2->flag & SELECT)) || - (seq->seq3 && (seq->seq3->flag & SELECT)) ) + if ((seq->seq1 && (seq->seq1->flag & SELECT)) || + (seq->seq2 && (seq->seq2->flag & SELECT)) || + (seq->seq3 && (seq->seq3->flag & SELECT)) ) { - return FALSE; + return false; } } } - return TRUE; + return true; } /* use to impose limits when dragging/extending - so impossible situations don't happen @@ -3405,29 +3405,29 @@ void BKE_sequence_single_fix(Sequence *seq) } } -int BKE_sequence_tx_test(Sequence *seq) +bool BKE_sequence_tx_test(Sequence *seq) { return (seq->type < SEQ_TYPE_EFFECT) || (BKE_sequence_effect_get_num_inputs(seq->type) == 0); } -static int seq_overlap(Sequence *seq1, Sequence *seq2) +static bool seq_overlap(Sequence *seq1, Sequence *seq2) { return (seq1 != seq2 && seq1->machine == seq2->machine && ((seq1->enddisp <= seq2->startdisp) || (seq1->startdisp >= seq2->enddisp)) == 0); } -int BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test) +bool BKE_sequence_test_overlap(ListBase *seqbasep, Sequence *test) { Sequence *seq; seq = seqbasep->first; while (seq) { if (seq_overlap(test, seq)) - return 1; + return true; seq = seq->next; } - return 0; + return false; } @@ -3487,7 +3487,7 @@ Sequence *BKE_sequencer_foreground_frame_get(Scene *scene, int frame) } /* return 0 if there werent enough space */ -int BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) +bool BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_scene) { int orig_machine = test->machine; test->machine++; @@ -3518,10 +3518,10 @@ int BKE_sequence_base_shuffle(ListBase *seqbasep, Sequence *test, Scene *evil_sc BKE_sequence_translate(evil_scene, test, new_frame - test->start); BKE_sequence_calc(evil_scene, test); - return 0; + return false; } else { - return 1; + return true; } } @@ -3572,7 +3572,7 @@ static int shuffle_seq_time_offset(Scene *scene, ListBase *seqbasep, char dir) return tot_ofs; } -int BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene) +bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene) { /* note: seq->tmp is used to tag strips to move */ @@ -3591,7 +3591,7 @@ int BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene) } } - return offset ? 0 : 1; + return offset ? false : true; } void BKE_sequencer_update_sound_bounds_all(Scene *scene) @@ -3861,7 +3861,7 @@ Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, int recu Sequence *rseq = NULL; for (iseq = seqbase->first; iseq; iseq = iseq->next) { - if (strcmp(name, iseq->name + 2) == 0) + if (STREQ(name, iseq->name + 2)) return iseq; else if (recursive && (iseq->seqbase.first) && (rseq = BKE_sequence_get_by_name(&iseq->seqbase, name, 1))) { return rseq; @@ -4072,7 +4072,7 @@ Sequence *BKE_sequencer_add_sound_strip(bContext *C, ListBase *seqbasep, SeqLoad if (sound == NULL || sound->playback_handle == NULL) { #if 0 - if (op) + if (op) BKE_report(op->reports, RPT_ERROR, "Unsupported audio format"); #endif @@ -4324,7 +4324,7 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * /* called on draw, needs to be fast, * we could cache and use a flag if we want to make checks for file paths resolving for eg. */ -int BKE_sequence_is_valid_check(Sequence *seq) +bool BKE_sequence_is_valid_check(Sequence *seq) { switch (seq->type) { case SEQ_TYPE_MASK: @@ -4337,6 +4337,6 @@ int BKE_sequence_is_valid_check(Sequence *seq) return (seq->sound != NULL); } - return TRUE; + return true; } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 248cd689258..435e81556ab 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1776,6 +1776,8 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd dy = gy - sds->res_min[1]; dz = gz - sds->res_min[2]; d_index = smoke_get_index(dx, sds->res[0], dy, sds->res[1], dz); + /* make sure emission cell is inside the new domain boundary */ + if (dx < 0 || dy < 0 || dz < 0 || dx >= sds->res[0] || dy >= sds->res[1] || dz >= sds->res[2]) continue; if (sfs->type == MOD_SMOKE_FLOW_TYPE_OUTFLOW) { // outflow apply_outflow_fields(d_index, density, heat, fuel, react, color_r, color_g, color_b); @@ -2284,7 +2286,9 @@ struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Objec { return createDomainGeometry(smd->domain, ob); } - else return CDDM_copy(dm); + else { + return CDDM_copy(dm); + } } static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct) diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index e2c6df5e528..8e5e0da20f9 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -200,18 +200,18 @@ static float sb_time_scale(Object *ob) SoftBody *sb= ob->soft; /* is supposed to be there */ if (sb) { return(sb->physics_speed); - /*hrms .. this could be IPO as well :) - estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)] - 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames - theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM) + /* hrms .. this could be IPO as well :) + * estimated range [0.001 sluggish slug - 100.0 very fast (i hope ODE solver can handle that)] + * 1 approx = a unit 1 pendulum at g = 9.8 [earth conditions] has period 65 frames + * theory would give a 50 frames period .. so there must be something inaccurate .. looking for that (BM) */ } return (1.0f); /* - this would be frames/sec independent timing assuming 25 fps is default - but does not work very well with NLA - return (25.0f/scene->r.frs_sec) - */ + * this would be frames/sec independent timing assuming 25 fps is default + * but does not work very well with NLA + * return (25.0f/scene->r.frs_sec) + */ } /*--- frame based timing ---*/ @@ -1034,7 +1034,7 @@ static int sb_detect_aabb_collisionCached(float UNUSED(force[3]), unsigned int U hash = vertexowner->soft->scratch->colliderhash; ihash = BLI_ghashIterator_new(hash); - while (!BLI_ghashIterator_isDone(ihash) ) { + while (BLI_ghashIterator_notDone(ihash) ) { ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); @@ -1113,7 +1113,7 @@ static int sb_detect_face_pointCached(float face_v1[3], float face_v2[3], float hash = vertexowner->soft->scratch->colliderhash; ihash = BLI_ghashIterator_new(hash); - while (!BLI_ghashIterator_isDone(ihash) ) { + while (BLI_ghashIterator_notDone(ihash) ) { ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); @@ -1205,7 +1205,7 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl hash = vertexowner->soft->scratch->colliderhash; ihash = BLI_ghashIterator_new(hash); - while (!BLI_ghashIterator_isDone(ihash) ) { + while (BLI_ghashIterator_notDone(ihash) ) { ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); @@ -1305,7 +1305,7 @@ static int sb_detect_face_collisionCached(float face_v1[3], float face_v2[3], fl normalize_v3(d_nvect); if ( /* isect_line_tri_v3(nv1, nv3, face_v1, face_v2, face_v3, &t, NULL) || - we did that edge already */ + * we did that edge already */ isect_line_tri_v3(nv3, nv4, face_v1, face_v2, face_v3, &t, NULL) || isect_line_tri_v3(nv4, nv1, face_v1, face_v2, face_v3, &t, NULL) ) { Vec3PlusStVec(force, -0.5f, d_nvect); @@ -1433,7 +1433,7 @@ static int sb_detect_edge_collisionCached(float edge_v1[3], float edge_v2[3], fl hash = vertexowner->soft->scratch->colliderhash; ihash = BLI_ghashIterator_new(hash); - while (!BLI_ghashIterator_isDone(ihash) ) { + while (BLI_ghashIterator_notDone(ihash) ) { ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); @@ -1763,7 +1763,7 @@ static int sb_detect_vertex_collisionCached(float opco[3], float facenormal[3], outerforceaccu[0]=outerforceaccu[1]=outerforceaccu[2]=0.0f; innerforceaccu[0]=innerforceaccu[1]=innerforceaccu[2]=0.0f; /* go */ - while (!BLI_ghashIterator_isDone(ihash) ) { + while (BLI_ghashIterator_notDone(ihash) ) { ccd_Mesh *ccdm = BLI_ghashIterator_getValue (ihash); ob = BLI_ghashIterator_getKey (ihash); diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 3c90da60103..3d633dc964a 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3103,7 +3103,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int numTex, numCol; int hasPCol, hasOrigSpace; int gridInternalEdges; - float *w = NULL; WeightTable wtable = {0}; /* MCol *mcol; */ /* UNUSED */ MEdge *medge = NULL; @@ -3307,7 +3306,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, int numFinalEdges = numVerts * (gridSideEdges + gridInternalEdges); int origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); int g2_wid = gridCuts + 2; - float *w2; + float *w, *w2; int s, x, y; w = get_ss_weights(&wtable, gridCuts, numVerts); @@ -3320,8 +3319,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, faceFlags->mat_nr = mpoly ? mpoly[origIndex].mat_nr : 0; faceFlags++; - origIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex; - /* set the face base vert */ *((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum; @@ -3429,7 +3426,7 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, faceOrigIndex++; } if (polyOrigIndex) { - *polyOrigIndex = origIndex; + *polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex; polyOrigIndex++; } diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 184984352ba..3936c533a41 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -791,6 +791,29 @@ int txt_utf8_index_to_offset(const char *str, int index) return offset; } +int txt_utf8_offset_to_column(const char *str, int offset) +{ + int column = 0, pos = 0; + while (pos < offset) { + column += BLI_str_utf8_char_width_safe(str + pos); + pos += BLI_str_utf8_size_safe(str + pos); + } + return column; +} + +int txt_utf8_column_to_offset(const char *str, int column) +{ + int offset = 0, pos = 0, col; + while (pos < column) { + col = BLI_str_utf8_char_width_safe(str + offset); + if (pos + col > column) + break; + offset += BLI_str_utf8_size_safe(str + offset); + pos += col; + } + return offset; +} + /* returns the real number of characters in string */ /* not the same as BLI_strlen_utf8, which returns length for wide characters */ static int txt_utf8_len(const char *src) @@ -804,6 +827,17 @@ static int txt_utf8_len(const char *src) return len; } +static int txt_utf8_width(const char *src) +{ + int col = 0; + + for (; *src; src += BLI_str_utf8_size(src)) { + col += BLI_str_utf8_char_width(src); + } + + return col; +} + void txt_move_up(Text *text, short sel) { TextLine **linep; @@ -815,10 +849,10 @@ void txt_move_up(Text *text, short sel) if (!*linep) return; if ((*linep)->prev) { - int index = txt_utf8_offset_to_index((*linep)->line, *charp); + int column = txt_utf8_offset_to_column((*linep)->line, *charp); *linep = (*linep)->prev; - if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; - else *charp = txt_utf8_index_to_offset((*linep)->line, index); + if (column > txt_utf8_width((*linep)->line)) *charp = (*linep)->len; + else *charp = txt_utf8_column_to_offset((*linep)->line, column); } else { @@ -839,10 +873,10 @@ void txt_move_down(Text *text, short sel) if (!*linep) return; if ((*linep)->next) { - int index = txt_utf8_offset_to_index((*linep)->line, *charp); + int column = txt_utf8_offset_to_column((*linep)->line, *charp); *linep = (*linep)->next; - if (index > txt_utf8_len((*linep)->line)) *charp = (*linep)->len; - else *charp = txt_utf8_index_to_offset((*linep)->line, index); + if (column > txt_utf8_width((*linep)->line)) *charp = (*linep)->len; + else *charp = txt_utf8_column_to_offset((*linep)->line, column); } else { txt_move_eol(text, sel); @@ -930,7 +964,9 @@ void txt_move_right(Text *text, short sel) tabsize++; (*charp) = i; } - else (*charp) += BLI_str_utf8_size((*linep)->line + *charp); + else { + (*charp) += BLI_str_utf8_size((*linep)->line + *charp); + } } if (!sel) txt_pop_sel(text); @@ -2825,7 +2861,7 @@ void txt_move_lines(struct Text *text, const int direction) } } -int setcurr_tab_spaces(Text *text, int space) +int txt_setcurr_tab_spaces(Text *text, int space) { int i = 0; int test = 0; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index 55a0f3752a1..bdf2ce622de 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -256,7 +256,9 @@ int do_colorband(const ColorBand *coba, float in, float out[4]) left.pos = 0.0f; cbd2 = &left; } - else cbd2 = cbd1 - 1; + else { + cbd2 = cbd1 - 1; + } if (in >= cbd1->pos && coba->ipotype < 2) { out[0] = cbd1->r; @@ -440,7 +442,7 @@ void default_tex(Tex *tex) tex->type = TEX_CLOUDS; tex->stype = 0; tex->flag = TEX_CHECKER_ODD; - tex->imaflag = TEX_INTERPOL | TEX_MIPMAP; + tex->imaflag = TEX_INTERPOL | TEX_MIPMAP | TEX_USEALPHA; tex->extend = TEX_REPEAT; tex->cropxmin = tex->cropymin = 0.0; tex->cropxmax = tex->cropymax = 1.0; @@ -911,15 +913,18 @@ void autotexname(Tex *tex) else if (tex->type == TEX_IMAGE) { ima = tex->ima; if (ima) { - BLI_strncpy(di, ima->name, sizeof(di)); - BLI_splitdirstring(di, fi); + BLI_split_file_part(ima->name, fi, sizeof(fi)); strcpy(di, "I."); strcat(di, fi); new_id(&bmain->tex, (ID *)tex, di); } - else new_id(&bmain->tex, (ID *)tex, texstr[tex->type]); + else { + new_id(&bmain->tex, (ID *)tex, texstr[tex->type]); + } + } + else { + new_id(&bmain->tex, (ID *)tex, texstr[tex->type]); } - else new_id(&bmain->tex, (ID *)tex, texstr[tex->type]); } } #endif diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index f63a1f2cec0..df10d1374bb 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -261,7 +261,9 @@ void BKE_tracking_get_projection_matrix(MovieTracking *tracking, MovieTrackingOb invert_m4_m4(imat, camera->mat); mult_m4_m4m4(mat, winmat, imat); } - else copy_m4_m4(mat, winmat); + else { + copy_m4_m4(mat, winmat); + } } /* **** space transformation functions **** */ @@ -1189,6 +1191,7 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char object->keyframe2 = 30; BKE_tracking_object_unique_name(tracking, object); + BKE_tracking_dopesheet_tag_update(tracking); return object; } @@ -1223,6 +1226,9 @@ int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *obj tracking->objectnr = index - 1; else tracking->objectnr = 0; + + BKE_tracking_dopesheet_tag_update(tracking); + return TRUE; } @@ -1446,7 +1452,7 @@ static void cameraIntrinscisOptionsFromTracking(libmv_cameraIntrinsicsOptions *c camera_intrinsics_options->k3 = camera->k3; camera_intrinsics_options->image_width = calibration_width; - camera_intrinsics_options->image_height = (double) calibration_height * aspy; + camera_intrinsics_options->image_height = (double) (calibration_height * aspy); } #endif @@ -1456,6 +1462,10 @@ MovieDistortion *BKE_tracking_distortion_new(void) distortion = MEM_callocN(sizeof(MovieDistortion), "BKE_tracking_distortion_create"); +#ifdef WITH_LIBMV + distortion->intrinsics = libmv_CameraIntrinsicsNewEmpty(); +#endif + return distortion; } @@ -1468,12 +1478,7 @@ void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking * cameraIntrinscisOptionsFromTracking(&camera_intrinsics_options, tracking, calibration_width, calibration_height); - if (!distortion->intrinsics) { - distortion->intrinsics = libmv_CameraIntrinsicsNew(&camera_intrinsics_options); - } - else { - libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options); - } + libmv_CameraIntrinsicsUpdate(distortion->intrinsics, &camera_intrinsics_options); #else (void) distortion; (void) tracking; @@ -1482,6 +1487,16 @@ void BKE_tracking_distortion_update(MovieDistortion *distortion, MovieTracking * #endif } +void BKE_tracking_distortion_set_threads(MovieDistortion *distortion, int threads) +{ +#ifdef WITH_LIBMV + libmv_CameraIntrinsicsSetThreads(distortion->intrinsics, threads); +#else + (void) distortion; + (void) threads; +#endif +} + MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) { MovieDistortion *new_distortion; @@ -1594,8 +1609,8 @@ void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float libmv_InvertIntrinsics(&camera_intrinsics_options, x, y, &x, &y); - r_co[0] = x * camera->focal + camera->principal[0]; - r_co[1] = y * camera->focal + camera->principal[1] * aspy; + r_co[0] = (float)x * camera->focal + camera->principal[0]; + r_co[1] = (float)y * camera->focal + camera->principal[1] * aspy; #else (void) camera; (void) co; @@ -1699,7 +1714,7 @@ static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int g ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *search_ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int use_mask, int num_samples_x, int num_samples_y, + int from_anchor, int use_mask, int num_samples_x, int num_samples_y, float pos[2]) { #ifdef WITH_LIBMV @@ -1719,6 +1734,28 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea get_marker_coords_for_tracking(frame_width, frame_height, marker, src_pixel_x, src_pixel_y); + /* from_anchor means search buffer was obtained for an anchored position, + * which means applying track offset rounded to pixel space (we could not + * store search buffer with sub-pixel precision) + * + * in this case we need to alter coordinates a bit, to compensate rounded + * fractional part of offset + */ + if (from_anchor) { + int a; + + for (a = 0; a < 5; a++) { + src_pixel_x[a] += (double) ((track->offset[0] * frame_width) - ((int) (track->offset[0] * frame_width))); + src_pixel_y[a] += (double) ((track->offset[1] * frame_height) - ((int) (track->offset[1] * frame_height))); + + /* when offset is negative, rounding happens in opposite direction */ + if (track->offset[0] < 0.0f) + src_pixel_x[a] += 1.0; + if (track->offset[1] < 0.0f) + src_pixel_y[a] += 1.0; + } + } + if (use_mask) { mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); } @@ -1751,6 +1788,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea (void) frame_height; (void) search_ibuf; (void) marker; + (void) from_anchor; (void) track; (void) use_mask; @@ -1779,7 +1817,7 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo if (search_ibuf) { pattern_ibuf = BKE_tracking_sample_pattern(ibuf->x, ibuf->y, search_ibuf, track, marker, - FALSE, num_samples_x, num_samples_y, NULL); + anchored, FALSE, num_samples_x, num_samples_y, NULL); IMB_freeImBuf(search_ibuf); } @@ -2726,7 +2764,7 @@ static void reconstruct_retrieve_libmv_intrinscis(MovieReconstructContext *conte tracking->camera.focal = focal_length; tracking->camera.principal[0] = principal_x; - tracking->camera.principal[1] = principal_y / aspy; + tracking->camera.principal[1] = principal_y / (double)aspy; tracking->camera.k1 = k1; tracking->camera.k2 = k2; diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c index dd6ed42bd92..066b6eff5c5 100644 --- a/source/blender/blenkernel/intern/unit.c +++ b/source/blender/blenkernel/intern/unit.c @@ -104,7 +104,7 @@ typedef struct bUnitCollection { /* Dummy */ static struct bUnitDef buDummyDef[] = { {"", NULL, "", NULL, NULL, 1.0, 0.0}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0}}; -static struct bUnitCollection buDummyCollecton = {buDummyDef, 0, 0, sizeof(buDummyDef)}; +static struct bUnitCollection buDummyCollection = {buDummyDef, 0, 0, sizeof(buDummyDef)}; /* Lengths */ static struct bUnitDef buMetricLenDef[] = { @@ -125,7 +125,7 @@ static struct bUnitDef buMetricLenDef[] = { #endif {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buMetricLenCollecton = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buMetricLenCollection = {buMetricLenDef, 3, 0, sizeof(buMetricLenDef) / sizeof(bUnitDef)}; static struct bUnitDef buImperialLenDef[] = { {"mile", "miles", "mi", "m", "Miles", UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, @@ -137,7 +137,7 @@ static struct bUnitDef buImperialLenDef[] = { {"thou", "thou", "thou", "mil", "Thou", UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, /* plural for thou has no 's' */ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialLenCollecton = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buImperialLenCollection = {buImperialLenDef, 4, 0, sizeof(buImperialLenDef) / sizeof(bUnitDef)}; /* Areas */ static struct bUnitDef buMetricAreaDef[] = { @@ -151,7 +151,7 @@ static struct bUnitDef buMetricAreaDef[] = { {"square micrometer", "square micrometers", "µm²", "um2", "Square Micrometers", UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buMetricAreaCollecton = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buMetricAreaCollection = {buMetricAreaDef, 3, 0, sizeof(buMetricAreaDef) / sizeof(bUnitDef)}; static struct bUnitDef buImperialAreaDef[] = { {"square mile", "square miles", "sq mi", "sq m", "Square Miles", UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, @@ -163,7 +163,7 @@ static struct bUnitDef buImperialAreaDef[] = { {"square thou", "square thous", "sq mil", NULL, "Square Thous", UN_SC_MIL * UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialAreaCollecton = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buImperialAreaCollection = {buImperialAreaDef, 4, 0, sizeof(buImperialAreaDef) / sizeof(bUnitDef)}; /* Volumes */ static struct bUnitDef buMetricVolDef[] = { @@ -177,7 +177,7 @@ static struct bUnitDef buMetricVolDef[] = { {"cubic micrometer", "cubic micrometers", "µm³", "um3", "Cubic Micrometers", UN_SC_UM * UN_SC_UM * UN_SC_UM, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buMetricVolCollecton = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buMetricVolCollection = {buMetricVolDef, 3, 0, sizeof(buMetricVolDef) / sizeof(bUnitDef)}; static struct bUnitDef buImperialVolDef[] = { {"cubic mile", "cubic miles", "cu mi", "cu m", "Cubic Miles", UN_SC_MI * UN_SC_MI * UN_SC_MI, 0.0, B_UNIT_DEF_NONE}, @@ -189,7 +189,7 @@ static struct bUnitDef buImperialVolDef[] = { {"cubic thou", "cubic thous", "cu mil", NULL, "Cubic Thous", UN_SC_MIL * UN_SC_MIL * UN_SC_MIL, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialVolCollecton = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buImperialVolCollection = {buImperialVolDef, 4, 0, sizeof(buImperialVolDef) / sizeof(bUnitDef)}; /* Mass */ static struct bUnitDef buMetricMassDef[] = { @@ -201,7 +201,7 @@ static struct bUnitDef buMetricMassDef[] = { {"gram", "grams", "g", NULL, "Grams", UN_SC_G, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buMetricMassCollecton = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buMetricMassCollection = {buMetricMassDef, 2, 0, sizeof(buMetricMassDef) / sizeof(bUnitDef)}; static struct bUnitDef buImperialMassDef[] = { {"ton", "tonnes", "ton", "t", "Tonnes", UN_SC_ITON, 0.0, B_UNIT_DEF_NONE}, @@ -211,7 +211,7 @@ static struct bUnitDef buImperialMassDef[] = { {"ounce", "ounces", "oz", NULL, "Ounces", UN_SC_OZ, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialMassCollecton = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buImperialMassCollection = {buImperialMassDef, 3, 0, sizeof(buImperialMassDef) / sizeof(bUnitDef)}; /* Even if user scales the system to a point where km^3 is used, velocity and * acceleration aren't scaled: that's why we have so few units for them */ @@ -222,27 +222,27 @@ static struct bUnitDef buMetricVelDef[] = { {"kilometer per hour", "kilometers per hour", "km/h", NULL, "Kilometers per hour", UN_SC_KM / 3600.0f, 0.0, B_UNIT_DEF_SUPPRESS}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buMetricVelCollecton = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buMetricVelCollection = {buMetricVelDef, 0, 0, sizeof(buMetricVelDef) / sizeof(bUnitDef)}; static struct bUnitDef buImperialVelDef[] = { {"foot per second", "feet per second", "ft/s", "fps", "Feet per second", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {"mile per hour", "miles per hour", "mph", NULL, "Miles per hour", UN_SC_MI / 3600.0f, 0.0, B_UNIT_DEF_SUPPRESS}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialVelCollecton = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buImperialVelCollection = {buImperialVelDef, 0, 0, sizeof(buImperialVelDef) / sizeof(bUnitDef)}; /* Acceleration */ static struct bUnitDef buMetricAclDef[] = { {"meter per second squared", "meters per second squared", "m/s²", "m/s2", "Meters per second squared", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buMetricAclCollecton = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buMetricAclCollection = {buMetricAclDef, 0, 0, sizeof(buMetricAclDef) / sizeof(bUnitDef)}; static struct bUnitDef buImperialAclDef[] = { {"foot per second squared", "feet per second squared", "ft/s²", "ft/s2", "Feet per second squared", UN_SC_FT, 0.0, B_UNIT_DEF_NONE}, /* base unit */ {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buImperialAclCollecton = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buImperialAclCollection = {buImperialAclDef, 0, 0, sizeof(buImperialAclDef) / sizeof(bUnitDef)}; /* Time */ static struct bUnitDef buNaturalTimeDef[] = { @@ -255,7 +255,7 @@ static struct bUnitDef buNaturalTimeDef[] = { {"microsecond", "microseconds", "µs", "us", "Microseconds", 0.000001, 0.0, B_UNIT_DEF_NONE}, {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} }; -static struct bUnitCollection buNaturalTimeCollecton = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef) / sizeof(bUnitDef)}; +static struct bUnitCollection buNaturalTimeCollection = {buNaturalTimeDef, 3, 0, sizeof(buNaturalTimeDef) / sizeof(bUnitDef)}; static struct bUnitDef buNaturalRotDef[] = { @@ -266,12 +266,24 @@ static struct bUnitDef buNaturalRotDef[] = { }; static struct bUnitCollection buNaturalRotCollection = {buNaturalRotDef, 0, 0, sizeof(buNaturalRotDef) / sizeof(bUnitDef)}; -#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / 9) / sizeof(void *)) - 1) -static struct bUnitCollection *bUnitSystems[][9] = { - {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollecton, NULL, NULL}, - {NULL, &buMetricLenCollecton, &buMetricAreaCollecton, &buMetricVolCollecton, &buMetricMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buMetricVelCollecton, &buMetricAclCollecton}, /* metric */ - {NULL, &buImperialLenCollecton, &buImperialAreaCollecton, &buImperialVolCollecton, &buImperialMassCollecton, &buNaturalRotCollection, &buNaturalTimeCollecton, &buImperialVelCollecton, &buImperialAclCollecton}, /* imperial */ - {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} +/* Camera Lengths */ +static struct bUnitDef buCameraLenDef[] = { + {"meter", "meters", "m", NULL, "Meters", UN_SC_KM, 0.0, B_UNIT_DEF_NONE}, /* base unit */ + {"decimeter", "decimeters", "dm", NULL, "10 Centimeters", UN_SC_HM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"centimeter", "centimeters", "cm", NULL, "Centimeters", UN_SC_DAM, 0.0, B_UNIT_DEF_SUPPRESS}, + {"millimeter", "millimeters", "mm", NULL, "Millimeters", UN_SC_M, 0.0, B_UNIT_DEF_NONE}, + {"micrometer", "micrometers", "µm", "um", "Micrometers", UN_SC_MM, 0.0, B_UNIT_DEF_SUPPRESS}, // micron too? + {NULL, NULL, NULL, NULL, NULL, 0.0, 0.0} +}; +static struct bUnitCollection buCameraLenCollection = {buCameraLenDef, 3, 0, sizeof(buCameraLenDef) / sizeof(bUnitDef)}; + + +#define UNIT_SYSTEM_TOT (((sizeof(bUnitSystems) / B_UNIT_TYPE_TOT) / sizeof(void *)) - 1) +static struct bUnitCollection *bUnitSystems[][B_UNIT_TYPE_TOT] = { + {NULL, NULL, NULL, NULL, NULL, &buNaturalRotCollection, &buNaturalTimeCollection, NULL, NULL, NULL}, + {NULL, &buMetricLenCollection, &buMetricAreaCollection, &buMetricVolCollection, &buMetricMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buMetricVelCollection, &buMetricAclCollection, &buCameraLenCollection}, /* metric */ + {NULL, &buImperialLenCollection, &buImperialAreaCollection, &buImperialVolCollection, &buImperialMassCollection, &buNaturalRotCollection, &buNaturalTimeCollection, &buImperialVelCollection, &buImperialAclCollection, &buCameraLenCollection}, /* imperial */ + {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} }; @@ -395,10 +407,10 @@ void bUnit_AsString(char *str, int len_max, double value, int prec, int system, bUnitCollection *usys = unit_get_system(system, type); if (usys == NULL || usys->units[0].name == NULL) - usys = &buDummyCollecton; + usys = &buDummyCollection; /* split output makes sense only for length, mass and time */ - if (split && (type == B_UNIT_LENGTH || type == B_UNIT_MASS || type == B_UNIT_TIME)) { + if (split && (type == B_UNIT_LENGTH || type == B_UNIT_MASS || type == B_UNIT_TIME || type == B_UNIT_CAMERA)) { bUnitDef *unit_a, *unit_b; double value_a, value_b; @@ -706,7 +718,7 @@ void bUnit_ToUnitAltName(char *str, int len_max, const char *orig_str, int syste /* print the alt_name */ if (unit->name_alt) - len_name = BLI_snprintf(str, len_max, "%s", unit->name_alt); + len_name = BLI_strncpy_rlen(str, unit->name_alt, len_max); else len_name = 0; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 7e51025883d..a88a9e4954b 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -111,8 +111,9 @@ static void delete_picture(AVFrame *f) } } -static int use_float_audio_buffer(int codec_id) +static int request_float_audio_buffer(int codec_id) { + /* If any of these codecs, we prefer the float sample format (if supported) */ return codec_id == CODEC_ID_AAC || codec_id == CODEC_ID_AC3 || codec_id == CODEC_ID_VORBIS; } @@ -551,6 +552,12 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex } } + if (codec_id == CODEC_ID_PNG) { + if (rd->im_format.planes == R_IMF_PLANES_RGBA) { + c->pix_fmt = PIX_FMT_ARGB; + } + } + if ((of->oformat->flags & AVFMT_GLOBALHEADER) // || !strcmp(of->oformat->name, "mp4") // || !strcmp(of->oformat->name, "mov") @@ -623,16 +630,55 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex c->bit_rate = ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; c->channels = rd->ffcodecdata.audio_channels; - if (use_float_audio_buffer(codec_id)) { + + if (request_float_audio_buffer(codec_id)) { + /* mainly for AAC codec which is experimental */ c->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; c->sample_fmt = AV_SAMPLE_FMT_FLT; } + codec = avcodec_find_encoder(c->codec_id); if (!codec) { //XXX error("Couldn't find a valid audio codec"); return NULL; } + if (codec->sample_fmts) { + /* check if the prefered sample format for this codec is supported. + * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation, + * you have various implementations around. float samples in particular are not always supported. + */ + const enum AVSampleFormat *p = codec->sample_fmts; + for (; *p!=-1; p++) { + if (*p == st->codec->sample_fmt) + break; + } + if (*p == -1) { + /* sample format incompatible with codec. Defaulting to a format known to work */ + st->codec->sample_fmt = codec->sample_fmts[0]; + } + } + + if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) { + BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size); + return NULL; + } + + if (codec->supported_samplerates) { + const int *p = codec->supported_samplerates; + int best = 0; + int best_dist = INT_MAX; + for (; *p; p++) { + int dist = abs(st->codec->sample_rate - *p); + if (dist < best_dist) { + best_dist = dist; + best = *p; + } + } + /* best is the closest supported sample rate (same as selected if best_dist == 0) */ + st->codec->sample_rate = best; + } + set_ffmpeg_properties(rd, c, "audio"); if (avcodec_open2(c, codec, NULL) < 0) { @@ -658,7 +704,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); - if (use_float_audio_buffer(codec_id)) { + if (c->sample_fmt == AV_SAMPLE_FMT_FLT) { audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float)); } else { @@ -740,7 +786,7 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report fmt->audio_codec = ffmpeg_audio_codec; - BLI_snprintf(of->filename, sizeof(of->filename), "%s", name); + BLI_strncpy(of->filename, name, sizeof(of->filename)); /* set the codec to the user's selection */ switch (ffmpeg_type) { case FFMPEG_AVI: @@ -837,7 +883,8 @@ static int start_ffmpeg_impl(struct RenderData *rd, int rectx, int recty, Report } if (avformat_write_header(of, NULL) < 0) { BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination"); - av_dict_free(&opts); + av_dict_free(&opts); + avio_close(of->pb); return 0; } @@ -963,7 +1010,7 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, AVCodecContext *c = audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; - if (use_float_audio_buffer(c->codec_id)) { + if (c->sample_fmt == AV_SAMPLE_FMT_FLT) { specs.format = AUD_FORMAT_FLOAT32; } else { @@ -980,7 +1027,6 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, return success; } -void BKE_ffmpeg_end(void); static void end_ffmpeg_impl(int is_autosplit); #ifdef WITH_AUDASPACE @@ -1493,6 +1539,9 @@ int BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd) if (codec == CODEC_ID_QTRLE) return TRUE; + if (codec == CODEC_ID_PNG) + return TRUE; + #ifdef FFMPEG_FFV1_ALPHA_SUPPORTED if (codec == CODEC_ID_FFV1) return TRUE; diff --git a/source/blender/blenlib/BLI_buffer.h b/source/blender/blenlib/BLI_buffer.h index 880a97acb80..fe835e7cadc 100644 --- a/source/blender/blenlib/BLI_buffer.h +++ b/source/blender/blenlib/BLI_buffer.h @@ -52,6 +52,7 @@ enum { }; #define BLI_buffer_declare_static(type_, name_, flag_, static_count_) \ + char name_ ## user; /* warn for free only */ \ type_ *name_ ## _static_[static_count_]; \ BLI_Buffer name_ = { \ /* clear the static memory if this is a calloc'd array */ \ @@ -66,15 +67,26 @@ enum { /* never use static*/ #define BLI_buffer_declare(type_, name_, flag_) \ + bool name_ ## user; /* warn for free only */ \ BLI_Buffer name_ = {NULL, \ sizeof(type_), \ 0, \ 0, \ flag_} - #define BLI_buffer_at(buffer_, type_, index_) ( \ - (((type_ *)(buffer_)->data)[(BLI_assert(sizeof(type_) == (buffer_)->elem_size)), index_])) + (((type_ *)(buffer_)->data)[ \ + (BLI_assert(sizeof(type_) == (buffer_)->elem_size)), \ + (BLI_assert(index_ >= 0 && index_ < (buffer_)->count)), \ + index_])) + +#define BLI_buffer_array(buffer_, type_) ( \ + &(BLI_buffer_at(buffer_, type_, 0))) + +#define BLI_buffer_resize_data(buffer_, type_, new_count_) ( \ + (BLI_buffer_resize(buffer_, new_count_), new_count_ ? BLI_buffer_array(buffer_, type_) : NULL)) + + #define BLI_buffer_append(buffer_, type_, val_) ( \ BLI_buffer_resize(buffer_, (buffer_)->count + 1), \ @@ -85,6 +97,10 @@ enum { void BLI_buffer_resize(BLI_Buffer *buffer, int new_count); /* Does not free the buffer structure itself */ -void BLI_buffer_free(BLI_Buffer *buffer); +void _bli_buffer_free(BLI_Buffer *buffer); +#define BLI_buffer_free(name_) { \ + _bli_buffer_free(name_); \ + (void)name_ ## user; /* ensure we free */ \ +} (void)0 #endif /* __BLI_BUFFER_H__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index c278370d211..b0e3f47b627 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -34,14 +34,12 @@ #define __BLI_FILEOPS_H__ #include <stdio.h> - +#include <sys/stat.h> #ifdef __cplusplus extern "C" { #endif -#include "BLI_fileops_types.h" - /* for size_t (needed on windows) */ #include <stddef.h> @@ -52,7 +50,7 @@ struct gzFile; int BLI_exists(const char *path); int BLI_copy(const char *path, const char *to); int BLI_rename(const char *from, const char *to); -int BLI_delete(const char *path, int dir, int recursive); +int BLI_delete(const char *path, bool dir, bool recursive); int BLI_move(const char *path, const char *to); int BLI_create_symlink(const char *path, const char *to); int BLI_stat(const char *path, struct stat *buffer); @@ -61,22 +59,24 @@ int BLI_stat(const char *path, struct stat *buffer); struct direntry; -int BLI_is_dir(const char *path); -int BLI_is_file(const char *path); +bool BLI_is_dir(const char *path); +bool BLI_is_file(const char *path); void BLI_dir_create_recursive(const char *dir); double BLI_dir_free_space(const char *dir); char *BLI_current_working_dir(char *dir, const size_t maxlen); unsigned int BLI_dir_contents(const char *dir, struct direntry **filelist); +void BLI_free_filelist(struct direntry * filelist, unsigned int nrentries); /* Files */ FILE *BLI_fopen(const char *filename, const char *mode); void *BLI_gzopen(const char *filename, const char *mode); int BLI_open(const char *filename, int oflag, int pmode); +int BLI_access(const char *filename, int mode); -int BLI_file_is_writable(const char *file); -int BLI_file_touch(const char *file); +bool BLI_file_is_writable(const char *file); +bool BLI_file_touch(const char *file); int BLI_file_gzip(const char *from, const char *to); char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r); @@ -85,7 +85,7 @@ size_t BLI_file_descriptor_size(int file); size_t BLI_file_size(const char *file); /* compare if one was last modified before the other */ -int BLI_file_older(const char *file1, const char *file2); +bool BLI_file_older(const char *file1, const char *file2); /* read ascii file as lines, empty list if reading fails */ struct LinkNode *BLI_file_read_as_lines(const char *file); @@ -104,5 +104,4 @@ void BLI_get_short_name(char short_name[256], const char *filename); } #endif -#endif - +#endif /* __BLI_FILEOPS_H__ */ diff --git a/source/blender/blenlib/BLI_fileops_types.h b/source/blender/blenlib/BLI_fileops_types.h index 1c6463eb6ea..a7372c01e52 100644 --- a/source/blender/blenlib/BLI_fileops_types.h +++ b/source/blender/blenlib/BLI_fileops_types.h @@ -42,7 +42,6 @@ typedef unsigned int mode_t; struct ImBuf; struct direntry { - char *string; mode_t type; char *relname; char *path; diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 7eac1425a5c..97564ca5363 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -69,9 +69,9 @@ GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info); void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_insert(GHash *gh, void *key, void *val); void *BLI_ghash_lookup(GHash *gh, const void *key); -int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); +bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); -int BLI_ghash_haskey(GHash *gh, const void *key); +bool BLI_ghash_haskey(GHash *gh, const void *key); int BLI_ghash_size(GHash *gh); /* *** */ @@ -130,11 +130,11 @@ void BLI_ghashIterator_step(GHashIterator *ghi); * \param ghi The iterator. * \return True if done, False otherwise. */ -int BLI_ghashIterator_isDone(GHashIterator *ghi); +bool BLI_ghashIterator_notDone(GHashIterator *ghi); #define GHASH_ITER(gh_iter_, ghash_) \ for (BLI_ghashIterator_init(&gh_iter_, ghash_); \ - !BLI_ghashIterator_isDone(&gh_iter_); \ + BLI_ghashIterator_notDone(&gh_iter_); \ BLI_ghashIterator_step(&gh_iter_)) /* *** */ diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h index b4cb1edd45a..b9d8a8f9d14 100644 --- a/source/blender/blenlib/BLI_gsqueue.h +++ b/source/blender/blenlib/BLI_gsqueue.h @@ -47,7 +47,7 @@ GSQueue *BLI_gsqueue_new(int elem_size); /** * Query if the queue is empty */ -int BLI_gsqueue_is_empty(GSQueue *gq); +bool BLI_gsqueue_is_empty(GSQueue *gq); /** * Query number elements in the queue diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h index c0941e00c9b..bc7b6000322 100644 --- a/source/blender/blenlib/BLI_heap.h +++ b/source/blender/blenlib/BLI_heap.h @@ -54,7 +54,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr); void BLI_heap_remove(Heap *heap, HeapNode *node); /* Return 0 if the heap is empty, 1 otherwise. */ -int BLI_heap_is_empty(Heap *heap); +bool BLI_heap_is_empty(Heap *heap); /* Return the size of the heap. */ unsigned int BLI_heap_size(Heap *heap); diff --git a/source/blender/blenlib/BLI_lasso.h b/source/blender/blenlib/BLI_lasso.h index a7e90a51e86..0addd463a70 100644 --- a/source/blender/blenlib/BLI_lasso.h +++ b/source/blender/blenlib/BLI_lasso.h @@ -35,7 +35,7 @@ struct rcti; void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const short moves); -int BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value); -int BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value); +bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves, const int sx, const int sy, const int error_value); +bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, int x0, int y0, int x1, int y1, const int error_value); #endif diff --git a/source/blender/blenlib/BLI_linklist.h b/source/blender/blenlib/BLI_linklist.h index da56a300b9b..3e7fdc8bf75 100644 --- a/source/blender/blenlib/BLI_linklist.h +++ b/source/blender/blenlib/BLI_linklist.h @@ -59,6 +59,7 @@ void BLI_linklist_prepend_arena(struct LinkNode **listp, void *ptr, struct Me void BLI_linklist_insert_after(struct LinkNode **listp, void *ptr); void BLI_linklist_free(struct LinkNode *list, LinkNodeFreeFP freefunc); +void BLI_linklist_freeN(struct LinkNode *list); void BLI_linklist_apply(struct LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata); #endif diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index aa4e697b48b..67c1ffcebc0 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -179,6 +179,11 @@ #include "intern/math_base_inline.c" #endif +#ifdef BLI_MATH_GCC_WARN_PRAGMA +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + /******************************* Float ******************************/ MINLINE float sqrt3f(float f); @@ -217,6 +222,10 @@ extern double round(double x); double double_round(double x, int ndigits); +#ifdef BLI_MATH_GCC_WARN_PRAGMA +# pragma GCC diagnostic pop +#endif + /* asserts, some math functions expect normalized inputs * check the vector is unit length, or zero length (which can't be helped in some cases). */ diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 13f47d94160..94fa88801f0 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -40,6 +40,11 @@ extern "C" { #include "intern/math_geom_inline.c" #endif +#ifdef BLI_MATH_GCC_WARN_PRAGMA +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + /********************************** Polygons *********************************/ void cent_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]); @@ -130,13 +135,15 @@ int isect_ray_tri_epsilon_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2], const float epsilon); /* point in polygon */ +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr); +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr); + int isect_point_quad_v2(const float p[2], const float a[2], const float b[2], const float c[2], const float d[2]); int isect_point_tri_v2(const float pt[2], const float v1[2], const float v2[2], const float v3[2]); int isect_point_tri_v2_cw(const float pt[2], const float v1[2], const float v2[2], const float v3[2]); int isect_point_tri_v2_int(const int x1, const int y1, const int x2, const int y2, const int a, const int b); int isect_point_tri_prism_v3(const float p[3], const float v1[3], const float v2[3], const float v3[3]); - void isect_point_quad_uv_v2(const float v0[2], const float v1[2], const float v2[2], const float v3[2], const float pt[2], float r_uv[2]); void isect_point_face_uv_v2(const int isquad, const float v0[2], const float v1[2], const float v2[2], @@ -281,6 +288,10 @@ MINLINE int min_axis_v3(const float vec[3]); MINLINE int poly_to_tri_count(const int poly_count, const int corner_count); +#ifdef BLI_MATH_GCC_WARN_PRAGMA +# pragma GCC diagnostic pop +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_inline.h b/source/blender/blenlib/BLI_math_inline.h index 6dad44644f2..2bf3b9532dd 100644 --- a/source/blender/blenlib/BLI_math_inline.h +++ b/source/blender/blenlib/BLI_math_inline.h @@ -56,6 +56,11 @@ extern "C" { # define MALWAYS_INLINE #endif +/* gcc 4.6 (supports push/pop) */ +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 406)) +# define BLI_MATH_GCC_WARN_PRAGMA 1 +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 42a6b90f738..c9ad19f74b4 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -42,6 +42,11 @@ extern "C" { /************************************* Init ***********************************/ +#ifdef BLI_MATH_GCC_WARN_PRAGMA +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wredundant-decls" +#endif + MINLINE void zero_v2(float r[2]); MINLINE void zero_v3(float r[3]); MINLINE void zero_v4(float r[4]); @@ -108,6 +113,7 @@ MINLINE void mul_v3_v3(float r[3], const float a[3]); MINLINE void mul_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void mul_v4_fl(float r[4], float f); MINLINE void mul_v4_v4fl(float r[3], const float a[3], float f); +MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]); MINLINE void madd_v3_v3fl(float r[3], const float a[3], float f); MINLINE void madd_v3_v3v3(float r[3], const float a[3], const float b[3]); @@ -260,6 +266,10 @@ void fill_vn_i(int *array_tar, const int size, const int val); void fill_vn_ushort(unsigned short *array_tar, const int size, const unsigned short val); void fill_vn_fl(float *array_tar, const int size, const float val); +#ifdef BLI_MATH_GCC_WARN_PRAGMA +# pragma GCC diagnostic pop +#endif + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 8c51c925d97..20fc489cbc3 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -40,10 +40,10 @@ struct direntry; const char *BLI_getDefaultDocumentFolder(void); -char *BLI_get_folder(int folder_id, const char *subfolder); -char *BLI_get_folder_create(int folder_id, const char *subfolder); -char *BLI_get_user_folder_notest(int folder_id, const char *subfolder); -char *BLI_get_folder_version(const int id, const int ver, const int do_check); +const char *BLI_get_folder(int folder_id, const char *subfolder); +const char *BLI_get_folder_create(int folder_id, const char *subfolder); +const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder); +const char *BLI_get_folder_version(const int id, const int ver, const bool do_check); /* folder_id */ @@ -86,11 +86,11 @@ void BLI_setenv_if_new(const char *env, const char *val); void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); void BLI_make_exist(char *dir); void BLI_make_existing_file(const char *name); -void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen); -void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen); -void BLI_split_file_part(const char *string, char *file, const size_t filelen); -void BLI_join_dirfile(char *string, const size_t maxlen, const char *dir, const char *file); -char *BLI_path_basename(char *path); +void BLI_split_dirfile(const char *string, char *dir, char *file, size_t dirlen, size_t filelen); +void BLI_split_dir_part(const char *string, char *dir, size_t dirlen); +void BLI_split_file_part(const char *string, char *file, size_t filelen); +void BLI_join_dirfile(char *string, size_t maxlen, const char *dir, const char *file); +const char *BLI_path_basename(const char *path); typedef enum bli_rebase_state { BLI_REBASE_NO_SRCDIR = 0, @@ -100,24 +100,24 @@ typedef enum bli_rebase_state { int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir); -char *BLI_last_slash(const char *string); -int BLI_add_slash(char *string); -void BLI_del_slash(char *string); -char *BLI_first_slash(char *string); - -void BLI_getlastdir(const char *dir, char *last, const size_t maxlen); -int BLI_testextensie(const char *str, const char *ext); -int BLI_testextensie_array(const char *str, const char **ext_array); -int BLI_testextensie_glob(const char *str, const char *ext_fnmatch); -int BLI_replace_extension(char *path, size_t maxlen, const char *ext); -int BLI_ensure_extension(char *path, size_t maxlen, const char *ext); -void BLI_uniquename(struct ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len); -int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len); +const char *BLI_last_slash(const char *string); +int BLI_add_slash(char *string); +void BLI_del_slash(char *string); +const char *BLI_first_slash(const char *string); + +void BLI_getlastdir(const char *dir, char *last, size_t maxlen); +bool BLI_testextensie(const char *str, const char *ext); +bool BLI_testextensie_array(const char *str, const char **ext_array); +bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch); +bool BLI_replace_extension(char *path, size_t maxlen, const char *ext); +bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext); +void BLI_uniquename(struct ListBase *list, void *vlink, const char * defname, char delim, short name_offs, short len); +bool BLI_uniquename_cb(bool (*unique_check)(void * arg, const char * name), + void *arg, const char * defname, char delim, char *name, short name_len); void BLI_newname(char *name, int add); int BLI_stringdec(const char *string, char *head, char *start, unsigned short *numlen); void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic); -int BLI_split_name_num(char *left, int *nr, const char *name, const char delim); -void BLI_splitdirstring(char *di, char *fi); +int BLI_split_name_num(char *left, int *nr, const char *name, char delim); /* make sure path separators conform to system one */ void BLI_clean(char *path) @@ -131,15 +131,15 @@ __attribute__((nonnull(1))) * converts it to a regular full path. * Also removes garbage from directory paths, like /../ or double slashes etc */ -void BLI_cleanup_file(const char *relabase, char *dir); /* removes trailing slash */ +void BLI_cleanup_file(const char *relabase, char *path); /* removes trailing slash */ void BLI_cleanup_dir(const char *relabase, char *dir); /* same as above but adds a trailing slash */ -void BLI_cleanup_path(const char *relabase, char *dir); /* doesn't touch trailing slash */ +void BLI_cleanup_path(const char *relabase, char *path); /* doesn't touch trailing slash */ /* go back one directory */ -int BLI_parent_dir(char *path); +bool BLI_parent_dir(char *path); /* return whether directory is root and thus has no parent dir */ -int BLI_has_parent(char *path); +bool BLI_has_parent(char *path); /** * Blender's path code replacement function. @@ -153,14 +153,15 @@ int BLI_has_parent(char *path); * \a framenum The framenumber to replace the frame code with. * \retval Returns true if the path was relative (started with "//"). */ -int BLI_path_abs(char *path, const char *basepath); -int BLI_path_frame(char *path, int frame, int digits); -int BLI_path_frame_range(char *path, int sta, int end, int digits); -int BLI_path_cwd(char *path); +bool BLI_path_abs(char *path, const char *basepath); +bool BLI_path_frame(char *path, int frame, int digits); +bool BLI_path_frame_range(char *path, int sta, int end, int digits); +bool BLI_path_cwd(char *path); void BLI_path_rel(char *file, const char *relfile); -int BLI_path_is_rel(const char *path); +bool BLI_path_is_rel(const char *path); +/* path string comparisons: case-insensitive for Windows, case-sensitive otherwise */ #ifdef WIN32 # define BLI_path_cmp BLI_strcasecmp # define BLI_path_ncmp BLI_strncasecmp diff --git a/source/blender/blenlib/BLI_rect.h b/source/blender/blenlib/BLI_rect.h index 3c9363039b2..9ce75de5ea8 100644 --- a/source/blender/blenlib/BLI_rect.h +++ b/source/blender/blenlib/BLI_rect.h @@ -43,8 +43,8 @@ struct rcti; extern "C" { #endif -int BLI_rcti_is_empty(const struct rcti *rect); -int BLI_rctf_is_empty(const struct rctf *rect); +bool BLI_rcti_is_empty(const struct rcti *rect); +bool BLI_rctf_is_empty(const struct rctf *rect); void BLI_rctf_init(struct rctf *rect, float xmin, float xmax, float ymin, float ymax); void BLI_rcti_init(struct rcti *rect, int xmin, int xmax, int ymin, int ymax); void BLI_rcti_init_minmax(struct rcti *rect); @@ -60,18 +60,18 @@ void BLI_rcti_scale(rcti *rect, const float scale); void BLI_rctf_scale(rctf *rect, const float scale); void BLI_rctf_interp(struct rctf *rect, const struct rctf *rect_a, const struct rctf *rect_b, const float fac); //void BLI_rcti_interp(struct rctf *rect, struct rctf *rect_a, struct rctf *rect_b, float fac); -int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]); -int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]); -int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit); -int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b); -int BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest); -int BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest); -int BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y); -int BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]); -int BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y); -int BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]); -int BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]); -int BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]); +bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]); +bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]); +bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit); +bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b); +bool BLI_rctf_isect(const struct rctf *src1, const struct rctf *src2, struct rctf *dest); +bool BLI_rcti_isect(const struct rcti *src1, const struct rcti *src2, struct rcti *dest); +bool BLI_rcti_isect_pt(const struct rcti *rect, const int x, const int y); +bool BLI_rcti_isect_pt_v(const struct rcti *rect, const int xy[2]); +bool BLI_rctf_isect_pt(const struct rctf *rect, const float x, const float y); +bool BLI_rctf_isect_pt_v(const struct rctf *rect, const float xy[2]); +bool BLI_rcti_isect_segment(const struct rcti *rect, const int s1[2], const int s2[2]); +bool BLI_rctf_isect_segment(const struct rctf *rect, const float s1[2], const float s2[2]); void BLI_rctf_union(struct rctf *rctf1, const struct rctf *rctf2); void BLI_rcti_union(struct rcti *rcti1, const struct rcti *rcti2); void BLI_rcti_rctf_copy(struct rcti *dst, const struct rctf *src); diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 70c89773f02..3bc9d733254 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -38,42 +38,20 @@ extern "C" { #endif -/** - * Duplicates the cstring \a str into a newly mallocN'd - * string and returns it. - * - * \param str The string to be duplicated - * \retval Returns the duplicated string - */ -char *BLI_strdup(const char *str) +char *BLI_strdupn(const char *str, const size_t len) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) #endif ; -/** - * Duplicates the first \a len bytes of cstring \a str - * into a newly mallocN'd string and returns it. \a str - * is assumed to be at least len bytes long. - * - * \param str The string to be duplicated - * \param len The number of bytes to duplicate - * \retval Returns the duplicated string - */ -char *BLI_strdupn(const char *str, const size_t len) +char *BLI_strdup(const char *str) #ifdef __GNUC__ __attribute__((warn_unused_result)) __attribute__((nonnull)) #endif ; -/** - * Appends the two strings, and returns new mallocN'ed string - * \param str1 first string for copy - * \param str2 second string for append - * \retval Returns dst - */ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -81,32 +59,19 @@ __attribute__((nonnull)) #endif ; -/** - * Like strncpy but ensures dst is always - * '\0' terminated. - * - * \param dst Destination for copy - * \param src Source string to copy - * \param maxncpy Maximum number of characters to copy (generally - * the size of dst) - * \retval Returns dst - */ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) #ifdef __GNUC__ __attribute__((nonnull)) #endif ; -/** - *Makes a copy of the text within the "" that appear after some text 'blahblah' - * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" - * - * - str: is the entire string to chop - * - prefix: is the part of the string to leave out - * - * Assume that the strings returned must be freed afterwards, and that the inputs will contain - * data we want... - */ +size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +__attribute__((nonnull)) +#endif +; + char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -114,16 +79,6 @@ __attribute__((nonnull)) #endif ; -/** - * Returns a copy of the cstring \a str into a newly mallocN'd - * string with all instances of oldText replaced with newText, - * and returns it. - * - * \param str The string to replace occurrences of oldText in - * \param oldText The text in the string to find and replace - * \param newText The text in the string to find and replace - * \retval Returns the duplicated string - */ char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -131,9 +86,6 @@ __attribute__((nonnull)) #endif ; -/* - * Replacement for snprintf - */ size_t BLI_snprintf(char *__restrict buffer, size_t len, const char *__restrict format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 4))) @@ -141,19 +93,12 @@ __attribute__((nonnull)) #endif ; -/* - * Replacement for vsnprintf - */ size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) #ifdef __GNUC__ __attribute__ ((format(printf, 3, 0))) #endif ; -/* - * Print formatted string into a newly mallocN'd string - * and return it. - */ char *BLI_sprintfN(const char *__restrict format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 1, 2))) @@ -168,11 +113,6 @@ __attribute__((nonnull)) #endif ; -/** - * Compare two strings without regard to case. - * - * \retval True if the strings are equal, false otherwise. - */ int BLI_strcaseeq(const char *a, const char *b) #ifdef __GNUC__ __attribute__((warn_unused_result)) @@ -214,7 +154,7 @@ void BLI_timestr(double _time, char *str) #ifdef __GNUC__ __attribute__((nonnull)) #endif -; /* time var is global */ +; void BLI_ascii_strtolower(char *str, const size_t len) #ifdef __GNUC__ @@ -226,6 +166,11 @@ void BLI_ascii_strtoupper(char *str, const size_t len) __attribute__((nonnull)) #endif ; +int BLI_str_rstrip_float_zero(char *str, const char pad) +#ifdef __GNUC__ +__attribute__((nonnull)) +#endif +; #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 30d5c28bf98..d20cbd2a91c 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -56,7 +56,14 @@ size_t BLI_strnlen_utf8(const char *start, const size_t maxlen); size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy); size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy); -#define BLI_UTF8_MAX 6 +/* count columns that character/string occupies, based on wcwidth.c */ +int BLI_wcwidth(wchar_t ucs); +int BLI_wcswidth(const wchar_t *pwcs, size_t n); +int BLI_str_utf8_char_width(const char *p); /* warning, can return -1 on bad chars */ +int BLI_str_utf8_char_width_safe(const char *p); + +#define BLI_UTF8_MAX 6 /* mem */ +#define BLI_UTF8_WIDTH_MAX 2 /* columns */ #define BLI_UTF8_ERR ((unsigned int)-1) #ifdef __cplusplus diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index bbafd28ddbc..bf5531d94af 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -167,7 +167,7 @@ typedef bool _BLI_Bool; (b) = (tval); \ } (void)0 - +/* ELEM#(a, ...): is the first arg equal any of the others */ #define ELEM(a, b, c) ((a) == (b) || (a) == (c)) #define ELEM3(a, b, c, d) (ELEM(a, b, c) || (a) == (d) ) #define ELEM4(a, b, c, d, e) (ELEM(a, b, c) || ELEM(a, d, e) ) @@ -295,9 +295,9 @@ typedef bool _BLI_Bool; #define UNPACK3(a) ((a)[0]), ((a)[1]), ((a)[2]) #define UNPACK4(a) ((a)[0]), ((a)[1]), ((a)[2]), ((a)[3]) /* op may be '&' or '*' */ -#define UNPACK2OP(a, op) op((a)[0]), op((a)[1]) -#define UNPACK3OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]) -#define UNPACK4OP(a, op) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3]) +#define UNPACK2OP(op, a) op((a)[0]), op((a)[1]) +#define UNPACK3OP(op, a) op((a)[0]), op((a)[1]), op((a)[2]) +#define UNPACK4OP(op, a) op((a)[0]), op((a)[1]), op((a)[2]), op((a)[3]) /* array helpers */ #define ARRAY_LAST_ITEM(arr_start, arr_dtype, elem_size, tot) \ @@ -326,6 +326,22 @@ typedef bool _BLI_Bool; #define STRINGIFY_APPEND(a, b) "" a #b #define STRINGIFY(x) STRINGIFY_APPEND("", x) +/* generic strcmp macros */ +#define STREQ(a, b) (strcmp(a, b) == 0) +#define STRNEQ(a, b) (!STREQ(a, b)) + +#define STRCASEEQ(a, b) (strcasecmp(a, b) == 0) +#define STRCASENEQ(a, b) (!STRCASEEQ(a, b)) + +#define STREQLEN(a, b, n) (strncmp(a, b, n) == 0) +#define STRNEQLEN(a, b, n) (!STREQLEN(a, b, n)) + +#define STRCASEEQLEN(a, b, n) (strncasecmp(a, b, n) == 0) +#define STRCASENEQLEN(a, b, n) (!STRCASEEQLEN(a, b, n)) + +#define STRPREFIX(a, b) (strncmp((a), (b), strlen(b)) == 0) + + /* useful for debugging */ #define AT __FILE__ ":" STRINGIFY(__LINE__) diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 70c7f1d9cae..20a4c3c274e 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -94,6 +94,15 @@ extern "C" { /* defines for using ISO C++ conformant names */ #define snprintf _snprintf +#ifdef _MSC_VER +# define R_OK 4 +# define W_OK 2 +// not accepted by access() on windows +//# define X_OK 1 +# define F_OK 0 +# define PATH_MAX 4096 +#endif + #ifndef FREE_WINDOWS typedef unsigned int mode_t; #endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 82ff09b5999..9b3fca280c4 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -29,6 +29,7 @@ set(INC ../makesdna ../../../intern/ghost ../../../intern/guardedalloc + ../../../extern/wcwidth ) set(INC_SYS diff --git a/source/blender/blenlib/SConscript b/source/blender/blenlib/SConscript index 19216442aa0..79e2a47aeb8 100644 --- a/source/blender/blenlib/SConscript +++ b/source/blender/blenlib/SConscript @@ -31,7 +31,7 @@ sources = env.Glob('intern/*.c') cflags='' # don't add ../blenkernel back! -incs = '. ../makesdna #/intern/guardedalloc #/intern/ghost' +incs = '. ../makesdna #/intern/guardedalloc #/intern/ghost #/extern/wcwidth' incs += ' ' + env['BF_FREETYPE_INC'] incs += ' ' + env['BF_ZLIB_INC'] diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 7ebe4430e20..ebc40ebc5e3 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -120,7 +120,7 @@ void *BLI_ghash_lookup(GHash *gh, const void *key) return NULL; } -int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { unsigned int hash = gh->hashfp(key) % gh->nbuckets; Entry *e; @@ -140,12 +140,12 @@ int BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFre else gh->buckets[hash] = n; gh->nentries--; - return 1; + return true; } p = e; } - return 0; + return false; } /* same as above but return the value, @@ -178,16 +178,16 @@ void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) return NULL; } -int BLI_ghash_haskey(GHash *gh, const void *key) +bool BLI_ghash_haskey(GHash *gh, const void *key) { unsigned int hash = gh->hashfp(key) % gh->nbuckets; Entry *e; for (e = gh->buckets[hash]; e; e = e->next) if (gh->cmpfp(key, e->key) == 0) - return 1; + return true; - return 0; + return false; } void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) @@ -271,9 +271,9 @@ void BLI_ghashIterator_step(GHashIterator *ghi) } } } -int BLI_ghashIterator_isDone(GHashIterator *ghi) +bool BLI_ghashIterator_notDone(GHashIterator *ghi) { - return !ghi->curEntry; + return ghi->curEntry != NULL; } /***/ diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index aa54969b6f8..53489c76962 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -33,9 +33,10 @@ #include <string.h> #include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" #include "BLI_memarena.h" #include "BLI_heap.h" -#include "BLI_utildefines.h" /***/ @@ -183,7 +184,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) return node; } -int BLI_heap_is_empty(Heap *heap) +bool BLI_heap_is_empty(Heap *heap) { return (heap->size == 0); } diff --git a/source/blender/blenlib/intern/BLI_linklist.c b/source/blender/blenlib/intern/BLI_linklist.c index 0e630efc349..b08fbe17a43 100644 --- a/source/blender/blenlib/intern/BLI_linklist.c +++ b/source/blender/blenlib/intern/BLI_linklist.c @@ -155,6 +155,18 @@ void BLI_linklist_free(LinkNode *list, LinkNodeFreeFP freefunc) } } +void BLI_linklist_freeN(LinkNode *list) +{ + while (list) { + LinkNode *next = list->next; + + MEM_freeN(list->link); + MEM_freeN(list); + + list = next; + } +} + void BLI_linklist_apply(LinkNode *list, LinkNodeApplyFP applyfunc, void *userdata) { for (; list; list = list->next) diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index 0ac6209fc95..b6b5b600ab1 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -74,7 +74,7 @@ void BLI_memarena_use_align(struct MemArena *ma, const int align) void BLI_memarena_free(MemArena *ma) { - BLI_linklist_free(ma->bufs, (void (*)(void *))MEM_freeN); + BLI_linklist_freeN(ma->bufs); MEM_freeN(ma); } diff --git a/source/blender/blenlib/intern/buffer.c b/source/blender/blenlib/intern/buffer.c index b2280b9a0d1..aac3a3bc3f3 100644 --- a/source/blender/blenlib/intern/buffer.c +++ b/source/blender/blenlib/intern/buffer.c @@ -70,7 +70,8 @@ void BLI_buffer_resize(BLI_Buffer *buffer, int new_count) buffer->count = new_count; } -void BLI_buffer_free(BLI_Buffer *buffer) +/* callers use BLI_buffer_free */ +void _bli_buffer_free(BLI_Buffer *buffer) { if ((buffer->flag & BLI_BUFFER_USE_STATIC) == 0) { if (buffer->data) { diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 24b3c36a329..29280c36222 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -138,7 +138,9 @@ char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r) if (readsize > 0) { size += readsize; } - else break; + else { + break; + } } gzclose(gzfile); @@ -155,37 +157,43 @@ char *BLI_file_ungzip_to_mem(const char *from_file, int *size_r) return mem; } - -/* return 1 when file can be written */ -int BLI_file_is_writable(const char *filename) +/** + * Returns true if the file with the specified name can be written. + * This implementation uses access(2), which makes the check according + * to the real UID and GID of the process, not its effective UID and GID. + * This shouldn't matter for Blender, which is not going to run privileged + * anyway. + */ +bool BLI_file_is_writable(const char *filename) { - int file; - - /* first try to open without creating */ - file = BLI_open(filename, O_BINARY | O_RDWR, 0666); - - if (file < 0) { - /* now try to open and create. a test without actually - * creating a file would be nice, but how? */ - file = BLI_open(filename, O_BINARY | O_RDWR | O_CREAT, 0666); - - if (file < 0) { - return 0; - } - else { - /* success, delete the file we create */ - close(file); - BLI_delete(filename, 0, 0); - return 1; - } + bool writable; + if (BLI_access(filename, W_OK) == 0) { + /* file exists and I can write to it */ + writable = true; + } + else if (errno != ENOENT) { + /* most likely file or containing directory cannot be accessed */ + writable = false; } else { - close(file); - return 1; + /* file doesn't exist -- check I can create it in parent directory */ + char parent[FILE_MAX]; + BLI_split_dirfile(filename, parent, NULL, sizeof(parent), 0); +#ifdef WIN32 + /* windows does not have X_OK */ + writable = BLI_access(parent, W_OK) == 0; +#else + writable = BLI_access(parent, X_OK | W_OK) == 0; +#endif } + return writable; } -int BLI_file_touch(const char *file) +/** + * Creates the file with nothing in it, or updates its last-modified date if it already exists. + * Returns true if successful. (like the unix touch command) + */ +bool BLI_file_touch(const char *file) { FILE *f = BLI_fopen(file, "r+b"); if (f != NULL) { @@ -198,9 +206,9 @@ int BLI_file_touch(const char *file) } if (f) { fclose(f); - return 1; + return true; } - return 0; + return false; } #ifdef WIN32 @@ -255,7 +263,12 @@ int BLI_open(const char *filename, int oflag, int pmode) return uopen(filename, oflag, pmode); } -int BLI_delete(const char *file, int dir, int recursive) +int BLI_access(const char *filename, int mode) +{ + return uaccess(filename, mode); +} + +int BLI_delete(const char *file, bool dir, bool recursive) { int err; @@ -279,6 +292,8 @@ int BLI_delete(const char *file, int dir, int recursive) return err; } +/* Not used anywhere! */ +#if 0 int BLI_move(const char *file, const char *to) { int err; @@ -308,7 +323,7 @@ int BLI_move(const char *file, const char *to) return err; } - +#endif int BLI_copy(const char *file, const char *to) { @@ -391,15 +406,16 @@ int BLI_rename(const char *from, const char *to) /* make sure the filenames are different (case insensitive) before removing */ if (BLI_exists(to) && BLI_strcasecmp(from, to)) - if (BLI_delete(to, 0, 0)) return 1; + if (BLI_delete(to, false, false)) return 1; return urename(from, to); } #else /* The UNIX world */ +/* results from recursive_operation and its callbacks */ enum { - /* operation succeeded succeeded */ + /* operation succeeded */ RecursiveOp_Callback_OK = 0, /* operation requested not to perform recursive digging for current path */ @@ -434,120 +450,122 @@ static char *strip_last_slash(const char *dir) return result; } -static int recursive_operation(const char *startfrom, const char *startto, RecursiveOp_Callback callback_dir_pre, + + +/** + * Scans \a startfrom, generating a corresponding destination name for each item found by + * prefixing it with startto, recursively scanning subdirectories, and invoking the specified + * callbacks for files and subdirectories found as appropriate. + * + * \param startfrom Top-level source path. + * \param startto Top-level destination path. + * \param callback_dir_pre Optional, to be invoked before entering a subdirectory, can return + * RecursiveOp_Callback_StopRecurs to skip the subdirectory. + * \param callback_file Optional, to be invoked on each file found. + * \param callback_dir_post optional, to be invoked after leaving a subdirectory. + * \return + */ +static int recursive_operation(const char *startfrom, const char *startto, + RecursiveOp_Callback callback_dir_pre, RecursiveOp_Callback callback_file, RecursiveOp_Callback callback_dir_post) { - struct dirent **dirlist; struct stat st; char *from = NULL, *to = NULL; char *from_path = NULL, *to_path = NULL; + struct dirent **dirlist = NULL; size_t from_alloc_len = -1, to_alloc_len = -1; int i, n, ret = 0; - /* ensure there's no trailing slash in file path */ - from = strip_last_slash(startfrom); - if (startto) - to = strip_last_slash(startto); + do { /* once */ + /* ensure there's no trailing slash in file path */ + from = strip_last_slash(startfrom); + if (startto) + to = strip_last_slash(startto); - ret = lstat(from, &st); - if (ret < 0) { - /* source wasn't found, nothing to operate with */ - return ret; - } - - if (!S_ISDIR(st.st_mode)) { - /* source isn't a directory, can't do recursive walking for it, - * so just call file callback and leave */ - if (callback_file) { - ret = callback_file(from, to); + ret = lstat(from, &st); + if (ret < 0) + /* source wasn't found, nothing to operate with */ + break; - if (ret != RecursiveOp_Callback_OK) - ret = -1; + if (!S_ISDIR(st.st_mode)) { + /* source isn't a directory, can't do recursive walking for it, + * so just call file callback and leave */ + if (callback_file != NULL) { + ret = callback_file(from, to); + if (ret != RecursiveOp_Callback_OK) + ret = -1; + } + break; } - MEM_freeN(from); - if (to) MEM_freeN(to); - - return ret; - } - - - n = scandir(startfrom, &dirlist, 0, alphasort); - if (n < 0) { - /* error opening directory for listing */ - perror("scandir"); - - MEM_freeN(from); - if (to) MEM_freeN(to); - - return -1; - } - - if (callback_dir_pre) { - /* call pre-recursive walking directory callback */ - ret = callback_dir_pre(from, to); - - if (ret != RecursiveOp_Callback_OK) { - MEM_freeN(from); - if (to) free(to); + n = scandir(startfrom, &dirlist, 0, alphasort); + if (n < 0) { + /* error opening directory for listing */ + perror("scandir"); + ret = -1; + break; + } - if (ret == RecursiveOp_Callback_StopRecurs) { - /* callback requested not to perform recursive walking, not an error */ - return 0; + if (callback_dir_pre != NULL) { + ret = callback_dir_pre(from, to); + if (ret != RecursiveOp_Callback_OK) { + if (ret == RecursiveOp_Callback_StopRecurs) + /* callback requested not to perform recursive walking, not an error */ + ret = 0; + else + ret = -1; + break; } - - return -1; } - } - for (i = 0; i < n; i++) { - struct dirent *dirent = dirlist[i]; + for (i = 0; i < n; i++) { + const struct dirent * const dirent = dirlist[i]; - if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) { - free(dirent); - continue; - } + if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) + continue; - join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name); + join_dirfile_alloc(&from_path, &from_alloc_len, from, dirent->d_name); + if (to) + join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name); - if (to) - join_dirfile_alloc(&to_path, &to_alloc_len, to, dirent->d_name); + if (dirent->d_type == DT_DIR) { + /* recursively dig into a subfolder */ + ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post); + } + else if (callback_file != NULL) { + ret = callback_file(from_path, to_path); + if (ret != RecursiveOp_Callback_OK) + ret = -1; + } - if (dirent->d_type == DT_DIR) { - /* recursively dig into a folder */ - ret = recursive_operation(from_path, to_path, callback_dir_pre, callback_file, callback_dir_post); + if (ret != 0) + break; } - else if (callback_file) { - /* call file callback for current path */ - ret = callback_file(from_path, to_path); - if (ret != RecursiveOp_Callback_OK) - ret = -1; - } - - if (ret != 0) { - while (i < n) { - free(dirlist[i++]); - } + if (ret != 0) break; - } - } - - free(dirlist); - if (ret == 0) { - if (callback_dir_post) { - /* call post-recursive directory callback */ + if (callback_dir_post != NULL) { ret = callback_dir_post(from, to); if (ret != RecursiveOp_Callback_OK) ret = -1; } } + while (false); - if (from_path) MEM_freeN(from_path); - if (to_path) MEM_freeN(to_path); - - MEM_freeN(from); - if (to) MEM_freeN(to); + if (dirlist != NULL) { + for (i = 0; i < n; i++) { + free(dirlist[i]); + } + free(dirlist); + } + if (from_path != NULL) + MEM_freeN(from_path); + if (to_path != NULL) + MEM_freeN(to_path); + if (from != NULL) + MEM_freeN(from); + if (to != NULL) + MEM_freeN(to); return ret; } @@ -589,7 +607,17 @@ int BLI_open(const char *filename, int oflag, int pmode) return open(filename, oflag, pmode); } -int BLI_delete(const char *file, int dir, int recursive) +int BLI_access(const char *filename, int mode) +{ + return access(filename, mode); +} + + +/** + * Deletes the specified file or directory (depending on dir), optionally + * doing recursive delete of directory contents. + */ +int BLI_delete(const char *file, bool dir, bool recursive) { if (strchr(file, '"')) { printf("Error: not deleted file %s because of quote!\n", file); @@ -608,20 +636,26 @@ int BLI_delete(const char *file, int dir, int recursive) return -1; } -static int check_the_same(const char *path_a, const char *path_b) +/** + * Do the two paths denote the same filesystem object? + */ +static bool check_the_same(const char *path_a, const char *path_b) { struct stat st_a, st_b; if (lstat(path_a, &st_a)) - return 0; + return false; if (lstat(path_b, &st_b)) - return 0; + return false; return st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino; } -static int set_permissions(const char *file, struct stat *st) +/** + * Sets the mode and ownership of file to the values from st. + */ +static int set_permissions(const char *file, const struct stat *st) { if (chown(file, st->st_uid, st->st_gid)) { perror("chown"); @@ -769,6 +803,8 @@ static int copy_single_file(const char *from, const char *to) return RecursiveOp_Callback_OK; } +/* Not used anywhere! */ +#if 0 static int move_callback_pre(const char *from, const char *to) { int ret = rename(from, to); @@ -789,16 +825,19 @@ static int move_single_file(const char *from, const char *to) return RecursiveOp_Callback_OK; } +/* if *file represents a directory, moves all its contents into *to, else renames + * file itself to *to. */ int BLI_move(const char *file, const char *to) { int ret = recursive_operation(file, to, move_callback_pre, move_single_file, NULL); - if (ret) { + if (ret && ret != -1) { return recursive_operation(file, NULL, NULL, delete_single_file, delete_callback_post); } return ret; } +#endif static char *check_destination(const char *file, const char *to) { @@ -806,7 +845,8 @@ static char *check_destination(const char *file, const char *to) if (!stat(to, &st)) { if (S_ISDIR(st.st_mode)) { - char *str, *filename, *path; + char *str, *path; + const char *filename; size_t len = 0; str = strip_last_slash(file); @@ -875,7 +915,7 @@ void BLI_dir_create_recursive(const char *dirname) BLI_strncpy(tmp, dirname, size); - lslash = BLI_last_slash(tmp); + lslash = (char *)BLI_last_slash(tmp); if (lslash) { /* Split about the last slash and recurse */ *lslash = 0; @@ -893,10 +933,9 @@ int BLI_rename(const char *from, const char *to) if (!BLI_exists(from)) return 0; if (BLI_exists(to)) - if (BLI_delete(to, 0, 0)) return 1; + if (BLI_delete(to, false, false)) return 1; return rename(from, to); } #endif - diff --git a/source/blender/blenlib/intern/freetypefont.c b/source/blender/blenlib/intern/freetypefont.c index 353b73a6403..2b3e2d233d9 100644 --- a/source/blender/blenlib/intern/freetypefont.c +++ b/source/blender/blenlib/intern/freetypefont.c @@ -449,7 +449,9 @@ static int check_freetypefont(PackedFile *pf) glyph_index = FT_Get_Char_Index(face, 'A'); err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP); - if (err) success = 0; + if (err) { + success = 0; + } else { glyph = face->glyph; if (glyph->format == ft_glyph_format_outline) { diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index d569534f2f3..272f840296e 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -32,6 +32,8 @@ #include <string.h> #include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" #include "BLI_gsqueue.h" typedef struct _GSQueueElem GSQueueElem; @@ -54,7 +56,7 @@ GSQueue *BLI_gsqueue_new(int elem_size) return gq; } -int BLI_gsqueue_is_empty(GSQueue *gq) +bool BLI_gsqueue_is_empty(GSQueue *gq) { return (gq->head == NULL); } diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c index 5cd8bb813a1..aa08a780394 100644 --- a/source/blender/blenlib/intern/lasso.c +++ b/source/blender/blenlib/intern/lasso.c @@ -53,77 +53,44 @@ void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves) } -int BLI_lasso_is_point_inside(const int mcords[][2], const short moves, - const int sx, const int sy, - const int error_value) +bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves, + const int sx, const int sy, + const int error_value) { - /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */ - float angletot = 0.0, dot, ang, cross, fp1[2], fp2[2]; - int a; - const int *p1, *p2; - if (sx == error_value) { - return 0; + return false; } - - p1 = mcords[moves - 1]; - p2 = mcords[0]; - - /* first vector */ - fp1[0] = (float)(p1[0] - sx); - fp1[1] = (float)(p1[1] - sy); - normalize_v2(fp1); - - for (a = 0; a < moves; a++) { - /* second vector */ - fp2[0] = (float)(p2[0] - sx); - fp2[1] = (float)(p2[1] - sy); - normalize_v2(fp2); - - /* dot and angle and cross */ - dot = fp1[0] * fp2[0] + fp1[1] * fp2[1]; - ang = fabs(saacos(dot)); - - cross = (float)((p1[1] - p2[1]) * (p1[0] - sx) + (p2[0] - p1[0]) * (p1[1] - sy)); - - if (cross < 0.0f) angletot -= ang; - else angletot += ang; - - /* circulate */ - fp1[0] = fp2[0]; fp1[1] = fp2[1]; - p1 = p2; - p2 = mcords[a + 1]; + else { + int pt[2] = {sx, sy}; + return isect_point_poly_v2_int(pt, mcords, moves); } - - if (fabsf(angletot) > 4.0f) return 1; - return 0; } /* edge version for lasso select. we assume boundbox check was done */ -int BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, - int x0, int y0, int x1, int y1, - const int error_value) +bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, + int x0, int y0, int x1, int y1, + const int error_value) { int v1[2], v2[2]; int a; if (x0 == error_value || x1 == error_value) { - return 0; + return false; } v1[0] = x0, v1[1] = y0; v2[0] = x1, v2[1] = y1; /* check points in lasso */ - if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) return 1; - if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) return 1; + if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) return true; + if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) return true; /* no points in lasso, so we have to intersect with lasso edge */ - if (isect_line_line_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) return 1; + if (isect_line_line_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) return true; for (a = 0; a < moves - 1; a++) { - if (isect_line_line_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) return 1; + if (isect_line_line_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) return true; } - return 0; + return false; } diff --git a/source/blender/blenlib/intern/math_base.c b/source/blender/blenlib/intern/math_base.c index 6bb238ac612..38d303e667a 100644 --- a/source/blender/blenlib/intern/math_base.c +++ b/source/blender/blenlib/intern/math_base.c @@ -57,7 +57,14 @@ double round(double x) return copysign(y, x); } #else /* OpenSuse 11.1 seems to need this. */ +# ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wredundant-decls" +# endif double round(double x); +# ifdef __GNUC__ +# pragma GCC diagnostic pop +# endif #endif /* from python 3.1 floatobject.c diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 8f7ecdcfde8..173c6d06861 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -106,12 +106,12 @@ float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], cons sub_v3_v3v3(vec1, v2, v1); sub_v3_v3v3(vec2, v4, v1); cross_v3_v3v3(n, vec1, vec2); - len = normalize_v3(n); + len = len_v3(n); sub_v3_v3v3(vec1, v4, v3); sub_v3_v3v3(vec2, v2, v3); cross_v3_v3v3(n, vec1, vec2); - len += normalize_v3(n); + len += len_v3(n); return (len / 2.0f); } @@ -119,14 +119,13 @@ float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], cons /* Triangles */ float area_tri_v3(const float v1[3], const float v2[3], const float v3[3]) { - float len, vec1[3], vec2[3], n[3]; + float vec1[3], vec2[3], n[3]; sub_v3_v3v3(vec1, v3, v2); sub_v3_v3v3(vec2, v1, v2); cross_v3_v3v3(n, vec1, vec2); - len = normalize_v3(n); - return (len / 2.0f); + return len_v3(n) / 2.0f; } float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]) @@ -729,6 +728,86 @@ static short IsectLLPt2Df(const float x0, const float y0, const float x1, const return 1; } +/* point in polygon (keep float and int versions in sync) */ +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr) +{ + /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */ + float angletot = 0.0; + float fp1[2], fp2[2]; + int i; + const float *p1, *p2; + + p1 = verts[nr - 1]; + p2 = verts[0]; + + /* first vector */ + fp1[0] = (float)(p1[0] - pt[0]); + fp1[1] = (float)(p1[1] - pt[1]); + normalize_v2(fp1); + + for (i = 0; i < nr; i++) { + float dot, ang, cross; + /* second vector */ + fp2[0] = (float)(p2[0] - pt[0]); + fp2[1] = (float)(p2[1] - pt[1]); + normalize_v2(fp2); + + /* dot and angle and cross */ + dot = dot_v2v2(fp1, fp2); + ang = fabsf(saacos(dot)); + cross = (float)((p1[1] - p2[1]) * (p1[0] - pt[0]) + (p2[0] - p1[0]) * (p1[1] - pt[1])); + + if (cross < 0.0f) angletot -= ang; + else angletot += ang; + + /* circulate */ + copy_v2_v2(fp1, fp2); + p1 = p2; + p2 = verts[i + 1]; + } + + return (fabsf(angletot) > 4.0f); +} +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr) +{ + /* we do the angle rule, define that all added angles should be about zero or (2 * PI) */ + float angletot = 0.0; + float fp1[2], fp2[2]; + int i; + const int *p1, *p2; + + p1 = verts[nr - 1]; + p2 = verts[0]; + + /* first vector */ + fp1[0] = (float)(p1[0] - pt[0]); + fp1[1] = (float)(p1[1] - pt[1]); + normalize_v2(fp1); + + for (i = 0; i < nr; i++) { + float dot, ang, cross; + /* second vector */ + fp2[0] = (float)(p2[0] - pt[0]); + fp2[1] = (float)(p2[1] - pt[1]); + normalize_v2(fp2); + + /* dot and angle and cross */ + dot = dot_v2v2(fp1, fp2); + ang = fabsf(saacos(dot)); + cross = (float)((p1[1] - p2[1]) * (p1[0] - pt[0]) + (p2[0] - p1[0]) * (p1[1] - pt[1])); + + if (cross < 0.0f) angletot -= ang; + else angletot += ang; + + /* circulate */ + copy_v2_v2(fp1, fp2); + p1 = p2; + p2 = verts[i + 1]; + } + + return (fabsf(angletot) > 4.0f); +} + /* point in tri */ /* only single direction */ @@ -2219,6 +2298,13 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo len_v2(dirs[3]), }; + /* variable 'area' is just for storage, + * the order its initialized doesn't matter */ +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wunsequenced" +#endif + /* inline mean_value_half_tan four times here */ float t[4] = { MEAN_VALUE_HALF_TAN_V2(area, 0, 1), @@ -2227,6 +2313,10 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo MEAN_VALUE_HALF_TAN_V2(area, 3, 0), }; +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + #undef MEAN_VALUE_HALF_TAN_V2 w[0] = (t[3] + t[0]) / lens[0]; @@ -2564,7 +2654,9 @@ void resolve_tri_uv(float r_uv[2], const float st[2], const float st0[2], const r_uv[0] = (float)((d * x[0] - b * x[1]) / det); r_uv[1] = (float)(((-c) * x[0] + a * x[1]) / det); } - else zero_v2(r_uv); + else { + zero_v2(r_uv); + } } /* bilinear reverse */ @@ -3063,7 +3155,9 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl add_v3_v3(accu_com, v); accu_weight += weight[a]; } - else add_v3_v3(accu_com, pos[a]); + else { + add_v3_v3(accu_com, pos[a]); + } if (rweight) { float v[3]; @@ -3072,8 +3166,9 @@ void vcloud_estimate_transform(int list_size, float (*pos)[3], float *weight, fl add_v3_v3(accu_rcom, v); accu_rweight += rweight[a]; } - else add_v3_v3(accu_rcom, rpos[a]); - + else { + add_v3_v3(accu_rcom, rpos[a]); + } } if (!weight || !rweight) { accu_weight = accu_rweight = list_size; diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 9d9e3e611e1..f116c9b8443 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -333,15 +333,15 @@ void mul_m4_v3(float mat[4][4], float vec[3]) vec[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; } -void mul_v3_m4v3(float in[3], float mat[4][4], const float vec[3]) +void mul_v3_m4v3(float r[3], float mat[4][4], const float vec[3]) { float x, y; x = vec[0]; y = vec[1]; - in[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; - in[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; - in[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; + r[0] = x * mat[0][0] + y * mat[1][0] + mat[2][0] * vec[2] + mat[3][0]; + r[1] = x * mat[0][1] + y * mat[1][1] + mat[2][1] * vec[2] + mat[3][1]; + r[2] = x * mat[0][2] + y * mat[1][2] + mat[2][2] * vec[2] + mat[3][2]; } void mul_v2_m2v2(float r[2], float mat[2][2], const float vec[2]) @@ -367,7 +367,7 @@ void mul_mat3_m4_v3(float mat[4][4], float vec[3]) void mul_project_m4_v3(float mat[4][4], float vec[3]) { - const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; + const float w = mul_project_m4_v3_zfac(mat, vec); mul_m4_v3(mat, vec); vec[0] /= w; diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 48e7de43a86..c8e8ff9602b 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -398,6 +398,15 @@ MINLINE void mul_v4_v4fl(float r[4], const float a[4], float f) r[3] = a[3] * f; } +/* note: could add a matrix inline */ +MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) +{ + return (mat[0][3] * co[0]) + + (mat[1][3] * co[1]) + + (mat[2][3] * co[2]) + mat[3][3]; +} + + MINLINE void madd_v2_v2fl(float r[2], const float a[2], float f) { r[0] += a[0] * f; diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index c159f707b98..6e52145c653 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -281,9 +281,9 @@ static float npfade(float t) return (t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f)); } -static float grad(int hash, float x, float y, float z) +static float grad(int hash_val, float x, float y, float z) { - int h = hash & 15; /* CONVERT LO 4 BITS OF HASH CODE */ + int h = hash_val & 15; /* CONVERT LO 4 BITS OF HASH CODE */ float u = h < 8 ? x : y, /* INTO 12 GRADIENT DIRECTIONS. */ v = h < 4 ? y : h == 12 || h == 14 ? x : z; return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 5265d862ab8..c3bc35a906b 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -41,11 +41,11 @@ #include "DNA_listBase.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_string_utf8.h" -#include "BLI_utildefines.h" #include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */ @@ -79,43 +79,50 @@ /* local */ #define UNIQUE_NAME_MAX 128 -static char bprogname[FILE_MAX]; /* path to program executable */ -static char bprogdir[FILE_MAX]; /* path in which executable is located */ +static char bprogname[FILE_MAX]; /* full path to program executable */ +static char bprogdir[FILE_MAX]; /* full path to directory in which executable is located */ static char btempdir[FILE_MAX]; /* temporary directory */ -static int add_win32_extension(char *name); -static char *blender_version_decimal(const int ver); - /* implementation */ +/** + * Looks for a sequence of decimal digits in string, preceding any filename extension, + * returning the integer value if found, or 0 if not. + * + * \param string String to scan. + * \param head Optional area to return copy of part of string prior to digits, or before dot if no digits. + * \param tail Optional area to return copy of part of string following digits, or from dot if no digits. + * \param numlen Optional to return number of digits found. + */ int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen) { - unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0; - short i, found = 0; - char *lslash = BLI_last_slash(string); - len2 = len = strlen(string); - if (lslash) - lenlslash = (int)(lslash - string); + unsigned short nums = 0, nume = 0; + short i; + bool found_digit = false; + const char * const lslash = BLI_last_slash(string); + const unsigned short string_len = strlen(string); + const unsigned short lslash_len = lslash != NULL ? (int)(lslash - string) : 0; + unsigned short name_end = string_len; - while (len > lenlslash && string[--len] != '.') {} - if (len == lenlslash && string[len] != '.') len = len2; + while (name_end > lslash_len && string[--name_end] != '.') {} /* name ends at dot if present */ + if (name_end == lslash_len && string[name_end] != '.') name_end = string_len; - for (i = len - 1; i >= lenlslash; i--) { + for (i = name_end - 1; i >= lslash_len; i--) { if (isdigit(string[i])) { - if (found) { + if (found_digit) { nums = i; } else { nume = i; nums = i; - found = 1; + found_digit = true; } } else { - if (found) break; + if (found_digit) break; } } - if (found) { + if (found_digit) { if (tail) strcpy(tail, &string[nume + 1]); if (head) { strcpy(head, string); @@ -124,56 +131,71 @@ int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *nu if (numlen) *numlen = nume - nums + 1; return ((int)atoi(&(string[nums]))); } - if (tail) strcpy(tail, string + len); + if (tail) strcpy(tail, string + name_end); if (head) { - strncpy(head, string, len); - head[len] = '\0'; + strncpy(head, string, name_end); + head[name_end] = '\0'; } if (numlen) *numlen = 0; return 0; } +/** + * Returns in area pointed to by string a string of the form "<head><pic><tail>", where pic + * is formatted as numlen digits with leading zeroes. + */ void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) { - char fmtstr[16] = ""; - if (pic < 0) pic = 0; - sprintf(fmtstr, "%%s%%.%dd%%s", numlen); - sprintf(string, fmtstr, head, pic, tail); + sprintf(string, "%s%.*d%s", head, numlen, MAX2(0, pic), tail); } -/* Foo.001 -> "Foo", 1 - * Returns the length of "Foo" */ +/** + * Looks for a numeric suffix preceded by delim character on the end of + * name, puts preceding part into *left and value of suffix into *nr. + * Returns the length of *left. + * + * Foo.001 -> "Foo", 1 + * Returning the length of "Foo" + * + * \param left Where to return copy of part preceding delim + * \param nr Where to return value of numeric suffix + * \param name String to split + * \param delim Delimiter character + * \return Length of \a left + */ int BLI_split_name_num(char *left, int *nr, const char *name, const char delim) { - int a; + const int name_len = strlen(name); *nr = 0; - a = strlen(name); - memcpy(left, name, (a + 1) * sizeof(char)); - - if (a > 1 && name[a - 1] == delim) return a; - - while (a--) { - if (name[a] == delim) { - left[a] = 0; - *nr = atol(name + a + 1); - /* casting down to an int, can overflow for large numbers */ - if (*nr < 0) - *nr = 0; - return a; - } - if (isdigit(name[a]) == 0) break; - - left[a] = 0; + memcpy(left, name, (name_len + 1) * sizeof(char)); + + /* name doesn't end with a delimiter "foo." */ + if ((name_len > 1 && name[name_len - 1] == delim) == 0) { + int a = name_len; + while (a--) { + if (name[a] == delim) { + left[a] = '\0'; /* truncate left part here */ + *nr = atol(name + a + 1); + /* casting down to an int, can overflow for large numbers */ + if (*nr < 0) + *nr = 0; + return a; + } + else if (isdigit(name[a]) == 0) { + /* non-numeric suffix - give up */ + break; + } + } } - for (a = 0; name[a]; a++) - left[a] = name[a]; - - return a; + return name_len; } +/** + * Looks for a string of digits within name (using BLI_stringdec) and adjusts it by add. + */ void BLI_newname(char *name, int add) { char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX]; @@ -196,9 +218,20 @@ void BLI_newname(char *name, int add) BLI_stringenc(name, head, tail, digits, pic); } - - -int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len) +/** + * Ensures name is unique (according to criteria specified by caller in unique_check callback), + * incrementing its numeric suffix as necessary. Returns true if name had to be adjusted. + * + * \param unique_check Return true if name is not unique + * \param arg Additional arg to unique_check--meaning is up to caller + * \param defname To initialize name if latter is empty + * \param delim Delimits numeric suffix in name + * \param name Name to be ensured unique + * \param name_len Maximum length of name area + * \return true if there if the name was changed + */ +bool BLI_uniquename_cb(bool (*unique_check)(void * arg, const char *name), + void *arg, const char *defname, char delim, char *name, short name_len) { if (name[0] == '\0') { BLI_strncpy(name, defname, name_len); @@ -211,7 +244,7 @@ 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 numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number); + const int numlen = BLI_snprintf(numstr, sizeof(numstr), "%c%03d", delim, ++number); /* highly unlikely the string only has enough room for the number * but support anyway */ @@ -229,10 +262,10 @@ int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, cons BLI_strncpy(name, tempname, name_len); - return 1; + return true; } - return 0; + return false; } /* little helper macro for BLI_uniquename */ @@ -250,28 +283,39 @@ int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, cons * defname: the name that should be used by default if none is specified already * delim: the character which acts as a delimiter between parts of the name */ -static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs) +static bool uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs) { Link *link; for (link = list->first; link; link = link->next) { if (link != vlink) { if (!strcmp(GIVE_STRADDR(link, name_offs), name)) { - return 1; + return true; } } } - return 0; + return false; } -static int uniquename_unique_check(void *arg, const char *name) +static bool uniquename_unique_check(void *arg, const char *name) { struct {ListBase *lb; void *vlink; short name_offs; } *data = arg; return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs); } -void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len) +/** + * Ensures that the specified block has a unique name within the containing list, + * incrementing its numeric suffix as necessary. + * + * \param list List containing the block + * \param vlink The block to check the name for + * \param defname To initialize block name if latter is empty + * \param delim Delimits numeric suffix in name + * \param name_offs Offset of name within block structure + * \param name_len Maximum length of name area + */ +void BLI_uniquename(ListBase *list, void *vlink, const char *defname, char delim, short name_offs, short name_len) { struct {ListBase *lb; void *vlink; short name_offs; } data; data.lb = list; @@ -299,19 +343,19 @@ void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char deli * If relbase is NULL then its ignored */ -void BLI_cleanup_path(const char *relabase, char *dir) +void BLI_cleanup_path(const char *relabase, char *path) { ptrdiff_t a; char *start, *eind; if (relabase) { - BLI_path_abs(dir, relabase); + BLI_path_abs(path, relabase); } else { - if (dir[0] == '/' && dir[1] == '/') { - if (dir[2] == '\0') { + if (path[0] == '/' && path[1] == '/') { + if (path[2] == '\0') { return; /* path is "//" - cant clean it */ } - dir = dir + 2; /* skip the first // */ + path = path + 2; /* leave the initial "//" untouched */ } } @@ -327,70 +371,72 @@ void BLI_cleanup_path(const char *relabase, char *dir) /* Note, this should really be moved to the file selector, * since this function is used in many areas */ - if (strcmp(dir, ".") == 0) { /* happens for example in FILE_MAIN */ - get_default_root(dir); + if (strcmp(path, ".") == 0) { /* happens for example in FILE_MAIN */ + get_default_root(path); return; } - while ( (start = strstr(dir, "\\..\\")) ) { + while ( (start = strstr(path, "\\..\\")) ) { eind = start + strlen("\\..\\") - 1; - a = start - dir - 1; + a = start - path - 1; while (a > 0) { - if (dir[a] == '\\') break; + if (path[a] == '\\') break; a--; } if (a < 0) { break; } else { - memmove(dir + a, eind, strlen(eind) + 1); + memmove(path + a, eind, strlen(eind) + 1); } } - while ( (start = strstr(dir, "\\.\\")) ) { + while ( (start = strstr(path, "\\.\\")) ) { eind = start + strlen("\\.\\") - 1; memmove(start, eind, strlen(eind) + 1); } - while ( (start = strstr(dir, "\\\\")) ) { + while ( (start = strstr(path, "\\\\")) ) { eind = start + strlen("\\\\") - 1; memmove(start, eind, strlen(eind) + 1); } #else - if (dir[0] == '.') { /* happens, for example in FILE_MAIN */ - dir[0] = '/'; - dir[1] = 0; + if (path[0] == '.') { /* happens, for example in FILE_MAIN */ + path[0] = '/'; + path[1] = 0; return; } - /* support for odd paths: eg /../home/me --> /home/me - * this is a valid path in blender but we cant handle this the usual way below - * simply strip this prefix then evaluate the path as usual. pythons os.path.normpath() does this */ - while ((strncmp(dir, "/../", 4) == 0)) { - memmove(dir, dir + 4, strlen(dir + 4) + 1); - } - - while ( (start = strstr(dir, "/../")) ) { - eind = start + (4 - 1) /* strlen("/../") - 1 */; - a = start - dir - 1; - while (a > 0) { - if (dir[a] == '/') break; - a--; - } - if (a < 0) { - break; + while ( (start = strstr(path, "/../")) ) { + a = start - path - 1; + if (a > 0) { + /* <prefix>/<parent>/../<postfix> => <prefix>/<postfix> */ + eind = start + (4 - 1) /* strlen("/../") - 1 */; /* strip "/.." and keep last "/" */ + while (a > 0 && path[a] != '/') { /* find start of <parent> */ + a--; + } + memmove(path + a, eind, strlen(eind) + 1); } else { - memmove(dir + a, eind, strlen(eind) + 1); + /* support for odd paths: eg /../home/me --> /home/me + * this is a valid path in blender but we cant handle this the usual way below + * simply strip this prefix then evaluate the path as usual. + * pythons os.path.normpath() does this */ + + /* Note: previous version of following call used an offset of 3 instead of 4, + * which meant that the "/../home/me" example actually became "home/me". + * Using offset of 3 gives behaviour consistent with the abovementioned + * Python routine. */ + memmove(path, path + 3, strlen(path + 3) + 1); } } - while ( (start = strstr(dir, "/./")) ) { + while ( (start = strstr(path, "/./")) ) { eind = start + (3 - 1) /* strlen("/./") - 1 */; memmove(start, eind, strlen(eind) + 1); } - while ( (start = strstr(dir, "//")) ) { + while ( (start = strstr(path, "//")) ) { eind = start + (2 - 1) /* strlen("//") - 1 */; memmove(start, eind, strlen(eind) + 1); } @@ -404,20 +450,28 @@ void BLI_cleanup_dir(const char *relabase, char *dir) } -void BLI_cleanup_file(const char *relabase, char *dir) +void BLI_cleanup_file(const char *relabase, char *path) { - BLI_cleanup_path(relabase, dir); - BLI_del_slash(dir); + BLI_cleanup_path(relabase, path); + BLI_del_slash(path); } -int BLI_path_is_rel(const char *path) +/** + * Does path begin with the special "//" prefix that Blender uses to indicate + * a path relative to the .blend file. + */ +bool BLI_path_is_rel(const char *path) { return path[0] == '/' && path[1] == '/'; } +/** + * Replaces *file with a relative version (prefixed by "//") such that BLI_path_abs, given + * the same *relfile, will convert it back to its original value. + */ void BLI_path_rel(char *file, const char *relfile) { - char *lslash; + const char *lslash; char temp[FILE_MAX]; char res[FILE_MAX]; @@ -519,7 +573,11 @@ void BLI_path_rel(char *file, const char *relfile) } } -int BLI_has_parent(char *path) +/** + * Cleans path and makes sure it ends with a slash. + * \return true if \a path has more than one other path separator in it. + */ +bool BLI_has_parent(char *path) { int len; int slashes = 0; @@ -534,25 +592,34 @@ int BLI_has_parent(char *path) return slashes > 1; } -int BLI_parent_dir(char *path) +/** + * Replaces path with the path of its parent directory, returning true if + * it was able to find a parent directory within the pathname. + */ +bool BLI_parent_dir(char *path) { static char parent_dir[] = {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ char tmp[FILE_MAX + 4]; BLI_strncpy(tmp, path, sizeof(tmp) - 4); BLI_add_slash(tmp); strcat(tmp, parent_dir); - BLI_cleanup_dir(NULL, tmp); + BLI_cleanup_dir(NULL, tmp); /* does all the work of normalizing the path for us */ if (!BLI_testextensie(tmp, parent_dir)) { BLI_strncpy(path, tmp, sizeof(tmp)); - return 1; + return true; } else { - return 0; + return false; } } -static int stringframe_chars(char *path, int *char_start, int *char_end) +/** + * Looks for a sequence of "#" characters in the last slash-separated component of *path, + * returning the indexes of the first and one past the last character in the sequence in + * *char_start and *char_end respectively. Returns true if such a sequence was found. + */ +static bool stringframe_chars(const char *path, int *char_start, int *char_end) { int ch_sta, ch_end, i; /* Insert current frame: file### -> file001 */ @@ -576,18 +643,22 @@ static int stringframe_chars(char *path, int *char_start, int *char_end) if (ch_end) { *char_start = ch_sta; *char_end = ch_end; - return 1; + return true; } else { *char_start = -1; *char_end = -1; - return 0; + return false; } } +/** + * Ensure *path contains at least one "#" character in its last slash-separated + * component, appending one digits long if not. + */ static void ensure_digits(char *path, int digits) { - char *file = BLI_last_slash(path); + char *file = (char *)BLI_last_slash(path); if (file == NULL) file = path; @@ -602,7 +673,11 @@ static void ensure_digits(char *path, int digits) } } -int BLI_path_frame(char *path, int frame, int digits) +/** + * Replaces "#" character sequence in last slash-separated component of *path + * with frame as decimal integer, with leading zeroes as necessary, to make digits digits. + */ +bool BLI_path_frame(char *path, int frame, int digits) { int ch_sta, ch_end; @@ -613,12 +688,17 @@ int BLI_path_frame(char *path, int frame, int digits) char tmp[FILE_MAX]; sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end - ch_sta, frame, path + ch_end); strcpy(path, tmp); - return 1; + return true; } - return 0; + return false; } -int BLI_path_frame_range(char *path, int sta, int end, int digits) +/** + * Replaces "#" character sequence in last slash-separated component of *path + * with sta and end as decimal integers, with leading zeroes as necessary, to make digits + * digits each, with a hyphen in-between. + */ +bool BLI_path_frame_range(char *path, int sta, int end, int digits) { int ch_sta, ch_end; @@ -631,14 +711,19 @@ int BLI_path_frame_range(char *path, int sta, int end, int digits) "%.*s%.*d-%.*d%s", ch_sta, path, ch_end - ch_sta, sta, ch_end - ch_sta, end, path + ch_end); BLI_strncpy(path, tmp, FILE_MAX); - return 1; + return true; } - return 0; + return false; } -int BLI_path_abs(char *path, const char *basepath) +/** + * If path begins with "//", strips that and replaces it with basepath directory. Also converts + * a drive-letter prefix to something more sensible if this is a non-drive-letter-based system. + * Returns true if "//" prefix expansion was done. + */ +bool BLI_path_abs(char *path, const char *basepath) { - int wasrelative = BLI_path_is_rel(path); + const bool wasrelative = BLI_path_is_rel(path); char tmp[FILE_MAX]; char base[FILE_MAX]; #ifdef WIN32 @@ -696,21 +781,23 @@ int BLI_path_abs(char *path, const char *basepath) /* Paths starting with // will get the blend file as their base, * this isn't standard in any os but is used in blender all over the place */ if (wasrelative) { - char *lslash = BLI_last_slash(base); + const char * const lslash = BLI_last_slash(base); if (lslash) { - int baselen = (int) (lslash - base) + 1; + const int baselen = (int) (lslash - base) + 1; /* length up to and including last "/" */ /* use path for temp storage here, we copy back over it right away */ - BLI_strncpy(path, tmp + 2, FILE_MAX); + BLI_strncpy(path, tmp + 2, FILE_MAX); /* strip "//" */ - memcpy(tmp, base, baselen); - BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); - BLI_strncpy(path, tmp, FILE_MAX); + memcpy(tmp, base, baselen); /* prefix with base up to last "/" */ + BLI_strncpy(tmp + baselen, path, sizeof(tmp) - baselen); /* append path after "//" */ + BLI_strncpy(path, tmp, FILE_MAX); /* return as result */ } else { + /* base doesn't seem to be a directory--ignore it and just strip "//" prefix on path */ BLI_strncpy(path, tmp + 2, FILE_MAX); } } else { + /* base ignored */ BLI_strncpy(path, tmp, FILE_MAX); } @@ -730,24 +817,27 @@ int BLI_path_abs(char *path, const char *basepath) } -/* - * Should only be done with command line paths. - * this is NOT something blenders internal paths support like the // prefix +/** + * Expands path relative to the current working directory, if it was relative. + * Returns true if such expansion was done. + * + * \note Should only be done with command line paths. + * this is _not_ something blenders internal paths support like the "//" prefix */ -int BLI_path_cwd(char *path) +bool BLI_path_cwd(char *path) { - int wasrelative = 1; - int filelen = strlen(path); + bool wasrelative = true; + const int filelen = strlen(path); #ifdef WIN32 if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) - wasrelative = 0; + wasrelative = false; #else if (filelen >= 2 && path[0] == '/') - wasrelative = 0; + wasrelative = false; #endif - if (wasrelative == 1) { + if (wasrelative) { char cwd[FILE_MAX] = ""; BLI_current_working_dir(cwd, sizeof(cwd)); /* in case the full path to the blend isn't used */ @@ -772,22 +862,9 @@ int BLI_path_cwd(char *path) return wasrelative; } - -/* 'di's filename component is moved into 'fi', di is made a dir path */ -void BLI_splitdirstring(char *di, char *fi) -{ - char *lslash = BLI_last_slash(di); - - if (lslash) { - BLI_strncpy(fi, lslash + 1, FILE_MAXFILE); - *(lslash + 1) = 0; - } - else { - BLI_strncpy(fi, di, FILE_MAXFILE); - di[0] = 0; - } -} - +/** + * Copies into *last the part of *dir following the second-last slash. + */ void BLI_getlastdir(const char *dir, char *last, const size_t maxlen) { const char *s = dir; @@ -814,7 +891,7 @@ void BLI_getlastdir(const char *dir, char *last, const size_t maxlen) const char *BLI_getDefaultDocumentFolder(void) { #ifndef WIN32 - const char *xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR"); + const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR"); if (xdg_documents_dir) return xdg_documents_dir; @@ -850,6 +927,7 @@ const char *BLI_getDefaultDocumentFolder(void) // #define PATH_DEBUG +/* returns a formatted representation of the specified version number. Non-reentrant! */ static char *blender_version_decimal(const int ver) { static char version_str[5]; @@ -857,7 +935,11 @@ static char *blender_version_decimal(const int ver) return version_str; } -static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) +/** + * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, + * returning true if result points to a directory. + */ +static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) { char tmppath[FILE_MAX]; @@ -869,44 +951,60 @@ static int test_path(char *targetpath, const char *path_base, const char *path_s BLI_make_file_string("/", targetpath, tmppath, folder_name); else BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); + /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) + * if folder_name is specified but not otherwise? */ if (BLI_is_dir(targetpath)) { #ifdef PATH_DEBUG printf("\t%s found: %s\n", __func__, targetpath); #endif - return 1; + return true; } else { #ifdef PATH_DEBUG printf("\t%s missing: %s\n", __func__, targetpath); #endif //targetpath[0] = '\0'; - return 0; + return false; } } -static int test_env_path(char *path, const char *envvar) +/** + * Puts the value of the specified environment variable into *path if it exists + * and points at a directory. Returns true if this was done. + */ +static bool test_env_path(char *path, const char *envvar) { const char *env = envvar ? getenv(envvar) : NULL; - if (!env) return 0; + if (!env) return false; if (BLI_is_dir(env)) { BLI_strncpy(path, env, FILE_MAX); #ifdef PATH_DEBUG printf("\t%s env %s found: %s\n", __func__, envvar, env); #endif - return 1; + return true; } else { path[0] = '\0'; #ifdef PATH_DEBUG printf("\t%s env %s missing: %s\n", __func__, envvar, env); #endif - return 0; + return false; } } -static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver) +/** + * Constructs in \a targetpath the name of a directory relative to a version-specific + * subdirectory in the parent directory of the Blender executable. + * + * \param targetpath String to return path + * \param folder_name Optional folder name within version-specific directory + * \param subfolder_name Optional subfolder name within folder_name + * \param ver To construct name of version-specific directory within bprogdir + * \return true if such a directory exists. + */ +static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver) { char relfolder[FILE_MAX]; @@ -927,22 +1025,34 @@ static int get_path_local(char *targetpath, const char *folder_name, const char } /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */ - if (test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder)) - return 1; - - return 0; + return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder); } -static int is_portable_install(void) +/** + * Is this an install with user files kept together with the Blender executable and its + * installation files. + */ +static bool is_portable_install(void) { - /* detect portable install by the existance of config folder */ + /* detect portable install by the existence of config folder */ const int ver = BLENDER_VERSION; char path[FILE_MAX]; return get_path_local(path, "config", NULL, ver); } -static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +/** + * Returns the path of a folder within the user-files area. + * + * + * \param targetpath String to return path + * \param folder_name default name of folder within user area + * \param subfolder_name optional name of subfolder within folder + * \param envvar name of environment variable which, if defined, overrides folder_name + * \param ver Blender version, used to construct a subdirectory name + * \return true if it was able to construct such a path. + */ +static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) { char user_path[FILE_MAX]; const char *user_base_path; @@ -959,7 +1069,7 @@ static int get_path_user(char *targetpath, const char *folder_name, const char * } else { BLI_strncpy(targetpath, user_path, FILE_MAX); - return 1; + return true; } } @@ -968,30 +1078,34 @@ static int get_path_user(char *targetpath, const char *folder_name, const char * BLI_strncpy(user_path, user_base_path, FILE_MAX); if (!user_path[0]) - return 0; + return false; #ifdef PATH_DEBUG printf("%s: %s\n", __func__, user_path); #endif if (subfolder_name) { - /* try $HOME/folder_name/subfolder_name */ return test_path(targetpath, user_path, folder_name, subfolder_name); } else { - /* try $HOME/folder_name */ return test_path(targetpath, user_path, NULL, folder_name); } } -static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +/** + * Returns the path of a folder within the Blender installation directory. + * + * \param targetpath String to return path + * \param folder_name default name of folder within installation area + * \param subfolder_name optional name of subfolder within folder + * \param envvar name of environment variable which, if defined, overrides folder_name + * \param ver Blender version, used to construct a subdirectory name + * \return true if it was able to construct such a path. + */ +static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) { char system_path[FILE_MAX]; const char *system_base_path; - - - /* first allow developer only overrides to the system path - * these are only used when running blender from source */ char cwd[FILE_MAX]; char relfolder[FILE_MAX]; @@ -1007,16 +1121,20 @@ static int get_path_system(char *targetpath, const char *folder_name, const char relfolder[0] = '\0'; } + /* first allow developer only overrides to the system path + * these are only used when running blender from source */ + /* try CWD/release/folder_name */ if (BLI_current_working_dir(cwd, sizeof(cwd))) { if (test_path(targetpath, cwd, "release", relfolder)) { - return 1; + return true; } } /* try EXECUTABLE_DIR/release/folder_name */ if (test_path(targetpath, bprogdir, "release", relfolder)) - return 1; + return true; + /* end developer overrides */ @@ -1029,7 +1147,7 @@ static int get_path_system(char *targetpath, const char *folder_name, const char } else { BLI_strncpy(targetpath, system_path, FILE_MAX); - return 1; + return true; } } @@ -1038,7 +1156,7 @@ static int get_path_system(char *targetpath, const char *folder_name, const char BLI_strncpy(system_path, system_base_path, FILE_MAX); if (!system_path[0]) - return 0; + return false; #ifdef PATH_DEBUG printf("%s: %s\n", __func__, system_path); @@ -1056,7 +1174,7 @@ static int get_path_system(char *targetpath, const char *folder_name, const char /* get a folder out of the 'folder_id' presets for paths */ /* returns the path if found, NULL string if not */ -char *BLI_get_folder(int folder_id, const char *subfolder) +const char *BLI_get_folder(int folder_id, const char *subfolder) { const int ver = BLENDER_VERSION; static char path[FILE_MAX] = ""; @@ -1103,7 +1221,10 @@ char *BLI_get_folder(int folder_id, const char *subfolder) return path; } -char *BLI_get_user_folder_notest(int folder_id, const char *subfolder) +/** + * Returns the path to a folder in the user area without checking that it actually exists first. + */ +const char *BLI_get_user_folder_notest(int folder_id, const char *subfolder) { const int ver = BLENDER_VERSION; static char path[FILE_MAX] = ""; @@ -1128,9 +1249,12 @@ char *BLI_get_user_folder_notest(int folder_id, const char *subfolder) return path; } -char *BLI_get_folder_create(int folder_id, const char *subfolder) +/** + * Returns the path to a folder in the user area, creating it if it doesn't exist. + */ +const char *BLI_get_folder_create(int folder_id, const char *subfolder) { - char *path; + const char *path; /* only for user folders */ if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE)) @@ -1146,10 +1270,14 @@ char *BLI_get_folder_create(int folder_id, const char *subfolder) return path; } -char *BLI_get_folder_version(const int id, const int ver, const int do_check) +/** + * Returns the path of the top-level version-specific local, user or system directory. + * If do_check, then the result will be NULL if the directory doesn't exist. + */ +const char *BLI_get_folder_version(const int id, const int ver, const bool do_check) { static char path[FILE_MAX] = ""; - int ok; + bool ok; switch (id) { case BLENDER_RESOURCE_PATH_USER: ok = get_path_user(path, NULL, NULL, NULL, ver); @@ -1162,11 +1290,11 @@ char *BLI_get_folder_version(const int id, const int ver, const int do_check) break; default: path[0] = '\0'; /* in case do_check is false */ - ok = FALSE; + ok = false; BLI_assert(!"incorrect ID"); } - if ((ok == FALSE) && do_check) { + if (!ok && do_check) { return NULL; } @@ -1183,6 +1311,9 @@ char *BLI_get_folder_version(const int id, const int ver, const int do_check) # undef PATH_DEBUG #endif +/** + * Sets the specified environment variable to the specified value. + */ void BLI_setenv(const char *env, const char *val) { /* free windows */ @@ -1208,6 +1339,8 @@ void BLI_setenv(const char *env, const char *val) /** * Only set an env var if already not there. * Like Unix setenv(env, val, 0); + * + * (not used anywhere). */ void BLI_setenv_if_new(const char *env, const char *val) { @@ -1216,6 +1349,9 @@ void BLI_setenv_if_new(const char *env, const char *val) } +/** + * Changes to the path separators to the native ones for this OS. + */ void BLI_clean(char *path) { #ifdef WIN32 @@ -1227,6 +1363,9 @@ void BLI_clean(char *path) #endif } +/** + * Replaces occurrences of from with to in *string. + */ void BLI_char_switch(char *string, char from, char to) { while (*string != 0) { @@ -1235,6 +1374,10 @@ void BLI_char_switch(char *string, char from, char to) } } +/** + * Strips off nonexistent subdirectories from the end of *dir, leaving the path of + * the lowest-level directory that does exist. + */ void BLI_make_exist(char *dir) { int a; @@ -1243,7 +1386,7 @@ void BLI_make_exist(char *dir) a = strlen(dir); - while (BLI_is_dir(dir) == 0) { + while (!BLI_is_dir(dir)) { a--; while (dir[a] != SEP) { a--; @@ -1263,21 +1406,28 @@ void BLI_make_exist(char *dir) } } +/** + * Ensures that the parent directory of *name exists. + */ void BLI_make_existing_file(const char *name) { - char di[FILE_MAX], fi[FILE_MAXFILE]; + char di[FILE_MAX]; + BLI_split_dir_part(name, di, sizeof(di)); - BLI_strncpy(di, name, sizeof(di)); - BLI_splitdirstring(di, fi); - - /* test exist */ - if (BLI_exists(di) == 0) { - BLI_dir_create_recursive(di); - } + /* make if if the dir doesn't exist */ + BLI_dir_create_recursive(di); } - -void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) +/** + * Returns in *string the concatenation of *dir and *file (also with *relabase on the + * front if specified and *dir begins with "//"). Normalizes all occurrences of path + * separators, including ensuring there is exactly one between the copies of *dir and *file, + * and between the copies of *relabase and *dir. + * + * \param relabase Optional prefix to substitute for "//" on front of *dir + * \param string Area to return result + */ +void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) { int sl; @@ -1310,7 +1460,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, /* Get the file name, chop everything past the last slash (ie. the filename) */ strcpy(string, relabase); - lslash = BLI_last_slash(string); + lslash = (char *)BLI_last_slash(string); if (lslash) *(lslash + 1) = 0; dir += 2; /* Skip over the relative reference */ @@ -1359,43 +1509,34 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, BLI_clean(string); } -int BLI_testextensie(const char *str, const char *ext) +/* does str end with ext. */ +bool BLI_testextensie(const char *str, const char *ext) { - short a, b; - int retval; - - a = strlen(str); - b = strlen(ext); - - if (a == 0 || b == 0 || b >= a) { - retval = 0; - } - else if (BLI_strcasecmp(ext, str + a - b)) { - retval = 0; - } - else { - retval = 1; - } - - return (retval); + const size_t a = strlen(str); + const size_t b = strlen(ext); + return !(a == 0 || b == 0 || b >= a) && (BLI_strcasecmp(ext, str + a - b) == 0); } -int BLI_testextensie_array(const char *str, const char **ext_array) +/* does str end with any of the suffixes in *ext_array. */ +bool BLI_testextensie_array(const char *str, const char **ext_array) { int i = 0; while (ext_array[i]) { if (BLI_testextensie(str, ext_array[i])) { - return 1; + return true; } i++; } - return 0; + return false; } -/* semicolon separated wildcards, eg: - * '*.zip;*.py;*.exe' */ -int BLI_testextensie_glob(const char *str, const char *ext_fnmatch) +/** + * Semicolon separated wildcards, eg: + * '*.zip;*.py;*.exe' + * does str match any of the semicolon-separated glob patterns in fnmatch. + */ +bool BLI_testextensie_glob(const char *str, const char *ext_fnmatch) { const char *ext_step = ext_fnmatch; char pattern[16]; @@ -1414,19 +1555,23 @@ int BLI_testextensie_glob(const char *str, const char *ext_fnmatch) BLI_strncpy(pattern, ext_step, len_ext); if (fnmatch(pattern, str, FNM_CASEFOLD) == 0) { - return 1; + return true; } ext_step += len_ext; } - return 0; + return false; } -int BLI_replace_extension(char *path, size_t maxlen, const char *ext) +/** + * Removes any existing extension on the end of \a path and appends \a ext. + * \return false if there was no room. + */ +bool BLI_replace_extension(char *path, size_t maxlen, const char *ext) { - size_t path_len = strlen(path); - size_t ext_len = strlen(ext); + const size_t path_len = strlen(path); + const size_t ext_len = strlen(ext); ssize_t a; for (a = path_len - 1; a >= 0; a--) { @@ -1440,24 +1585,26 @@ int BLI_replace_extension(char *path, size_t maxlen, const char *ext) } if (a + ext_len >= maxlen) - return 0; + return false; memcpy(path + a, ext, ext_len + 1); - return 1; + return true; } -/* strip's trailing '.'s and adds the extension only when needed */ -int BLI_ensure_extension(char *path, size_t maxlen, const char *ext) +/** + * Strip's trailing '.'s and adds the extension only when needed + */ +bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext) { - size_t path_len = strlen(path); - size_t ext_len = strlen(ext); + const size_t path_len = strlen(path); + const size_t ext_len = strlen(ext); ssize_t a; - /* first check the extension is alread there */ + /* first check the extension is already there */ if ( (ext_len <= path_len) && (strcmp(path + (path_len - ext_len), ext) == 0)) { - return 1; + return true; } for (a = path_len - 1; a >= 0; a--) { @@ -1471,10 +1618,10 @@ int BLI_ensure_extension(char *path, size_t maxlen, const char *ext) a++; if (a + ext_len >= maxlen) - return 0; + return false; memcpy(path + a, ext, ext_len + 1); - return 1; + return true; } /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt" @@ -1485,8 +1632,8 @@ int BLI_ensure_extension(char *path, size_t maxlen, const char *ext) * */ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen) { - char *lslash_str = BLI_last_slash(string); - size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0; + const char *lslash_str = BLI_last_slash(string); + const size_t lslash = lslash_str ? (size_t)(lslash_str - string) + 1 : 0; if (dir) { if (lslash) { @@ -1502,17 +1649,26 @@ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t d } } +/** + * Copies the parent directory part of string into *dir, max length dirlen. + */ void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen) { BLI_split_dirfile(string, dir, NULL, dirlen, 0); } +/** + * Copies the leaf filename part of string into *file, max length filelen. + */ void BLI_split_file_part(const char *string, char *file, const size_t filelen) { BLI_split_dirfile(string, NULL, file, 0, filelen); } -/* simple appending of filename to dir, does not check for valid path! */ +/** + * Simple appending of filename to dir, does not check for valid path! + * Puts result into *dst, which may be same area as *dir. + */ void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file) { size_t dirlen = BLI_strnlen(dir, maxlen); @@ -1549,10 +1705,15 @@ void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const cha BLI_strncpy(dst + dirlen, file, maxlen - dirlen); } -/* like pythons os.path.basename( ) */ -char *BLI_path_basename(char *path) +/** + * like pythons os.path.basename() + * + * \return The pointer into \a path string immediately after last slash, + * or start of \a path if none found. + */ +const char *BLI_path_basename(const char *path) { - char *filename = BLI_last_slash(path); + const char * const filename = BLI_last_slash(path); return filename ? filename + 1 : path; } @@ -1591,11 +1752,29 @@ char *BLI_path_basename(char *path) * this function returns wrong results! * XXX: test on empty base_dir and return an error ? */ -int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir) + +/** + * + * \param abs Optional string to return new full path + * \param abs_len Size of *abs string + * \param rel Optional area to return new path relative to parent directory of .blend file + * (only meaningful if item is in a subdirectory thereof) + * \param rel_len Size of *rel area + * \param base_dir Path of .blend file + * \param src_dir Original path of item (any initial "//" will be expanded to + * parent directory of .blend file) + * \param dest_dir New directory into which item will be moved + * \return bli_rebase_state + * + * \note Not actually used anywhere! + */ +int BLI_rebase_path(char *abs, size_t abs_len, + char *rel, size_t rel_len, + const char *base_dir, const char *src_dir, const char *dest_dir) { - char path[FILE_MAX]; - char dir[FILE_MAX]; - char base[FILE_MAX]; + char path[FILE_MAX]; /* original full path of item */ + char dir[FILE_MAX]; /* directory part of src_dir */ + char base[FILE_MAX]; /* basename part of src_dir */ char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */ char dest_path[FILE_MAX]; char rel_dir[FILE_MAX]; @@ -1627,21 +1806,23 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const /* if image is "below" current .blend file directory */ if (!BLI_path_ncmp(path, blend_dir, len)) { - /* if image is _in_ current .blend file directory */ if (BLI_path_cmp(dir, blend_dir) == 0) { + /* image is directly in .blend file parent directory => put directly in dest_dir */ BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base); } - /* "below" */ else { + /* "below" (in subdirectory of .blend file parent directory) => put in same relative directory structure in dest_dir */ /* rel = image_path_dir - blend_dir */ BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); - + /* subdirectories relative to blend_dir */ BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir); + /* same subdirectories relative to dest_dir */ BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base); + /* keeping original item basename */ } } - /* image is out of current directory */ + /* image is out of current directory -- just put straight in dest_dir */ else { BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base); } @@ -1651,7 +1832,7 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const if (rel) { strncat(rel, rel_dir, rel_len); - strncat(rel, base, rel_len); + strncat(rel, base, rel_len); /* FIXME: could overflow rel area! */ } /* return 2 if (src == dest) */ @@ -1663,12 +1844,13 @@ int BLI_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const return BLI_REBASE_OK; } -char *BLI_first_slash(char *string) +/** + * Returns pointer to the leftmost path separator in string. Not actually used anywhere. + */ +const char *BLI_first_slash(const char *string) { - char *ffslash, *fbslash; - - ffslash = strchr(string, '/'); - fbslash = strchr(string, '\\'); + char * const ffslash = strchr(string, '/'); + char * const fbslash = strchr(string, '\\'); if (!ffslash) return fbslash; else if (!fbslash) return ffslash; @@ -1677,12 +1859,13 @@ char *BLI_first_slash(char *string) else return fbslash; } -char *BLI_last_slash(const char *string) +/** + * Returns pointer to the rightmost path separator in string. + */ +const char *BLI_last_slash(const char *string) { - char *lfslash, *lbslash; - - lfslash = strrchr(string, '/'); - lbslash = strrchr(string, '\\'); + const char * const lfslash = strrchr(string, '/'); + const char * const lbslash = strrchr(string, '\\'); if (!lfslash) return lbslash; else if (!lbslash) return lfslash; @@ -1691,7 +1874,10 @@ char *BLI_last_slash(const char *string) else return lfslash; } -/* adds a slash if there isn't one there already */ +/** + * Appends a slash to string if there isn't one there already. + * Returns the new length of the string. + */ int BLI_add_slash(char *string) { int len = strlen(string); @@ -1703,7 +1889,9 @@ int BLI_add_slash(char *string) return len; } -/* removes a slash if there is one */ +/** + * Removes the last slash and everything after it to the end of string, if there is one. + */ void BLI_del_slash(char *string) { int len = strlen(string); @@ -1718,6 +1906,11 @@ void BLI_del_slash(char *string) } } +/** + * Tries appending each of the semicolon-separated extensions in the PATHEXT + * environment variable (Windows-only) onto *name in turn until such a file is found. + * Returns success/failure. + */ static int add_win32_extension(char *name) { int retval = 0; @@ -1934,16 +2127,26 @@ static void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir } } +/** + * Sets btempdir to userdir if specified and is a valid directory, otherwise + * chooses a suitable OS-specific temporary directory. + */ void BLI_init_temporary_dir(char *userdir) { BLI_where_is_temp(btempdir, FILE_MAX, userdir); } +/** + * Returns the path to the temporary directory. + */ const char *BLI_temporary_dir(void) { return btempdir; } +/** + * Puts in *dir path to OS-specific temporary directory. + */ void BLI_system_temporary_dir(char *dir) { BLI_where_is_temp(dir, FILE_MAX, NULL); @@ -1951,6 +2154,10 @@ void BLI_system_temporary_dir(char *dir) #ifdef WITH_ICONV +/** + * Converts a string encoded in the charset named by *code to UTF-8. + * Opens a new iconv context each time it is run, which is probably not the + * most efficient. */ void BLI_string_to_utf8(char *original, char *utf_8, const char *code) { size_t inbytesleft = strlen(original); @@ -1971,6 +2178,7 @@ void BLI_string_to_utf8(char *original, char *utf_8, const char *code) rv = iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft); if (rv == (size_t) -1) { printf("iconv Error\n"); + iconv_close(cd); return; } *utf_8 = '\0'; diff --git a/source/blender/blenlib/intern/rct.c b/source/blender/blenlib/intern/rct.c index 4bd7715ea7a..127855161c0 100644 --- a/source/blender/blenlib/intern/rct.c +++ b/source/blender/blenlib/intern/rct.c @@ -48,23 +48,23 @@ * * \return True if \a rect is empty. */ -int BLI_rcti_is_empty(const rcti *rect) +bool BLI_rcti_is_empty(const rcti *rect) { return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin)); } -int BLI_rctf_is_empty(const rctf *rect) +bool BLI_rctf_is_empty(const rctf *rect) { return ((rect->xmax <= rect->xmin) || (rect->ymax <= rect->ymin)); } -int BLI_rcti_isect_pt(const rcti *rect, const int x, const int y) +bool BLI_rcti_isect_pt(const rcti *rect, const int x, const int y) { - if (x < rect->xmin) return 0; - if (x > rect->xmax) return 0; - if (y < rect->ymin) return 0; - if (y > rect->ymax) return 0; - return 1; + if (x < rect->xmin) return false; + if (x > rect->xmax) return false; + if (y < rect->ymin) return false; + if (y > rect->ymax) return false; + return true; } /** @@ -74,31 +74,31 @@ int BLI_rcti_isect_pt(const rcti *rect, const int x, const int y) * * \return True if \a rect is empty. */ -int BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2]) +bool BLI_rcti_isect_pt_v(const rcti *rect, const int xy[2]) { - if (xy[0] < rect->xmin) return 0; - if (xy[0] > rect->xmax) return 0; - if (xy[1] < rect->ymin) return 0; - if (xy[1] > rect->ymax) return 0; - return 1; + if (xy[0] < rect->xmin) return false; + if (xy[0] > rect->xmax) return false; + if (xy[1] < rect->ymin) return false; + if (xy[1] > rect->ymax) return false; + return true; } -int BLI_rctf_isect_pt(const rctf *rect, const float x, const float y) +bool BLI_rctf_isect_pt(const rctf *rect, const float x, const float y) { - if (x < rect->xmin) return 0; - if (x > rect->xmax) return 0; - if (y < rect->ymin) return 0; - if (y > rect->ymax) return 0; - return 1; + if (x < rect->xmin) return false; + if (x > rect->xmax) return false; + if (y < rect->ymin) return false; + if (y > rect->ymax) return false; + return true; } -int BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2]) +bool BLI_rctf_isect_pt_v(const rctf *rect, const float xy[2]) { - if (xy[0] < rect->xmin) return 0; - if (xy[0] > rect->xmax) return 0; - if (xy[1] < rect->ymin) return 0; - if (xy[1] > rect->ymax) return 0; - return 1; + if (xy[0] < rect->xmin) return false; + if (xy[0] > rect->xmax) return false; + if (xy[1] < rect->ymin) return false; + if (xy[1] > rect->ymax) return false; + return true; } /* based closely on 'isect_line_line_v2_int', but in modified so corner cases are treated as intersections */ @@ -127,17 +127,17 @@ static int isect_segments_fl(const float v1[2], const float v2[2], const float v } } -int BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2]) +bool BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2]) { /* first do outside-bounds check for both points of the segment */ - if (s1[0] < rect->xmin && s2[0] < rect->xmin) return 0; - if (s1[0] > rect->xmax && s2[0] > rect->xmax) return 0; - if (s1[1] < rect->ymin && s2[1] < rect->ymin) return 0; - if (s1[1] > rect->ymax && s2[1] > rect->ymax) return 0; + if (s1[0] < rect->xmin && s2[0] < rect->xmin) return false; + if (s1[0] > rect->xmax && s2[0] > rect->xmax) return false; + if (s1[1] < rect->ymin && s2[1] < rect->ymin) return false; + if (s1[1] > rect->ymax && s2[1] > rect->ymax) return false; /* if either points intersect then we definetly intersect */ if (BLI_rcti_isect_pt_v(rect, s1) || BLI_rcti_isect_pt_v(rect, s2)) { - return 1; + return true; } else { /* both points are outside but may insersect the rect */ @@ -147,32 +147,32 @@ int BLI_rcti_isect_segment(const rcti *rect, const int s1[2], const int s2[2]) tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; tvec2[0] = rect->xmin; tvec2[1] = rect->ymax; if (isect_segments_i(s1, s2, tvec1, tvec2)) { - return 1; + return true; } /* diagonal: [\] */ tvec1[0] = rect->xmin; tvec1[1] = rect->ymax; tvec2[0] = rect->xmax; tvec2[1] = rect->ymin; if (isect_segments_i(s1, s2, tvec1, tvec2)) { - return 1; + return true; } /* no intersection */ - return 0; + return false; } } -int BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2]) +bool BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2]) { /* first do outside-bounds check for both points of the segment */ - if (s1[0] < rect->xmin && s2[0] < rect->xmin) return 0; - if (s1[0] > rect->xmax && s2[0] > rect->xmax) return 0; - if (s1[1] < rect->ymin && s2[1] < rect->ymin) return 0; - if (s1[1] > rect->ymax && s2[1] > rect->ymax) return 0; + if (s1[0] < rect->xmin && s2[0] < rect->xmin) return false; + if (s1[0] > rect->xmax && s2[0] > rect->xmax) return false; + if (s1[1] < rect->ymin && s2[1] < rect->ymin) return false; + if (s1[1] > rect->ymax && s2[1] > rect->ymax) return false; /* if either points intersect then we definetly intersect */ if (BLI_rctf_isect_pt_v(rect, s1) || BLI_rctf_isect_pt_v(rect, s2)) { - return 1; + return true; } else { /* both points are outside but may insersect the rect */ @@ -182,18 +182,18 @@ int BLI_rctf_isect_segment(const rctf *rect, const float s1[2], const float s2[2 tvec1[0] = rect->xmin; tvec1[1] = rect->ymin; tvec2[0] = rect->xmin; tvec2[1] = rect->ymax; if (isect_segments_fl(s1, s2, tvec1, tvec2)) { - return 1; + return true; } /* diagonal: [\] */ tvec1[0] = rect->xmin; tvec1[1] = rect->ymax; tvec2[0] = rect->xmax; tvec2[1] = rect->ymin; if (isect_segments_fl(s1, s2, tvec1, tvec2)) { - return 1; + return true; } /* no intersection */ - return 0; + return false; } } @@ -353,49 +353,49 @@ void BLI_rctf_interp(rctf *rect, const rctf *rect_a, const rctf *rect_b, const f /* BLI_rcti_interp() not needed yet */ -int BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]) +bool BLI_rctf_clamp_pt_v(const struct rctf *rect, float xy[2]) { - int change = 0; - if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; } - if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; } - if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; } - if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; } + bool change = false; + if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = true; } + if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = true; } + if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = true; } + if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = true; } return change; } -int BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]) +bool BLI_rcti_clamp_pt_v(const struct rcti *rect, int xy[2]) { - int change = 0; - if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = 1; } - if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = 1; } - if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = 1; } - if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = 1; } + bool change = false; + if (xy[0] < rect->xmin) { xy[0] = rect->xmin; change = true; } + if (xy[0] > rect->xmax) { xy[0] = rect->xmax; change = true; } + if (xy[1] < rect->ymin) { xy[1] = rect->ymin; change = true; } + if (xy[1] > rect->ymax) { xy[1] = rect->ymax; change = true; } return change; } -int BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit) +bool BLI_rctf_compare(const struct rctf *rect_a, const struct rctf *rect_b, const float limit) { if (fabsf(rect_a->xmin - rect_b->xmin) < limit) if (fabsf(rect_a->xmax - rect_b->xmax) < limit) if (fabsf(rect_a->ymin - rect_b->ymin) < limit) if (fabsf(rect_a->ymax - rect_b->ymax) < limit) - return 1; + return true; - return 0; + return false; } -int BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b) +bool BLI_rcti_compare(const struct rcti *rect_a, const struct rcti *rect_b) { if (rect_a->xmin == rect_b->xmin) if (rect_a->xmax == rect_b->xmax) if (rect_a->ymin == rect_b->ymin) if (rect_a->ymax == rect_b->ymax) - return 1; + return true; - return 0; + return false; } -int BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest) +bool BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest) { float xmin, xmax; float ymin, ymax; @@ -412,7 +412,7 @@ int BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest) dest->ymin = ymin; dest->ymax = ymax; } - return 1; + return true; } else { if (dest) { @@ -421,11 +421,11 @@ int BLI_rctf_isect(const rctf *src1, const rctf *src2, rctf *dest) dest->ymin = 0; dest->ymax = 0; } - return 0; + return false; } } -int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest) +bool BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest) { int xmin, xmax; int ymin, ymax; @@ -442,7 +442,7 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest) dest->ymin = ymin; dest->ymax = ymax; } - return 1; + return true; } else { if (dest) { @@ -451,7 +451,7 @@ int BLI_rcti_isect(const rcti *src1, const rcti *src2, rcti *dest) dest->ymin = 0; dest->ymax = 0; } - return 0; + return false; } } diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 1358fdd2a62..71cd5e529a2 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -71,6 +71,7 @@ #ifdef WIN32 # include <io.h> # include <direct.h> +# include <limits.h> /* PATH_MAX */ # include "BLI_winstuff.h" # include "utfconv.h" #else @@ -91,14 +92,14 @@ #include "BLI_fileops_types.h" #include "BLI_path_util.h" -/* vars: */ -static int totnum, actnum; -static struct direntry *files; +#include "../imbuf/IMB_imbuf.h" -static struct ListBase dirbase_ = {NULL, NULL}; -static struct ListBase *dirbase = &dirbase_; - -/* can return NULL when the size is not big enough */ +/** + * Copies the current working directory into *dir (max size maxncpy), and + * returns a pointer to same. + * + * \note can return NULL when the size is not big enough + */ char *BLI_current_working_dir(char *dir, const size_t maxncpy) { const char *pwd = getenv("PWD"); @@ -110,26 +111,33 @@ char *BLI_current_working_dir(char *dir, const size_t maxncpy) return getcwd(dir, maxncpy); } - +/* + * Ordering function for sorting lists of files/directories. Returns -1 if + * entry1 belongs before entry2, 0 if they are equal, 1 if they should be swapped. + */ static int bli_compare(struct direntry *entry1, struct direntry *entry2) { /* type is equal to stat.st_mode */ + /* directories come before non-directories */ if (S_ISDIR(entry1->type)) { if (S_ISDIR(entry2->type) == 0) return (-1); } else { if (S_ISDIR(entry2->type)) return (1); } + /* non-regular files come after regular files */ if (S_ISREG(entry1->type)) { if (S_ISREG(entry2->type) == 0) return (-1); } else { if (S_ISREG(entry2->type)) return (1); } + /* arbitrary, but consistent, ordering of different types of non-regular files */ if ((entry1->type & S_IFMT) < (entry2->type & S_IFMT)) return (-1); if ((entry1->type & S_IFMT) > (entry2->type & S_IFMT)) return (1); - + + /* OK, now we know their S_IFMT fields are the same, go on to a name comparison */ /* make sure "." and ".." are always first */ if (strcmp(entry1->relname, ".") == 0) return (-1); if (strcmp(entry2->relname, ".") == 0) return (1); @@ -139,7 +147,10 @@ static int bli_compare(struct direntry *entry1, struct direntry *entry2) return (BLI_natstrcmp(entry1->relname, entry2->relname)); } - +/** + * Returns the number of free bytes on the volume containing the specified pathname. */ +/* Not actually used anywhere. + */ double BLI_dir_free_space(const char *dir) { #ifdef WIN32 @@ -180,7 +191,9 @@ double BLI_dir_free_space(const char *dir) slash = strrchr(name, '/'); if (slash) slash[1] = 0; } - else strcpy(name, "/"); + else { + strcpy(name, "/"); + } #if defined(__FreeBSD__) || defined(linux) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__GNU__) || defined(__GLIBC__) if (statfs(name, &disk)) return(-1); @@ -197,89 +210,77 @@ double BLI_dir_free_space(const char *dir) #endif } -static void bli_builddir(const char *dirname, const char *relname) +struct BuildDirCtx { + struct direntry *files; /* array[nrfiles] */ + int nrfiles; +}; + +/** + * Scans the directory named *dirname and appends entries for its contents to files. + */ +static void bli_builddir(struct BuildDirCtx *dir_ctx, const char *dirname) { - struct dirent *fname; - struct dirlink *dlink; - int rellen, newnum = 0; - char buf[256]; + struct ListBase dirbase = {NULL, NULL}; + int newnum = 0; DIR *dir; - BLI_strncpy(buf, relname, sizeof(buf)); - rellen = strlen(relname); - - if (rellen) { - buf[rellen] = '/'; - rellen++; - } -#ifndef WIN32 - if (chdir(dirname) == -1) { - perror(dirname); - return; - } -#else - UTF16_ENCODE(dirname); - if (!SetCurrentDirectoryW(dirname_16)) { - perror(dirname); - free(dirname_16); - return; - } - UTF16_UN_ENCODE(dirname); + if ((dir = opendir(dirname)) != NULL) { -#endif - if ((dir = (DIR *)opendir("."))) { - while ((fname = (struct dirent *) readdir(dir)) != NULL) { - dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); - if (dlink) { - BLI_strncpy(buf + rellen, fname->d_name, sizeof(buf) - rellen); - dlink->name = BLI_strdup(buf); - BLI_addhead(dirbase, dlink); + const struct dirent *fname; + while ((fname = readdir(dir)) != NULL) { + struct dirlink * const dlink = (struct dirlink *)malloc(sizeof(struct dirlink)); + if (dlink != NULL) { + dlink->name = BLI_strdup(fname->d_name); + BLI_addhead(&dirbase, dlink); newnum++; } } - + if (newnum) { - if (files) { - void *tmp = realloc(files, (totnum + newnum) * sizeof(struct direntry)); + if (dir_ctx->files) { + void * const tmp = realloc(dir_ctx->files, (dir_ctx->nrfiles + newnum) * sizeof(struct direntry)); if (tmp) { - files = (struct direntry *)tmp; + dir_ctx->files = (struct direntry *)tmp; } else { /* realloc fail */ - free(files); - files = NULL; + free(dir_ctx->files); + dir_ctx->files = NULL; } } - if (files == NULL) - files = (struct direntry *)malloc(newnum * sizeof(struct direntry)); + if (dir_ctx->files == NULL) + dir_ctx->files = (struct direntry *)malloc(newnum * sizeof(struct direntry)); - if (files) { - dlink = (struct dirlink *) dirbase->first; + if (dir_ctx->files) { + struct dirlink * dlink = (struct dirlink *) dirbase.first; + struct direntry *file = &dir_ctx->files[dir_ctx->nrfiles]; while (dlink) { - memset(&files[actnum], 0, sizeof(struct direntry)); - files[actnum].relname = dlink->name; - files[actnum].path = BLI_strdupcat(dirname, dlink->name); + char fullname[PATH_MAX]; + memset(file, 0, sizeof(struct direntry)); + file->relname = dlink->name; + file->path = BLI_strdupcat(dirname, dlink->name); + BLI_join_dirfile(fullname, sizeof(fullname), dirname, dlink->name); // use 64 bit file size, only needed for WIN32 and WIN64. // Excluding other than current MSVC compiler until able to test #ifdef WIN32 { - wchar_t *name_16 = alloc_utf16_from_8(dlink->name, 0); -#if (defined(WIN32) || defined(WIN64)) && (_MSC_VER >= 1500) - _wstat64(name_16, &files[actnum].s); + wchar_t *name_16 = alloc_utf16_from_8(fullname, 0); +#if defined(_MSC_VER) && (_MSC_VER >= 1500) + _wstat64(name_16, &file->s); #elif defined(__MINGW32__) - _stati64(dlink->name, &files[actnum].s); + _stati64(fullname, &file->s); #endif free(name_16); } #else - stat(dlink->name, &files[actnum].s); + stat(fullname, &file->s); #endif - files[actnum].type = files[actnum].s.st_mode; - files[actnum].flags = 0; - totnum++; - actnum++; + file->type = file->s.st_mode; + file->flags = 0; + dir_ctx->nrfiles++; + file++; dlink = dlink->next; } } @@ -288,8 +289,10 @@ static void bli_builddir(const char *dirname, const char *relname) exit(1); } - BLI_freelist(dirbase); - if (files) qsort(files, actnum, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare); + BLI_freelist(&dirbase); + if (dir_ctx->files) { + qsort(dir_ctx->files, dir_ctx->nrfiles, sizeof(struct direntry), (int (*)(const void *, const void *))bli_compare); + } } else { printf("%s empty directory\n", dirname); @@ -302,12 +305,17 @@ static void bli_builddir(const char *dirname, const char *relname) } } -static void bli_adddirstrings(void) +/** + * Fills in the "mode[123]", "size" and "string" fields in the elements of the files + * array with descriptive details about each item. "string" will have a format similar to "ls -l". + */ +static void bli_adddirstrings(struct BuildDirCtx *dir_ctx) { char datum[100]; - char buf[512]; +// char buf[512]; // UNUSED char size[250]; - static const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; + const char *types[8] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"}; + /* symbolic display, indexed by mode field value */ int num, mode; #ifdef WIN32 __int64 st_size; @@ -319,7 +327,7 @@ static void bli_adddirstrings(void) struct tm *tm; time_t zero = 0; - for (num = 0, file = files; num < actnum; num++, file++) { + for (num = 0, file = dir_ctx->files; num < dir_ctx->nrfiles; num++, file++) { #ifdef WIN32 mode = 0; BLI_strncpy(file->mode1, types[0], sizeof(file->mode1)); @@ -330,7 +338,7 @@ static void bli_adddirstrings(void) BLI_strncpy(file->mode1, types[(mode & 0700) >> 6], sizeof(file->mode1)); BLI_strncpy(file->mode2, types[(mode & 0070) >> 3], sizeof(file->mode2)); - BLI_strncpy(file->mode3, types[(mode & 0007)], sizeof(file->mode3)); + BLI_strncpy(file->mode3, types[(mode & 0007)], sizeof(file->mode3)); if (((mode & S_ISGID) == S_ISGID) && (file->mode2[2] == '-')) file->mode2[2] = 'l'; @@ -375,6 +383,9 @@ static void bli_adddirstrings(void) */ st_size = file->s.st_size; + /* FIXME: Either change decimal prefixes to binary ones + * <http://en.wikipedia.org/wiki/Binary_prefix>, or change + * divisor factors from 1024 to 1000. */ if (st_size > 1024 * 1024 * 1024) { BLI_snprintf(file->size, sizeof(file->size), "%.2f GB", ((double)st_size) / (1024 * 1024 * 1024)); } @@ -408,61 +419,86 @@ static void bli_adddirstrings(void) BLI_snprintf(size, sizeof(size), "%10d", (int) st_size); } +#if 0 BLI_snprintf(buf, sizeof(buf), "%s %s %s %7s %s %s %10s %s", file->mode1, file->mode2, file->mode3, file->owner, file->date, file->time, size, file->relname); - - file->string = BLI_strdup(buf); +#endif } } +/** + * Scans the contents of the directory named *dirname, and allocates and fills in an + * array of entries describing them in *filelist. The length of the array is the function result. + */ unsigned int BLI_dir_contents(const char *dirname, struct direntry **filelist) { - /* reset global variables - * memory stored in files is free()'d in - * filesel.c:freefilelist() */ + struct BuildDirCtx dir_ctx; - actnum = totnum = 0; - files = NULL; + dir_ctx.nrfiles = 0; + dir_ctx.files = NULL; - bli_builddir(dirname, ""); - bli_adddirstrings(); + bli_builddir(&dir_ctx, dirname); + bli_adddirstrings(&dir_ctx); - if (files) { - *(filelist) = files; + if (dir_ctx.files) { + *filelist = dir_ctx.files; } else { // keep blender happy. Blender stores this in a variable // where 0 has special meaning..... - *(filelist) = files = malloc(sizeof(struct direntry)); + *filelist = malloc(sizeof(struct direntry)); } - return(actnum); + return dir_ctx.nrfiles; } +/* frees storage for an array of direntries, including the array itself. */ +void BLI_free_filelist(struct direntry *filelist, unsigned int nrentries) +{ + unsigned int i; + for (i = 0; i < nrentries; ++i) { + struct direntry * const entry = filelist + i; + if (entry->image) { + IMB_freeImBuf(entry->image); + } + if (entry->relname) + MEM_freeN(entry->relname); + if (entry->path) + MEM_freeN(entry->path); + /* entry->poin assumed not to point to anything needing freeing here */ + } + free(filelist); +} + + +/** + * Returns the file size of an opened file descriptor. + */ size_t BLI_file_descriptor_size(int file) { - struct stat buf; - - if (file <= 0) return (-1); - fstat(file, &buf); /* CHANGE */ - return (buf.st_size); + struct stat st; + if ((file < 0) || (fstat(file, &st) == -1)) + return -1; + return st.st_size; } +/** + * Returns the size of a file. + */ size_t BLI_file_size(const char *path) { - int size, file = BLI_open(path, O_BINARY | O_RDONLY, 0); - - if (file == -1) + struct stat stats; + if (BLI_stat(path, &stats) == -1) return -1; - - size = BLI_file_descriptor_size(file); - close(file); - return size; + return stats.st_size; } - +/** + * Returns the st_mode from statting the specified path name, or 0 if it couldn't be statted + * (most likely doesn't exist or no access). + */ int BLI_exists(const char *name) { #if defined(WIN32) @@ -509,18 +545,27 @@ int BLI_stat(const char *path, struct stat *buffer) } #endif -/* would be better in fileops.c except that it needs stat.h so add here */ -int BLI_is_dir(const char *file) +/** + * Does the specified path point to a directory? + * \note Would be better in fileops.c except that it needs stat.h so add here + */ +bool BLI_is_dir(const char *file) { return S_ISDIR(BLI_exists(file)); } -int BLI_is_file(const char *path) +/** + * Does the specified path point to a non-directory? + */ +bool BLI_is_file(const char *path) { - int mode = BLI_exists(path); + const int mode = BLI_exists(path); return (mode && !S_ISDIR(mode)); } +/** + * Reads the contents of a text file and returns the lines in a linked list. + */ LinkNode *BLI_file_read_as_lines(const char *name) { FILE *fp = BLI_fopen(name, "r"); @@ -549,6 +594,9 @@ LinkNode *BLI_file_read_as_lines(const char *name) char *line = BLI_strdupn(&buf[last], i - last); BLI_linklist_prepend(&lines, line); + /* faster to build singly-linked list in reverse order */ + /* alternatively, could process buffer in reverse order so + * list ends up right way round to start with */ last = i + 1; } } @@ -557,18 +605,22 @@ LinkNode *BLI_file_read_as_lines(const char *name) } fclose(fp); - + + /* get them the right way round */ BLI_linklist_reverse(&lines); return lines; } +/* + * Frees memory from a previous call to BLI_file_read_as_lines. + */ void BLI_file_free_lines(LinkNode *lines) { - BLI_linklist_free(lines, (void (*)(void *))MEM_freeN); + BLI_linklist_freeN(lines); } /** is file1 older then file2 */ -int BLI_file_older(const char *file1, const char *file2) +bool BLI_file_older(const char *file1, const char *file2) { #ifdef WIN32 struct _stat st1, st2; @@ -576,16 +628,16 @@ int BLI_file_older(const char *file1, const char *file2) UTF16_ENCODE(file1); UTF16_ENCODE(file2); - if (_wstat(file1_16, &st1)) return 0; - if (_wstat(file2_16, &st2)) return 0; + if (_wstat(file1_16, &st1)) return false; + if (_wstat(file2_16, &st2)) return false; UTF16_UN_ENCODE(file2); UTF16_UN_ENCODE(file1); #else struct stat st1, st2; - if (stat(file1, &st1)) return 0; - if (stat(file2, &st2)) return 0; + if (stat(file1, &st1)) return false; + if (stat(file2, &st2)) return false; #endif return (st1.st_mtime < st2.st_mtime); } diff --git a/source/blender/blenlib/intern/string.c b/source/blender/blenlib/intern/string.c index 3500f3f1805..906a3095f91 100644 --- a/source/blender/blenlib/intern/string.c +++ b/source/blender/blenlib/intern/string.c @@ -43,6 +43,15 @@ #include "BLI_utildefines.h" +/** + * Duplicates the first \a len bytes of cstring \a str + * into a newly mallocN'd string and returns it. \a str + * is assumed to be at least len bytes long. + * + * \param str The string to be duplicated + * \param len The number of bytes to duplicate + * \retval Returns the duplicated string + */ char *BLI_strdupn(const char *str, const size_t len) { char *n = MEM_mallocN(len + 1, "strdup"); @@ -51,11 +60,25 @@ char *BLI_strdupn(const char *str, const size_t len) return n; } + +/** + * Duplicates the cstring \a str into a newly mallocN'd + * string and returns it. + * + * \param str The string to be duplicated + * \retval Returns the duplicated string + */ char *BLI_strdup(const char *str) { return BLI_strdupn(str, strlen(str)); } +/** + * Appends the two strings, and returns new mallocN'ed string + * \param str1 first string for copy + * \param str2 second string for append + * \retval Returns dst + */ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) { size_t len; @@ -69,18 +92,52 @@ char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) return n; } +/** + * Like strncpy but ensures dst is always + * '\0' terminated. + * + * \param dst Destination for copy + * \param src Source string to copy + * \param maxncpy Maximum number of characters to copy (generally + * the size of dst) + * \retval Returns dst + */ char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) { - size_t srclen = strlen(src); - size_t cpylen = (srclen > (maxncpy - 1)) ? (maxncpy - 1) : srclen; + size_t srclen = BLI_strnlen(src, maxncpy - 1); BLI_assert(maxncpy != 0); - - memcpy(dst, src, cpylen); - dst[cpylen] = '\0'; - + + memcpy(dst, src, srclen); + dst[srclen] = '\0'; return dst; } +/** + * Like strncpy but ensures dst is always + * '\0' terminated. + * + * \note This is a duplicate of #BLI_strncpy that returns bytes copied. + * And is a drop in replacement for 'snprintf(str, sizeof(str), "%s", arg);' + * + * \param dst Destination for copy + * \param src Source string to copy + * \param maxncpy Maximum number of characters to copy (generally + * the size of dst) + * \retval The number of bytes copied (The only difference from BLI_strncpy). + */ +size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) +{ + size_t srclen = BLI_strnlen(src, maxncpy - 1); + BLI_assert(maxncpy != 0); + + memcpy(dst, src, srclen); + dst[srclen] = '\0'; + return srclen; +} + +/** + * Portable replacement for #vsnprintf + */ size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restrict format, va_list arg) { size_t n; @@ -101,6 +158,9 @@ size_t BLI_vsnprintf(char *__restrict buffer, size_t count, const char *__restri return n; } +/** + * Portable replacement for #snprintf + */ size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restrict format, ...) { size_t n; @@ -113,6 +173,10 @@ size_t BLI_snprintf(char *__restrict buffer, size_t count, const char *__restric return n; } +/** + * Print formatted string into a newly #MEM_mallocN'd string + * and return it. + */ char *BLI_sprintfN(const char *__restrict format, ...) { DynStr *ds; @@ -180,17 +244,17 @@ escape_finish: return len; } - -/* Makes a copy of the text within the "" that appear after some text 'blahblah' +/** + * Makes a copy of the text within the "" that appear after some text 'blahblah' * i.e. for string 'pose["apples"]' with prefix 'pose[', it should grab "apples" - * - * - str: is the entire string to chop - * - prefix: is the part of the string to leave out * - * Assume that the strings returned must be freed afterwards, and that the inputs will contain + * - str: is the entire string to chop + * - prefix: is the part of the string to leave out + * + * Assume that the strings returned must be freed afterwards, and that the inputs will contain * data we want... * - * TODO, return the offset and a length so as to avoid doing an allocation. + * \return the offset and a length so as to avoid doing an allocation. */ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) { @@ -210,12 +274,19 @@ char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict return BLI_strdupn("", 0); } -/* Replaces all occurrences of oldText with newText in str, returning a new string that doesn't - * contain the 'replaced' occurrences. +/** + * Returns a copy of the cstring \a str into a newly mallocN'd + * string with all instances of oldText replaced with newText, + * and returns it. + * + * \note A rather wasteful string-replacement utility, though this shall do for now... + * Feel free to replace this with an even safe + nicer alternative + * + * \param str The string to replace occurrences of oldText in + * \param oldText The text in the string to find and replace + * \param newText The text in the string to find and replace + * \retval Returns the duplicated string */ - -/* A rather wasteful string-replacement utility, though this shall do for now... - * Feel free to replace this with an even safe + nicer alternative */ char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const char *__restrict newText) { DynStr *ds = NULL; @@ -282,12 +353,19 @@ char *BLI_replacestr(char *__restrict str, const char *__restrict oldText, const } } +/** + * Compare two strings without regard to case. + * + * \retval True if the strings are equal, false otherwise. + */ int BLI_strcaseeq(const char *a, const char *b) { return (BLI_strcasecmp(a, b) == 0); } -/* strcasestr not available in MSVC */ +/** + * Portable replacement for #strcasestr (not available in MSVC) + */ char *BLI_strcasestr(const char *s, const char *find) { register char c, sc; @@ -431,10 +509,15 @@ void BLI_timestr(double _time, char *str) } /* determine the length of a fixed-size string */ -size_t BLI_strnlen(const char *str, const size_t maxlen) +size_t BLI_strnlen(const char *s, size_t maxlen) { - const char *end = memchr(str, '\0', maxlen); - return end ? (size_t) (end - str) : maxlen; + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return len; } void BLI_ascii_strtolower(char *str, const size_t len) @@ -454,3 +537,31 @@ void BLI_ascii_strtoupper(char *str, const size_t len) if (str[i] >= 'a' && str[i] <= 'z') str[i] -= 'a' - 'A'; } + +/** + * Strip trailing zeros from a float, eg: + * 0.0000 -> 0.0 + * 2.0010 -> 2.001 + * + * \param str + * \param len + * \return The number of zeto's stripped. + */ +int BLI_str_rstrip_float_zero(char *str, const char pad) +{ + char *p = strchr(str, '.'); + int totstrip = 0; + if (p) { + char *end_p; + p++; /* position at first decimal place */ + end_p = p + (strlen(p) - 1); /* position at last character */ + if (end_p > p) { + while (end_p != p && *end_p == '0') { + *end_p = pad; + end_p--; + } + } + } + + return totstrip; +} diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 26235de4dd2..fe8f3c20ab4 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -33,6 +33,7 @@ #include <string.h> #include <wchar.h> #include <wctype.h> +#include <wcwidth.h> #include <stdio.h> #include <stdlib.h> @@ -317,6 +318,42 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst_w, const char *__rest /* end wchar_t / utf8 functions */ /* --------------------------------------------------------------------------*/ +/* count columns that character/string occupies, based on wcwidth.c */ + +int BLI_wcwidth(wchar_t ucs) +{ + return mk_wcwidth(ucs); +} + +int BLI_wcswidth(const wchar_t *pwcs, size_t n) +{ + return mk_wcswidth(pwcs, n); +} + +int BLI_str_utf8_char_width(const char *p) +{ + unsigned int unicode = BLI_str_utf8_as_unicode(p); + if (unicode == BLI_UTF8_ERR) + return -1; + + return BLI_wcwidth((wchar_t)unicode); +} + +int BLI_str_utf8_char_width_safe(const char *p) +{ + int columns; + + unsigned int unicode = BLI_str_utf8_as_unicode(p); + if (unicode == BLI_UTF8_ERR) + return 1; + + columns = BLI_wcwidth((wchar_t)unicode); + + return (columns < 0) ? 1 : columns; +} + +/* --------------------------------------------------------------------------*/ + /* copied from glib's gutf8.c, added 'Err' arg */ /* note, glib uses unsigned int for unicode, best we do the same, diff --git a/source/blender/blenlib/intern/winstuff.c b/source/blender/blenlib/intern/winstuff.c index 65fb490b218..d11bee255c2 100644 --- a/source/blender/blenlib/intern/winstuff.c +++ b/source/blender/blenlib/intern/winstuff.c @@ -38,8 +38,6 @@ #include <conio.h> #include "MEM_guardedalloc.h" -#include "BLI_path_util.h" -#include "BLI_string.h" #include "../blenkernel/BKE_global.h" /* G.background, bad level include (no function calls) */ @@ -47,6 +45,7 @@ #include "BLI_winstuff.h" #include "BLI_utildefines.h" #include "BLI_path_util.h" +#include "BLI_string.h" #include "utf_winfunc.h" #include "utfconv.h" @@ -141,7 +140,7 @@ void RegisterBlendExtension(void) lresult = RegCreateKeyEx(root, ".blend", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, &dwd); if (lresult == ERROR_SUCCESS) { - sprintf(buffer, "%s", "blendfile"); + strcpy(buffer, "blendfile"); lresult = RegSetValueEx(hkey, NULL, 0, REG_SZ, (BYTE *)buffer, strlen(buffer) + 1); RegCloseKey(hkey); } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4bd8f82562c..5834e2b9927 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -381,7 +381,7 @@ static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) for (i = 0, entry = onm->entries; i < nentries; i++, entry++) { if (entry->old == addr) { - ID *id = id = entry->newp; + ID *id = entry->newp; if (id && (!lib || id->lib)) { return id; } @@ -496,16 +496,6 @@ void blo_split_main(ListBase *mainlist, Main *main) split_libdata(lbarray[i], main->next); } -/* removes things like /blah/blah/../../blah/ etc, then writes in *name the full path */ -static void cleanup_path(const char *relabase, char *name) -{ - char filename[FILE_MAXFILE]; - - BLI_splitdirstring(name, filename); - BLI_cleanup_dir(relabase, name); - strcat(name, filename); -} - static void read_file_version(FileData *fd, Main *main) { BHead *bhead; @@ -534,7 +524,7 @@ static Main *blo_find_main(FileData *fd, const char *filepath, const char *relab char name1[FILE_MAX]; BLI_strncpy(name1, filepath, sizeof(name1)); - cleanup_path(relabase, name1); + BLI_cleanup_path(relabase, name1); // printf("blo_find_main: relabase %s\n", relabase); // printf("blo_find_main: original in %s\n", filepath); @@ -1178,7 +1168,7 @@ int BLO_is_a_library(const char *path, char *dir, char *group) dir[len - 1] = '\0'; /* Find the last slash */ - fd = BLI_last_slash(dir); + fd = (char *)BLI_last_slash(dir); if (fd == NULL) return 0; *fd = 0; @@ -1187,10 +1177,10 @@ int BLO_is_a_library(const char *path, char *dir, char *group) *fd = '/'; /* put back the removed slash separating the dir and the .blend file name */ } else { - char *gp = fd + 1; // in case we have a .blend file, gp points to the group + const char * const gp = fd + 1; // in case we have a .blend file, gp points to the group /* Find the last slash */ - fd = BLI_last_slash(dir); + fd = (char *)BLI_last_slash(dir); if (!fd || !BLO_has_bfile_extension(fd+1)) return 0; /* now we know that we are in a blend file and it is safe to @@ -3259,7 +3249,9 @@ static void direct_link_curve(FileData *fd, Curve *cu) cu->strinfo= newdataadr(fd, cu->strinfo); cu->tb = newdataadr(fd, cu->tb); - if (cu->vfont == NULL) link_list(fd, &(cu->nurb)); + if (cu->vfont == NULL) { + link_list(fd, &(cu->nurb)); + } else { cu->nurb.first=cu->nurb.last= NULL; @@ -3839,8 +3831,10 @@ static void lib_link_mesh(FileData *fd, Main *main) me->mat[i] = newlibadr_us(fd, me->id.lib, me->mat[i]); } } - else me->totcol = 0; - + else { + me->totcol = 0; + } + me->ipo = newlibadr_us(fd, me->id.lib, me->ipo); // XXX: deprecated: old anim sys me->key = newlibadr_us(fd, me->id.lib, me->key); me->texcomesh = newlibadr_us(fd, me->id.lib, me->texcomesh); @@ -5345,8 +5339,9 @@ static void direct_link_scene(FileData *fd, Scene *sce) /* link cache */ direct_link_pointcache_list(fd, &rbw->ptcaches, &rbw->pointcache, FALSE); /* make sure simulation starts from the beginning after loading file */ - if (rbw->pointcache) - rbw->ltime = rbw->pointcache->startframe; + if (rbw->pointcache) { + rbw->ltime = (float)rbw->pointcache->startframe; + } } } @@ -5750,7 +5745,9 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc } #endif } - else if (v3d->scenelock) v3d->lay = sc->scene->lay; + else if (v3d->scenelock) { + v3d->lay = sc->scene->lay; + } /* not very nice, but could help */ if ((v3d->layact & v3d->lay) == 0) v3d->layact = v3d->lay; @@ -5946,6 +5943,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) rv3d->clipbb = newdataadr(fd, rv3d->clipbb); rv3d->depths = NULL; + rv3d->gpuoffscreen = NULL; rv3d->ri = NULL; rv3d->render_engine = NULL; rv3d->sms = NULL; @@ -6111,7 +6109,7 @@ static void direct_link_screen(FileData *fd, bScreen *sc) soops->treestore->totelem = soops->treestore->usedelem; soops->storeflag |= SO_TREESTORE_CLEANUP; // at first draw } - soops->tree.first = soops->tree.last= NULL; + soops->tree.first = soops->tree.last= NULL; } else if (sl->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)sl; @@ -6282,7 +6280,7 @@ static void direct_link_library(FileData *fd, Library *lib, Main *main) } /* make sure we have full path in lib->filepath */ BLI_strncpy(lib->filepath, lib->name, sizeof(lib->name)); - cleanup_path(fd->relabase, lib->filepath); + BLI_cleanup_path(fd->relabase, lib->filepath); // printf("direct_link_library: name %s\n", lib->name); // printf("direct_link_library: filepath %s\n", lib->filepath); @@ -7647,6 +7645,21 @@ static void do_versions_affine_tracker_track(MovieTrackingTrack *track) } } +/* initialize userdef with non-UI dependency stuff */ +/* other initializers (such as theme color defaults) go to resources.c */ +static void do_versions_userdef(FileData *fd, BlendFileData *bfd) +{ + Main *bmain = bfd->main; + UserDef *user = bfd->user; + + if (user == NULL) return; + + if (bmain->versionfile < 267) { + + if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit")) + user->image_gpubuffer_limit = 10; + } +} static void do_versions(FileData *fd, Library *lib, Main *main) { @@ -8872,8 +8885,8 @@ static void do_versions(FileData *fd, Library *lib, Main *main) if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 5)) { Scene *scene; - Image *image, *nimage; - Tex *tex, *otex; + Image *image; + Tex *tex; bNodeTreeType *ntreetype; bNodeTree *ntree; @@ -8920,67 +8933,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main) else { BKE_image_alpha_mode_from_extension(image); } - - image->flag &= ~IMA_DONE_TAG; } - /* use alpha flag moved from texture to image datablock */ for (tex = main->tex.first; tex; tex = tex->id.next) { if (tex->type == TEX_IMAGE && (tex->imaflag & TEX_USEALPHA) == 0) { image = blo_do_versions_newlibadr(fd, tex->id.lib, tex->ima); - /* skip if no image or already tested */ - if (!image || (image->flag & (IMA_DONE_TAG|IMA_IGNORE_ALPHA))) - continue; - - image->flag |= IMA_DONE_TAG; - - /* we might have some textures using alpha and others not, so we check if - * they exist and duplicate the image datablock if necessary */ - for (otex = main->tex.first; otex; otex = otex->id.next) - if (otex->type == TEX_IMAGE && (otex->imaflag & TEX_USEALPHA)) - if (image == blo_do_versions_newlibadr(fd, otex->id.lib, otex->ima)) - break; - - /* no duplication if the texture and image datablock are not - * from the same .blend file, the image datablock may not have - * been loaded from a library file otherwise */ - if (otex && (tex->id.lib == image->id.lib)) { - /* copy image datablock */ - nimage = BKE_image_copy(main, image); - nimage->flag |= IMA_IGNORE_ALPHA|IMA_DONE_TAG; - nimage->id.us--; - - /* we need to do some trickery to make file loading think - * this new datablock is part of file we're loading */ - blo_do_versions_oldnewmap_insert(fd->libmap, nimage, nimage, 0); - nimage->id.lib = image->id.lib; - nimage->id.flag |= (image->id.flag & LIB_NEED_LINK); - - /* assign new image, and update the users counts accordingly */ - for (otex = main->tex.first; otex; otex = otex->id.next) { - if (otex->type == TEX_IMAGE && (otex->imaflag & TEX_USEALPHA) == 0) { - if (image == blo_do_versions_newlibadr(fd, otex->id.lib, otex->ima)) { - if (!(otex->id.flag & LIB_NEED_LINK)) { - image->id.us--; - nimage->id.us++; - } - otex->ima = nimage; - break; - } - } - } - } - else { - /* no other textures using alpha, just set the flag */ + if (image && (image->flag & IMA_DO_PREMUL) == 0) image->flag |= IMA_IGNORE_ALPHA; - } } } - for (image = main->image.first; image; image = image->id.next) - image->flag &= ~IMA_DONE_TAG; - ntreetype = ntreeGetType(NTREE_COMPOSIT); if (ntreetype && ntreetype->foreach_nodetree) ntreetype->foreach_nodetree(main, fd, do_version_node_straight_image_alpha_workaround); @@ -8988,6 +8951,15 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) do_version_node_straight_image_alpha_workaround(fd, NULL, ntree); } + else if (main->versionfile < 266 || (main->versionfile == 266 && main->subversionfile < 1)) { + /* texture use alpha was removed for 2.66 but added back again for 2.66a, + * for compatibility all textures assumed it to be enabled */ + Tex *tex; + + for (tex = main->tex.first; tex; tex = tex->id.next) + if (tex->type == TEX_IMAGE) + tex->imaflag |= TEX_USEALPHA; + } if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) { Curve *cu; @@ -9024,14 +8996,14 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if (!MAIN_VERSION_ATLEAST(main, 265, 8)) { + if (MAIN_VERSION_OLDER(main, 265, 9)) { Mesh *me; for (me = main->mesh.first; me; me = me->id.next) { BKE_mesh_do_versions_cd_flag_init(me); } } - if (!MAIN_VERSION_ATLEAST(main, 265, 9)) { + if (MAIN_VERSION_OLDER(main, 265, 10)) { Brush *br; for (br = main->brush.first; br; br = br->id.next) { if (br->ob_mode & OB_MODE_TEXTURE_PAINT) { @@ -9041,7 +9013,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } // add storage for compositor translate nodes when not existing - if (!MAIN_VERSION_ATLEAST(main, 265, 10)) { + if (MAIN_VERSION_OLDER(main, 265, 11)) { bNodeTreeType *ntreetype; bNodeTree *ntree; @@ -9053,8 +9025,17 @@ static void do_versions(FileData *fd, Library *lib, Main *main) do_version_node_fix_translate_wrapping(NULL, NULL, ntree); } - // if (main->versionfile < 265 || (main->versionfile == 265 && main->subversionfile < 7)) { - + if (main->versionfile < 267) { + + /* TIP: to initialize new variables added, use the new function + DNA_struct_elem_find(fd->filesdna, "structname", "typename", "varname") + example: + if (!DNA_struct_elem_find(fd->filesdna, "UserDef", "short", "image_gpubuffer_limit")) + user->image_gpubuffer_limit = 10; + */ + + } + #ifdef WITH_FREESTYLE /* default values in Freestyle settings */ { @@ -9155,7 +9136,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) #endif /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ - /* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */ + /* WATCH IT 2!: Userdef struct init see do_versions_userdef() above! */ /* don't forget to set version number in blender.c! */ } @@ -9355,9 +9336,11 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath) } /* do before read_libraries, but skip undo case */ -// if (fd->memfile==NULL) (the mesh shuffle hacks don't work yet? ton) + if (fd->memfile==NULL) do_versions(fd, NULL, bfd->main); + do_versions_userdef(fd, bfd); + read_libraries(fd, &mainlist); blo_join_main(&mainlist); @@ -10806,7 +10789,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) PackedFile *pf = mainptr->curlib->packedfile; BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read packed library: '%s'"), - mainptr->curlib->name); + mainptr->curlib->name); fd = blo_openblendermemory(pf->data, pf->size, basefd->reports); @@ -10814,9 +10797,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) BLI_strncpy(fd->relabase, mainptr->curlib->filepath, sizeof(fd->relabase)); } else { - BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"), - mainptr->curlib->filepath, mainptr->curlib->name); - fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports); + BKE_reportf_wrap(basefd->reports, RPT_INFO, TIP_("Read library: '%s', '%s'"), + mainptr->curlib->filepath, mainptr->curlib->name); + fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports); } /* allow typing in a new lib path */ if (G.debug_value == -666) { @@ -10831,7 +10814,7 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) if (scanf("%s", newlib_path) > 0) { BLI_strncpy(mainptr->curlib->name, newlib_path, sizeof(mainptr->curlib->name)); BLI_strncpy(mainptr->curlib->filepath, newlib_path, sizeof(mainptr->curlib->filepath)); - cleanup_path(G.main->name, mainptr->curlib->filepath); + BLI_cleanup_path(G.main->name, mainptr->curlib->filepath); fd = blo_openblenderfile(mainptr->curlib->filepath, basefd->reports); @@ -10863,7 +10846,9 @@ static void read_libraries(FileData *basefd, ListBase *mainlist) /* subversion */ read_file_version(fd, mainptr); } - else mainptr->curlib->filedata = NULL; + else { + mainptr->curlib->filedata = NULL; + } if (fd == NULL) { BKE_reportf_wrap(basefd->reports, RPT_WARNING, TIP_("Cannot find lib '%s'"), diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index f4d841fd22a..36f3ea3654c 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -480,7 +480,7 @@ static void versions_gpencil_add_main(ListBase *lb, ID *id, const char *name) *( (short *)id->name )= ID_GD; new_id(lb, id, name); - /* alphabetic insterion: is in new_id */ + /* alphabetic insertion: is in new_id */ if (G.debug & G_DEBUG) printf("Converted GPencil to ID: %s\n", id->name + 2); diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 65a60e11ab3..0fba8c4b2ab 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1547,7 +1547,9 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) else if (sbuts->mainb == BUTS_EDIT) { sbuts->mainb = CONTEXT_EDITING; } - else sbuts->mainb = CONTEXT_SCENE; + else { + sbuts->mainb = CONTEXT_SCENE; + } } } } @@ -2550,7 +2552,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *main) if (main->subversionfile < 4) { for (sce = main->scene.first; sce; sce = sce->id.next) { sce->r.bake_mode = 1; /* prevent to include render stuff here */ - sce->r.bake_filter = 2; + sce->r.bake_filter = 16; sce->r.bake_osa = 5; sce->r.bake_flag = R_BAKE_CLEAR; } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 50e1e229eba..f9b8fbaca53 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -383,6 +383,17 @@ static void writedata(WriteData *wd, int filecode, int len, const void *adr) /* if (len) mywrite(wd, adr, len); } +/* use this to force writing of lists in same order as reading (using link_list) */ +static void writelist(WriteData *wd, int filecode, const char *structname, ListBase *lb) +{ + Link *link = lb->first; + + while (link) { + writestruct(wd, filecode, structname, 1, link); + link = link->next; + } +} + /* *************** writing some direct data structs used in more code parts **************** */ /*These functions are used by blender's .blend system for file saving/loading.*/ void IDP_WriteProperty_OnlyData(IDProperty *prop, void *wd); @@ -462,6 +473,9 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) { FModifier *fcm; + /* Write all modifiers first (for faster reloading) */ + writelist(wd, DATA, "FModifier", fmodifiers); + /* Modifiers */ for (fcm= fmodifiers->first; fcm; fcm= fcm->next) { FModifierTypeInfo *fmi= fmodifier_get_typeinfo(fcm); @@ -502,9 +516,6 @@ static void write_fmodifiers(WriteData *wd, ListBase *fmodifiers) break; } } - - /* Write the modifier */ - writestruct(wd, DATA, "FModifier", 1, fcm); } } @@ -512,10 +523,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) { FCurve *fcu; + writelist(wd, DATA, "FCurve", fcurves); for (fcu=fcurves->first; fcu; fcu=fcu->next) { - /* F-Curve */ - writestruct(wd, DATA, "FCurve", 1, fcu); - /* curve data */ if (fcu->bezt) writestruct(wd, DATA, "BezTriple", fcu->totvert, fcu->bezt); @@ -533,9 +542,8 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves) writestruct(wd, DATA, "ChannelDriver", 1, driver); /* variables */ - for (dvar= driver->variables.first; dvar; dvar= dvar->next) { - writestruct(wd, DATA, "DriverVar", 1, dvar); - + writelist(wd, DATA, "DriverVar", &driver->variables); + for (dvar= driver->variables.first; dvar; dvar= dvar->next) { DRIVER_TARGETS_USED_LOOPER(dvar) { if (dtar->rna_path) @@ -601,10 +609,8 @@ static void write_nlastrips(WriteData *wd, ListBase *strips) { NlaStrip *strip; + writelist(wd, DATA, "NlaStrip", strips); for (strip= strips->first; strip; strip= strip->next) { - /* write the strip first */ - writestruct(wd, DATA, "NlaStrip", 1, strip); - /* write the strip's F-Curves and modifiers */ write_fcurves(wd, &strip->fcurves); write_fmodifiers(wd, &strip->modifiers); @@ -801,14 +807,15 @@ typedef struct RenderInfo { static void write_renderinfo(WriteData *wd, Main *mainvar) { bScreen *curscreen; - Scene *sce; + Scene *sce, *curscene = NULL; RenderInfo data; /* XXX in future, handle multiple windows with multiple screens? */ current_screen_compat(mainvar, &curscreen); - + if (curscreen) curscene = curscreen->scene; + for (sce= mainvar->scene.first; sce; sce= sce->id.next) { - if (sce->id.lib == NULL && (sce == curscreen->scene || (sce->r.scemode & R_BG_RENDER))) { + if (sce->id.lib == NULL && (sce == curscene || (sce->r.scemode & R_BG_RENDER))) { data.sfra = sce->r.sfra; data.efra = sce->r.efra; memset(data.scene_name, 0, sizeof(data.scene_name)); @@ -2354,16 +2361,16 @@ static void write_gpencils(WriteData *wd, ListBase *lb) writestruct(wd, ID_GD, "bGPdata", 1, gpd); /* write grease-pencil layers to file */ + writelist(wd, DATA, "bGPDlayer", &gpd->layers); for (gpl= gpd->layers.first; gpl; gpl= gpl->next) { - writestruct(wd, DATA, "bGPDlayer", 1, gpl); /* write this layer's frames to file */ + writelist(wd, DATA, "bGPDframe", &gpl->frames); for (gpf= gpl->frames.first; gpf; gpf= gpf->next) { - writestruct(wd, DATA, "bGPDframe", 1, gpf); /* write strokes */ + writelist(wd, DATA, "bGPDstroke", &gpf->strokes); for (gps= gpf->strokes.first; gps; gps= gps->next) { - writestruct(wd, DATA, "bGPDstroke", 1, gps); writestruct(wd, DATA, "bGPDspoint", gps->totpoints, gps->points); } } @@ -2594,7 +2601,7 @@ static void write_libraries(WriteData *wd, Main *main) /* to be able to restore quit.blend and temp saves, the packed blend has to be in undo buffers... */ /* XXX needs rethink, just like save UI in undo files now - would be nice to append things only for the] - quit.blend and temp saves */ + * quit.blend and temp saves */ if (foundone) { writestruct(wd, ID_LI, "Library", 1, main->curlib); @@ -3386,7 +3393,7 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL return 0; } - BLI_delete(tempname, 0, 0); + BLI_delete(tempname, false, false); } else if (-1==ret) { BKE_report(reports, RPT_ERROR, "Failed opening .gz file"); diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index bf719a5c790..c3ec5dd83b3 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -57,7 +57,6 @@ set(SRC operators/bmo_smooth_laplacian.c operators/bmo_symmetrize.c operators/bmo_subdivide.c - operators/bmo_subdivide.h operators/bmo_triangulate.c operators/bmo_unsubdivide.c operators/bmo_utils.c diff --git a/source/blender/bmesh/SConscript b/source/blender/bmesh/SConscript index fa6bdbcf26f..de839f7f6a6 100644 --- a/source/blender/bmesh/SConscript +++ b/source/blender/bmesh/SConscript @@ -34,16 +34,16 @@ sources += env.Glob('operators/*.c') sources += env.Glob('tools/*.c') incs = [ - './', - '../blenfont', - '../blenlib', - '../makesdna', - '../blenkernel', - '#/intern/guardedalloc', - '#/extern/bullet2/src', - '#/extern/rangetree', - '#/intern/opennl/extern' - ] + './', + '../blenfont', + '../blenlib', + '../makesdna', + '../blenkernel', + '#/intern/guardedalloc', + '#/extern/bullet2/src', + '#/extern/rangetree', + '#/intern/opennl/extern' + ] defs = [] diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 6dc0218da93..845785a26d7 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -252,6 +252,9 @@ enum { * not have functions clobber them */ }; +struct BPy_BMGeneric; +extern void bpy_bm_generic_invalidate(struct BPy_BMGeneric *self); + /* defines */ #define BM_ELEM_CD_GET_VOID_P(ele, offset) \ (assert(offset != -1), (void *)((char *)(ele)->head.data + (offset))) diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index 643e73e02b4..a11d45a7a5a 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -942,7 +942,7 @@ static bool disk_is_flagged(BMVert *v, int flag) */ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) { - BMFace *f, *newf; + BMFace *f, *f_new; #ifdef USE_BMESH_HOLES BMLoopList *lst; ListBase holes = {NULL, NULL}; @@ -1036,15 +1036,15 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) } /* create region face */ - newf = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL; - if (UNLIKELY(!newf || BMO_error_occurred(bm))) { + f_new = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL; + if (UNLIKELY(!f_new || BMO_error_occurred(bm))) { if (!BMO_error_occurred(bm)) err = N_("Invalid boundary region to join faces"); goto error; } /* copy over loop data */ - l_iter = l_first = BM_FACE_FIRST_LOOP(newf); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { BMLoop *l2 = l_iter->radial_next; @@ -1064,34 +1064,34 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) } } while ((l_iter = l_iter->next) != l_first); - BM_elem_attrs_copy(bm, bm, faces[0], newf); + BM_elem_attrs_copy(bm, bm, faces[0], f_new); #ifdef USE_BMESH_HOLES /* add holes */ - BLI_movelisttolist(&newf->loops, &holes); + BLI_movelisttolist(&f_new->loops, &holes); #endif /* update loop face pointer */ #ifdef USE_BMESH_HOLES - for (lst = newf->loops.first; lst; lst = lst->next) + for (lst = f_new->loops.first; lst; lst = lst->next) #endif { #ifdef USE_BMESH_HOLES l_iter = l_first = lst->first; #else - l_iter = l_first = BM_FACE_FIRST_LOOP(newf); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); #endif do { - l_iter->f = newf; + l_iter->f = f_new; } while ((l_iter = l_iter->next) != l_first); } bm_elements_systag_disable(faces, totface, _FLAG_JF); - BM_ELEM_API_FLAG_DISABLE(newf, _FLAG_JF); + BM_ELEM_API_FLAG_DISABLE(f_new, _FLAG_JF); /* handle multi-res data */ if (CustomData_has_layer(&bm->ldata, CD_MDISPS)) { - l_iter = l_first = BM_FACE_FIRST_LOOP(newf); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { for (i = 0; i < totface; i++) { BM_loop_interp_multires(bm, l_iter, faces[i]); @@ -1120,8 +1120,8 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) BLI_array_free(deledges); BLI_array_free(delverts); - BM_CHECK_ELEMENT(newf); - return newf; + BM_CHECK_ELEMENT(f_new); + return f_new; error: bm_elements_systag_disable(faces, totface, _FLAG_JF); @@ -1210,18 +1210,18 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMFace *f2; BMLoop *l_iter, *l_first; - BMLoop *v1loop = NULL, *v2loop = NULL, *f1loop = NULL, *f2loop = NULL; + BMLoop *l_v1 = NULL, *l_v2 = NULL, *l_f1 = NULL, *l_f2 = NULL; BMEdge *e; int i, len, f1len, f2len; /* verify that v1 and v2 are in face */ len = f->len; for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f); i < len; i++, l_iter = l_iter->next) { - if (l_iter->v == v1) v1loop = l_iter; - else if (l_iter->v == v2) v2loop = l_iter; + if (l_iter->v == v1) l_v1 = l_iter; + else if (l_iter->v == v2) l_v2 = l_iter; } - if (!v1loop || !v2loop) { + if (!l_v1 || !l_v2) { return NULL; } @@ -1229,28 +1229,28 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : 0); f2 = bm_face_create__sfme(bm, f); - f1loop = bm_loop_create(bm, v2, e, f, v2loop, 0); - f2loop = bm_loop_create(bm, v1, e, f2, v1loop, 0); + l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0); + l_f2 = bm_loop_create(bm, v1, e, f2, l_v1, 0); - f1loop->prev = v2loop->prev; - f2loop->prev = v1loop->prev; - v2loop->prev->next = f1loop; - v1loop->prev->next = f2loop; + l_f1->prev = l_v2->prev; + l_f2->prev = l_v1->prev; + l_v2->prev->next = l_f1; + l_v1->prev->next = l_f2; - f1loop->next = v1loop; - f2loop->next = v2loop; - v1loop->prev = f1loop; - v2loop->prev = f2loop; + l_f1->next = l_v1; + l_f2->next = l_v2; + l_v1->prev = l_f1; + l_v2->prev = l_f2; #ifdef USE_BMESH_HOLES lst = f->loops.first; lst2 = f2->loops.first; - lst2->first = lst2->last = f2loop; - lst->first = lst->last = f1loop; + lst2->first = lst2->last = l_f2; + lst->first = lst->last = l_f1; #else /* find which of the faces the original first loop is in */ - l_iter = l_first = f1loop; + l_iter = l_first = l_f1; first_loop_f1 = 0; do { if (l_iter == f->l_first) @@ -1261,23 +1261,23 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, /* original first loop was in f1, find a suitable first loop for f2 * which is as similar as possible to f1. the order matters for tools * such as duplifaces. */ - if (f->l_first->prev == f1loop) - f2->l_first = f2loop->prev; - else if (f->l_first->next == f1loop) - f2->l_first = f2loop->next; + if (f->l_first->prev == l_f1) + f2->l_first = l_f2->prev; + else if (f->l_first->next == l_f1) + f2->l_first = l_f2->next; else - f2->l_first = f2loop; + f2->l_first = l_f2; } else { /* original first loop was in f2, further do same as above */ f2->l_first = f->l_first; - if (f->l_first->prev == f2loop) - f->l_first = f1loop->prev; - else if (f->l_first->next == f2loop) - f->l_first = f1loop->next; + if (f->l_first->prev == l_f2) + f->l_first = l_f1->prev; + else if (f->l_first->next == l_f2) + f->l_first = l_f1->next; else - f->l_first = f1loop; + f->l_first = l_f1; } #endif @@ -1293,8 +1293,8 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, } while ((l_iter = l_iter->next) != l_first); /* link up the new loops into the new edges radial */ - bmesh_radial_append(e, f1loop); - bmesh_radial_append(e, f2loop); + bmesh_radial_append(e, l_f1); + bmesh_radial_append(e, l_f2); f2->len = f2len; @@ -1306,7 +1306,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, f->len = f1len; - if (r_l) *r_l = f2loop; + if (r_l) *r_l = l_f2; #ifdef USE_BMESH_HOLES if (holes) { @@ -1349,77 +1349,77 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, */ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) { - BMLoop *nextl; - BMEdge *ne; - BMVert *nv, *ov; + BMLoop *l_next; + BMEdge *e_new; + BMVert *v_new, *v_old; int i, valence1 = 0, valence2 = 0; bool edok; BLI_assert(bmesh_vert_in_edge(e, tv) != false); - ov = bmesh_edge_other_vert_get(e, tv); + v_old = bmesh_edge_other_vert_get(e, tv); - valence1 = bmesh_disk_count(ov); + valence1 = bmesh_disk_count(v_old); valence2 = bmesh_disk_count(tv); - nv = BM_vert_create(bm, tv->co, tv, 0); - ne = BM_edge_create(bm, nv, tv, e, 0); + v_new = BM_vert_create(bm, tv->co, tv, 0); + e_new = BM_edge_create(bm, v_new, tv, e, 0); - bmesh_disk_edge_remove(ne, tv); - bmesh_disk_edge_remove(ne, nv); + bmesh_disk_edge_remove(e_new, tv); + bmesh_disk_edge_remove(e_new, v_new); /* remove e from tv's disk cycle */ bmesh_disk_edge_remove(e, tv); - /* swap out tv for nv in e */ - bmesh_edge_swapverts(e, tv, nv); + /* swap out tv for v_new in e */ + bmesh_edge_swapverts(e, tv, v_new); - /* add e to nv's disk cycle */ - bmesh_disk_edge_append(e, nv); + /* add e to v_new's disk cycle */ + bmesh_disk_edge_append(e, v_new); - /* add ne to nv's disk cycle */ - bmesh_disk_edge_append(ne, nv); + /* add e_new to v_new's disk cycle */ + bmesh_disk_edge_append(e_new, v_new); - /* add ne to tv's disk cycle */ - bmesh_disk_edge_append(ne, tv); + /* add e_new to tv's disk cycle */ + bmesh_disk_edge_append(e_new, tv); /* verify disk cycles */ - edok = bmesh_disk_validate(valence1, ov->e, ov); + edok = bmesh_disk_validate(valence1, v_old->e, v_old); BMESH_ASSERT(edok != false); edok = bmesh_disk_validate(valence2, tv->e, tv); BMESH_ASSERT(edok != false); - edok = bmesh_disk_validate(2, nv->e, nv); + edok = bmesh_disk_validate(2, v_new->e, v_new); BMESH_ASSERT(edok != false); /* Split the radial cycle if present */ - nextl = e->l; + l_next = e->l; e->l = NULL; - if (nextl) { - BMLoop *nl, *l; - int radlen = bmesh_radial_length(nextl); + if (l_next) { + BMLoop *l_new, *l; + int radlen = bmesh_radial_length(l_next); int first1 = 0, first2 = 0; /* Take the next loop. Remove it from radial. Split it. Append to appropriate radials */ - while (nextl) { - l = nextl; + while (l_next) { + l = l_next; l->f->len++; - nextl = nextl != nextl->radial_next ? nextl->radial_next : NULL; + l_next = l_next != l_next->radial_next ? l_next->radial_next : NULL; bmesh_radial_loop_remove(l, NULL); - nl = bm_loop_create(bm, NULL, NULL, l->f, l, 0); - nl->prev = l; - nl->next = (l->next); - nl->prev->next = nl; - nl->next->prev = nl; - nl->v = nv; + l_new = bm_loop_create(bm, NULL, NULL, l->f, l, 0); + l_new->prev = l; + l_new->next = (l->next); + l_new->prev->next = l_new; + l_new->next->prev = l_new; + l_new->v = v_new; /* assign the correct edge to the correct loop */ - if (bmesh_verts_in_edge(nl->v, nl->next->v, e)) { - nl->e = e; - l->e = ne; + if (bmesh_verts_in_edge(l_new->v, l_new->next->v, e)) { + l_new->e = e; + l->e = e_new; - /* append l into ne's rad cycle */ + /* append l into e_new's rad cycle */ if (!first1) { first1 = 1; l->radial_next = l->radial_prev = NULL; @@ -1430,14 +1430,14 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) l->radial_next = l->radial_prev = NULL; } - bmesh_radial_append(nl->e, nl); + bmesh_radial_append(l_new->e, l_new); bmesh_radial_append(l->e, l); } - else if (bmesh_verts_in_edge(nl->v, nl->next->v, ne)) { - nl->e = ne; + else if (bmesh_verts_in_edge(l_new->v, l_new->next->v, e_new)) { + l_new->e = e_new; l->e = e; - /* append l into ne's rad cycle */ + /* append l into e_new's rad cycle */ if (!first1) { first1 = 1; l->radial_next = l->radial_prev = NULL; @@ -1448,7 +1448,7 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) l->radial_next = l->radial_prev = NULL; } - bmesh_radial_append(nl->e, nl); + bmesh_radial_append(l_new->e, l_new); bmesh_radial_append(l->e, l); } @@ -1457,14 +1457,14 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) /* verify length of radial cycle */ edok = bmesh_radial_validate(radlen, e->l); BMESH_ASSERT(edok != false); - edok = bmesh_radial_validate(radlen, ne->l); + edok = bmesh_radial_validate(radlen, e_new->l); BMESH_ASSERT(edok != false); /* verify loop->v and loop->next->v pointers for e */ for (i = 0, l = e->l; i < radlen; i++, l = l->radial_next) { BMESH_ASSERT(l->e == e); //BMESH_ASSERT(l->radial_next == l); - BMESH_ASSERT(!(l->prev->e != ne && l->next->e != ne)); + BMESH_ASSERT(!(l->prev->e != e_new && l->next->e != e_new)); edok = bmesh_verts_in_edge(l->v, l->next->v, e); BMESH_ASSERT(edok != false); @@ -1477,12 +1477,12 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) BM_CHECK_ELEMENT(l->e); BM_CHECK_ELEMENT(l->f); } - /* verify loop->v and loop->next->v pointers for ne */ - for (i = 0, l = ne->l; i < radlen; i++, l = l->radial_next) { - BMESH_ASSERT(l->e == ne); + /* verify loop->v and loop->next->v pointers for e_new */ + for (i = 0, l = e_new->l; i < radlen; i++, l = l->radial_next) { + BMESH_ASSERT(l->e == e_new); // BMESH_ASSERT(l->radial_next == l); BMESH_ASSERT(!(l->prev->e != e && l->next->e != e)); - edok = bmesh_verts_in_edge(l->v, l->next->v, ne); + edok = bmesh_verts_in_edge(l->v, l->next->v, e_new); BMESH_ASSERT(edok != false); BMESH_ASSERT(l->v != l->next->v); BMESH_ASSERT(l->e != l->next->e); @@ -1494,20 +1494,20 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) } } - BM_CHECK_ELEMENT(ne); - BM_CHECK_ELEMENT(nv); - BM_CHECK_ELEMENT(ov); + BM_CHECK_ELEMENT(e_new); + BM_CHECK_ELEMENT(v_new); + BM_CHECK_ELEMENT(v_old); BM_CHECK_ELEMENT(e); BM_CHECK_ELEMENT(tv); - if (r_e) *r_e = ne; - return nv; + if (r_e) *r_e = e_new; + return v_new; } /** * \brief Join Edge Kill Vert (JEKV) * - * Takes an edge \a ke and pointer to one of its vertices \a kv + * Takes an edge \a e_kill and pointer to one of its vertices \a v_kill * and collapses the edge on that vertex. * * \par Examples: @@ -1535,25 +1535,25 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) * faces with just 2 edges. It is up to the caller to decide what to do with * these faces. */ -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_double) +BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_edge_double) { - BMEdge *oe; - BMVert *ov, *tv; - BMLoop *killoop, *l; + BMEdge *e_old; + BMVert *v_old, *tv; + BMLoop *l_kill, *l; int len, radlen = 0, i, valence1, valence2; bool edok, halt = false; - if (bmesh_vert_in_edge(ke, kv) == 0) { + if (bmesh_vert_in_edge(e_kill, v_kill) == 0) { return NULL; } - len = bmesh_disk_count(kv); + len = bmesh_disk_count(v_kill); if (len == 2) { - oe = bmesh_disk_edge_next(ke, kv); - tv = bmesh_edge_other_vert_get(ke, kv); - ov = bmesh_edge_other_vert_get(oe, kv); - halt = bmesh_verts_in_edge(kv, tv, oe); /* check for double edges */ + e_old = bmesh_disk_edge_next(e_kill, v_kill); + tv = bmesh_edge_other_vert_get(e_kill, v_kill); + v_old = bmesh_edge_other_vert_get(e_old, v_kill); + halt = bmesh_verts_in_edge(v_kill, tv, e_old); /* check for double edges */ if (halt) { return NULL; @@ -1561,56 +1561,56 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_doub else { BMEdge *e_splice; - /* For verification later, count valence of ov and tv */ - valence1 = bmesh_disk_count(ov); + /* For verification later, count valence of v_old and tv */ + valence1 = bmesh_disk_count(v_old); valence2 = bmesh_disk_count(tv); if (check_edge_double) { - e_splice = BM_edge_exists(tv, ov); + e_splice = BM_edge_exists(tv, v_old); } - /* remove oe from kv's disk cycle */ - bmesh_disk_edge_remove(oe, kv); - /* relink oe->kv to be oe->tv */ - bmesh_edge_swapverts(oe, kv, tv); - /* append oe to tv's disk cycle */ - bmesh_disk_edge_append(oe, tv); - /* remove ke from tv's disk cycle */ - bmesh_disk_edge_remove(ke, tv); - - /* deal with radial cycle of ke */ - radlen = bmesh_radial_length(ke->l); - if (ke->l) { - /* first step, fix the neighboring loops of all loops in ke's radial cycle */ - for (i = 0, killoop = ke->l; i < radlen; i++, killoop = killoop->radial_next) { + /* remove e_old from v_kill's disk cycle */ + bmesh_disk_edge_remove(e_old, v_kill); + /* relink e_old->v_kill to be e_old->tv */ + bmesh_edge_swapverts(e_old, v_kill, tv); + /* append e_old to tv's disk cycle */ + bmesh_disk_edge_append(e_old, tv); + /* remove e_kill from tv's disk cycle */ + bmesh_disk_edge_remove(e_kill, tv); + + /* deal with radial cycle of e_kill */ + radlen = bmesh_radial_length(e_kill->l); + if (e_kill->l) { + /* first step, fix the neighboring loops of all loops in e_kill's radial cycle */ + for (i = 0, l_kill = e_kill->l; i < radlen; i++, l_kill = l_kill->radial_next) { /* relink loops and fix vertex pointer */ - if (killoop->next->v == kv) { - killoop->next->v = tv; + if (l_kill->next->v == v_kill) { + l_kill->next->v = tv; } - killoop->next->prev = killoop->prev; - killoop->prev->next = killoop->next; - if (BM_FACE_FIRST_LOOP(killoop->f) == killoop) { - BM_FACE_FIRST_LOOP(killoop->f) = killoop->next; + l_kill->next->prev = l_kill->prev; + l_kill->prev->next = l_kill->next; + if (BM_FACE_FIRST_LOOP(l_kill->f) == l_kill) { + BM_FACE_FIRST_LOOP(l_kill->f) = l_kill->next; } - killoop->next = NULL; - killoop->prev = NULL; + l_kill->next = NULL; + l_kill->prev = NULL; /* fix len attribute of face */ - killoop->f->len--; + l_kill->f->len--; } - /* second step, remove all the hanging loops attached to ke */ - radlen = bmesh_radial_length(ke->l); + /* second step, remove all the hanging loops attached to e_kill */ + radlen = bmesh_radial_length(e_kill->l); if (LIKELY(radlen)) { BMLoop **loops = BLI_array_alloca(loops, radlen); - killoop = ke->l; + l_kill = e_kill->l; /* this should be wrapped into a bme_free_radial function to be used by bmesh_KF as well... */ for (i = 0; i < radlen; i++) { - loops[i] = killoop; - killoop = killoop->radial_next; + loops[i] = l_kill; + l_kill = l_kill->radial_next; } for (i = 0; i < radlen; i++) { bm->totloop--; @@ -1618,27 +1618,27 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_doub } } - /* Validate radial cycle of oe */ - edok = bmesh_radial_validate(radlen, oe->l); + /* Validate radial cycle of e_old */ + edok = bmesh_radial_validate(radlen, e_old->l); BMESH_ASSERT(edok != false); } /* deallocate edge */ - bm_kill_only_edge(bm, ke); + bm_kill_only_edge(bm, e_kill); /* deallocate vertex */ - bm_kill_only_vert(bm, kv); + bm_kill_only_vert(bm, v_kill); - /* Validate disk cycle lengths of ov, tv are unchanged */ - edok = bmesh_disk_validate(valence1, ov->e, ov); + /* Validate disk cycle lengths of v_old, tv are unchanged */ + edok = bmesh_disk_validate(valence1, v_old->e, v_old); BMESH_ASSERT(edok != false); edok = bmesh_disk_validate(valence2, tv->e, tv); BMESH_ASSERT(edok != false); - /* Validate loop cycle of all faces attached to 'oe' */ - for (i = 0, l = oe->l; i < radlen; i++, l = l->radial_next) { - BMESH_ASSERT(l->e == oe); - edok = bmesh_verts_in_edge(l->v, l->next->v, oe); + /* Validate loop cycle of all faces attached to 'e_old' */ + for (i = 0, l = e_old->l; i < radlen; i++, l = l->radial_next) { + BMESH_ASSERT(l->e == e_old); + edok = bmesh_verts_in_edge(l->v, l->next->v, e_old); BMESH_ASSERT(edok != false); edok = bmesh_loop_validate(l->f); BMESH_ASSERT(edok != false); @@ -1652,15 +1652,15 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_doub if (check_edge_double) { if (e_splice) { /* removes e_splice */ - BM_edge_splice(bm, e_splice, oe); + BM_edge_splice(bm, e_splice, e_old); } } - BM_CHECK_ELEMENT(ov); + BM_CHECK_ELEMENT(v_old); BM_CHECK_ELEMENT(tv); - BM_CHECK_ELEMENT(oe); + BM_CHECK_ELEMENT(e_old); - return oe; + return e_old; } } return NULL; @@ -1699,9 +1699,9 @@ BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_doub */ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) { - BMLoop *l_iter, *f1loop = NULL, *f2loop = NULL; - int newlen = 0, i, f1len = 0, f2len = 0, edok; - + BMLoop *l_iter, *l_f1 = NULL, *l_f2 = NULL; + int newlen = 0, i, f1len = 0, f2len = 0; + bool edok; /* can't join a face to itself */ if (f1 == f2) { return NULL; @@ -1716,23 +1716,23 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) f1len = f1->len; f2len = f2->len; - if (!((f1loop = BM_face_edge_share_loop(f1, e)) && - (f2loop = BM_face_edge_share_loop(f2, e)))) + if (!((l_f1 = BM_face_edge_share_loop(f1, e)) && + (l_f2 = BM_face_edge_share_loop(f2, e)))) { return NULL; } /* validate direction of f2's loop cycle is compatible */ - if (f1loop->v == f2loop->v) { + if (l_f1->v == l_f2->v) { return NULL; } /* validate that for each face, each vertex has another edge in its disk cycle that is * not e, and not shared. */ - if (bmesh_radial_face_find(f1loop->next->e, f2) || - bmesh_radial_face_find(f1loop->prev->e, f2) || - bmesh_radial_face_find(f2loop->next->e, f1) || - bmesh_radial_face_find(f2loop->prev->e, f1) ) + if (bmesh_radial_face_find(l_f1->next->e, f2) || + bmesh_radial_face_find(l_f1->prev->e, f2) || + bmesh_radial_face_find(l_f2->next->e, f1) || + bmesh_radial_face_find(l_f2->prev->e, f1) ) { return NULL; } @@ -1751,12 +1751,12 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) } for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f1); i < f1len; i++, l_iter = l_iter->next) { - if (l_iter != f1loop) { + if (l_iter != l_f1) { BM_elem_flag_enable(l_iter->v, BM_ELEM_INTERNAL_TAG); } } for (i = 0, l_iter = BM_FACE_FIRST_LOOP(f2); i < f2len; i++, l_iter = l_iter->next) { - if (l_iter != f2loop) { + if (l_iter != l_f2) { /* as soon as a duplicate is found, bail out */ if (BM_elem_flag_test(l_iter->v, BM_ELEM_INTERNAL_TAG)) { return NULL; @@ -1765,15 +1765,15 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) } /* join the two loop */ - f1loop->prev->next = f2loop->next; - f2loop->next->prev = f1loop->prev; + l_f1->prev->next = l_f2->next; + l_f2->next->prev = l_f1->prev; - f1loop->next->prev = f2loop->prev; - f2loop->prev->next = f1loop->next; + l_f1->next->prev = l_f2->prev; + l_f2->prev->next = l_f1->next; - /* if f1loop was baseloop, make f1loop->next the base. */ - if (BM_FACE_FIRST_LOOP(f1) == f1loop) - BM_FACE_FIRST_LOOP(f1) = f1loop->next; + /* if l_f1 was baseloop, make l_f1->next the base. */ + if (BM_FACE_FIRST_LOOP(f1) == l_f1) + BM_FACE_FIRST_LOOP(f1) = l_f1->next; /* increase length of f1 */ f1->len += (f2->len - 2); @@ -1784,18 +1784,18 @@ BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e) l_iter->f = f1; /* remove edge from the disk cycle of its two vertices */ - bmesh_disk_edge_remove(f1loop->e, f1loop->e->v1); - bmesh_disk_edge_remove(f1loop->e, f1loop->e->v2); + bmesh_disk_edge_remove(l_f1->e, l_f1->e->v1); + bmesh_disk_edge_remove(l_f1->e, l_f1->e->v2); /* deallocate edge and its two loops as well as f2 */ if (bm->etoolflagpool) { - BLI_mempool_free(bm->etoolflagpool, f1loop->e->oflags); + BLI_mempool_free(bm->etoolflagpool, l_f1->e->oflags); } - BLI_mempool_free(bm->epool, f1loop->e); + BLI_mempool_free(bm->epool, l_f1->e); bm->totedge--; - BLI_mempool_free(bm->lpool, f1loop); + BLI_mempool_free(bm->lpool, l_f1); bm->totloop--; - BLI_mempool_free(bm->lpool, f2loop); + BLI_mempool_free(bm->lpool, l_f2); bm->totloop--; if (bm->ftoolflagpool) { BLI_mempool_free(bm->ftoolflagpool, f2->oflags); @@ -1889,7 +1889,7 @@ bool bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len BMLoop *l; BMEdge *e; int i, maxindex; - BMLoop *nl; + BMLoop *l_new; visithash = BLI_ghash_ptr_new(__func__); @@ -1908,9 +1908,9 @@ bool bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len BLI_ghash_insert(visithash, e, SET_INT_IN_POINTER(maxindex)); BM_ITER_ELEM (l, &liter, e, BM_LOOPS_OF_EDGE) { - nl = (l->v == v) ? l->prev : l->next; - if (!BLI_ghash_haskey(visithash, nl->e)) { - BLI_array_append(stack, nl->e); + l_new = (l->v == v) ? l->prev : l->next; + if (!BLI_ghash_haskey(visithash, l_new->e)) { + BLI_array_append(stack, l_new->e); } } } @@ -2072,7 +2072,7 @@ bool BM_edge_splice(BMesh *bm, BMEdge *e, BMEdge *e_target) */ bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) { - BMEdge *ne; + BMEdge *e_new; int radlen; BLI_assert(l_sep->e == e); @@ -2088,15 +2088,15 @@ bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) e->l = l_sep->radial_next; } - ne = BM_edge_create(bm, e->v1, e->v2, e, 0); + e_new = BM_edge_create(bm, e->v1, e->v2, e, 0); bmesh_radial_loop_remove(l_sep, e); - bmesh_radial_append(ne, l_sep); - l_sep->e = ne; + bmesh_radial_append(e_new, l_sep); + l_sep->e = e_new; BLI_assert(bmesh_radial_length(e->l) == radlen - 1); - BLI_assert(bmesh_radial_length(ne->l) == 1); + BLI_assert(bmesh_radial_length(e_new->l) == 1); - BM_CHECK_ELEMENT(ne); + BM_CHECK_ELEMENT(e_new); BM_CHECK_ELEMENT(e); return true; @@ -2105,57 +2105,57 @@ bool bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep) /** * \brief Un-glue Region Make Vert (URMV) * - * Disconnects a face from its vertex fan at loop \a sl + * Disconnects a face from its vertex fan at loop \a l_sep * * \return The newly created BMVert */ -BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) +BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep) { BMVert **vtar; int len, i; - BMVert *nv = NULL; - BMVert *sv = sl->v; + BMVert *v_new = NULL; + BMVert *v_sep = l_sep->v; /* peel the face from the edge radials on both sides of the * loop vert, disconnecting the face from its fan */ - bmesh_edge_separate(bm, sl->e, sl); - bmesh_edge_separate(bm, sl->prev->e, sl->prev); + bmesh_edge_separate(bm, l_sep->e, l_sep); + bmesh_edge_separate(bm, l_sep->prev->e, l_sep->prev); - if (bmesh_disk_count(sv) == 2) { - /* If there are still only two edges out of sv, then + if (bmesh_disk_count(v_sep) == 2) { + /* If there are still only two edges out of v_sep, then * this whole URMV was just a no-op, so exit now. */ - return sv; + return v_sep; } /* Update the disk start, so that v->e points to an edge * not touching the split loop. This is so that BM_vert_split - * will leave the original sv on some *other* fan (not the + * will leave the original v_sep on some *other* fan (not the * one-face fan that holds the unglue face). */ - while (sv->e == sl->e || sv->e == sl->prev->e) { - sv->e = bmesh_disk_edge_next(sv->e, sv); + while (v_sep->e == l_sep->e || v_sep->e == l_sep->prev->e) { + v_sep->e = bmesh_disk_edge_next(v_sep->e, v_sep); } /* Split all fans connected to the vert, duplicating it for * each fans. */ - bmesh_vert_separate(bm, sv, &vtar, &len); + bmesh_vert_separate(bm, v_sep, &vtar, &len); /* There should have been at least two fans cut apart here, * otherwise the early exit would have kicked in. */ BLI_assert(len >= 2); - nv = sl->v; + v_new = l_sep->v; /* Desired result here is that a new vert should always be * created for the unglue face. This is so we can glue any * extras back into the original vert. */ - BLI_assert(nv != sv); - BLI_assert(sv == vtar[0]); + BLI_assert(v_new != v_sep); + BLI_assert(v_sep == vtar[0]); /* If there are more than two verts as a result, glue together * all the verts except the one this URMV intended to create */ if (len > 2) { for (i = 0; i < len; i++) { - if (vtar[i] == nv) { + if (vtar[i] == v_new) { break; } } @@ -2174,18 +2174,18 @@ BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl) MEM_freeN(vtar); - return nv; + return v_new; } /** * \brief Unglue Region Make Vert (URMV) * - * Disconnects sf from the vertex fan at \a sv + * Disconnects f_sep from the vertex fan at \a v_sep * * \return The newly created BMVert */ -BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv) +BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep) { - BMLoop *l = BM_face_vert_share_loop(sf, sv); + BMLoop *l = BM_face_vert_share_loop(f_sep, v_sep); return bmesh_urmv_loop(bm, l); } diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index d8cfc973394..a1f378aaa5d 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -73,9 +73,9 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, ); BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e); -BMEdge *bmesh_jekv(BMesh *bm, BMEdge *ke, BMVert *kv, const bool check_edge_splice); +BMEdge *bmesh_jekv(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool check_edge_splice); BMFace *bmesh_jfke(BMesh *bm, BMFace *f1, BMFace *f2, BMEdge *e); -BMVert *bmesh_urmv(BMesh *bm, BMFace *sf, BMVert *sv); -BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *sl); +BMVert *bmesh_urmv(BMesh *bm, BMFace *f_sep, BMVert *v_sep); +BMVert *bmesh_urmv_loop(BMesh *bm, BMLoop *l_sep); #endif /* __BMESH_CORE_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_interp.c b/source/blender/bmesh/intern/bmesh_interp.c index 44b8baace4c..d0ab0ea5d60 100644 --- a/source/blender/bmesh/intern/bmesh_interp.c +++ b/source/blender/bmesh/intern/bmesh_interp.c @@ -126,7 +126,7 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM { void *src[2]; float w[2]; - BMLoop *v1loop = NULL, *vloop = NULL, *v2loop = NULL; + BMLoop *l_v1 = NULL, *l_v = NULL, *l_v2 = NULL; BMLoop *l_iter = NULL; if (!e1->l) { @@ -139,23 +139,23 @@ void BM_data_interp_face_vert_edge(BMesh *bm, BMVert *v1, BMVert *UNUSED(v2), BM l_iter = e1->l; do { if (l_iter->v == v1) { - v1loop = l_iter; - vloop = v1loop->next; - v2loop = vloop->next; + l_v1 = l_iter; + l_v = l_v1->next; + l_v2 = l_v->next; } else if (l_iter->v == v) { - v1loop = l_iter->next; - vloop = l_iter; - v2loop = l_iter->prev; + l_v1 = l_iter->next; + l_v = l_iter; + l_v2 = l_iter->prev; } - if (!v1loop || !v2loop) + if (!l_v1 || !l_v2) return; - src[0] = v1loop->head.data; - src[1] = v2loop->head.data; + src[0] = l_v1->head.data; + src[1] = l_v2->head.data; - CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, vloop->head.data); + CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, l_v->head.data); } while ((l_iter = l_iter->radial_next) != e1->l); } diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index 36a5412e401..c7be4424a21 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -20,11 +20,11 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_mempool.h" -#include "BLI_utildefines.h" #include "BKE_customdata.h" diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 3c4fa490477..b9352a25063 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -247,8 +247,6 @@ void BM_mesh_free(BMesh *bm) if (bm->py_handle) { /* keep this out of 'BM_mesh_data_free' because we want python * to be able to clear the mesh and maintain access. */ - extern void bpy_bm_generic_invalidate(void *self); - bpy_bm_generic_invalidate(bm->py_handle); bm->py_handle = NULL; } diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 4c0c1507dbf..e0c8cb61900 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -782,7 +782,9 @@ void BM_mesh_bm_to_me(BMesh *bm, Mesh *me, bool do_tessface) hmd->indexar[j++] = BM_elem_index_get(eve); } } - else j++; + else { + j++; + } } hmd->totindex = j; diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index d98598cac89..afb3fc8112c 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -300,14 +300,14 @@ BMEdge *BM_verts_connect(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f) BM_ITER_ELEM (f_iter, &fiter, v1, BM_FACES_OF_VERT) { BM_ITER_ELEM (v_iter, &viter, f_iter, BM_FACES_OF_VERT) { if (v_iter == v2) { - BMLoop *nl; + BMLoop *l_new; - f_iter = BM_face_split(bm, f_iter, v1, v2, &nl, NULL, false); + f_iter = BM_face_split(bm, f_iter, v1, v2, &l_new, NULL, false); if (r_f) { *r_f = f_iter; } - return nl->e; + return l_new->e; } } } @@ -339,51 +339,51 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l BMEdge *example, const bool no_double) { const bool has_mdisp = CustomData_has_layer(&bm->ldata, CD_MDISPS); - BMFace *nf, *of; + BMFace *f_new, *f_tmp; BLI_assert(v1 != v2); /* do we have a multires layer? */ if (has_mdisp) { - of = BM_face_copy(bm, f, false, false); + f_tmp = BM_face_copy(bm, f, false, false); } #ifdef USE_BMESH_HOLES - nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, no_double); + f_new = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, no_double); #else - nf = bmesh_sfme(bm, f, v1, v2, r_l, example, no_double); + f_new = bmesh_sfme(bm, f, v1, v2, r_l, example, no_double); #endif - if (nf) { - BM_elem_attrs_copy(bm, bm, f, nf); - copy_v3_v3(nf->no, f->no); + if (f_new) { + BM_elem_attrs_copy(bm, bm, f, f_new); + copy_v3_v3(f_new->no, f->no); /* handle multires update */ - if (has_mdisp && (nf != f)) { + if (has_mdisp && (f_new != f)) { BMLoop *l_iter; BMLoop *l_first; l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { - BM_loop_interp_multires(bm, l_iter, of); + BM_loop_interp_multires(bm, l_iter, f_tmp); } while ((l_iter = l_iter->next) != l_first); - l_iter = l_first = BM_FACE_FIRST_LOOP(nf); + l_iter = l_first = BM_FACE_FIRST_LOOP(f_new); do { - BM_loop_interp_multires(bm, l_iter, of); + BM_loop_interp_multires(bm, l_iter, f_tmp); } while ((l_iter = l_iter->next) != l_first); - BM_face_kill(bm, of); + BM_face_kill(bm, f_tmp); #if 0 /* BM_face_multires_bounds_smooth doesn't flip displacement correct */ BM_face_multires_bounds_smooth(bm, f); - BM_face_multires_bounds_smooth(bm, nf); + BM_face_multires_bounds_smooth(bm, f_new); #endif } } - return nf; + return f_new; } /** @@ -406,62 +406,62 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[][3], int n, BMLoop **r_l, BMEdge *example) { - BMFace *nf, *of; + BMFace *f_new, *f_tmp; BMLoop *l_dummy; - BMEdge *e, *newe; - BMVert *newv; + BMEdge *e, *e_new; + BMVert *v_new; int i, j; BLI_assert(v1 != v2); - of = BM_face_copy(bm, f, true, true); + f_tmp = BM_face_copy(bm, f, true, true); if (!r_l) r_l = &l_dummy; #ifdef USE_BMESH_HOLES - nf = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, false); + f_new = bmesh_sfme(bm, f, v1, v2, r_l, NULL, example, false); #else - nf = bmesh_sfme(bm, f, v1, v2, r_l, example, false); + f_new = bmesh_sfme(bm, f, v1, v2, r_l, example, false); #endif - /* bmesh_sfme returns in r_l a Loop for nf going from v1 to v2. + /* bmesh_sfme returns in r_l a Loop for f_new going from v1 to v2. * The radial_next is for f and goes from v2 to v1 */ - if (nf) { - BM_elem_attrs_copy(bm, bm, f, nf); - copy_v3_v3(nf->no, f->no); + if (f_new) { + BM_elem_attrs_copy(bm, bm, f, f_new); + copy_v3_v3(f_new->no, f->no); e = (*r_l)->e; for (i = 0; i < n; i++) { - newv = bmesh_semv(bm, v2, e, &newe); - BLI_assert(newv != NULL); - /* bmesh_semv returns in newe the edge going from newv to tv */ - copy_v3_v3(newv->co, cos[i]); + v_new = bmesh_semv(bm, v2, e, &e_new); + BLI_assert(v_new != NULL); + /* bmesh_semv returns in e_new the edge going from v_new to tv */ + copy_v3_v3(v_new->co, cos[i]); - /* interpolate the loop data for the loops with (v == newv), using orig face */ + /* interpolate the loop data for the loops with (v == v_new), using orig face */ for (j = 0; j < 2; j++) { - BMEdge *e_iter = (j == 0) ? e : newe; + BMEdge *e_iter = (j == 0) ? e : e_new; BMLoop *l_iter = e_iter->l; do { - if (l_iter->v == newv) { + if (l_iter->v == v_new) { /* this interpolates both loop and vertex data */ - BM_loop_interp_from_face(bm, l_iter, of, true, true); + BM_loop_interp_from_face(bm, l_iter, f_tmp, true, true); } } while ((l_iter = l_iter->radial_next) != e_iter->l); } - e = newe; + e = e_new; } } - BM_face_verts_kill(bm, of); + BM_face_verts_kill(bm, f_tmp); - return nf; + return f_new; } /** * \brief Vert Collapse Faces * - * Collapses vertex \a kv that has only two manifold edges + * Collapses vertex \a v_kill that has only two manifold edges * onto a vertex it shares an edge with. * \a fac defines the amount of interpolation for Custom Data. * @@ -472,8 +472,8 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ * Except this takes a factor and merges custom data. * * \param bm The bmesh - * \param ke The edge to collapse - * \param kv The vertex to collapse into the edge + * \param e_kill The edge to collapse + * \param v_kill The vertex to collapse into the edge * \param fac The factor along the edge * \param join_faces When true the faces around the vertex will be joined * otherwise collapse the vertex by merging the 2 edges this vert touches into one. @@ -481,11 +481,11 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, float cos[ * * \returns The New Edge */ -BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, +BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, const bool join_faces, const bool kill_degenerate_faces) { - BMEdge *ne = NULL; - BMVert *tv = bmesh_edge_other_vert_get(ke, kv); + BMEdge *e_new = NULL; + BMVert *tv = bmesh_edge_other_vert_get(e_kill, v_kill); BMEdge *e2; BMVert *tv2; @@ -497,17 +497,17 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, float w[2]; /* Only intended to be called for 2-valence vertices */ - BLI_assert(bmesh_disk_count(kv) <= 2); + BLI_assert(bmesh_disk_count(v_kill) <= 2); /* first modify the face loop data */ w[0] = 1.0f - fac; w[1] = fac; - if (ke->l) { - l_iter = ke->l; + if (e_kill->l) { + l_iter = e_kill->l; do { - if (l_iter->v == tv && l_iter->next->v == kv) { + if (l_iter->v == tv && l_iter->next->v == v_kill) { tvloop = l_iter; kvloop = l_iter->next; @@ -515,30 +515,30 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, src[1] = tvloop->head.data; CustomData_bmesh_interp(&bm->ldata, src, w, NULL, 2, kvloop->head.data); } - } while ((l_iter = l_iter->radial_next) != ke->l); + } while ((l_iter = l_iter->radial_next) != e_kill->l); } /* now interpolate the vertex data */ - BM_data_interp_from_verts(bm, kv, tv, kv, fac); + BM_data_interp_from_verts(bm, v_kill, tv, v_kill, fac); - e2 = bmesh_disk_edge_next(ke, kv); - tv2 = BM_edge_other_vert(e2, kv); + e2 = bmesh_disk_edge_next(e_kill, v_kill); + tv2 = BM_edge_other_vert(e2, v_kill); if (join_faces) { BMFace **faces = NULL; BMFace *f; BLI_array_staticdeclare(faces, 8); - BM_ITER_ELEM (f, &iter, kv, BM_FACES_OF_VERT) { + BM_ITER_ELEM (f, &iter, v_kill, BM_FACES_OF_VERT) { BLI_array_append(faces, f); } if (BLI_array_count(faces) >= 2) { BMFace *f2 = BM_faces_join(bm, faces, BLI_array_count(faces), true); if (f2) { - BMLoop *nl = NULL; - if (BM_face_split(bm, f2, tv, tv2, &nl, NULL, false)) { - ne = nl->e; + BMLoop *l_new = NULL; + if (BM_face_split(bm, f2, tv, tv2, &l_new, NULL, false)) { + e_new = l_new->e; } } } @@ -549,16 +549,16 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, /* single face or no faces */ /* same as BM_vert_collapse_edge() however we already * have vars to perform this operation so don't call. */ - ne = bmesh_jekv(bm, ke, kv, true); - /* ne = BM_edge_exists(tv, tv2); */ /* same as return above */ + e_new = bmesh_jekv(bm, e_kill, v_kill, true); + /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */ - if (ne && kill_degenerate_faces) { + if (e_new && kill_degenerate_faces) { BLI_array_declare(bad_faces); BMFace **bad_faces = NULL; BMIter fiter; BMFace *f; - BMVert *verts[2] = {ne->v1, ne->v2}; + BMVert *verts[2] = {e_new->v1, e_new->v2}; int i; for (i = 0; i < 2; i++) { @@ -577,7 +577,7 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, } } - return ne; + return e_new; } @@ -588,37 +588,37 @@ BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, * * \return The New Edge */ -BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv, +BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool kill_degenerate_faces) { /* nice example implementation but we want loops to have their customdata * accounted for */ #if 0 - BMEdge *ne = NULL; + BMEdge *e_new = NULL; /* Collapse between 2 edges */ /* in this case we want to keep all faces and not join them, * rather just get rid of the vertex - see bug [#28645] */ - BMVert *tv = bmesh_edge_other_vert_get(ke, kv); + BMVert *tv = bmesh_edge_other_vert_get(e_kill, v_kill); if (tv) { - BMEdge *e2 = bmesh_disk_edge_next(ke, kv); + BMEdge *e2 = bmesh_disk_edge_next(e_kill, v_kill); if (e2) { - BMVert *tv2 = BM_edge_other_vert(e2, kv); + BMVert *tv2 = BM_edge_other_vert(e2, v_kill); if (tv2) { /* only action, other calls here only get the edge to return */ - ne = bmesh_jekv(bm, ke, kv); + e_new = bmesh_jekv(bm, e_kill, v_kill); - /* ne = BM_edge_exists(tv, tv2); */ /* same as return above */ + /* e_new = BM_edge_exists(tv, tv2); */ /* same as return above */ } } } - return ne; + return e_new; #else /* with these args faces are never joined, same as above * but account for loop customdata */ - return BM_vert_collapse_faces(bm, ke, kv, 1.0f, false, kill_degenerate_faces); + return BM_vert_collapse_faces(bm, e_kill, v_kill, 1.0f, false, kill_degenerate_faces); #endif } @@ -637,7 +637,7 @@ BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv, */ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float percent) { - BMVert *nv, *v2; + BMVert *v_new, *v2; BMFace **oldfaces = NULL; BMEdge *e_dummy; BLI_array_staticdeclare(oldfaces, 32); @@ -668,21 +668,21 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce } v2 = bmesh_edge_other_vert_get(e, v); - nv = bmesh_semv(bm, v, e, r_e); + v_new = bmesh_semv(bm, v, e, r_e); - BLI_assert(nv != NULL); + BLI_assert(v_new != NULL); - sub_v3_v3v3(nv->co, v2->co, v->co); - madd_v3_v3v3fl(nv->co, v->co, nv->co, percent); + sub_v3_v3v3(v_new->co, v2->co, v->co); + madd_v3_v3v3fl(v_new->co, v->co, v_new->co, percent); if (r_e) { (*r_e)->head.hflag = e->head.hflag; BM_elem_attrs_copy(bm, bm, e, *r_e); } - /* v->nv->v2 */ - BM_data_interp_face_vert_edge(bm, v2, v, nv, e, percent); - BM_data_interp_from_verts(bm, v, v2, nv, percent); + /* v->v_new->v2 */ + BM_data_interp_face_vert_edge(bm, v2, v, v_new, e, percent); + BM_data_interp_from_verts(bm, v, v2, v_new, percent); if (do_mdisp) { int i, j; @@ -742,7 +742,7 @@ BMVert *BM_edge_split(BMesh *bm, BMEdge *e, BMVert *v, BMEdge **r_e, float perce BLI_array_free(oldfaces); } - return nv; + return v_new; } /** @@ -752,13 +752,13 @@ BMVert *BM_edge_split_n(BMesh *bm, BMEdge *e, int numcuts) { int i; float percent; - BMVert *nv = NULL; + BMVert *v_new = NULL; for (i = 0; i < numcuts; i++) { percent = 1.0f / (float)(numcuts + 1 - i); - nv = BM_edge_split(bm, e, e->v2, NULL, percent); + v_new = BM_edge_split(bm, e, e->v2, NULL, percent); } - return nv; + return v_new; } #if 0 diff --git a/source/blender/bmesh/intern/bmesh_mods.h b/source/blender/bmesh/intern/bmesh_mods.h index 358268cb589..93d6ca10edb 100644 --- a/source/blender/bmesh/intern/bmesh_mods.h +++ b/source/blender/bmesh/intern/bmesh_mods.h @@ -47,9 +47,9 @@ BMFace *BM_face_split_n(BMesh *bm, BMFace *f, float cos[][3], int n, BMLoop **r_l, BMEdge *example); -BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *ke, BMVert *kv, float fac, +BMEdge *BM_vert_collapse_faces(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, float fac, const bool join_faces, const bool kill_degenerate_faces); -BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *ke, BMVert *kv, +BMEdge *BM_vert_collapse_edge(BMesh *bm, BMEdge *e_kill, BMVert *v_kill, const bool kill_degenerate_faces); diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index fd6571d136e..978aec0c610 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -451,7 +451,7 @@ typedef struct BMOIter { char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; -void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); +void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void *BMO_iter_new(BMOIter *iter, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 053d70349e8..0e1d4fec4d3 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -120,13 +120,13 @@ BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, BMO_slot_map_insert(op, slot, element, NULL, 0); } -BLI_INLINE int BMO_slot_map_contains(BMOpSlot *slot, const void *element) +BLI_INLINE bool BMO_slot_map_contains(BMOpSlot *slot, const void *element) { BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); /* sanity check */ if (UNLIKELY(slot->data.ghash == NULL)) { - return 0; + return false; } return BLI_ghash_haskey(slot->data.ghash, element); diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 00f8dbe06bf..f52dd7f2be9 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -1355,7 +1355,7 @@ static void bmo_flag_layer_clear(BMesh *bm) bm->elem_index_dirty &= ~(BM_VERT | BM_EDGE | BM_FACE); } -void *BMO_slot_buffer_elem_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) +void *BMO_slot_buffer_get_first(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); @@ -1521,7 +1521,7 @@ static int bmo_name_to_slotcode(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char int i = 0; while (slot_args->slot_name) { - if (strncmp(identifier, slot_args->slot_name, MAX_SLOTNAME) == 0) { + if (STREQLEN(identifier, slot_args->slot_name, MAX_SLOTNAME)) { return i; } slot_args++; @@ -1546,7 +1546,7 @@ static int bmo_opname_to_opcode(const char *opname) int i; for (i = 0; i < bmo_opdefines_total; i++) { - if (!strcmp(opname, bmo_opdefines[i]->opname)) { + if (STREQ(opname, bmo_opdefines[i]->opname)) { return i; } } diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index ea9ad2ed151..1aa4383d761 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -30,9 +30,6 @@ struct BMesh; struct BMOperator; -void BMO_push(BMesh *bm, BMOperator *op); -void BMO_pop(BMesh *bm); - void bmo_automerge_exec(BMesh *bm, BMOperator *op); void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op); void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 9592c34fc75..4041fc2c755 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -35,12 +35,17 @@ * degenerate faces. */ -#include "BLI_math.h" -#include "BLI_array.h" +#include "DNA_listBase.h" #include "MEM_guardedalloc.h" +#include "BLI_math.h" +#include "BLI_array.h" +#include "BLI_scanfill.h" +#include "BLI_listbase.h" + #include "bmesh.h" + #include "intern/bmesh_private.h" /** @@ -151,6 +156,103 @@ static void bm_face_calc_poly_normal_vertex_cos(BMFace *f, float n[3], } /** + * For tools that insist on using triangles, ideally we would cache this data. + * + * \param r_loops Store face loop pointers, (f->len) + * \param r_index Store triangle triples, indicies into \a r_loops, ((f->len - 2) * 3) + */ +int BM_face_calc_tessellation(BMFace *f, BMLoop **r_loops, int (*_r_index)[3]) +{ + int *r_index = (int *)_r_index; + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter; + int totfilltri; + + if (f->len == 3) { + *r_loops++ = (l_iter = l_first); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = ( l_iter->next); + + r_index[0] = 0; + r_index[1] = 1; + r_index[2] = 2; + totfilltri = 1; + } + else if (f->len == 4) { + *r_loops++ = (l_iter = l_first); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = (l_iter = l_iter->next); + *r_loops++ = ( l_iter->next); + + r_index[0] = 0; + r_index[1] = 1; + r_index[2] = 2; + + r_index[3] = 0; + r_index[4] = 2; + r_index[5] = 3; + totfilltri = 2; + } + else { + int j; + + ScanFillContext sf_ctx; + ScanFillVert *sf_vert, *sf_vert_last = NULL, *sf_vert_first = NULL; + /* ScanFillEdge *e; */ /* UNUSED */ + ScanFillFace *sf_tri; + + BLI_scanfill_begin(&sf_ctx); + + j = 0; + l_iter = l_first; + do { + sf_vert = BLI_scanfill_vert_add(&sf_ctx, l_iter->v->co); + sf_vert->tmp.p = l_iter; + + if (sf_vert_last) { + /* e = */ BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert); + } + + sf_vert_last = sf_vert; + if (sf_vert_first == NULL) { + sf_vert_first = sf_vert; + } + + r_loops[j] = l_iter; + + /* mark order */ + BM_elem_index_set(l_iter, j++); /* set_loop */ + + } while ((l_iter = l_iter->next) != l_first); + + /* complete the loop */ + BLI_scanfill_edge_add(&sf_ctx, sf_vert_first, sf_vert); + + totfilltri = BLI_scanfill_calc_ex(&sf_ctx, 0, f->no); + BLI_assert(totfilltri <= f->len - 2); + BLI_assert(totfilltri == BLI_countlist(&sf_ctx.fillfacebase)); + + for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { + int i1 = BM_elem_index_get((BMLoop *)sf_tri->v1->tmp.p); + int i2 = BM_elem_index_get((BMLoop *)sf_tri->v2->tmp.p); + int i3 = BM_elem_index_get((BMLoop *)sf_tri->v3->tmp.p); + + if (i1 > i2) { SWAP(int, i1, i2); } + if (i2 > i3) { SWAP(int, i2, i3); } + if (i1 > i2) { SWAP(int, i1, i2); } + + *r_index++ = i1; + *r_index++ = i2; + *r_index++ = i3; + } + + BLI_scanfill_end(&sf_ctx); + } + + return totfilltri; +} + +/** * get the area of the face */ float BM_face_calc_area(BMFace *f) diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index 601caae2337..c439a41f672 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -27,6 +27,12 @@ * \ingroup bmesh */ +int BM_face_calc_tessellation(BMFace *f, BMLoop **r_loops, int (*r_index)[3]) +#ifdef __GNUC__ + __attribute__((warn_unused_result)) + __attribute__((nonnull)) +#endif +; float BM_face_calc_area(BMFace *f); float BM_face_calc_perimeter(BMFace *f); void BM_face_calc_center_bounds(BMFace *f, float center[3]); diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 44dc483d5a7..26b0e42a1c1 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -680,7 +680,7 @@ bool BM_edge_is_wire(BMEdge *e) */ bool BM_vert_is_manifold(BMVert *v) { - BMEdge *e, *oe; + BMEdge *e, *e_old; BMLoop *l; int len, count, flag; @@ -691,7 +691,7 @@ bool BM_vert_is_manifold(BMVert *v) /* count edges while looking for non-manifold edges */ len = 0; - oe = e = v->e; + e_old = e = v->e; do { /* loose edge or edge shared by more than two faces, * edges with 1 face user are OK, otherwise we could @@ -700,14 +700,14 @@ bool BM_vert_is_manifold(BMVert *v) return false; } len++; - } while ((e = bmesh_disk_edge_next(e, v)) != oe); + } while ((e = bmesh_disk_edge_next(e, v)) != e_old); count = 1; flag = 1; e = NULL; - oe = v->e; - l = oe->l; - while (e != oe) { + e_old = v->e; + l = e_old->l; + while (e != e_old) { l = (l->v == v) ? l->prev : l->next; e = l->e; count++; /* count the edges */ @@ -716,13 +716,13 @@ bool BM_vert_is_manifold(BMVert *v) /* we've hit the edge of an open mesh, reset once */ flag = 0; count = 1; - oe = e; + e_old = e; e = NULL; - l = oe->l; + l = e_old->l; } else if (l->radial_next == l) { /* break the loop */ - e = oe; + e = e_old; } else { l = l->radial_next; @@ -769,9 +769,9 @@ int BM_edge_is_manifold(BMEdge *e) bool BM_edge_is_contiguous(BMEdge *e) { const BMLoop *l = e->l; - const BMLoop *l_other = l->radial_next; - return (l && (l_other != l) && /* not 0 or 1 face users */ - (l_other->radial_next == l) && /* 2 face users */ + const BMLoop *l_other; + return (l && ((l_other = l->radial_next) != l) && /* not 0 or 1 face users */ + (l_other->radial_next == l) && /* 2 face users */ (l_other->v != l->v)); } @@ -1352,6 +1352,8 @@ BMEdge *BM_edge_exists(BMVert *v1, BMVert *v2) BMIter iter; BMEdge *e; + BLI_assert(v1 != v2); + BM_ITER_ELEM (e, &iter, v1, BM_EDGES_OF_VERT) { if (e->v1 == v2 || e->v2 == v2) return e; @@ -1652,3 +1654,38 @@ bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag) } while ((l_iter = l_iter->next) != l_first); return false; } + +static void bm_mesh_calc_volume_face(BMFace *f, float *r_vol) +{ + int tottri = f->len - 2; + BMLoop **loops = BLI_array_alloca(loops, f->len); + int (*index)[3] = BLI_array_alloca(index, tottri); + int j; + + tottri = BM_face_calc_tessellation(f, loops, index); + BLI_assert(tottri <= f->len - 2); + + for (j = 0; j < tottri; j++) { + const float *p1 = loops[index[j][0]]->v->co; + const float *p2 = loops[index[j][1]]->v->co; + const float *p3 = loops[index[j][2]]->v->co; + + /* co1.dot(co2.cross(co3)) / 6.0 */ + float cross[3]; + cross_v3_v3v3(cross, p2, p3); + *r_vol += (1.0f / 6.0f) * dot_v3v3(p1, cross); + } +} +float BM_mesh_calc_volume(BMesh *bm) +{ + /* warning, calls own tessellation function, may be slow */ + float vol = 0.0f; + BMFace *f; + BMIter fiter; + + BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { + bm_mesh_calc_volume_face(f, &vol); + } + + return fabsf(vol); +} diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 7cb5749a4bf..f894912aad3 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -110,4 +110,6 @@ bool BM_edge_is_any_vert_flag_test(BMEdge *e, const char hflag); bool BM_face_is_any_vert_flag_test(BMFace *f, const char hflag); bool BM_face_is_any_edge_flag_test(BMFace *f, const char hflag); +float BM_mesh_calc_volume(BMesh *bm); + #endif /* __BMESH_QUERIES_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_structure.c b/source/blender/bmesh/intern/bmesh_structure.c index 2f568a498c5..0398f9c558f 100644 --- a/source/blender/bmesh/intern/bmesh_structure.c +++ b/source/blender/bmesh/intern/bmesh_structure.c @@ -63,15 +63,15 @@ BMVert *bmesh_edge_other_vert_get(BMEdge *e, BMVert *v) return NULL; } -bool bmesh_edge_swapverts(BMEdge *e, BMVert *orig, BMVert *newv) +bool bmesh_edge_swapverts(BMEdge *e, BMVert *v_orig, BMVert *v_new) { - if (e->v1 == orig) { - e->v1 = newv; + if (e->v1 == v_orig) { + e->v1 = v_new; e->v1_disk_link.next = e->v1_disk_link.prev = NULL; return true; } - else if (e->v2 == orig) { - e->v2 = newv; + else if (e->v2 == v_orig) { + e->v2 = v_new; e->v2_disk_link.next = e->v2_disk_link.prev = NULL; return true; } diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index ac6d4089372..a50b708961c 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -163,7 +163,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker) static void *bmw_ShellWalker_step(BMWalker *walker) { BMEdge *curedge, *next = NULL; - BMVert *ov = NULL; + BMVert *v_old = NULL; bool restrictpass = true; BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker)); @@ -183,7 +183,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker) { BMwShellWalker *newstate; - ov = BM_edge_other_vert(curedge, shellWalk.base); + v_old = BM_edge_other_vert(curedge, shellWalk.base); /* push a new state onto the stac */ newState = BMW_state_add(walker); @@ -191,7 +191,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker) /* populate the new stat */ - newState->base = ov; + newState->base = v_old; newState->curedge = curedge; } } diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 795531d6776..052ae9336ab 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -55,7 +55,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) } } - BM_mesh_bevel(bm, offset, seg, vonly, false, NULL, -1); + BM_mesh_bevel(bm, offset, seg, vonly, false, false, NULL, -1); BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); } diff --git a/source/blender/bmesh/operators/bmo_connect.c b/source/blender/bmesh/operators/bmo_connect.c index 9a17ebea38d..dc00d020083 100644 --- a/source/blender/bmesh/operators/bmo_connect.c +++ b/source/blender/bmesh/operators/bmo_connect.c @@ -44,10 +44,10 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) { BMIter iter, liter; - BMFace *f, *nf; + BMFace *f, *f_new; BMLoop *(*loops_split)[2] = NULL; BLI_array_declare(loops_split); - BMLoop *l, *nl, *lastl = NULL; + BMLoop *l, *l_new; BMVert *(*verts_pair)[2] = NULL; BLI_array_declare(verts_pair); int i; @@ -56,7 +56,8 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) /* BMESH_TODO, loop over vert faces: * faster then looping over all faces, then searching each for flagged verts*/ - for (f = BM_iter_new(&iter, bm, BM_FACES_OF_MESH, NULL); f; f = BM_iter_step(&iter)) { + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l_last; BLI_array_empty(loops_split); BLI_array_empty(verts_pair); @@ -64,22 +65,21 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) continue; } - l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f); - lastl = NULL; - for ( ; l; l = BM_iter_step(&liter)) { + l_last = NULL; + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { if (BMO_elem_flag_test(bm, l->v, VERT_INPUT)) { - if (!lastl) { - lastl = l; + if (!l_last) { + l_last = l; continue; } - if (lastl != l->prev && lastl != l->next) { + if (l_last != l->prev && l_last != l->next) { BLI_array_grow_one(loops_split); - loops_split[BLI_array_count(loops_split) - 1][0] = lastl; + loops_split[BLI_array_count(loops_split) - 1][0] = l_last; loops_split[BLI_array_count(loops_split) - 1][1] = l; } - lastl = l; + l_last = l; } } @@ -106,16 +106,16 @@ void bmo_connect_verts_exec(BMesh *bm, BMOperator *op) } for (i = 0; i < BLI_array_count(verts_pair); i++) { - nf = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &nl, NULL, false); - f = nf; + f_new = BM_face_split(bm, f, verts_pair[i][0], verts_pair[i][1], &l_new, NULL, false); + f = f_new; - if (!nl || !nf) { + if (!l_new || !f_new) { BMO_error_raise(bm, op, BMERR_CONNECTVERT_FAILED, NULL); BLI_array_free(loops_split); return; } - BMO_elem_flag_enable(bm, nf, FACE_NEW); - BMO_elem_flag_enable(bm, nl->e, EDGE_OUT); + BMO_elem_flag_enable(bm, f_new, FACE_NEW); + BMO_elem_flag_enable(bm, l_new->e, EDGE_OUT); } } @@ -160,19 +160,19 @@ static int clamp_index(const int x, const int len) * isn't there should be... */ #define ARRAY_SWAP(elemtype, arr1, arr2) \ { \ - int i; \ + int i_; \ elemtype *arr_tmp = NULL; \ BLI_array_declare(arr_tmp); \ - for (i = 0; i < BLI_array_count(arr1); i++) { \ - BLI_array_append(arr_tmp, arr1[i]); \ + for (i_ = 0; i_ < BLI_array_count(arr1); i_++) { \ + BLI_array_append(arr_tmp, arr1[i_]); \ } \ BLI_array_empty(arr1); \ - for (i = 0; i < BLI_array_count(arr2); i++) { \ - BLI_array_append(arr1, arr2[i]); \ + for (i_ = 0; i_ < BLI_array_count(arr2); i_++) { \ + BLI_array_append(arr1, arr2[i_]); \ } \ BLI_array_empty(arr2); \ - for (i = 0; i < BLI_array_count(arr_tmp); i++) { \ - BLI_array_append(arr2, arr_tmp[i]); \ + for (i_ = 0; i_ < BLI_array_count(arr_tmp); i_++) { \ + BLI_array_append(arr2, arr_tmp[i_]); \ } \ BLI_array_free(arr_tmp); \ } (void)0 @@ -228,8 +228,8 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { if (!BMO_elem_flag_test(bm, e, EDGE_DONE)) { - BMVert *v, *ov; - /* BMEdge *e2, *e3, *oe = e; */ /* UNUSED */ + BMVert *v, *v_old; + /* BMEdge *e2, *e3, *e_old = e; */ /* UNUSED */ BMEdge *e2, *e3; if (c > 2) { @@ -265,7 +265,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) e2 = e; e = e2; - ov = v; + v_old = v; do { if (c == 0) { BLI_array_append(ee1, e2); @@ -301,7 +301,7 @@ void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op) } /* test for connected loops, and set cl1 or cl2 if so */ - if (v == ov) { + if (v == v_old) { if (c == 0) { cl1 = 1; } diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index ae07c2cf0bc..9fab89f8e0a 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -26,12 +26,12 @@ #include "MEM_guardedalloc.h" -#include "BLI_heap.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_array.h" #include "BLI_smallhash.h" #include "BLI_rand.h" +#include "BLI_heap.h" #include "bmesh.h" @@ -810,9 +810,9 @@ static EPath *edge_find_shortest_path(BMesh *bm, BMOperator *op, BMEdge *edge, E } if (use_restrict) { - int *group = (int *)BMO_slot_map_data_get(slot_restrict, e); - if (group) { - if (!(*group & path->group)) { + int *group_flag = (int *)BMO_slot_map_data_get(slot_restrict, e); + if (group_flag) { + if (!(*group_flag & path->group)) { v2 = NULL; continue; } @@ -925,15 +925,12 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BMO_elem_flag_enable(bm, f, ELE_ORIG); } - i = 0; - BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { BM_elem_index_set(e, i); /* set_inline */ if (!BMO_elem_flag_test(bm, e, EDGE_MARK)) { edata[i].tag = 2; } - - i++; } bm->elem_index_dirty &= ~BM_EDGE; @@ -1491,6 +1488,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) if (use_smooth) { BM_elem_flag_enable(f, BM_ELEM_SMOOTH); } + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT); } MEM_freeN(vert_arr); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index 47b2497816f..a78a8ec5197 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -41,7 +41,7 @@ #define VERT_MARK 1 -static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f) +static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh *bm, BMFace *f) { BMWalker regwalker; BMIter liter2; @@ -75,11 +75,12 @@ static bool UNUSED_FUNCTION(check_hole_in_region) (BMesh * bm, BMFace * f) void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) { BMOIter oiter; - BMFace *f, *f2 /* , *nf = NULL */; + BMFace *f; BLI_array_declare(faces); BLI_array_declare(regions); BMFace ***regions = NULL; BMFace **faces = NULL; + BMFace *act_face = bm->act_face; BMWalker regwalker; int i; @@ -100,7 +101,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) /* collect region */ BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { - + BMFace *f_iter; if (!BMO_elem_flag_test(bm, f, FACE_MARK)) { continue; } @@ -113,15 +114,15 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) BMW_FLAG_NOP, /* no need to check BMW_FLAG_TEST_HIDDEN, faces are already marked by the bmo */ BMW_NIL_LAY); - for (f2 = BMW_begin(®walker, f); f2; f2 = BMW_step(®walker)) { - BLI_array_append(faces, f2); + for (f_iter = BMW_begin(®walker, f); f_iter; f_iter = BMW_step(®walker)) { + BLI_array_append(faces, f_iter); } BMW_end(®walker); for (i = 0; i < BLI_array_count(faces); i++) { - f2 = faces[i]; - BMO_elem_flag_disable(bm, f2, FACE_MARK); - BMO_elem_flag_enable(bm, f2, FACE_ORIG); + f_iter = faces[i]; + BMO_elem_flag_disable(bm, f_iter, FACE_MARK); + BMO_elem_flag_enable(bm, f_iter, FACE_ORIG); } if (BMO_error_occurred(bm)) { @@ -135,6 +136,7 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) } for (i = 0; i < BLI_array_count(regions); i++) { + BMFace *f_new; int tot = 0; faces = regions[i]; @@ -147,8 +149,15 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) while (faces[tot]) tot++; - f = BM_faces_join(bm, faces, tot, true); - if (!f) { + f_new = BM_faces_join(bm, faces, tot, true); + + if (f_new) { + /* maintain active face */ + if (act_face && bm->act_face == NULL) { + bm->act_face = f_new; + } + } + else { BMO_error_raise(bm, op, BMERR_DISSOLVEFACES_FAILED, "Could not create merged face"); goto cleanup; @@ -156,8 +165,8 @@ void bmo_dissolve_faces_exec(BMesh *bm, BMOperator *op) /* if making the new face failed (e.g. overlapping test) * unmark the original faces for deletion */ - BMO_elem_flag_disable(bm, f, FACE_ORIG); - BMO_elem_flag_enable(bm, f, FACE_NEW); + BMO_elem_flag_disable(bm, f_new, FACE_ORIG); + BMO_elem_flag_enable(bm, f_new, FACE_NEW); } @@ -196,23 +205,33 @@ cleanup: void bmo_dissolve_edgeloop_exec(BMesh *bm, BMOperator *op) { /* BMOperator fop; */ + BMFace *act_face = bm->act_face; BMOIter oiter; BMIter iter; BMVert *v, **verts = NULL; BLI_array_declare(verts); BMEdge *e; - BMFace *fa, *fb; int i; BMO_ITER (e, &oiter, op->slots_in, "edges", BM_EDGE) { + BMFace *fa, *fb; + if (BM_edge_face_pair(e, &fa, &fb)) { + BMFace *f_new; BMO_elem_flag_enable(bm, e->v1, VERT_MARK); BMO_elem_flag_enable(bm, e->v2, VERT_MARK); /* BMESH_TODO - check on delaying edge removal since we may end up removing more then * one edge, and later reference a removed edge */ - BM_faces_join_pair(bm, fa, fb, e, true); + f_new = BM_faces_join_pair(bm, fa, fb, e, true); + + if (f_new) { + /* maintain active face */ + if (act_face && bm->act_face == NULL) { + bm->act_face = f_new; + } + } } } @@ -245,9 +264,9 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) /* might want to make this an option or mode - campbell */ /* BMOperator fop; */ + BMFace *act_face = bm->act_face; BMOIter eiter; BMEdge *e; - BMIter viter; BMVert *v; @@ -263,12 +282,20 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) BMFace *fa, *fb; if (BM_edge_face_pair(e, &fa, &fb)) { + BMFace *f_new; /* join faces */ /* BMESH_TODO - check on delaying edge removal since we may end up removing more then * one edge, and later reference a removed edge */ - BM_faces_join_pair(bm, fa, fb, e, true); + f_new = BM_faces_join_pair(bm, fa, fb, e, true); + + if (f_new) { + /* maintain active face */ + if (act_face && bm->act_face == NULL) { + bm->act_face = f_new; + } + } } } @@ -285,34 +312,32 @@ void bmo_dissolve_edges_exec(BMesh *bm, BMOperator *op) static bool test_extra_verts(BMesh *bm, BMVert *v) { - BMIter iter, liter, iter2, iter3; - BMFace *f, *f2; + BMIter fiter, liter, eiter, fiter_sub; + BMFace *f; BMLoop *l; BMEdge *e; - bool found; /* test faces around verts for verts that would be wrongly killed * by dissolve faces. */ - f = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v); - for ( ; f; f = BM_iter_step(&iter)) { - l = BM_iter_new(&liter, bm, BM_LOOPS_OF_FACE, f); - for ( ; l; l = BM_iter_step(&liter)) { + BM_ITER_ELEM(f, &fiter, v, BM_FACES_OF_VERT) { + BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { if (!BMO_elem_flag_test(bm, l->v, VERT_MARK)) { /* if an edge around a vert is a boundary edge, * then dissolve faces won't destroy it. * also if it forms a boundary with one * of the face region */ - found = false; - e = BM_iter_new(&iter2, bm, BM_EDGES_OF_VERT, l->v); - for ( ; e; e = BM_iter_step(&iter2)) { + bool found = false; + BM_ITER_ELEM(e, &eiter, l->v, BM_EDGES_OF_VERT) { + BMFace *f_iter; if (BM_edge_is_boundary(e)) { found = true; } - f2 = BM_iter_new(&iter3, bm, BM_FACES_OF_EDGE, e); - for ( ; f2; f2 = BM_iter_step(&iter3)) { - if (!BMO_elem_flag_test(bm, f2, FACE_MARK)) { - found = true; - break; + else { + BM_ITER_ELEM(f_iter, &fiter_sub, e, BM_FACES_OF_EDGE) { + if (!BMO_elem_flag_test(bm, f_iter, FACE_MARK)) { + found = true; + break; + } } } if (found == true) { diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 4fde6150f05..62220510623 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -30,6 +30,7 @@ #include "BLI_math.h" #include "BLI_array.h" +#include "BLI_buffer.h" #include "BKE_customdata.h" @@ -271,7 +272,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMIter iter, fiter, viter; BMEdge *e, *e_new; - BMVert *v, *v2; + BMVert *v; BMFace *f; bool found, fwd, delorig = false; BMOpSlot *slot_facemap_out; @@ -441,7 +442,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) /* link isolated vert */ for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) { - v2 = *((void **)BMO_iter_map_value(&siter)); + BMVert *v2 = *((void **)BMO_iter_map_value(&siter)); BM_edge_create(bm, v, v2, v->e, BM_CREATE_NO_DOUBLE); } @@ -612,15 +613,18 @@ static void solidify_add_thickness(BMesh *bm, const float dist) float *vert_accum = vert_angles + bm->totvert; int i, index; + BLI_buffer_declare_static(float, face_angles_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BLI_buffer_declare_static(float *, verts_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BM_mesh_elem_index_ensure(bm, BM_VERT); BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { if (BMO_elem_flag_test(bm, f, FACE_MARK)) { /* array for passing verts to angle_poly_v3 */ - float *face_angles = BLI_array_alloca(face_angles, f->len); + float *face_angles = BLI_buffer_resize_data(&face_angles_buf, float, f->len); /* array for receiving angles from angle_poly_v3 */ - float **verts = BLI_array_alloca(verts, f->len); + float **verts = BLI_buffer_resize_data(&verts_buf, float *, f->len); BM_ITER_ELEM_INDEX (l, &loopIter, f, BM_LOOPS_OF_FACE, i) { verts[i] = l->v->co; @@ -639,6 +643,9 @@ static void solidify_add_thickness(BMesh *bm, const float dist) } } + BLI_buffer_free(&face_angles_buf); + BLI_buffer_free(&verts_buf); + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { index = BM_elem_index_get(v); if (vert_accum[index]) { /* zero if unselected */ diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 5e2404c9919..7dc2884c5ed 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -28,11 +28,11 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_array.h" #include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_utildefines.h" #include "Bullet-C-Api.h" diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 7beac676868..8b65764fe1c 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -40,7 +40,7 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot { BMIter liter; BMLoop *l; - BMVert *v2, *doub; + BMVert *v2, *v_double; bool split = false; BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { @@ -51,15 +51,15 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot (v2 != l->prev->v) && (v2 != l->next->v)) { - doub = l->v; + v_double = l->v; split = true; break; } } - if (split && doub != v2) { - BMLoop *nl; - BMFace *f2 = BM_face_split(bm, f, doub, v2, &nl, NULL, false); + if (split && v_double != v2) { + BMLoop *l_new; + BMFace *f2 = BM_face_split(bm, f, v_double, v2, &l_new, NULL, false); remdoubles_splitface(f, bm, op, slot_targetmap); remdoubles_splitface(f2, bm, op, slot_targetmap); diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index ba755a866de..6b91d5fded9 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -29,10 +29,10 @@ #include "DNA_meshdata_types.h" #include "BLI_array.h" -#include "BLI_heap.h" #include "BLI_math.h" #include "BLI_math_geom.h" #include "BLI_smallhash.h" +#include "BLI_heap.h" #include "BKE_customdata.h" #include "BKE_mesh.h" @@ -69,7 +69,6 @@ struct BLaplacianSystem { }; typedef struct BLaplacianSystem LaplacianSystem; -static float compute_volume(BMesh *bm); static float cotan_weight(float *v1, float *v2, float *v3); static int vert_is_boundary(BMVert *v); static LaplacianSystem *init_laplacian_system(int a_numEdges, int a_numFaces, int a_numVerts); @@ -85,7 +84,6 @@ static void delete_void_pointer(void *data) { if (data) { MEM_freeN(data); - data = NULL; } } @@ -416,45 +414,6 @@ static int vert_is_boundary(BMVert *v) return 0; } -static float compute_volume(BMesh *bm) -{ - float vol = 0.0f; - float x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4; - int i; - BMFace *f; - BMIter fiter; - BMIter vi; - BMVert *vn; - BMVert *vf[4]; - - BM_ITER_MESH (f, &fiter, bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM_INDEX (vn, &vi, f, BM_VERTS_OF_FACE, i) { - vf[i] = vn; - } - x1 = vf[0]->co[0]; - y1 = vf[0]->co[1]; - z1 = vf[0]->co[2]; - - x2 = vf[1]->co[0]; - y2 = vf[1]->co[1]; - z2 = vf[1]->co[2]; - - x3 = vf[2]->co[0]; - y3 = vf[2]->co[1]; - z3 = vf[2]->co[2]; - - vol += (1.0f / 6.0f) * (0.0f - x3 * y2 * z1 + x2 * y3 * z1 + x3 * y1 * z2 - x1 * y3 * z2 - x2 * y1 * z3 + x1 * y2 * z3); - - if (i == 4) { - x4 = vf[3]->co[0]; - y4 = vf[3]->co[1]; - z4 = vf[3]->co[2]; - vol += (1.0f / 6.0f) * (x1 * y3 * z4 - x1 * y4 * z3 - x3 * y1 * z4 + x3 * z1 * y4 + y1 * x4 * z3 - x4 * y3 * z1); - } - } - return fabs(vol); -} - static void volume_preservation(BMOperator *op, float vini, float vend, int usex, int usey, int usez) { float beta; @@ -510,7 +469,7 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } if (preserve_volume) { - vini = compute_volume(sys->bm); + vini = BM_mesh_calc_volume(sys->bm); } BMO_ITER (v, &siter, sys->op->slots_in, "verts", BM_VERT) { m_vertex_id = BM_elem_index_get(v); @@ -527,7 +486,7 @@ static void validate_solution(LaplacianSystem *sys, int usex, int usey, int usez } } if (preserve_volume) { - vend = compute_volume(sys->bm); + vend = BM_mesh_calc_volume(sys->bm); volume_preservation(sys->op, vini, vend, usex, usey, usez); } diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 36ad8ef506b..88e903c1651 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -40,7 +40,47 @@ #include "intern/bmesh_operators_private.h" /* own include */ -#include "bmo_subdivide.h" /* own include */ +typedef struct SubDParams { + int numcuts; + float smooth; + float fractal; + float along_normal; + //int beauty; + bool use_smooth; + bool use_sphere; + bool use_fractal; + int seed; + int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ + BMOperator *op; + BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */ + BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */ + float fractal_ofs[3]; +} SubDParams; + +typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, + const SubDParams *params); + +/* + * note: this is a pattern-based edge subdivider. + * it tries to match a pattern to edge selections on faces, + * then executes functions to cut them. + */ +typedef struct SubDPattern { + int seledges[20]; /* selected edges mask, for splitting */ + + /* verts starts at the first new vert cut, not the first vert in the face */ + subd_pattern_fill_fp connectexec; + int len; /* total number of verts, before any subdivision */ +} SubDPattern; + +/* generic subdivision rules: + * + * - two selected edges in a face should make a link + * between them. + * + * - one edge should do, what? make pretty topology, or just + * split the edge only? + */ /* flags for all elements share a common bitfield space */ #define SUBD_SPLIT 1 @@ -71,29 +111,29 @@ /* connects face with smallest len, which I think should always be correct for * edge subdivision */ -static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_nf) +static BMEdge *connect_smallest_face(BMesh *bm, BMVert *v1, BMVert *v2, BMFace **r_f_new) { BMIter iter, iter2; BMVert *v; - BMLoop *nl; - BMFace *face, *curf = NULL; + BMLoop *l_new; + BMFace *f, *f_cur = NULL; /* this isn't the best thing in the world. it doesn't handle cases where there's * multiple faces yet. that might require a convexity test to figure out which * face is "best" and who knows what for non-manifold conditions. */ - for (face = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v1); face; face = BM_iter_step(&iter)) { - for (v = BM_iter_new(&iter2, bm, BM_VERTS_OF_FACE, face); v; v = BM_iter_step(&iter2)) { + for (f = BM_iter_new(&iter, bm, BM_FACES_OF_VERT, v1); f; f = BM_iter_step(&iter)) { + for (v = BM_iter_new(&iter2, bm, BM_VERTS_OF_FACE, f); v; v = BM_iter_step(&iter2)) { if (v == v2) { - if (!curf || face->len < curf->len) curf = face; + if (!f_cur || f->len < f_cur->len) f_cur = f; } } } - if (curf) { - face = BM_face_split(bm, curf, v1, v2, &nl, NULL, false); + if (f_cur) { + f = BM_face_split(bm, f_cur, v1, v2, &l_new, NULL, false); - if (r_nf) *r_nf = face; - return nl ? nl->e : NULL; + if (r_f_new) *r_f_new = f; + return l_new ? l_new->e : NULL; } return NULL; @@ -151,7 +191,7 @@ static void alter_co(BMesh *bm, BMVert *v, BMEdge *UNUSED(origed), const SubDPar mid_v3_v3v3(normal, vsta->no, vend->no); ortho_basis_v3v3_v3(base1, base2, normal); - add_v3_v3v3(co2, v->co, params->off); + add_v3_v3v3(co2, v->co, params->fractal_ofs); mul_v3_fl(co2, 10.0f); tvec[0] = fac * (BLI_gTurbulence(1.0, co2[0], co2[1], co2[2], 15, 0, 2) - 0.5f); @@ -242,31 +282,31 @@ static BMVert *subdivideedgenum(BMesh *bm, BMEdge *edge, BMEdge *oedge, static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *params, BMVert *vsta, BMVert *vend) { - BMEdge *eed = edge, *newe, temp = *edge; - BMVert *v, ov1 = *edge->v1, ov2 = *edge->v2, *v1 = edge->v1, *v2 = edge->v2; + BMEdge *eed = edge, *e_new, e_tmp = *edge; + BMVert *v, v1_tmp = *edge->v1, v2_tmp = *edge->v2, *v1 = edge->v1, *v2 = edge->v2; int i, numcuts = params->numcuts; - temp.v1 = &ov1; - temp.v2 = &ov2; + e_tmp.v1 = &v1_tmp; + e_tmp.v2 = &v2_tmp; for (i = 0; i < numcuts; i++) { - v = subdivideedgenum(bm, eed, &temp, i, params->numcuts, params, &newe, vsta, vend); + v = subdivideedgenum(bm, eed, &e_tmp, i, params->numcuts, params, &e_new, vsta, vend); BMO_elem_flag_enable(bm, v, SUBD_SPLIT); BMO_elem_flag_enable(bm, eed, SUBD_SPLIT); - BMO_elem_flag_enable(bm, newe, SUBD_SPLIT); + BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT); BMO_elem_flag_enable(bm, v, ELE_SPLIT); BMO_elem_flag_enable(bm, eed, ELE_SPLIT); - BMO_elem_flag_enable(bm, newe, SUBD_SPLIT); + BMO_elem_flag_enable(bm, e_new, SUBD_SPLIT); BM_CHECK_ELEMENT(v); if (v->e) BM_CHECK_ELEMENT(v->e); if (v->e && v->e->l) BM_CHECK_ELEMENT(v->e->l->f); } - alter_co(bm, v1, &temp, params, 0, &ov1, &ov2); - alter_co(bm, v2, &temp, params, 1.0, &ov1, &ov2); + alter_co(bm, v1, &e_tmp, params, 0, &v1_tmp, &v2_tmp); + alter_co(bm, v2, &e_tmp, params, 1.0, &v1_tmp, &v2_tmp); } /* note: the patterns are rotated as necessary to @@ -286,7 +326,7 @@ static void bm_subdivide_multicut(BMesh *bm, BMEdge *edge, const SubDParams *par static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; + BMFace *f_new; int i, add, numcuts = params->numcuts; /* if it's odd, the middle face is a quad, otherwise it's a triangle */ @@ -296,16 +336,16 @@ static void quad_1edge_split(BMesh *bm, BMFace *UNUSED(face), if (i == numcuts / 2) { add -= 1; } - connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf); + connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new); } } else { add = 2; for (i = 0; i < numcuts; i++) { - connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf); + connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new); if (i == numcuts / 2) { add -= 1; - connect_smallest_face(bm, verts[i], verts[numcuts + add], &nf); + connect_smallest_face(bm, verts[i], verts[numcuts + add], &f_new); } } @@ -332,13 +372,13 @@ static const SubDPattern quad_1edge = { static void quad_2edge_split_path(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; + BMFace *f_new; int i, numcuts = params->numcuts; for (i = 0; i < numcuts; i++) { - connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &nf); + connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new); } - connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &nf); + connect_smallest_face(bm, verts[numcuts * 2 + 3], verts[numcuts * 2 + 1], &f_new); } static const SubDPattern quad_2edge_path = { @@ -360,27 +400,27 @@ static const SubDPattern quad_2edge_path = { static void quad_2edge_split_innervert(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; - BMVert *v, *lastv; - BMEdge *e, *ne, olde; + BMFace *f_new; + BMVert *v, *v_last; + BMEdge *e, *e_new, e_tmp; int i, numcuts = params->numcuts; - lastv = verts[numcuts]; + v_last = verts[numcuts]; for (i = numcuts - 1; i >= 0; i--) { - e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &nf); + e = connect_smallest_face(bm, verts[i], verts[numcuts + (numcuts - i)], &f_new); - olde = *e; - v = bm_subdivide_edge_addvert(bm, e, &olde, params, 0.5f, 0.5f, &ne, e->v1, e->v2); + e_tmp = *e; + v = bm_subdivide_edge_addvert(bm, e, &e_tmp, params, 0.5f, 0.5f, &e_new, e->v1, e->v2); if (i != numcuts - 1) { - connect_smallest_face(bm, lastv, v, &nf); + connect_smallest_face(bm, v_last, v, &f_new); } - lastv = v; + v_last = v; } - connect_smallest_face(bm, lastv, verts[numcuts * 2 + 2], &nf); + connect_smallest_face(bm, v_last, verts[numcuts * 2 + 2], &f_new); } static const SubDPattern quad_2edge_innervert = { @@ -402,15 +442,15 @@ static const SubDPattern quad_2edge_innervert = { static void quad_2edge_split_fan(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; + BMFace *f_new; /* BMVert *v; */ /* UNUSED */ - /* BMVert *lastv = verts[2]; */ /* UNUSED */ - /* BMEdge *e, *ne; */ /* UNUSED */ + /* BMVert *v_last = verts[2]; */ /* UNUSED */ + /* BMEdge *e, *e_new; */ /* UNUSED */ int i, numcuts = params->numcuts; for (i = 0; i < numcuts; i++) { - connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &nf); - connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &nf); + connect_smallest_face(bm, verts[i], verts[numcuts * 2 + 2], &f_new); + connect_smallest_face(bm, verts[numcuts + (numcuts - i)], verts[numcuts * 2 + 2], &f_new); } } @@ -435,21 +475,21 @@ static const SubDPattern quad_2edge_fan = { static void quad_3edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; + BMFace *f_new; int i, add = 0, numcuts = params->numcuts; for (i = 0; i < numcuts; i++) { if (i == numcuts / 2) { if (numcuts % 2 != 0) { - connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &nf); + connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new); } add = numcuts * 2 + 2; } - connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &nf); + connect_smallest_face(bm, verts[numcuts - i - 1 + add], verts[i + numcuts + 1], &f_new); } for (i = 0; i < numcuts / 2 + 1; i++) { - connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &nf); + connect_smallest_face(bm, verts[i], verts[(numcuts - i) + numcuts * 2 + 1], &f_new); } } @@ -474,9 +514,9 @@ static const SubDPattern quad_3edge = { static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; + BMFace *f_new; BMVert *v, *v1, *v2; - BMEdge *e, *ne, temp; + BMEdge *e, *e_new, e_tmp; BMVert **lines; int numcuts = params->numcuts; int i, j, a, b, s = numcuts + 2 /* , totv = numcuts * 4 + 4 */; @@ -501,25 +541,25 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts a = i; b = numcuts + 1 + numcuts + 1 + (numcuts - i - 1); - e = connect_smallest_face(bm, verts[a], verts[b], &nf); + e = connect_smallest_face(bm, verts[a], verts[b], &f_new); if (!e) continue; BMO_elem_flag_enable(bm, e, ELE_INNER); - BMO_elem_flag_enable(bm, nf, ELE_INNER); + BMO_elem_flag_enable(bm, f_new, ELE_INNER); v1 = lines[(i + 1) * s] = verts[a]; v2 = lines[(i + 1) * s + s - 1] = verts[b]; - temp = *e; + e_tmp = *e; for (a = 0; a < numcuts; a++) { - v = subdivideedgenum(bm, e, &temp, a, numcuts, params, &ne, + v = subdivideedgenum(bm, e, &e_tmp, a, numcuts, params, &e_new, v1, v2); BMESH_ASSERT(v != NULL); - BMO_elem_flag_enable(bm, ne, ELE_INNER); + BMO_elem_flag_enable(bm, e_new, ELE_INNER); lines[(i + 1) * s + a + 1] = v; } } @@ -528,12 +568,12 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts for (j = 1; j < numcuts + 1; j++) { a = i * s + j; b = (i - 1) * s + j; - e = connect_smallest_face(bm, lines[a], lines[b], &nf); + e = connect_smallest_face(bm, lines[a], lines[b], &f_new); if (!e) continue; BMO_elem_flag_enable(bm, e, ELE_INNER); - BMO_elem_flag_enable(bm, nf, ELE_INNER); + BMO_elem_flag_enable(bm, f_new, ELE_INNER); } } @@ -555,11 +595,11 @@ static void quad_4edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts static void tri_1edge_split(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; + BMFace *f_new; int i, numcuts = params->numcuts; for (i = 0; i < numcuts; i++) { - connect_smallest_face(bm, verts[i], verts[numcuts + 1], &nf); + connect_smallest_face(bm, verts[i], verts[numcuts + 1], &f_new); } } @@ -584,9 +624,9 @@ static const SubDPattern tri_1edge = { static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, const SubDParams *params) { - BMFace *nf; - BMEdge *e, *ne, temp; - BMVert ***lines, *v, ov1, ov2; + BMFace *f_new; + BMEdge *e, *e_new, e_tmp; + BMVert ***lines, *v, v1_tmp, v2_tmp; void *stackarr[1]; int i, j, a, b, numcuts = params->numcuts; @@ -607,26 +647,26 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, lines[i + 1] = MEM_callocN(sizeof(void *) * (2 + i), "triangle vert table row"); a = numcuts * 2 + 2 + i; b = numcuts + numcuts - i; - e = connect_smallest_face(bm, verts[a], verts[b], &nf); + e = connect_smallest_face(bm, verts[a], verts[b], &f_new); if (!e) goto cleanup; BMO_elem_flag_enable(bm, e, ELE_INNER); - BMO_elem_flag_enable(bm, nf, ELE_INNER); + BMO_elem_flag_enable(bm, f_new, ELE_INNER); lines[i + 1][0] = verts[a]; lines[i + 1][i + 1] = verts[b]; - temp = *e; - ov1 = *verts[a]; - ov2 = *verts[b]; - temp.v1 = &ov1; - temp.v2 = &ov2; + e_tmp = *e; + v1_tmp = *verts[a]; + v2_tmp = *verts[b]; + e_tmp.v1 = &v1_tmp; + e_tmp.v2 = &v2_tmp; for (j = 0; j < i; j++) { - v = subdivideedgenum(bm, e, &temp, j, i, params, &ne, + v = subdivideedgenum(bm, e, &e_tmp, j, i, params, &e_new, verts[a], verts[b]); lines[i + 1][j + 1] = v; - BMO_elem_flag_enable(bm, ne, ELE_INNER); + BMO_elem_flag_enable(bm, e_new, ELE_INNER); } } @@ -644,15 +684,15 @@ static void tri_3edge_subdivide(BMesh *bm, BMFace *UNUSED(face), BMVert **verts, */ for (i = 1; i < numcuts + 1; i++) { for (j = 0; j < i; j++) { - e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &nf); + e = connect_smallest_face(bm, lines[i][j], lines[i + 1][j + 1], &f_new); BMO_elem_flag_enable(bm, e, ELE_INNER); - BMO_elem_flag_enable(bm, nf, ELE_INNER); + BMO_elem_flag_enable(bm, f_new, ELE_INNER); - e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &nf); + e = connect_smallest_face(bm, lines[i][j + 1], lines[i + 1][j + 1], &f_new); BMO_elem_flag_enable(bm, e, ELE_INNER); - BMO_elem_flag_enable(bm, nf, ELE_INNER); + BMO_elem_flag_enable(bm, f_new, ELE_INNER); } } @@ -711,7 +751,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_declare(loops_split); BMLoop **loops = NULL; BLI_array_declare(loops); - BMLoop *nl, *l; + BMLoop *l_new, *l; BMFace *face; BLI_array_declare(verts); float smooth, fractal, along_normal; @@ -731,9 +771,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) use_grid_fill = BMO_slot_bool_get(op->slots_in, "use_grid_fill"); use_only_quads = BMO_slot_bool_get(op->slots_in, "use_only_quads"); use_sphere = BMO_slot_bool_get(op->slots_in, "use_sphere"); - - BLI_srandom(seed); - + patterns[1] = NULL; /* straight cut is patterns[1] == NULL */ switch (cornertype) { @@ -790,9 +828,14 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) params.use_fractal = (fractal != 0.0f); params.use_sphere = use_sphere; params.origkey = skey; - params.off[0] = (float)BLI_drand() * 200.0f; - params.off[1] = (float)BLI_drand() * 200.0f; - params.off[2] = (float)BLI_drand() * 200.0f; + + if (params.use_fractal) { + BLI_srandom(seed); + + params.fractal_ofs[0] = (float)BLI_drand() * 200.0f; + params.fractal_ofs[1] = (float)BLI_drand() * 200.0f; + params.fractal_ofs[2] = (float)BLI_drand() * 200.0f; + } BMO_slot_map_to_flag(bm, op->slots_in, "custom_patterns", BM_FACE, FACE_CUSTOMFILL); @@ -820,9 +863,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) matched = 0; totesel = 0; - BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, i) { - edges[i] = nl->e; - verts[i] = nl->v; + BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, i) { + edges[i] = l_new->e; + verts[i] = l_new->v; if (BMO_elem_flag_test(bm, edges[i], SUBD_SPLIT)) { if (!e1) e1 = edges[i]; @@ -1042,8 +1085,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) if (loops_split[j][0]) { BLI_assert(BM_edge_exists(loops_split[j][0]->v, loops_split[j][1]->v) == NULL); - /* BMFace *nf = */ /* UNUSED */ - BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &nl, NULL, false); + /* BMFace *f_new = */ /* UNUSED */ + BM_face_split(bm, face, loops_split[j][0]->v, loops_split[j][1]->v, &l_new, NULL, false); } } @@ -1054,8 +1097,8 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } a = 0; - BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) { - if (nl->v == facedata[i].start) { + BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) { + if (l_new->v == facedata[i].start) { a = j + 1; break; } @@ -1063,9 +1106,9 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) BLI_array_grow_items(verts, face->len); - BM_ITER_ELEM_INDEX (nl, &liter, face, BM_LOOPS_OF_FACE, j) { + BM_ITER_ELEM_INDEX (l_new, &liter, face, BM_LOOPS_OF_FACE, j) { b = (j - a + face->len) % face->len; - verts[b] = nl->v; + verts[b] = l_new->v; } BM_CHECK_ELEMENT(face); diff --git a/source/blender/bmesh/operators/bmo_subdivide.h b/source/blender/bmesh/operators/bmo_subdivide.h deleted file mode 100644 index 529075aab02..00000000000 --- a/source/blender/bmesh/operators/bmo_subdivide.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * Contributor(s): Joseph Eagar. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/bmesh/operators/bmo_subdivide.h - * \ingroup bmesh - */ - -#ifndef __BMO_SUBDIVIDE_H__ -#define __BMO_SUBDIVIDE_H__ - -typedef struct SubDParams { - int numcuts; - float smooth; - float fractal; - float along_normal; - //int beauty; - short use_smooth; - short use_sphere; - short use_fractal; - int seed; - int origkey; /* shapekey holding displaced vertex coordinates for current geometry */ - BMOperator *op; - BMOpSlot *slot_edge_percents; /* BMO_slot_get(params->op->slots_in, "edge_percents"); */ - BMOpSlot *slot_custom_patterns; /* BMO_slot_get(params->op->slots_in, "custom_patterns"); */ - float off[3]; -} SubDParams; - -typedef void (*subd_pattern_fill_fp)(BMesh *bm, BMFace *face, BMVert **verts, - const SubDParams *params); - -/* - * note: this is a pattern-based edge subdivider. - * it tries to match a pattern to edge selections on faces, - * then executes functions to cut them. - */ -typedef struct SubDPattern { - int seledges[20]; /* selected edges mask, for splitting */ - - /* verts starts at the first new vert cut, not the first vert in the face */ - subd_pattern_fill_fp connectexec; - int len; /* total number of verts, before any subdivision */ -} SubDPattern; - -/* generic subdivision rules: - * - * - two selected edges in a face should make a link - * between them. - * - * - one edge should do, what? make pretty topology, or just - * split the edge only? - */ - -#endif /* __BMO_SUBDIVIDE_H__ */ diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index 0d603faf3c4..00838533104 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -151,8 +151,6 @@ static bool bm_loop_is_radial_boundary(BMLoop *l_first) return true; } -extern float BM_vert_calc_mean_tagged_edge_length(BMVert *v); - void bmo_wireframe_exec(BMesh *bm, BMOperator *op) { const bool use_boundary = BMO_slot_bool_get(op->slots_in, "use_boundary"); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 5adef16de14..f685b741176 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -375,8 +375,8 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, } } -/* Like offset_meet, but here f1 and f2 must not be NULL and give the - * planes in which to run the offset lines. +/* Like offset_meet, but with a mid edge between them that is used + * to calculate the planes in which to run the offset lines. * They may not meet exactly: the offsets for the edges may be different * or both the planes and the lines may be angled so that they can't meet. * In that case, pick a close point on emid, which should be the dividing @@ -384,16 +384,13 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, * TODO: should have a global 'offset consistency' prepass to adjust offset * widths so that all edges have the same offset at both ends. */ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, EdgeHalf *emid, - BMVert *v, BMFace *f1, BMFace *f2, float meetco[3]) + BMVert *v, float meetco[3]) { float dir1[3], dir2[3], dirmid[3], norm_perp1[3], norm_perp2[3], off1a[3], off1b[3], off2a[3], off2b[3], isect2[3], co[3], f1no[3], f2no[3]; int iret; - BLI_assert(f1 != NULL && f2 != NULL); - (void)f1, (void)f2; /* UNUSED */ - /* get direction vectors for two offset lines */ sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); @@ -692,8 +689,7 @@ static void build_boundary(BevelParams *bp, BevVert *bv) if (e->prev->prev->is_bev) { BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */ /* find meet point between e->prev->prev and e and attach e->prev there */ - offset_in_two_planes(e->prev->prev, e, e->prev, bv->v, - e->prev->prev->fnext, e->fprev, co); + offset_in_two_planes(e->prev->prev, e, e->prev, bv->v, co); v = add_new_bound_vert(mem_arena, vm, co); v->efirst = e->prev->prev; v->elast = v->ebev = e; @@ -2056,6 +2052,51 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) } } +/* + * Calculate and return an offset that is the lesser of the current + * bp.offset and the maximum possible offset before geometry + * collisions happen. + * Currently this is a quick and dirty estimate of the max + * possible: half the minimum edge length of any vertex involved + * in a bevel. This is usually conservative. + * The correct calculation is quite complicated. + * TODO: implement this correctly. + */ +static float bevel_limit_offset(BMesh *bm, BevelParams *bp) +{ + BMVert *v; + BMEdge *e; + BMIter v_iter, e_iter; + float limited_offset, half_elen; + bool vbeveled; + + limited_offset = bp->offset; + BM_ITER_MESH(v, &v_iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + if (bp->vertex_only) { + vbeveled = true; + } + else { + vbeveled = false; + BM_ITER_ELEM(e, &e_iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(BM_edge_other_vert(e, v), BM_ELEM_TAG)) { + vbeveled = true; + break; + } + } + } + if (vbeveled) { + BM_ITER_ELEM(e, &e_iter, v, BM_EDGES_OF_VERT) { + half_elen = 0.5f * BM_edge_calc_length(e); + if (half_elen < limited_offset) + limited_offset = half_elen; + } + } + } + } + return limited_offset; +} + /** * - Currently only bevels BM_ELEM_TAG'd verts and edges. * @@ -2063,10 +2104,13 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) * the caller needs to ensure this is cleared before calling * if its going to use this face tag. * + * - If limit_offset is set, adjusts offset down if necessary + * to avoid geometry collisions. + * * \warning all tagged edges _must_ be manifold. */ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, - const bool vertex_only, const bool use_weights, + const bool vertex_only, const bool use_weights, const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group) { BMIter iter; @@ -2087,6 +2131,9 @@ void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, bp.mem_arena = BLI_memarena_new((1 << 16), __func__); BLI_memarena_use_calloc(bp.mem_arena); + if (limit_offset) + bp.offset = bevel_limit_offset(bm, &bp); + /* The analysis of the input vertices and execution additional constructions */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index f214125fa1c..bee26357aca 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -30,7 +30,7 @@ struct MDeformVert; void BM_mesh_bevel(BMesh *bm, const float offset, const float segments, - const bool vertex_only, const bool use_weights, + const bool vertex_only, const bool use_weights, const bool limit_offset, const struct MDeformVert *dvert, const int vertex_group); #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c index 3a724769f2a..a5122b242be 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_dissolve.c +++ b/source/blender/bmesh/tools/bmesh_decimate_dissolve.c @@ -114,14 +114,14 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool /* check twice because cumulative effect could dissolve over angle limit */ (BM_edge_calc_face_angle(e) < angle_limit)) { - BMFace *nf = BM_faces_join_pair(bm, e->l->f, - e->l->radial_next->f, - e, - false); /* join faces */ + BMFace *f_new = BM_faces_join_pair(bm, e->l->f, + e->l->radial_next->f, + e, + false); /* join faces */ /* there may be some errors, we don't mind, just move on */ - if (nf) { - BM_face_normal_update(nf); + if (f_new) { + BM_face_normal_update(f_new); } else { BMO_error_clear(bm); @@ -210,10 +210,10 @@ void BM_mesh_decimate_dissolve_ex(BMesh *bm, const float angle_limit, const bool /* check twice because cumulative effect could dissolve over angle limit */ bm_vert_edge_face_angle(v) < angle_limit) { - BMEdge *ne = BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */ + BMEdge *e_new = BM_vert_collapse_edge(bm, v->e, v, true); /* join edges */ - if (ne && ne->l) { - BM_edge_normals_update(ne); + if (e_new && e_new->l) { + BM_edge_normals_update(e_new); } } } diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 7e9a5784552..c48e83686b5 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -181,7 +181,6 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool unsigned vert_seek_b_tot = 0; #endif - BMVert *v; BMIter iter; const unsigned int offset = 0; @@ -192,12 +191,14 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool /* if tag_only is set, we assume the caller knows what verts to tag * needed for the operator */ if (tag_only == false) { + BMVert *v; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { BM_elem_flag_enable(v, BM_ELEM_TAG); } } for (iter_step = 0; iter_step < iterations; iter_step++) { + BMVert *v; bool iter_done; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { @@ -223,7 +224,6 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const bool unsigned int i; #endif BMVert *v_first = NULL; - BMVert *v; /* we could avoid iterating from the start each time */ BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index 1d3f973dbc0..3ae5c712f0a 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -48,7 +48,6 @@ static void bm_edgesplit_validate_seams(BMesh *bm) BMEdge *e; unsigned char *vtouch; - unsigned char *vt; BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -65,6 +64,7 @@ static void bm_edgesplit_validate_seams(BMesh *bm) BM_elem_flag_disable(e, BM_ELEM_TAG); } else if (BM_edge_is_boundary(e)) { + unsigned char *vt; vt = &vtouch[BM_elem_index_get(e->v1)]; if (*vt < 2) (*vt)++; vt = &vtouch[BM_elem_index_get(e->v2)]; if (*vt < 2) (*vt)++; diff --git a/source/blender/collada/AnimationExporter.cpp b/source/blender/collada/AnimationExporter.cpp index a69f7918e40..48958fbfc90 100644 --- a/source/blender/collada/AnimationExporter.cpp +++ b/source/blender/collada/AnimationExporter.cpp @@ -36,9 +36,10 @@ void forEachObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) } } -void AnimationExporter::exportAnimations(Scene *sce) +bool AnimationExporter::exportAnimations(Scene *sce) { - if (hasAnimations(sce)) { + bool has_animations = hasAnimations(sce); + if (has_animations) { this->scene = sce; openLibrary(); @@ -47,6 +48,7 @@ void AnimationExporter::exportAnimations(Scene *sce) closeLibrary(); } + return has_animations; } // called for each exported object @@ -257,6 +259,12 @@ std::string AnimationExporter::getObjectBoneName(Object *ob, const FCurve *fcu) return id_name(ob); } +std::string AnimationExporter::getAnimationPathId(const FCurve *fcu) +{ + std::string rna_path = std::string(fcu->rna_path); + return translate_id(rna_path); +} + //convert f-curves to animation curves and write void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformName, bool is_param, Material *ma) { @@ -303,16 +311,27 @@ void AnimationExporter::dae_animation(Object *ob, FCurve *fcu, char *transformNa //Create anim Id if (ob->type == OB_ARMATURE) { ob_name = getObjectBoneName(ob, fcu); - BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s.%s", (char *)translate_id(ob_name).c_str(), - transformName, axis_name); + BLI_snprintf( + anim_id, + sizeof(anim_id), + "%s_%s.%s", + (char *)translate_id(ob_name).c_str(), + (char *)translate_id(transformName).c_str(), + axis_name); } else { if (ma) ob_name = id_name(ob) + "_material"; else ob_name = id_name(ob); - BLI_snprintf(anim_id, sizeof(anim_id), "%s_%s_%s", (char *)translate_id(ob_name).c_str(), - fcu->rna_path, axis_name); + + BLI_snprintf( + anim_id, + sizeof(anim_id), + "%s_%s_%s", + (char *)translate_id(ob_name).c_str(), + (char *)getAnimationPathId(fcu).c_str(), + axis_name); } openAnimation(anim_id, COLLADABU::Utils::EMPTY_STRING); @@ -882,7 +901,7 @@ std::string AnimationExporter::create_source_from_vector(COLLADASW::InputSemanti } -std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object * ob, Bone *bone, const std::string& anim_id) +std::string AnimationExporter::create_4x4_source(std::vector<float> &frames, Object *ob, Bone *bone, const std::string &anim_id) { COLLADASW::InputSemantic::Semantics semantic = COLLADASW::InputSemantic::OUTPUT; std::string source_id = anim_id + get_semantic_suffix(semantic); diff --git a/source/blender/collada/AnimationExporter.h b/source/blender/collada/AnimationExporter.h index d2f50b22d02..a6f1b89aedb 100644 --- a/source/blender/collada/AnimationExporter.h +++ b/source/blender/collada/AnimationExporter.h @@ -98,7 +98,7 @@ public: { this->sw = sw; } - void exportAnimations(Scene *sce); + bool exportAnimations(Scene *sce); // called for each exported object void operator() (Object *ob); @@ -141,7 +141,7 @@ protected: std::string get_semantic_suffix(COLLADASW::InputSemantic::Semantics semantic); void add_source_parameters(COLLADASW::SourceBase::ParameterNameList& param, - COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform); + COLLADASW::InputSemantic::Semantics semantic, bool is_rot, const char *axis, bool transform); void get_source_values(BezTriple *bezt, COLLADASW::InputSemantic::Semantics semantic, bool rotation, float *values, int *length); @@ -184,6 +184,7 @@ protected: char *extract_transform_name(char *rna_path); std::string getObjectBoneName(Object *ob, const FCurve * fcu); + std::string getAnimationPathId(const FCurve *fcu); void getBakedPoseData(Object *obarm, int startFrame, int endFrame, bool ActionBake, bool ActionBakeFirstFrame); diff --git a/source/blender/collada/ArmatureImporter.cpp b/source/blender/collada/ArmatureImporter.cpp index 221a5008f10..ed84dee046f 100644 --- a/source/blender/collada/ArmatureImporter.cpp +++ b/source/blender/collada/ArmatureImporter.cpp @@ -134,10 +134,10 @@ void ArmatureImporter::create_bone(SkinInfo* skin, COLLADAFW::Node *node, EditBo // set parent tail if (parent && totchild == 1) { - copy_v3_v3(parent->tail, bone->head); + copy_v3_v3(parent->tail, bone->head); // not setting BONE_CONNECTED because this would lock child bone location with respect to parent - bone->flag |= BONE_CONNECTED; + bone->flag |= BONE_CONNECTED; // XXX increase this to prevent "very" small bones? const float epsilon = 0.000001f; diff --git a/source/blender/collada/ControllerExporter.cpp b/source/blender/collada/ControllerExporter.cpp index 6b367b9cea9..35fcc926bea 100644 --- a/source/blender/collada/ControllerExporter.cpp +++ b/source/blender/collada/ControllerExporter.cpp @@ -404,7 +404,7 @@ void ControllerExporter::add_weight_extras(Key *key) kb = kb->next; for (; kb; kb = kb->next) { // XXX why is the weight not used here and set to 0.0? - float weight = kb->curval; + // float weight = kb->curval; extra.addExtraTechniqueParameter ("KHR", "morph_weights" , 0.000, "MORPH_WEIGHT_TO_TARGET"); } } diff --git a/source/blender/collada/DocumentExporter.cpp b/source/blender/collada/DocumentExporter.cpp index 71909b33db8..c03316e1fe5 100644 --- a/source/blender/collada/DocumentExporter.cpp +++ b/source/blender/collada/DocumentExporter.cpp @@ -266,20 +266,32 @@ void DocumentExporter::exportCurrentScene(Scene *sce) // <library_animations> AnimationExporter ae(&sw, this->export_settings); - ae.exportAnimations(sce); + bool has_animations = ae.exportAnimations(sce); // <library_controllers> ArmatureExporter arm_exporter(&sw, this->export_settings); ControllerExporter controller_exporter(&sw , this->export_settings); - //for Morph controller export, removing the check - /*if (bc_has_object_type(export_set, OB_ARMATURE)) - {*/ - controller_exporter.export_controllers(sce); - //} + if (bc_has_object_type(export_set, OB_ARMATURE) || this->export_settings->include_shapekeys) + { + controller_exporter.export_controllers(sce); + } // <library_visual_scenes> SceneExporter se(&sw, &arm_exporter, this->export_settings); + + if (has_animations && this->export_settings->export_transformation_type == BC_TRANSFORMATION_TYPE_MATRIX) { + // channels adressing <matrix> objects is not (yet) supported + // So we force usage of <location>, <translation> and <scale> + fprintf(stdout, + "For animated Ojects we must use decomposed <matrix> elements,\n" \ + "Forcing usage of TransLocRot transformation type."); + se.setExportTransformationType(BC_TRANSFORMATION_TYPE_TRANSROTLOC); + } + else { + se.setExportTransformationType(this->export_settings->export_transformation_type); + } + se.exportScene(sce); // <scene> diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index e4a654dc99a..6741e92cb5c 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -323,10 +323,10 @@ void EffectsExporter::operator()(Material *ma, Object *ob) { if (me->pdata.layers[i].type == CD_MTEXPOLY) { MTexPoly *txface = (MTexPoly *)me->pdata.layers[i].data; - MFace *mface = me->mface; - for (int j = 0; j < me->totpoly; j++, mface++, txface++) { + MPoly *mpoly = me->mpoly; + for (int j = 0; j < me->totpoly; j++, mpoly++, txface++) { - Material *mat = give_current_material(ob, mface->mat_nr + 1); + Material *mat = give_current_material(ob, mpoly->mat_nr + 1); if (mat != ma) continue; diff --git a/source/blender/collada/ExportSettings.h b/source/blender/collada/ExportSettings.h index ec71fb2747c..f9eb4cbc26f 100644 --- a/source/blender/collada/ExportSettings.h +++ b/source/blender/collada/ExportSettings.h @@ -28,6 +28,7 @@ #define __EXPORTSETTINGS_H__ #include "collada.h" +#include "collada.h" struct ExportSettings { public: @@ -48,6 +49,7 @@ public: bool triangulate; bool use_object_instantiation; bool sort_by_name; + BC_export_transformation_type export_transformation_type; bool second_life; char *filepath; diff --git a/source/blender/collada/ExtraHandler.cpp b/source/blender/collada/ExtraHandler.cpp index bcf7e573d24..7b8d315b8c5 100644 --- a/source/blender/collada/ExtraHandler.cpp +++ b/source/blender/collada/ExtraHandler.cpp @@ -57,7 +57,7 @@ bool ExtraHandler::textData(const char *text, size_t textLength) if (currentElement.length() == 0 || currentExtraTags == 0) return false; - BLI_snprintf(buf, textLength + 1, "%s", text); + BLI_strncpy(buf, text, textLength + 1); currentExtraTags->addTag(currentElement, std::string(buf)); return true; } diff --git a/source/blender/collada/GeometryExporter.cpp b/source/blender/collada/GeometryExporter.cpp index 751628acf53..6644c46ac86 100644 --- a/source/blender/collada/GeometryExporter.cpp +++ b/source/blender/collada/GeometryExporter.cpp @@ -76,7 +76,6 @@ void GeometryExporter::operator()(Object *ob) #endif bool use_instantiation = this->export_settings->use_object_instantiation; - bool triangulate = this->export_settings->triangulate; Mesh *me = bc_get_mesh_copy( mScene, ob, this->export_settings->export_mesh_type, @@ -379,8 +378,6 @@ void GeometryExporter::createPolylist(short material_index, // <p> int texindex = 0; - unsigned int vi = 0; - unsigned int ni = 0; for (i = 0; i < totpolys; i++) { MPoly *p = &mpolys[i]; int loop_count = p->totloop; @@ -442,19 +439,14 @@ void GeometryExporter::createVertsSource(std::string geom_id, Mesh *me) void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) { - if (!CustomData_has_layer(&me->fdata, CD_MCOL)) + if (!CustomData_has_layer(&me->ldata, CD_MLOOPCOL)) return; - MFace *f; - int totcolor = 0, i, j; - - for (i = 0, f = me->mface; i < me->totface; i++, f++) - totcolor += f->v4 ? 4 : 3; COLLADASW::FloatSourceF source(mSW); source.setId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR)); source.setArrayId(getIdBySemantics(geom_id, COLLADASW::InputSemantic::COLOR) + ARRAY_ID_SUFFIX); - source.setAccessorCount(totcolor); + source.setAccessorCount(me->totloop); source.setAccessorStride(3); COLLADASW::SourceBase::ParameterNameList ¶m = source.getParameterNameList(); @@ -464,14 +456,21 @@ void GeometryExporter::createVertexColorSource(std::string geom_id, Mesh *me) source.prepareToAppendValues(); - int index = CustomData_get_active_layer_index(&me->fdata, CD_MCOL); - - MCol *mcol = (MCol *)me->fdata.layers[index].data; - MCol *c = mcol; + int index = CustomData_get_active_layer_index(&me->ldata, CD_MLOOPCOL); + MCol *mcol = (MCol *)me->ldata.layers[index].data; - for (i = 0, f = me->mface; i < me->totface; i++, c += 4, f++) - for (j = 0; j < (f->v4 ? 4 : 3); j++) - source.appendValues(c[j].b / 255.0f, c[j].g / 255.0f, c[j].r / 255.0f); + MPoly *mpoly; + int i; + for (i = 0, mpoly = me->mpoly; i < me->totpoly; i++, mpoly++) { + MCol *color = mcol + mpoly->loopstart; + for (int j = 0; j < mpoly->totloop; j++, color++) { + source.appendValues( + color->b / 255.0f, + color->g / 255.0f, + color->r / 255.0f + ); + } + } source.finish(); } @@ -563,19 +562,19 @@ void GeometryExporter::createNormalsSource(std::string geom_id, Mesh *me, std::v void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector<BCPolygonNormalsIndices> &polygons_normals, Mesh *me) { - MVert *vert = me->mvert; std::map<unsigned int, unsigned int> shared_normal_indices; + int last_normal_index = -1; + MVert *verts = me->mvert; + MLoop *mloops = me->mloop; for (int poly_index = 0; poly_index < me->totpoly; poly_index++) { MPoly *mpoly = &me->mpoly[poly_index]; - MLoop *mloops = me->mloop; - unsigned int last_normal_index = -1; if (!(mpoly->flag & ME_SMOOTH)) { - // For flat faces calculate use face normal as vertex normal: + // For flat faces use face normal as vertex normal: float vector[3]; - BKE_mesh_calc_poly_normal(mpoly, mloops, vert, vector); + BKE_mesh_calc_poly_normal(mpoly, mloops, verts, vector); Normal n = { vector[0], vector[1], vector[2] }; normals.push_back(n); @@ -593,8 +592,7 @@ void GeometryExporter::create_normals(std::vector<Normal> &normals, std::vector< else { float vector[3]; - normal_short_to_float_v3(vector, vert[vertex_index].no); - normalize_v3(vector); + normal_short_to_float_v3(vector, verts[vertex_index].no); Normal n = { vector[0], vector[1], vector[2] }; normals.push_back(n); diff --git a/source/blender/collada/GeometryExporter.h b/source/blender/collada/GeometryExporter.h index 4b1427c11ca..3719072fe0c 100644 --- a/source/blender/collada/GeometryExporter.h +++ b/source/blender/collada/GeometryExporter.h @@ -117,7 +117,7 @@ private: struct GeometryFunctor { // f should have - // void operator()(Object* ob) + // void operator()(Object *ob) template<class Functor> void forEachMeshObjectInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { diff --git a/source/blender/collada/MaterialExporter.h b/source/blender/collada/MaterialExporter.h index 09d10846b53..ef44bf8a03e 100644 --- a/source/blender/collada/MaterialExporter.h +++ b/source/blender/collada/MaterialExporter.h @@ -88,7 +88,7 @@ public: struct MaterialFunctor { // calls f for each unique material linked to each object in sce // f should have - // void operator()(Material* ma) + // void operator()(Material *ma) template<class Functor> void forEachMaterialInExportSet(Scene *sce, Functor &f, LinkNode *export_set) { diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 69944563b6a..71d3ada03dd 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -384,7 +384,6 @@ void MeshImporter::allocate_poly_data(COLLADAFW::Mesh *collada_mesh, Mesh *me) for (int i = 0; i < totuvset; i++) { COLLADAFW::MeshVertexData::InputInfos *info = collada_mesh->getUVCoords().getInputInfosArray()[i]; COLLADAFW::String &uvname = info->mName; - int x = 0; // Allocate space for UV_data CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname.c_str()); CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, uvname.c_str()); @@ -556,7 +555,7 @@ void MeshImporter::read_polys(COLLADAFW::Mesh *collada_mesh, Mesh *me) int collada_meshtype = mp->getPrimitiveType(); - // since we cannot set mpoly->mat_nr here, we store a portion of me->mface in Primitive + // since we cannot set mpoly->mat_nr here, we store a portion of me->mpoly in Primitive Primitive prim = {mpoly, 0}; COLLADAFW::IndexListArray& index_list_array = mp->getUVCoordIndicesArray(); @@ -1085,7 +1084,7 @@ bool MeshImporter::write_geometry(const COLLADAFW::Geometry *geom) read_vertices(mesh, me); read_polys(mesh, me); - BKE_mesh_calc_edges(me, 0); + BKE_mesh_calc_edges(me, false, false); // read_lines() must be called after the face edges have been generated. // Oterwise the loose edges will be silently deleted again. diff --git a/source/blender/collada/MeshImporter.h b/source/blender/collada/MeshImporter.h index 751e6faf02b..5275420f4b5 100644 --- a/source/blender/collada/MeshImporter.h +++ b/source/blender/collada/MeshImporter.h @@ -154,22 +154,22 @@ public: virtual Mesh *get_mesh_by_geom_uid(const COLLADAFW::UniqueId& geom_uid); MTex *assign_textures_to_uvlayer(COLLADAFW::TextureCoordinateBinding &ctexture, - Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, - MTex *color_texture); + Mesh *me, TexIndexTextureArrayMap& texindex_texarray_map, + MTex *color_texture); void optimize_material_assignements(); MTFace *assign_material_to_geom(COLLADAFW::MaterialBinding cmaterial, - std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, - Object *ob, const COLLADAFW::UniqueId *geom_uid, - char *layername, MTFace *texture_face, - std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index); + std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, + Object *ob, const COLLADAFW::UniqueId *geom_uid, + char *layername, MTFace *texture_face, + std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map, short mat_index); Object *create_mesh_object(COLLADAFW::Node *node, COLLADAFW::InstanceGeometry *geom, - bool isController, - std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, - std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map); + bool isController, + std::map<COLLADAFW::UniqueId, Material*>& uid_material_map, + std::map<Material*, TexIndexTextureArrayMap>& material_texture_mapping_map); // create a mesh storing a pointer in a map so it can be retrieved later by geometry UID bool write_geometry(const COLLADAFW::Geometry* geom); diff --git a/source/blender/collada/SceneExporter.cpp b/source/blender/collada/SceneExporter.cpp index dbf7d40b373..f3844be525e 100644 --- a/source/blender/collada/SceneExporter.cpp +++ b/source/blender/collada/SceneExporter.cpp @@ -36,7 +36,12 @@ SceneExporter::SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, : COLLADASW::LibraryVisualScenes(sw), arm_exporter(arm), export_settings(export_settings) { } - + +void SceneExporter::setExportTransformationType(BC_export_transformation_type transformation_type) +{ + this->transformation_type = transformation_type; +} + void SceneExporter::exportScene(Scene *sce) { // <library_visual_scenes> <visual_scene> @@ -84,6 +89,7 @@ void SceneExporter::exportHierarchy(Scene *sce) } } + void SceneExporter::writeNodes(Object *ob, Scene *sce) { // Add associated armature first if available @@ -130,8 +136,9 @@ void SceneExporter::writeNodes(Object *ob, Scene *sce) if (ob->type == OB_MESH && armature_exported) // for skinned mesh we write obmat in <bind_shape_matrix> TransformWriter::add_node_transform_identity(colladaNode); - else - TransformWriter::add_node_transform_ob(colladaNode, ob); + else { + TransformWriter::add_node_transform_ob(colladaNode, ob, this->transformation_type); + } // <instance_geometry> if (ob->type == OB_MESH) { diff --git a/source/blender/collada/SceneExporter.h b/source/blender/collada/SceneExporter.h index f438c002f91..c7c15dba2cb 100644 --- a/source/blender/collada/SceneExporter.h +++ b/source/blender/collada/SceneExporter.h @@ -97,8 +97,10 @@ class SceneExporter: COLLADASW::LibraryVisualScenes, protected TransformWriter, public: SceneExporter(COLLADASW::StreamWriter *sw, ArmatureExporter *arm, const ExportSettings *export_settings); void exportScene(Scene *sce); + void setExportTransformationType(BC_export_transformation_type transformation_type); private: + BC_export_transformation_type transformation_type; // required for writeNodes() for bone-parented objects friend class ArmatureExporter; void exportHierarchy(Scene *sce); diff --git a/source/blender/collada/TransformWriter.cpp b/source/blender/collada/TransformWriter.cpp index fa813e0b961..e1c32482835 100644 --- a/source/blender/collada/TransformWriter.cpp +++ b/source/blender/collada/TransformWriter.cpp @@ -51,13 +51,17 @@ void TransformWriter::add_node_transform(COLLADASW::Node& node, float mat[4][4], converter->mat4_to_dae_double(dmat, local); TransformBase::decompose(local, loc, rot, NULL, scale); - //if (node.getType() == COLLADASW::Node::JOINT) - node.addMatrix("transform", dmat); - //else - //add_transform(node, loc, rot, scale); + + if (node.getType() == COLLADASW::Node::JOINT) { + // XXX Why are joints handled differently ? + node.addMatrix("transform", dmat); + } + else { + add_transform(node, loc, rot, scale); + } } -void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) +void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type) { #if 0 float rot[3], loc[3], scale[3]; @@ -114,8 +118,23 @@ void TransformWriter::add_node_transform_ob(COLLADASW::Node& node, Object *ob) double d_obmat[4][4]; converter.mat4_to_dae_double(d_obmat, ob->obmat); - node.addMatrix("transform",d_obmat); - //add_transform(node, ob->loc, ob->rot, ob->size); + + switch (transformation_type) { + case BC_TRANSFORMATION_TYPE_MATRIX : { + node.addMatrix("transform",d_obmat); + break; + } + case BC_TRANSFORMATION_TYPE_TRANSROTLOC: { + add_transform(node, ob->loc, ob->rot, ob->size); + break; + } + case BC_TRANSFORMATION_TYPE_BOTH : { + node.addMatrix("transform",d_obmat); + add_transform(node, ob->loc, ob->rot, ob->size); + break; + } + } + } void TransformWriter::add_node_transform_identity(COLLADASW::Node& node) diff --git a/source/blender/collada/TransformWriter.h b/source/blender/collada/TransformWriter.h index d2a4b54a570..7f69a4b9c95 100644 --- a/source/blender/collada/TransformWriter.h +++ b/source/blender/collada/TransformWriter.h @@ -33,13 +33,14 @@ #include "DNA_object_types.h" #include "collada_internal.h" +#include "collada.h" class TransformWriter : protected TransformBase { protected: void add_node_transform(COLLADASW::Node& node, float mat[4][4], float parent_mat[4][4]); - void add_node_transform_ob(COLLADASW::Node& node, Object *ob); + void add_node_transform_ob(COLLADASW::Node& node, Object *ob, BC_export_transformation_type transformation_type); void add_node_transform_identity(COLLADASW::Node& node); diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index e75123c1e76..1eb5ac6ca4d 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -78,6 +78,7 @@ int collada_export(Scene *sce, int triangulate, int use_object_instantiation, int sort_by_name, + BC_export_transformation_type export_transformation_type, int second_life) { ExportSettings export_settings; @@ -85,7 +86,7 @@ int collada_export(Scene *sce, /* annoying, collada crashes if file cant be created! [#27162] */ if (!BLI_exists(filepath)) { BLI_make_existing_file(filepath); /* makes the dir if its not there */ - if (BLI_file_touch(filepath) == 0) { + if (!BLI_file_touch(filepath)) { fprintf(stdout, "Collada export: Can not create: %s\n", filepath); return 0; } @@ -107,10 +108,11 @@ int collada_export(Scene *sce, export_settings.include_material_textures= include_material_textures != 0; export_settings.use_texture_copies = use_texture_copies != 0; - export_settings.triangulate = triangulate != 0; - export_settings.use_object_instantiation = use_object_instantiation != 0; - export_settings.sort_by_name = sort_by_name != 0; - export_settings.second_life = second_life != 0; + export_settings.triangulate = triangulate != 0; + export_settings.use_object_instantiation = use_object_instantiation != 0; + export_settings.sort_by_name = sort_by_name != 0; + export_settings.export_transformation_type = export_transformation_type; + export_settings.second_life = second_life != 0; int includeFilter = OB_REL_NONE; diff --git a/source/blender/collada/collada.h b/source/blender/collada/collada.h index 642259da7fc..b3a8156b6fe 100644 --- a/source/blender/collada/collada.h +++ b/source/blender/collada/collada.h @@ -41,6 +41,12 @@ typedef enum BC_export_mesh_type { BC_MESH_TYPE_RENDER } BC_export_mesh_type; +typedef enum BC_export_transformation_type { + BC_TRANSFORMATION_TYPE_MATRIX, + BC_TRANSFORMATION_TYPE_TRANSROTLOC, + BC_TRANSFORMATION_TYPE_BOTH +} BC_export_transformation_type; + struct bContext; struct Scene; @@ -48,8 +54,8 @@ struct Scene; * both return 1 on success, 0 on error */ int collada_import(bContext *C, - const char *filepath, - int import_units); + const char *filepath, + int import_units); int collada_export(Scene *sce, const char *filepath, @@ -62,14 +68,15 @@ int collada_export(Scene *sce, int include_shapekeys, int deform_bones_only, - int active_uv_only, - int include_uv_textures, - int include_material_textures, - int use_texture_copies, + int active_uv_only, + int include_uv_textures, + int include_material_textures, + int use_texture_copies, int triangulate, int use_object_instantiation, int sort_by_name, + BC_export_transformation_type export_transformation_type, int second_life); diff --git a/source/blender/collada/collada_internal.cpp b/source/blender/collada/collada_internal.cpp index 85f98dad437..c3df2f0dc2f 100644 --- a/source/blender/collada/collada_internal.cpp +++ b/source/blender/collada/collada_internal.cpp @@ -224,6 +224,12 @@ void clear_global_id_map() } /** Look at documentation of translate_map */ +std::string translate_id(const char *idString) +{ + std::string id = std::string(idString); + return translate_id(id); +} + std::string translate_id(const std::string &id) { if (id.size() == 0) { diff --git a/source/blender/collada/collada_internal.h b/source/blender/collada/collada_internal.h index 7d59932bac9..2e855764f4b 100644 --- a/source/blender/collada/collada_internal.h +++ b/source/blender/collada/collada_internal.h @@ -92,6 +92,7 @@ public: extern void clear_global_id_map(); /** Look at documentation of translate_map */ extern std::string translate_id(const std::string &id); +extern std::string translate_id(const char *idString); extern std::string id_name(void *id); diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index c56aa3fdaf0..66f7feb8928 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -116,11 +116,11 @@ int bc_set_parent(Object *ob, Object *par, bContext *C, bool is_parent_space) DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA); DAG_id_tag_update(&par->id, OB_RECALC_OB); - /** done once after import + /** done once after import */ +#if 0 DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); - */ - +#endif return true; } @@ -299,15 +299,17 @@ int bc_get_active_UVLayer(Object *ob) return CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); } -std::string bc_url_encode(std::string data) { +std::string bc_url_encode(std::string data) +{ /* XXX We probably do not need to do a full encoding. - But in case that is necessary,then it can be added here. - */ + * But in case that is necessary,then it can be added here. + */ return bc_replace_string(data,"#", "%23"); } std::string bc_replace_string(std::string data, const std::string& pattern, - const std::string& replacement) { + const std::string& replacement) +{ size_t pos = 0; while((pos = data.find(pattern, pos)) != std::string::npos) { data.replace(pos, pattern.length(), replacement); @@ -317,15 +319,15 @@ std::string bc_replace_string(std::string data, const std::string& pattern, } /** - Calculate a rescale factor such that the imported scene's scale - is preserved. I.e. 1 meter in the import will also be - 1 meter in the current scene. - XXX : I am not sure if it is correct to map 1 Blender Unit - to 1 Meter for unit type NONE. But it looks reasonable to me. -*/ + * Calculate a rescale factor such that the imported scene's scale + * is preserved. I.e. 1 meter in the import will also be + * 1 meter in the current scene. + * XXX : I am not sure if it is correct to map 1 Blender Unit + * to 1 Meter for unit type NONE. But it looks reasonable to me. + */ void bc_match_scale(std::vector<Object *> *objects_done, - Scene &sce, - UnitConverter &bc_unit) { + Scene &sce, + UnitConverter &bc_unit) { Object *ob = NULL; diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index a64583b68ff..fc546188816 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -20,9 +20,9 @@ * Monique Dewanchand */ - #ifdef __cplusplus +#ifdef __cplusplus extern "C" { - #endif +#endif #include "DNA_color_types.h" #include "DNA_node_types.h" diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.cpp b/source/blender/compositor/intern/COM_ExecutionGroup.cpp index ffc36281874..14fd7e0b6cf 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.cpp +++ b/source/blender/compositor/intern/COM_ExecutionGroup.cpp @@ -40,6 +40,8 @@ #include "MEM_guardedalloc.h" #include "BLI_math.h" +#include "BLI_string.h" +#include "BKE_global.h" #include "PIL_time.h" #include "WM_api.h" #include "WM_types.h" @@ -60,6 +62,8 @@ ExecutionGroup::ExecutionGroup() this->m_openCL = false; this->m_singleThreaded = false; this->m_chunksFinished = 0; + BLI_rcti_init(&this->m_viewerBorder, 0, 0, 0, 0); + this->m_executionStartTime = 0; } CompositorPriority ExecutionGroup::getRenderPriotrity() @@ -196,6 +200,7 @@ void ExecutionGroup::determineResolution(unsigned int resolution[2]) resolution[0] = operation->getWidth(); resolution[1] = operation->getHeight(); this->setResolution(resolution); + BLI_rcti_init(&this->m_viewerBorder, 0, this->m_width, 0, this->m_height); } void ExecutionGroup::determineNumberOfChunks() @@ -207,8 +212,10 @@ void ExecutionGroup::determineNumberOfChunks() } else { const float chunkSizef = this->m_chunkSize; - this->m_numberOfXChunks = ceil(this->m_width / chunkSizef); - this->m_numberOfYChunks = ceil(this->m_height / chunkSizef); + const int border_width = BLI_rcti_size_x(&this->m_viewerBorder); + const int border_height = BLI_rcti_size_y(&this->m_viewerBorder); + this->m_numberOfXChunks = ceil(border_width / chunkSizef); + this->m_numberOfYChunks = ceil(border_height / chunkSizef); this->m_numberOfChunks = this->m_numberOfXChunks * this->m_numberOfYChunks; } } @@ -225,6 +232,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph) if (this->m_numberOfChunks == 0) {return; } /// @note: early break out unsigned int chunkNumber; + this->m_executionStartTime = PIL_check_seconds_timer(); + this->m_chunksFinished = 0; this->m_bTree = bTree; unsigned int index; @@ -245,6 +254,9 @@ void ExecutionGroup::execute(ExecutionSystem *graph) chunkorder = viewer->getChunkOrder(); } + const int border_width = BLI_rcti_size_x(&this->m_viewerBorder); + const int border_height = BLI_rcti_size_y(&this->m_viewerBorder); + switch (chunkorder) { case COM_TO_RANDOM: for (index = 0; index < 2 * this->m_numberOfChunks; index++) { @@ -258,14 +270,14 @@ void ExecutionGroup::execute(ExecutionSystem *graph) case COM_TO_CENTER_OUT: { ChunkOrderHotspot *hotspots[1]; - hotspots[0] = new ChunkOrderHotspot(this->m_width * centerX, this->m_height * centerY, 0.0f); + hotspots[0] = new ChunkOrderHotspot(border_width * centerX, border_height * centerY, 0.0f); rcti rect; ChunkOrder *chunkOrders = (ChunkOrder *)MEM_mallocN(sizeof(ChunkOrder) * this->m_numberOfChunks, __func__); for (index = 0; index < this->m_numberOfChunks; index++) { determineChunkRect(&rect, index); chunkOrders[index].setChunkNumber(index); - chunkOrders[index].setX(rect.xmin); - chunkOrders[index].setY(rect.ymin); + chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin); + chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin); chunkOrders[index].determineDistance(hotspots, 1); } @@ -281,10 +293,10 @@ void ExecutionGroup::execute(ExecutionSystem *graph) case COM_TO_RULE_OF_THIRDS: { ChunkOrderHotspot *hotspots[9]; - unsigned int tx = this->m_width / 6; - unsigned int ty = this->m_height / 6; - unsigned int mx = this->m_width / 2; - unsigned int my = this->m_height / 2; + unsigned int tx = border_width / 6; + unsigned int ty = border_height / 6; + unsigned int mx = border_width / 2; + unsigned int my = border_height / 2; unsigned int bx = mx + 2 * tx; unsigned int by = my + 2 * ty; @@ -303,8 +315,8 @@ void ExecutionGroup::execute(ExecutionSystem *graph) for (index = 0; index < this->m_numberOfChunks; index++) { determineChunkRect(&rect, index); chunkOrders[index].setChunkNumber(index); - chunkOrders[index].setX(rect.xmin); - chunkOrders[index].setY(rect.ymin); + chunkOrders[index].setX(rect.xmin - this->m_viewerBorder.xmin); + chunkOrders[index].setY(rect.ymin - this->m_viewerBorder.ymin); chunkOrders[index].determineDistance(hotspots, 9); } @@ -403,6 +415,35 @@ MemoryBuffer *ExecutionGroup::constructConsolidatedMemoryBuffer(MemoryProxy *mem return result; } +void ExecutionGroup::printBackgroundStats(void) +{ + uintptr_t mem_in_use, mmap_in_use, peak_memory; + float megs_used_memory, mmap_used_memory, megs_peak_memory; + double execution_time; + char timestr[64]; + + execution_time = PIL_check_seconds_timer() - this->m_executionStartTime; + + mem_in_use = MEM_get_memory_in_use(); + mmap_in_use = MEM_get_mapped_memory_in_use(); + peak_memory = MEM_get_peak_memory(); + + megs_used_memory = (mem_in_use - mmap_in_use) / (1024.0 * 1024.0); + mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); + megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); + + fprintf(stdout, "Mem:%.2fM (%.2fM, Peak %.2fM) ", + megs_used_memory, mmap_used_memory, megs_peak_memory); + + BLI_timestr(execution_time, timestr); + printf("| Elapsed %s ", timestr); + printf("| Tree %s, Tile %d-%d ", this->m_bTree->id.name + 2, + this->m_chunksFinished, this->m_numberOfChunks); + + fputc('\n', stdout); + fflush(stdout); +} + void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memoryBuffers) { if (this->m_chunkExecutionStates[chunkNumber] == COM_ES_SCHEDULED) @@ -426,18 +467,26 @@ void ExecutionGroup::finalizeChunkExecution(int chunkNumber, MemoryBuffer **memo float progress = this->m_chunksFinished; progress /= this->m_numberOfChunks; this->m_bTree->progress(this->m_bTree->prh, progress); + + if (G.background) + printBackgroundStats(); } } inline void ExecutionGroup::determineChunkRect(rcti *rect, const unsigned int xChunk, const unsigned int yChunk) const { + const int border_width = BLI_rcti_size_x(&this->m_viewerBorder); + const int border_height = BLI_rcti_size_y(&this->m_viewerBorder); + if (this->m_singleThreaded) { - BLI_rcti_init(rect, 0, this->m_width, 0, this->m_height); + BLI_rcti_init(rect, this->m_viewerBorder.xmin, border_width, this->m_viewerBorder.ymin, border_height); } else { - const unsigned int minx = xChunk * this->m_chunkSize; - const unsigned int miny = yChunk * this->m_chunkSize; - BLI_rcti_init(rect, minx, min(minx + this->m_chunkSize, this->m_width), miny, min(miny + this->m_chunkSize, this->m_height)); + const unsigned int minx = xChunk * this->m_chunkSize + this->m_viewerBorder.xmin; + const unsigned int miny = yChunk * this->m_chunkSize + this->m_viewerBorder.ymin; + const unsigned int width = min((unsigned int) this->m_viewerBorder.xmax, this->m_width); + const unsigned int height = min((unsigned int) this->m_viewerBorder.ymax, this->m_height); + BLI_rcti_init(rect, min(minx, this->m_width), min(minx + this->m_chunkSize, width), min(miny, this->m_height), min(miny + this->m_chunkSize, height)); } } @@ -472,9 +521,9 @@ bool ExecutionGroup::scheduleAreaWhenPossible(ExecutionSystem *graph, rcti *area float chunkSizef = this->m_chunkSize; int indexx, indexy; - int minxchunk = floor(area->xmin / chunkSizef); + int minxchunk = floor((area->xmin - this->m_viewerBorder.xmin) / chunkSizef); int maxxchunk = ceil((area->xmax - 1) / chunkSizef); - int minychunk = floor(area->ymin / chunkSizef); + int minychunk = floor((area->ymin - this->m_viewerBorder.ymin) / chunkSizef); int maxychunk = ceil((area->ymax - 1) / chunkSizef); minxchunk = max(minxchunk, 0); minychunk = max(minychunk, 0); @@ -574,3 +623,13 @@ bool ExecutionGroup::isOpenCL() { return this->m_openCL; } + +void ExecutionGroup::setViewerBorder(float xmin, float xmax, float ymin, float ymax) +{ + NodeOperation *operation = this->getOutputNodeOperation(); + + if (operation->isViewerOperation() || operation->isPreviewOperation()) { + BLI_rcti_init(&this->m_viewerBorder, xmin * this->m_width, xmax * this->m_width, + ymin * this->m_height, ymax * this->m_height); + } +} diff --git a/source/blender/compositor/intern/COM_ExecutionGroup.h b/source/blender/compositor/intern/COM_ExecutionGroup.h index 00104c24194..b5f02e05be1 100644 --- a/source/blender/compositor/intern/COM_ExecutionGroup.h +++ b/source/blender/compositor/intern/COM_ExecutionGroup.h @@ -161,7 +161,18 @@ private: * @see openCL */ bool m_initialized; - + + /** + * @brief denotes boundary for border compositing + * @note measured in pixel space + */ + rcti m_viewerBorder; + + /** + * @brief start time of execution + */ + double m_executionStartTime; + // methods /** * @brief check whether parameter operation can be added to the execution group @@ -335,6 +346,11 @@ public: * @see determineChunkRect */ MemoryBuffer *allocateOutputBuffer(int chunkNumber, rcti *rect); + + /** + * @brief print execution statistics to stdout when running in a background mode + */ + void printBackgroundStats(void); /** * @brief after a chunk is executed the needed resources can be freed or unlocked. @@ -395,6 +411,12 @@ public: */ CompositorPriority getRenderPriotrity(); + /** + * @brief set border for viewer operation + * @note all the coordinates are assumed to be in normalized space + */ + void setViewerBorder(float xmin, float xmax, float ymin, float ymax); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("COM:ExecutionGroup") #endif diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index 1ec4ac7699b..2b2af73d0c8 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -78,11 +78,22 @@ ExecutionSystem::ExecutionSystem(RenderData *rd, bNodeTree *editingtree, bool re this->groupOperations(); /* group operations in ExecutionGroups */ unsigned int index; unsigned int resolution[2]; + + rctf *viewer_border = &editingtree->viewer_border; + bool use_viewer_border = (editingtree->flag & NTREE_VIEWER_BORDER) && + viewer_border->xmin < viewer_border->xmax && + viewer_border->ymin < viewer_border->ymax; + for (index = 0; index < this->m_groups.size(); index++) { resolution[0] = 0; resolution[1] = 0; ExecutionGroup *executionGroup = this->m_groups[index]; executionGroup->determineResolution(resolution); + + if (use_viewer_border) { + executionGroup->setViewerBorder(viewer_border->xmin, viewer_border->xmax, + viewer_border->ymin, viewer_border->ymax); + } } #ifdef COM_DEBUG diff --git a/source/blender/compositor/nodes/COM_CompositorNode.cpp b/source/blender/compositor/nodes/COM_CompositorNode.cpp index fc4dea8cee3..a78f96adfc6 100644 --- a/source/blender/compositor/nodes/COM_CompositorNode.cpp +++ b/source/blender/compositor/nodes/COM_CompositorNode.cpp @@ -41,10 +41,11 @@ void CompositorNode::convertToOperations(ExecutionSystem *graph, CompositorConte compositorOperation->setSceneName(editorNode->id->name); compositorOperation->setRenderData(context->getRenderData()); compositorOperation->setbNodeTree(context->getbNodeTree()); - compositorOperation->setIgnoreAlpha(editorNode->custom2 & 1); + compositorOperation->setIgnoreAlpha(editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA); imageSocket->relinkConnections(compositorOperation->getInputSocket(0), 0, graph); alphaSocket->relinkConnections(compositorOperation->getInputSocket(1)); depthSocket->relinkConnections(compositorOperation->getInputSocket(2)); graph->addOperation(compositorOperation); addPreviewOperation(graph, context, compositorOperation->getInputSocket(0)); } + diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp index ab4e464327d..3e8f1fb0f74 100644 --- a/source/blender/compositor/nodes/COM_MixNode.cpp +++ b/source/blender/compositor/nodes/COM_MixNode.cpp @@ -124,6 +124,16 @@ void MixNode::convertToOperations(ExecutionSystem *graph, CompositorContext *con convertProg->setUseValueAlphaMultiply(useAlphaPremultiply); convertProg->setUseClamp(useClamp); + if (color1Socket->isConnected()) { + convertProg->setResolutionInputSocketIndex(1); + } + else { + if (color2Socket->isConnected()) + convertProg->setResolutionInputSocketIndex(2); + else + convertProg->setResolutionInputSocketIndex(0); + } + valueSocket->relinkConnections(convertProg->getInputSocket(0), 0, graph); color1Socket->relinkConnections(convertProg->getInputSocket(1), 1, graph); color2Socket->relinkConnections(convertProg->getInputSocket(2), 2, graph); diff --git a/source/blender/compositor/nodes/COM_ViewerNode.cpp b/source/blender/compositor/nodes/COM_ViewerNode.cpp index 94f3c2ebd80..8f9e58fee13 100644 --- a/source/blender/compositor/nodes/COM_ViewerNode.cpp +++ b/source/blender/compositor/nodes/COM_ViewerNode.cpp @@ -47,7 +47,7 @@ void ViewerNode::convertToOperations(ExecutionSystem *graph, CompositorContext * viewerOperation->setChunkOrder((OrderOfChunks)editorNode->custom1); viewerOperation->setCenterX(editorNode->custom3); viewerOperation->setCenterY(editorNode->custom4); - viewerOperation->setIgnoreAlpha(editorNode->custom2 & 1); + viewerOperation->setIgnoreAlpha(editorNode->custom2 & CMP_NODE_OUTPUT_IGNORE_ALPHA); viewerOperation->setViewSettings(context->getViewSettings()); viewerOperation->setDisplaySettings(context->getDisplaySettings()); diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.cpp b/source/blender/compositor/operations/COM_MixBaseOperation.cpp index 2d40629e764..438fb84ebb7 100644 --- a/source/blender/compositor/operations/COM_MixBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MixBaseOperation.cpp @@ -69,29 +69,3 @@ void MixBaseOperation::deinitExecution() this->m_inputColor1Operation = NULL; this->m_inputColor2Operation = NULL; } - -void MixBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) -{ - InputSocket *socket; - unsigned int tempPreferredResolution[2] = {0, 0}; - unsigned int tempResolution[2]; - - socket = this->getInputSocket(1); - socket->determineResolution(tempResolution, tempPreferredResolution); - if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { - this->setResolutionInputSocketIndex(1); - } - else { - socket = this->getInputSocket(2); - tempPreferredResolution[0] = 0; - tempPreferredResolution[1] = 0; - socket->determineResolution(tempResolution, tempPreferredResolution); - if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { - this->setResolutionInputSocketIndex(2); - } - else { - this->setResolutionInputSocketIndex(0); - } - } - NodeOperation::determineResolution(resolution, preferredResolution); -} diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.h b/source/blender/compositor/operations/COM_MixBaseOperation.h index 88d1d00c2bf..75ca1c3f6c6 100644 --- a/source/blender/compositor/operations/COM_MixBaseOperation.h +++ b/source/blender/compositor/operations/COM_MixBaseOperation.h @@ -71,8 +71,6 @@ public: */ void deinitExecution(); - void determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]); - void setUseValueAlphaMultiply(const bool value) { this->m_valueAlphaMultiply = value; } bool useValueAlphaMultiply() { return this->m_valueAlphaMultiply; } void setUseClamp(bool value) { this->m_useClamp = value; } diff --git a/source/blender/compositor/operations/COM_PreviewOperation.h b/source/blender/compositor/operations/COM_PreviewOperation.h index 9e774d0e41b..0da6b8e4e56 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.h +++ b/source/blender/compositor/operations/COM_PreviewOperation.h @@ -26,6 +26,7 @@ #include "DNA_image_types.h" #include "DNA_color_types.h" #include "BLI_rect.h" +#include "BKE_global.h" class PreviewOperation : public NodeOperation { protected: @@ -42,7 +43,7 @@ protected: const ColorManagedDisplaySettings *m_displaySettings; public: PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings); - bool isOutputOperation(bool rendering) const { return true; } + bool isOutputOperation(bool rendering) const { return !G.background; } void initExecution(); void deinitExecution(); const CompositorPriority getRenderPriority() const; diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 23a3abe61ee..08f6f8ada4a 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -25,7 +25,7 @@ #include "BLI_listbase.h" #include "BKE_image.h" -TextureBaseOperation::TextureBaseOperation() : NodeOperation() +TextureBaseOperation::TextureBaseOperation() : SingleThreadedNodeOperation() { this->addInputSocket(COM_DT_VECTOR); //offset this->addInputSocket(COM_DT_VECTOR); //size @@ -48,6 +48,7 @@ void TextureBaseOperation::initExecution() this->m_inputOffset = getInputSocketReader(0); this->m_inputSize = getInputSocketReader(1); this->m_pool = BKE_image_pool_new(); + SingleThreadedNodeOperation::initExecution(); } void TextureBaseOperation::deinitExecution() { @@ -55,6 +56,7 @@ void TextureBaseOperation::deinitExecution() this->m_inputOffset = NULL; BKE_image_pool_free(this->m_pool); this->m_pool = NULL; + SingleThreadedNodeOperation::deinitExecution(); } void TextureBaseOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -89,8 +91,8 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel int retval; const float cx = this->getWidth() / 2; const float cy = this->getHeight() / 2; - const float u = (cx - x) / this->getWidth() * 2; - const float v = (cy - y) / this->getHeight() * 2; + const float u = (x - cx) / this->getWidth() * 2; + const float v = (y - cy) / this->getHeight() * 2; this->m_inputSize->read(textureSize, x, y, sampler); this->m_inputOffset->read(textureOffset, x, y, sampler); @@ -115,3 +117,26 @@ void TextureBaseOperation::executePixel(float output[4], float x, float y, Pixel output[0] = output[1] = output[2] = output[3]; } } + +MemoryBuffer *TextureBaseOperation::createMemoryBuffer(rcti *rect2) +{ + int height = getHeight(); + int width = getWidth(); + + rcti rect; + rect.xmin = 0; + rect.ymin = 0; + rect.xmax = width; + rect.ymax = height; + MemoryBuffer *result = new MemoryBuffer(NULL, &rect); + + float *data = result->getBuffer(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++, data += 4) { + this->executePixel(data, x, y, COM_PS_NEAREST); + } + } + + return result; +} diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index 227ad37579a..fc9369099a6 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -24,7 +24,7 @@ #ifndef _COM_TextureOperation_h #define _COM_TextureOperation_h -#include "COM_NodeOperation.h" +#include "COM_SingleThreadedNodeOperation.h" #include "DNA_texture_types.h" #include "BLI_listbase.h" extern "C" { @@ -39,7 +39,7 @@ extern "C" { * * @todo: rename to operation. */ -class TextureBaseOperation : public NodeOperation { +class TextureBaseOperation : public SingleThreadedNodeOperation { private: Tex *m_texture; const RenderData *m_rd; @@ -59,6 +59,7 @@ protected: */ TextureBaseOperation(); + MemoryBuffer *createMemoryBuffer(rcti *rect2); public: void executePixel(float output[4], float x, float y, PixelSampler sampler); diff --git a/source/blender/compositor/operations/COM_TranslateOperation.cpp b/source/blender/compositor/operations/COM_TranslateOperation.cpp index 9f6924eb428..e2582c3b67b 100644 --- a/source/blender/compositor/operations/COM_TranslateOperation.cpp +++ b/source/blender/compositor/operations/COM_TranslateOperation.cpp @@ -42,8 +42,6 @@ void TranslateOperation::initExecution() this->m_inputOperation = this->getInputSocketReader(0); this->m_inputXOperation = this->getInputSocketReader(1); this->m_inputYOperation = this->getInputSocketReader(2); - - ensureDelta(); } void TranslateOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_ViewerBaseOperation.h b/source/blender/compositor/operations/COM_ViewerBaseOperation.h index 9f7e80ad6fc..7ead96b5c29 100644 --- a/source/blender/compositor/operations/COM_ViewerBaseOperation.h +++ b/source/blender/compositor/operations/COM_ViewerBaseOperation.h @@ -25,6 +25,7 @@ #include "COM_NodeOperation.h" #include "DNA_image_types.h" #include "BLI_rect.h" +#include "BKE_global.h" class ViewerBaseOperation : public NodeOperation { protected: @@ -45,7 +46,7 @@ protected: const ColorManagedDisplaySettings *m_displaySettings; public: - bool isOutputOperation(bool rendering) const { return isActiveViewerOutput(); } + bool isOutputOperation(bool rendering) const { if (G.background) return false; return isActiveViewerOutput(); } void initExecution(); void deinitExecution(); void setImage(Image *image) { this->m_image = image; } diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 533420ad641..d6188720cdf 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -384,6 +384,10 @@ static short acf_generic_dataexpand_setting_valid(bAnimContext *ac, bAnimListEle case ACHANNEL_SETTING_MUTE: return ((ac) && (ac->spacetype == SPACE_NLA)); + /* select is ok for most "ds*" channels (e.g. dsmat) */ + case ACHANNEL_SETTING_SELECT: + return 1; + /* other flags are never supported */ default: return 0; @@ -425,7 +429,7 @@ static void acf_summary_backdrop(bAnimContext *ac, bAnimListElem *ale, float ymi static void acf_summary_name(bAnimListElem *UNUSED(ale), char *name) { if (name) - BLI_strncpy(name, "DopeSheet Summary", ANIM_CHAN_NAME_SIZE); + BLI_strncpy(name, IFACE_("DopeSheet Summary"), ANIM_CHAN_NAME_SIZE); } // FIXME: this is really a temp icon I think @@ -896,6 +900,27 @@ static void acf_fcurve_name(bAnimListElem *ale, char *name) getname_anim_fcurve(name, ale->id, ale->data); } +/* "name" property for fcurve entries */ +static short acf_fcurve_name_prop(bAnimListElem *ale, PointerRNA *ptr, PropertyRNA **prop) +{ + FCurve *fcu = (FCurve *)ale->data; + + /* Ctrl-Click Usability Convenience Hack: + * For disabled F-Curves, allow access to the RNA Path + * as our "name" so that user can perform quick fixes + */ + if (fcu->flag & FCURVE_DISABLED) { + RNA_pointer_create(ale->id, &RNA_FCurve, ale->data, ptr); + *prop = RNA_struct_find_property(ptr, "data_path"); + } + else { + /* for "normal" F-Curves - no editable name, but *prop may not be set properly yet... */ + *prop = NULL; + } + + return (*prop != NULL); +} + /* check if some setting exists for this channel */ static short acf_fcurve_setting_valid(bAnimContext *ac, bAnimListElem *ale, int setting) { @@ -967,7 +992,7 @@ static bAnimChannelType ACF_FCURVE = acf_generic_group_offset, /* offset */ acf_fcurve_name, /* name */ - NULL, /* name prop */ + acf_fcurve_name_prop, /* name prop */ NULL, /* icon */ acf_fcurve_setting_valid, /* has setting */ @@ -1070,7 +1095,7 @@ static int acf_filldrivers_icon(bAnimListElem *UNUSED(ale)) static void acf_filldrivers_name(bAnimListElem *UNUSED(ale), char *name) { - BLI_strncpy(name, "Drivers", ANIM_CHAN_NAME_SIZE); + BLI_strncpy(name, IFACE_("Drivers"), ANIM_CHAN_NAME_SIZE); } /* check if some setting exists for this channel */ @@ -2338,7 +2363,7 @@ static void acf_shapekey_name(bAnimListElem *ale, char *name) if (kb->name[0]) BLI_strncpy(name, kb->name, ANIM_CHAN_NAME_SIZE); else - BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, "Key %d", ale->index); + BLI_snprintf(name, ANIM_CHAN_NAME_SIZE, IFACE_("Key %d"), ale->index); } } @@ -3490,10 +3515,13 @@ void ANIM_channel_draw_widgets(bContext *C, bAnimContext *ac, bAnimListElem *ale /* if rename index matches, add widget for this */ if (ac->ads->renameIndex == channel_index + 1) { - PointerRNA ptr; - PropertyRNA *prop; + PointerRNA ptr = {{NULL}}; + PropertyRNA *prop = NULL; - /* draw renaming widget if we can get RNA pointer for it */ + /* draw renaming widget if we can get RNA pointer for it + * NOTE: property may only be available in some cases, even if we have + * a callback available (e.g. broken F-Curve rename) + */ if (acf->name_prop(ale, &ptr, &prop)) { uiBut *but; diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 15a8222dec2..dd18d07732d 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -2272,7 +2272,7 @@ static void rename_anim_channels(bAnimContext *ac, int channel_index) ED_region_tag_redraw(ac->ar); } -static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *evt) +static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { bAnimContext ac; ARegion *ar; @@ -2293,7 +2293,7 @@ static int animchannels_rename_invoke(bContext *C, wmOperator *UNUSED(op), wmEve * so that the tops of channels get caught ok. Since ACHANNEL_FIRST is really ACHANNEL_HEIGHT, we simply use * ACHANNEL_HEIGHT_HALF. */ - UI_view2d_region_to_view(v2d, evt->mval[0], evt->mval[1], &x, &y); + UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &x, &y); if (ac.datatype == ANIMCONT_NLA) { SpaceNla *snla = (SpaceNla *)ac.sl; @@ -2609,7 +2609,7 @@ static int mouse_anim_channels(bAnimContext *ac, float UNUSED(x), int channel_in /* ------------------- */ /* handle clicking */ -static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int animchannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; ARegion *ar; @@ -2667,7 +2667,7 @@ static void ANIM_OT_channels_click(wmOperatorType *ot) ot->poll = animedit_poll_channels_active; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* properties */ /* NOTE: don't save settings, otherwise, can end up with some weird behaviour (sticky extend) */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 3480db2c5d8..7648d998216 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -449,7 +449,7 @@ short ANIM_animdata_get_context(const bContext *C, bAnimContext *ac) if (ANIMDATA_HAS_NLA(id)) { \ nlaOk \ } \ - else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) && ANIMDATA_HAS_KEYS(id)) { \ + else if (!(ads->filterflag & ADS_FILTER_NLA_NOACT) || ANIMDATA_HAS_KEYS(id)) { \ nlaOk \ } \ } \ @@ -1001,22 +1001,39 @@ static short skip_fcurve_with_name(bDopeSheet *ads, FCurve *fcu, ID *owner_id) /* Check if F-Curve has errors and/or is disabled * > returns: (bool) True if F-Curve has errors/is disabled */ -static short fcurve_has_errors(FCurve *fcu) +static bool fcurve_has_errors(FCurve *fcu) { /* F-Curve disabled - path eval error */ if (fcu->flag & FCURVE_DISABLED) { - return 1; + return true; } /* driver? */ if (fcu->driver) { - /* for now, just check if the entire thing got disabled... */ - if (fcu->driver->flag & DRIVER_FLAG_INVALID) - return 1; + ChannelDriver *driver = fcu->driver; + DriverVar *dvar; + + /* error flag on driver usually means that there is an error + * BUT this may not hold with PyDrivers as this flag gets cleared + * if no critical errors prevent the driver from working... + */ + if (driver->flag & DRIVER_FLAG_INVALID) + return true; + + /* check variables for other things that need linting... */ + // TODO: maybe it would be more efficient just to have a quick flag for this? + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + DRIVER_TARGETS_USED_LOOPER(dvar) + { + if (dtar->flag & DTAR_FLAG_INVALID) + return true; + } + DRIVER_TARGETS_LOOPER_END + } } /* no errors found */ - return 0; + return false; } /* find the next F-Curve that is usable for inclusion */ @@ -1060,7 +1077,7 @@ static FCurve *animfilter_fcurve_next(bDopeSheet *ads, FCurve *first, bActionGro /* error-based filtering... */ if ((ads) && (ads->filterflag & ADS_FILTER_ONLY_ERRORS)) { /* skip if no errors... */ - if (fcurve_has_errors(fcu) == 0) + if (fcurve_has_errors(fcu) == false) continue; } @@ -1297,7 +1314,9 @@ static size_t animfilter_block_data(bAnimContext *ac, ListBase *anim_data, bDope ANIMDATA_FILTER_CASES(iat, { /* AnimData */ /* specifically filter animdata block */ - ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id); + if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(adt)) ) { + ANIMCHANNEL_NEW_CHANNEL(adt, ANIMTYPE_ANIMDATA, id); + } }, { /* NLA */ items += animfilter_nla(ac, anim_data, ads, adt, filter_mode, id); @@ -1347,7 +1366,9 @@ static size_t animdata_filter_shapekey(bAnimContext *ac, ListBase *anim_data, Ke // TODO: somehow manage to pass dopesheet info down here too? if (key->adt) { if (filter_mode & ANIMFILTER_ANIMDATA) { - ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key); + if (ANIMCHANNEL_SELOK(SEL_ANIMDATA(key->adt)) ) { + ANIMCHANNEL_NEW_CHANNEL(key->adt, ANIMTYPE_ANIMDATA, key); + } } else if (key->adt->action) { items = animfilter_action(ac, anim_data, NULL, key->adt->action, filter_mode, (ID *)key); diff --git a/source/blender/editors/animation/anim_ipo_utils.c b/source/blender/editors/animation/anim_ipo_utils.c index b6d24e21057..2352cad0cbc 100644 --- a/source/blender/editors/animation/anim_ipo_utils.c +++ b/source/blender/editors/animation/anim_ipo_utils.c @@ -42,6 +42,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_anim_types.h" #include "RNA_access.h" @@ -63,9 +65,9 @@ int getname_anim_fcurve(char *name, ID *id, FCurve *fcu) return icon; else if (ELEM3(NULL, id, fcu, fcu->rna_path)) { if (fcu == NULL) - strcpy(name, "<invalid>"); + strcpy(name, IFACE_("<invalid>")); else if (fcu->rna_path == NULL) - strcpy(name, "<no path>"); + strcpy(name, IFACE_("<no path>")); else /* id == NULL */ BLI_snprintf(name, 256, "%s[%d]", fcu->rna_path, fcu->array_index); } diff --git a/source/blender/editors/animation/anim_markers.c b/source/blender/editors/animation/anim_markers.c index 62725cb6c70..7a3fc3a8d9b 100644 --- a/source/blender/editors/animation/anim_markers.c +++ b/source/blender/editors/animation/anim_markers.c @@ -28,7 +28,6 @@ * \ingroup edanimation */ - #include <math.h> #include "MEM_guardedalloc.h" @@ -36,10 +35,6 @@ #include "DNA_scene_types.h" #include "DNA_object_types.h" -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - #include "BLI_blenlib.h" #include "BLI_math_base.h" #include "BLI_utildefines.h" @@ -51,6 +46,10 @@ #include "BKE_scene.h" #include "BKE_screen.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + #include "WM_api.h" #include "WM_types.h" @@ -277,7 +276,9 @@ static void add_marker_to_cfra_elem(ListBase *lb, TimeMarker *marker, short only ce->sel = marker->flag; return; } - else if (ce->cfra > marker->frame) break; + else if (ce->cfra > marker->frame) { + break; + } } cen = MEM_callocN(sizeof(CfraElem), "add_to_cfra_elem"); @@ -513,8 +514,8 @@ static int ed_markers_poll_markers_exist(bContext *C) * that operator would otherwise have used. If NULL, the operator's standard * exec() callback will be called instead in the appropriate places. */ -static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent *evt, - int (*invoke_func)(bContext *, wmOperator *, wmEvent *)) +static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, const wmEvent *event, + int (*invoke_func)(bContext *, wmOperator *, const wmEvent *)) { ScrArea *sa = CTX_wm_area(C); int retval = OPERATOR_PASS_THROUGH; @@ -523,7 +524,7 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent /* allow operator to run now */ if (invoke_func) - retval = invoke_func(C, op, evt); + retval = invoke_func(C, op, event); else if (op->type->exec) retval = op->type->exec(C, op); else @@ -544,9 +545,9 @@ static int ed_markers_opwrap_invoke_custom(bContext *C, wmOperator *op, wmEvent * though will need to implement their own wrapper which calls the second-tier callback themselves * (passing through the custom invoke function they use) */ -static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_markers_opwrap_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - return ed_markers_opwrap_invoke_custom(C, op, evt, NULL); + return ed_markers_opwrap_invoke_custom(C, op, event, NULL); } /* ************************** add markers *************************** */ @@ -684,14 +685,14 @@ static void ed_marker_move_exit(bContext *C, wmOperator *op) ED_area_headerprint(CTX_wm_area(C), NULL); } -static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_move_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (ed_marker_move_init(C, op)) { MarkerMove *mm = op->customdata; - mm->evtx = evt->x; - mm->firstx = evt->x; - mm->event_type = evt->type; + mm->evtx = event->x; + mm->firstx = event->x; + mm->event_type = event->type; /* add temp handler */ WM_event_add_modal_handler(C, op); @@ -705,9 +706,9 @@ static int ed_marker_move_invoke(bContext *C, wmOperator *op, wmEvent *evt) return OPERATOR_CANCELLED; } -static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_move_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { - return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_move_invoke); + return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_move_invoke); } /* note, init has to be called succesfully */ @@ -756,7 +757,7 @@ static int ed_marker_move_cancel(bContext *C, wmOperator *op) -static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_move_modal(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); MarkerMove *mm = op->customdata; @@ -765,14 +766,14 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) float dx, fac; char str[256]; - switch (evt->type) { + switch (event->type) { case ESCKEY: ed_marker_move_cancel(C, op); return OPERATOR_CANCELLED; case RIGHTMOUSE: /* press = user manually demands transform to be canceled */ - if (evt->val == KM_PRESS) { + if (event->val == KM_PRESS) { ed_marker_move_cancel(C, op); return OPERATOR_CANCELLED; } @@ -782,7 +783,7 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) case PADENTER: case LEFTMOUSE: case MIDDLEMOUSE: - if (WM_modal_tweak_exit(evt, mm->event_type)) { + if (WM_modal_tweak_exit(event, mm->event_type)) { ed_marker_move_exit(C, op); WM_event_add_notifier(C, NC_SCENE | ND_MARKERS, NULL); WM_event_add_notifier(C, NC_ANIMATION | ND_MARKERS, NULL); @@ -795,17 +796,17 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) dx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); - if (evt->x != mm->evtx) { /* XXX maybe init for first time */ + if (event->x != mm->evtx) { /* XXX maybe init for first time */ int a, offs, totmark = 0; - mm->evtx = evt->x; + mm->evtx = event->x; - fac = ((float)(evt->x - mm->firstx) * dx); + fac = ((float)(event->x - mm->firstx) * dx); if (mm->slink->spacetype == SPACE_TIME) - apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0); + apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, FPS, 0.1 * FPS, 0); else - apply_keyb_grid(evt->shift, evt->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/); + apply_keyb_grid(event->shift, event->ctrl, &fac, 0.0, 1.0, 0.1, 0 /*was: U.flag & USER_AUTOGRABGRID*/); offs = (int)fac; RNA_int_set(op->ptr, "frames", offs); @@ -864,8 +865,8 @@ static int ed_marker_move_modal(bContext *C, wmOperator *op, wmEvent *evt) } } - if (evt->val == KM_PRESS) { - if (handleNumInput(&mm->num, evt)) { + if (event->val == KM_PRESS) { + if (handleNumInput(&mm->num, event)) { char str_tx[NUM_STR_REP_LEN]; float value = RNA_int_get(op->ptr, "frames"); applyNumInput(&mm->num, &value); @@ -981,15 +982,15 @@ static int ed_marker_duplicate_exec(bContext *C, wmOperator *op) } -static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ed_marker_duplicate_apply(C); - return ed_marker_move_invoke(C, op, evt); + return ed_marker_move_invoke(C, op, event); } -static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_duplicate_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { - return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_duplicate_invoke); + return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_duplicate_invoke); } static void MARKER_OT_duplicate(wmOperatorType *ot) @@ -1036,7 +1037,7 @@ static void select_timeline_marker_frame(ListBase *markers, int frame, unsigned } } -static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) +static int ed_marker_select(bContext *C, const wmEvent *event, int extend, int camera) { ListBase *markers = ED_context_get_markers(C); ARegion *ar = CTX_wm_region(C); @@ -1047,8 +1048,8 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) if (markers == NULL) return OPERATOR_PASS_THROUGH; - x = evt->x - ar->winrct.xmin; - y = evt->y - ar->winrct.ymin; + x = event->x - ar->winrct.xmin; + y = event->y - ar->winrct.ymin; UI_view2d_region_to_view(v2d, x, y, &viewx, NULL); @@ -1103,19 +1104,19 @@ static int ed_marker_select(bContext *C, wmEvent *evt, int extend, int camera) return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; } -static int ed_marker_select_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { short extend = RNA_boolean_get(op->ptr, "extend"); short camera = 0; #ifdef DURIAN_CAMERA_SWITCH camera = RNA_boolean_get(op->ptr, "camera"); #endif - return ed_marker_select(C, evt, extend, camera); + return ed_marker_select(C, event, extend, camera); } -static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_select_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { - return ed_markers_opwrap_invoke_custom(C, op, evt, ed_marker_select_invoke); + return ed_markers_opwrap_invoke_custom(C, op, event, ed_marker_select_invoke); } static void MARKER_OT_select(wmOperatorType *ot) @@ -1200,9 +1201,9 @@ static int ed_marker_border_select_exec(bContext *C, wmOperator *op) return 1; } -static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_select_border_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { - return ed_markers_opwrap_invoke_custom(C, op, evt, WM_border_select_invoke); + return ed_markers_opwrap_invoke_custom(C, op, event, WM_border_select_invoke); } static void MARKER_OT_select_border(wmOperatorType *ot) @@ -1309,10 +1310,10 @@ static int ed_marker_delete_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_delete_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { // XXX: must we keep these confirmations? - return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_confirm); + return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_confirm); } static void MARKER_OT_delete(wmOperatorType *ot) @@ -1352,7 +1353,7 @@ static int ed_marker_rename_exec(bContext *C, wmOperator *op) } } -static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { /* must initialize the marker name first if there is a marker selected */ TimeMarker *marker = ED_markers_get_first_selected(ED_context_get_markers(C)); @@ -1360,7 +1361,7 @@ static int ed_marker_rename_invoke_wrapper(bContext *C, wmOperator *op, wmEvent RNA_string_set(op->ptr, "name", marker->name); /* now see if the operator is usable */ - return ed_markers_opwrap_invoke_custom(C, op, evt, WM_operator_props_popup); + return ed_markers_opwrap_invoke_custom(C, op, event, WM_operator_props_popup); } static void MARKER_OT_rename(wmOperatorType *ot) @@ -1414,9 +1415,9 @@ static int ed_marker_make_links_scene_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, wmEvent *evt) +static int ed_marker_make_links_scene_invoke_wrapper(bContext *C, wmOperator *op, const wmEvent *event) { - return ed_markers_opwrap_invoke_custom(C, op, evt, WM_menu_invoke); + return ed_markers_opwrap_invoke_custom(C, op, event, WM_menu_invoke); } static void MARKER_OT_make_links_scene(wmOperatorType *ot) diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 6687cce88cd..b9a3daa4e51 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -115,7 +115,7 @@ static int change_frame_exec(bContext *C, wmOperator *op) /* ---- */ /* Get frame from mouse coordinates */ -static int frame_from_event(bContext *C, wmEvent *event) +static int frame_from_event(bContext *C, const wmEvent *event) { ARegion *region = CTX_wm_region(C); float viewx; @@ -128,7 +128,7 @@ static int frame_from_event(bContext *C, wmEvent *event) } /* Modal Operator init */ -static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* Change to frame that mouse is over before adding modal handler, * as user could click on a single frame (jump to frame) as well as @@ -145,7 +145,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* Modal event handling of frame changing */ -static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) +static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) { /* execute the events */ switch (event->type) { diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 6d1e6eab26b..ed8398b7c8b 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -714,7 +714,6 @@ static float visualkey_get_value(PointerRNA *ptr, PropertyRNA *prop, int array_i else if (ptr->type == &RNA_PoseBone) { Object *ob = (Object *)ptr->id.data; /* we assume that this is always set, and is an object */ bPoseChannel *pchan = (bPoseChannel *)ptr->data; - float tmat[4][4]; /* Although it is not strictly required for this particular space conversion, * arg1 must not be null, as there is a null check for the other conversions to @@ -1298,7 +1297,7 @@ void ANIM_OT_keyframe_insert(wmOperatorType *ot) * then calls the menu if necessary before */ -static int insert_key_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int insert_key_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); @@ -1308,7 +1307,7 @@ static int insert_key_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(e uiLayout *layout; /* call the menu, which will call this operator again, hence the canceled */ - pup = uiPupMenuBegin(C, op->type->name, ICON_NONE); + pup = uiPupMenuBegin(C, RNA_struct_ui_name(op->type->srna), ICON_NONE); layout = uiPupMenuLayout(pup); uiItemsEnumO(layout, "ANIM_OT_keyframe_insert_menu", "type"); uiPupMenuEnd(C, pup); @@ -1624,17 +1623,21 @@ static int insert_key_button_exec(bContext *C, wmOperator *op) success += insert_keyframe_direct(op->reports, ptr, prop, fcu, cfra, 0); } else { - if (G.debug & G_DEBUG) - printf("Button Insert-Key: no path to property\n"); - BKE_report(op->reports, RPT_WARNING, "Failed to resolve path to property, try using a keying set instead"); + BKE_report(op->reports, RPT_WARNING, + "Failed to resolve path to property, try manually specifying this using a Keying Set instead"); } } - else if (G.debug & G_DEBUG) { - printf("ptr.data = %p, prop = %p,", (void *)ptr.data, (void *)prop); - if (prop) - printf("animatable = %d\n", RNA_property_animateable(&ptr, prop)); - else - printf("animatable = NULL\n"); + else { + if (prop && !RNA_property_animateable(&ptr, prop)) { + BKE_reportf(op->reports, RPT_WARNING, + "\"%s\" property cannot be animated", + RNA_property_identifier(prop)); + } + else { + BKE_reportf(op->reports, RPT_WARNING, + "Button doesn't appear to have any property information attached (ptr.data = %p, prop = %p)", + (void *)ptr.data, (void *)prop); + } } if (success) { diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 4e8d7bdafe5..ad09fcb5966 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -468,7 +468,7 @@ void ANIM_OT_keyingset_button_remove(wmOperatorType *ot) /* Change Active KeyingSet Operator ------------------------ */ /* This operator checks if a menu should be shown for choosing the KeyingSet to make the active one */ -static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int keyingset_active_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; @@ -879,7 +879,7 @@ short ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks) if (ksi == NULL) return MODIFYKEY_MISSING_TYPEINFO; /* TODO: check for missing callbacks! */ - + /* check if it can be used in the current context */ if (ksi->poll(ksi, C)) { /* if a list of data sources are provided, run a special iterator over them, diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 531c0551c87..28fb74f0cdd 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -214,7 +214,7 @@ static int armature_click_extrude_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int armature_click_extrude_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int armature_click_extrude_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* TODO most of this code is copied from set3dcursor_invoke, * it would be better to reuse code in set3dcursor_invoke */ @@ -320,8 +320,8 @@ void updateDuplicateSubtargetObjects(EditBone *dupBone, ListBase *editbones, Obj bConstraint *curcon; ListBase *conlist; - if ( (pchan = BKE_pose_channel_verify(dst_ob->pose, dupBone->name)) ) { - if ( (conlist = &pchan->constraints) ) { + if ((pchan = BKE_pose_channel_verify(dst_ob->pose, dupBone->name))) { + if ((conlist = &pchan->constraints)) { for (curcon = conlist->first; curcon; curcon = curcon->next) { /* does this constraint have a subtarget in * this armature? diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index 6417a795712..561e196bf41 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -72,7 +72,7 @@ EditBone *editbone_name_exists(ListBase *edbo, const char *name) } /* note: there's a unique_bone_name() too! */ -static int editbone_unique_check(void *arg, const char *name) +static bool editbone_unique_check(void *arg, const char *name) { struct {ListBase *lb; void *bone; } *data = arg; EditBone *dupli = editbone_name_exists(data->lb, name); @@ -91,7 +91,7 @@ void unique_editbone_name(ListBase *edbo, char *name, EditBone *bone) /* ************************************************** */ /* Bone Renaming - API */ -static int bone_unique_check(void *arg, const char *name) +static bool bone_unique_check(void *arg, const char *name) { return BKE_armature_find_bone_name((bArmature *)arg, name) != NULL; } @@ -152,7 +152,9 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n unique_editbone_name(arm->edbo, newname, NULL); BLI_strncpy(eBone->name, newname, MAXBONENAME); } - else return; + else { + return; + } } else { Bone *bone = BKE_armature_find_bone_name(arm, oldname); @@ -161,7 +163,9 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n unique_bone_name(arm, newname); BLI_strncpy(bone->name, newname, MAXBONENAME); } - else return; + else { + return; + } } /* do entire dbase - objects */ diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index c64bb5c4683..3a4dc31c82d 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -671,7 +671,7 @@ static int armature_parent_set_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { EditBone *actbone = CTX_data_active_bone(C); uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE); diff --git a/source/blender/editors/armature/armature_select.c b/source/blender/editors/armature/armature_select.c index b7a436cc209..7ff318bb6b6 100644 --- a/source/blender/editors/armature/armature_select.c +++ b/source/blender/editors/armature/armature_select.c @@ -166,7 +166,7 @@ void *get_nearest_bone(bContext *C, short findunsel, int x, int y) /* called in space.c */ /* previously "selectconnected_armature" */ -static int armature_select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bArmature *arm; EditBone *bone, *curBone, *next; @@ -323,7 +323,9 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2], else dep = 2; } - else dep = 2; + else { + dep = 2; + } } else { /* bone found */ @@ -333,7 +335,9 @@ static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2], else dep = 3; } - else dep = 3; + else { + dep = 3; + } } if (ebone == ebone_next_act) { @@ -390,8 +394,10 @@ void ED_armature_deselect_all(Object *obedit, int toggle) // } } } - else sel = toggle; - + else { + sel = toggle; + } + /* Set the flags */ for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { if (sel == 2) { diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 05f48ad73f4..4120be08b46 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -147,6 +147,15 @@ void ED_armature_edit_bone_remove(bArmature *arm, EditBone *exBone) bone_free(arm, exBone); } +bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child) +{ + for (ebone_child = ebone_child->parent; ebone_child; ebone_child = ebone_child->parent) { + if (ebone_child == ebone_parent) + return true; + } + return false; +} + /* *************************************************************** */ /* Mirroring */ diff --git a/source/blender/editors/armature/editarmature_generate.c b/source/blender/editors/armature/editarmature_generate.c index 89772d38e8f..bade93af8c1 100644 --- a/source/blender/editors/armature/editarmature_generate.c +++ b/source/blender/editors/armature/editarmature_generate.c @@ -263,7 +263,7 @@ EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *U parent = ED_armature_edit_bone_add(arm, "Bone"); copy_v3_v3(parent->head, iter->p); - if (iter->size > 0) { + if (iter->size > FLT_EPSILON) { parent->rad_head = iter->size * size_buffer; } @@ -278,7 +278,7 @@ EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *U child->parent = parent; child->flag |= BONE_CONNECTED; - if (iter->size > 0) { + if (iter->size > FLT_EPSILON) { child->rad_head = iter->size * size_buffer; parent->rad_tail = iter->size * size_buffer; } @@ -299,7 +299,7 @@ EditBone *subdivideArcBy(ToolSettings *toolsettings, bArmature *arm, ListBase *U iter->tail(iter); copy_v3_v3(parent->tail, iter->p); - if (iter->size > 0) { + if (iter->size > FLT_EPSILON) { parent->rad_tail = iter->size * size_buffer; } diff --git a/source/blender/editors/armature/editarmature_retarget.c b/source/blender/editors/armature/editarmature_retarget.c index 62cce6b2c1e..536c5ff1f7c 100644 --- a/source/blender/editors/armature/editarmature_retarget.c +++ b/source/blender/editors/armature/editarmature_retarget.c @@ -409,11 +409,11 @@ static void renameTemplateBone(char *name, char *template_name, ListBase *editbo for (i = 0, j = 0; i < (MAXBONENAME - 1) && j < (MAXBONENAME - 1) && template_name[i] != '\0'; i++) { if (template_name[i] == '&') { if (template_name[i + 1] == 'S' || template_name[i + 1] == 's') { - j += sprintf(name + j, "%s", side_string); + j += BLI_strncpy_rlen(name + j, side_string, MAXBONENAME); i++; } else if (template_name[i + 1] == 'N' || template_name[i + 1] == 'n') { - j += sprintf(name + j, "%s", num_string); + j += BLI_strncpy_rlen(name + j, num_string, MAXBONENAME); i++; } else { @@ -896,7 +896,7 @@ static void RIG_reconnectControlBones(RigGraph *rg) /* look on deform bones first */ BLI_ghashIterator_init(&ghi, rg->bones_map); - for (; !BLI_ghashIterator_isDone(&ghi); BLI_ghashIterator_step(&ghi)) { + for (; BLI_ghashIterator_notDone(&ghi); BLI_ghashIterator_step(&ghi)) { EditBone *bone = (EditBone *)BLI_ghashIterator_getValue(&ghi); /* don't link with parent */ diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index ec96c574f75..a3515e0983d 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -28,9 +28,6 @@ #include "DNA_scene_types.h" #include "DNA_armature_types.h" -#include "RNA_define.h" -#include "RNA_access.h" - #include "BLI_blenlib.h" #include "BLI_math.h" @@ -39,6 +36,9 @@ #include "BKE_context.h" #include "BKE_sketch.h" +#include "RNA_define.h" +#include "RNA_access.h" + #include "ED_view3d.h" #include "ED_screen.h" @@ -170,20 +170,20 @@ const char *BIF_listTemplates(const bContext *UNUSED(C)) GHashIterator ghi; const char *menu_header = IFACE_("Template %t|None %x0|"); char *p; + const size_t template_size = (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30); if (TEMPLATES_MENU != NULL) { MEM_freeN(TEMPLATES_MENU); } - TEMPLATES_MENU = MEM_callocN(sizeof(char) * (BLI_ghash_size(TEMPLATES_HASH) * 32 + 30), "skeleton template menu"); + TEMPLATES_MENU = MEM_callocN(sizeof(char) * template_size, "skeleton template menu"); p = TEMPLATES_MENU; - - p += sprintf(TEMPLATES_MENU, "%s", menu_header); + p += BLI_strncpy_rlen(p, menu_header, template_size); BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); - while (!BLI_ghashIterator_isDone(&ghi)) { + while (BLI_ghashIterator_notDone(&ghi)) { Object *ob = BLI_ghashIterator_getValue(&ghi); int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); @@ -203,7 +203,7 @@ int BIF_currentTemplate(const bContext *C) GHashIterator ghi; BLI_ghashIterator_init(&ghi, TEMPLATES_HASH); - while (!BLI_ghashIterator_isDone(&ghi)) { + while (BLI_ghashIterator_notDone(&ghi)) { Object *ob = BLI_ghashIterator_getValue(&ghi); int key = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(&ghi)); @@ -922,17 +922,18 @@ static void sk_projectDrawPoint(bContext *C, float vec[3], SK_Stroke *stk, SK_Dr float fp[3] = {0, 0, 0}; float dvec[3]; float mval_f[2]; + float zfac; if (last != NULL) { copy_v3_v3(fp, last->p); } - initgrabz(ar->regiondata, fp[0], fp[1], fp[2]); + zfac = ED_view3d_calc_zfac(ar->regiondata, fp, NULL); /* method taken from editview.c - mouse_cursor() */ if (ED_view3d_project_short_global(ar, fp, cval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { VECSUB2D(mval_f, cval, dd->mval); - ED_view3d_win_to_delta(ar, mval_f, dvec); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); sub_v3_v3v3(vec, fp, dvec); } else { @@ -2231,7 +2232,7 @@ void BDR_drawSketch(const bContext *C) } } -static int sketch_delete(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int sketch_delete(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { SK_Sketch *sketch = contextSketch(C, 0); if (sketch) { @@ -2328,7 +2329,7 @@ SK_Sketch *viewcontextSketch(ViewContext *vc, int create) return sketch; } -static int sketch_convert(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int sketch_convert(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { SK_Sketch *sketch = contextSketch(C, 0); if (sketch != NULL) { @@ -2338,7 +2339,7 @@ static int sketch_convert(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(e return OPERATOR_FINISHED; } -static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { SK_Sketch *sketch = contextSketch(C, 0); if (sketch != NULL) { @@ -2349,7 +2350,7 @@ static int sketch_cancel(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(ev return OPERATOR_PASS_THROUGH; } -static int sketch_finish(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int sketch_finish(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { SK_Sketch *sketch = contextSketch(C, 0); if (sketch != NULL) { @@ -2361,7 +2362,7 @@ static int sketch_finish(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(ev return OPERATOR_PASS_THROUGH; } -static int sketch_select(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int sketch_select(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { SK_Sketch *sketch = contextSketch(C, 0); if (sketch) { @@ -2381,7 +2382,7 @@ static int sketch_draw_stroke_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int sketch_draw_stroke(bContext *C, wmOperator *op, wmEvent *event) +static int sketch_draw_stroke(bContext *C, wmOperator *op, const wmEvent *event) { short snap = RNA_boolean_get(op->ptr, "snap"); SK_DrawData *dd; @@ -2407,7 +2408,7 @@ static int sketch_draw_gesture_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event) +static int sketch_draw_gesture(bContext *C, wmOperator *op, const wmEvent *event) { short snap = RNA_boolean_get(op->ptr, "snap"); SK_DrawData *dd; @@ -2425,7 +2426,7 @@ static int sketch_draw_gesture(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short gesture, SK_Stroke *stk) +static int sketch_draw_modal(bContext *C, wmOperator *op, const wmEvent *event, short gesture, SK_Stroke *stk) { short snap = RNA_boolean_get(op->ptr, "snap"); SK_DrawData *dd = op->customdata; @@ -2483,19 +2484,19 @@ static int sketch_draw_modal(bContext *C, wmOperator *op, wmEvent *event, short return retval; } -static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) +static int sketch_draw_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) { SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ return sketch_draw_modal(C, op, event, 0, sketch->active_stroke); } -static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, wmEvent *event) +static int sketch_draw_gesture_modal(bContext *C, wmOperator *op, const wmEvent *event) { SK_Sketch *sketch = contextSketch(C, 1); /* create just to be sure */ return sketch_draw_modal(C, op, event, 1, sketch->gesture); } -static int sketch_draw_preview(bContext *C, wmOperator *op, wmEvent *event) +static int sketch_draw_preview(bContext *C, wmOperator *op, const wmEvent *event) { short snap = RNA_boolean_get(op->ptr, "snap"); SK_Sketch *sketch = contextSketch(C, 0); diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c index 3d1d5d2f6ba..40b96132699 100644 --- a/source/blender/editors/armature/pose_edit.c +++ b/source/blender/editors/armature/pose_edit.c @@ -201,7 +201,7 @@ void ED_pose_recalculate_paths(Scene *scene, Object *ob) /* show popup to determine settings */ -static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); @@ -793,7 +793,7 @@ void ARMATURE_OT_layers_show_all(wmOperatorType *ot) /* ------------------- */ /* Present a popup to get the layers that should be used */ -static int pose_armature_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int pose_armature_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = (ob) ? ob->data : NULL; @@ -810,7 +810,7 @@ static int pose_armature_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt RNA_boolean_set_array(op->ptr, "layers", layers); /* part to sync with other similar operators... */ - return WM_operator_props_popup(C, op, evt); + return WM_operator_props_popup(C, op, event); } /* Set the visible layers for the active armature (edit and pose modes) */ @@ -879,7 +879,7 @@ void ARMATURE_OT_armature_layers(wmOperatorType *ot) /* ------------------- */ /* Present a popup to get the layers that should be used */ -static int pose_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int pose_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ @@ -900,7 +900,7 @@ static int pose_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt) RNA_boolean_set_array(op->ptr, "layers", layers); /* part to sync with other similar operators... */ - return WM_operator_props_popup(C, op, evt); + return WM_operator_props_popup(C, op, event); } /* Set the visible layers for the active armature (edit and pose modes) */ @@ -954,7 +954,7 @@ void POSE_OT_bone_layers(wmOperatorType *ot) /* ------------------- */ /* Present a popup to get the layers that should be used */ -static int armature_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int armature_bone_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ @@ -975,7 +975,7 @@ static int armature_bone_layers_invoke(bContext *C, wmOperator *op, wmEvent *evt RNA_boolean_set_array(op->ptr, "layers", layers); /* part to sync with other similar operators... */ - return WM_operator_props_popup(C, op, evt); + return WM_operator_props_popup(C, op, event); } /* Set the visible layers for the active armature (edit and pose modes) */ diff --git a/source/blender/editors/armature/pose_group.c b/source/blender/editors/armature/pose_group.c index 06a88f013d7..99f54de134a 100644 --- a/source/blender/editors/armature/pose_group.c +++ b/source/blender/editors/armature/pose_group.c @@ -126,7 +126,7 @@ void POSE_OT_group_remove(wmOperatorType *ot) /* ------------ */ /* invoke callback which presents a list of bone-groups for the user to choose from */ -static int pose_groups_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int pose_groups_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = ED_pose_object_from_context(C); bPose *pose; diff --git a/source/blender/editors/armature/pose_lib.c b/source/blender/editors/armature/pose_lib.c index 457874c7ae6..09c0f7e9647 100644 --- a/source/blender/editors/armature/pose_lib.c +++ b/source/blender/editors/armature/pose_lib.c @@ -389,7 +389,7 @@ static void poselib_add_menu_invoke__replacemenu(bContext *C, uiLayout *layout, } } -static int poselib_add_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int poselib_add_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); Object *ob = get_poselib_object(C); @@ -613,7 +613,7 @@ void POSELIB_OT_pose_remove(wmOperatorType *ot) ot->prop = prop; } -static int poselib_rename_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int poselib_rename_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = get_poselib_object(C); bAction *act = (ob) ? ob->poselib : NULL; @@ -638,7 +638,7 @@ static int poselib_rename_invoke(bContext *C, wmOperator *op, wmEvent *evt) } /* part to sync with other similar operators... */ - return WM_operator_props_popup(C, op, evt); + return WM_operator_props_popup(C, op, event); } static int poselib_rename_exec(bContext *C, wmOperator *op) @@ -1185,7 +1185,7 @@ static void poselib_preview_handle_search(tPoseLib_PreviewData *pld, unsigned sh } /* handle events for poselib_preview_poses */ -static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, wmEvent *event) +static int poselib_preview_handle_event(bContext *UNUSED(C), wmOperator *op, const wmEvent *event) { tPoseLib_PreviewData *pld = op->customdata; int ret = OPERATOR_RUNNING_MODAL; @@ -1539,7 +1539,7 @@ static int poselib_preview_cancel(bContext *C, wmOperator *op) } /* main modal status check */ -static int poselib_preview_modal(bContext *C, wmOperator *op, wmEvent *event) +static int poselib_preview_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseLib_PreviewData *pld = op->customdata; int ret; @@ -1559,7 +1559,7 @@ static int poselib_preview_modal(bContext *C, wmOperator *op, wmEvent *event) } /* Modal Operator init */ -static int poselib_preview_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int poselib_preview_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { tPoseLib_PreviewData *pld; diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index 186c7a1fe89..4fa1389426d 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -208,7 +208,7 @@ static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend) /* within active object context */ /* previously known as "selectconnected_posearmature" */ -static int pose_select_connected_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bArmature *arm = (bArmature *)ob->data; diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index fee37a9c0fb..4d6f8f520f5 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -614,12 +614,12 @@ static int pose_slide_invoke_common(bContext *C, wmOperator *op, tPoseSlideOp *p } /* common code for modal() */ -static int pose_slide_modal(bContext *C, wmOperator *op, wmEvent *evt) +static int pose_slide_modal(bContext *C, wmOperator *op, const wmEvent *event) { tPoseSlideOp *pso = op->customdata; wmWindow *win = CTX_wm_window(C); - switch (evt->type) { + switch (event->type) { case LEFTMOUSE: /* confirm */ case RETKEY: { @@ -660,7 +660,7 @@ static int pose_slide_modal(bContext *C, wmOperator *op, wmEvent *evt) /* calculate percentage based on position of mouse (we only use x-axis for now. * since this is more convenient for users to do), and store new percentage value */ - pso->percentage = (evt->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx); + pso->percentage = (event->x - pso->ar->winrct.xmin) / ((float)pso->ar->winx); RNA_float_set(op->ptr, "percentage", pso->percentage); /* update percentage indicator in header */ @@ -717,7 +717,7 @@ static void pose_slide_opdef_properties(wmOperatorType *ot) /* ------------------------------------ */ /* invoke() - for 'push' mode */ -static int pose_slide_push_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int pose_slide_push_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { tPoseSlideOp *pso; @@ -774,7 +774,7 @@ void POSE_OT_push(wmOperatorType *ot) /* ........................ */ /* invoke() - for 'relax' mode */ -static int pose_slide_relax_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int pose_slide_relax_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { tPoseSlideOp *pso; @@ -831,7 +831,7 @@ void POSE_OT_relax(wmOperatorType *ot) /* ........................ */ /* invoke() - for 'breakdown' mode */ -static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int pose_slide_breakdown_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { tPoseSlideOp *pso; diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index 454b0f0bceb..d04938fd59b 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -1659,7 +1659,7 @@ int filterSmartReebGraph(ReebGraph *UNUSED(rg), float UNUSED(threshold)) float avg_vec[3] = {0, 0, 0}; for (BLI_ghashIterator_init(&ghi, arc->faces); - !BLI_ghashIterator_isDone(&ghi); + BLI_ghashIterator_notDone(&ghi); BLI_ghashIterator_step(&ghi)) { EditFace *efa = BLI_ghashIterator_getValue(&ghi); @@ -2045,7 +2045,7 @@ void mergeArcFaces(ReebGraph *UNUSED(rg), ReebArc *aDst, ReebArc *aSrc) GHashIterator ghi; for (BLI_ghashIterator_init(&ghi, aSrc->faces); - !BLI_ghashIterator_isDone(&ghi); + BLI_ghashIterator_notDone(&ghi); BLI_ghashIterator_step(&ghi)) { EditFace *efa = BLI_ghashIterator_getValue(&ghi); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index d01e5c5d9bf..e134507600e 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -626,7 +626,9 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu) bezt++; } } - else fp += a * 12; + else { + fp += a * 12; + } } else { BPoint *bp = nu->bp; @@ -640,7 +642,9 @@ static void switch_keys_direction(Curve *cu, Nurb *actnu) bp++; } } - else fp += a * 4; + else { + fp += a * 4; + } } nu = nu->next; @@ -672,7 +676,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex) gh = BLI_ghash_ptr_new("dupli_keyIndex gh"); for (hashIter = BLI_ghashIterator_new(keyindex); - !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_notDone(hashIter); BLI_ghashIterator_step(hashIter)) { void *cv = BLI_ghashIterator_getKey(hashIter); @@ -1473,7 +1477,9 @@ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag) if (*u == -1) *u = b; else return 0; } - else if (sel > 1) return 0; /* because sel == 1 is still ok */ + else if (sel > 1) { + return 0; /* because sel == 1 is still ok */ + } } for (a = 0; a < nu->pntsu; a++) { @@ -1486,7 +1492,9 @@ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag) if (*v == -1) *v = a; else return 0; } - else if (sel > 1) return 0; + else if (sel > 1) { + return 0; + } } if (*u == -1 && *v > -1) return 1; @@ -1781,7 +1789,7 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag) else { /* which row or column is selected */ - if (isNurbselUV(nu, &u, &v, flag) ) { + if (isNurbselUV(nu, &u, &v, flag)) { /* deselect all */ bp = nu->bp; @@ -1872,7 +1880,7 @@ static void adduplicateflagNurb(Object *obedit, short flag) for (a = 0; a < nu->pntsu; a++) { enda = -1; starta = a; - while ( (bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag) ) { + while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) { select_beztriple(bezt, DESELECT, flag, HIDDEN); enda = a; if (a >= nu->pntsu - 1) break; @@ -2431,12 +2439,12 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short BezTriple *bezt; BPoint *bp; int a; - short lastsel = 0; + short lastsel = false; if (next == 0) return; for (nu = editnurb->first; nu; nu = nu->next) { - lastsel = 0; + lastsel = false; if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; @@ -2447,12 +2455,12 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short bezt += next; if (!(bezt->f2 & SELECT) || (selstatus == 0)) { short sel = select_beztriple(bezt, selstatus, 1, VISIBLE); - if ((sel == 1) && (cont == 0)) lastsel = 1; + if ((sel == 1) && (cont == 0)) lastsel = true; } } else { bezt += next; - lastsel = 0; + lastsel = false; } /* move around in zigzag way so that we go through each */ bezt -= (next - next / abs(next)); @@ -2468,12 +2476,12 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short bp += next; if (!(bp->f1 & SELECT) || (selstatus == 0)) { short sel = select_bpoint(bp, selstatus, 1, VISIBLE); - if ((sel == 1) && (cont == 0)) lastsel = 1; + if ((sel == 1) && (cont == 0)) lastsel = true; } } else { bp += next; - lastsel = 0; + lastsel = false; } /* move around in zigzag way so that we go through each */ bp -= (next - next / abs(next)); @@ -2878,7 +2886,7 @@ static void subdividenurb(Object *obedit, int number_cuts) keyIndex_updateBezt(editnurb, prevbezt, beztn, 1); beztn++; - if (BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, prevbezt) && BEZSELECTED_HIDDENHANDLES(cu, bezt)) { float prevvec[3][3]; memcpy(prevvec, prevbezt->vec, sizeof(float) * 9); @@ -3062,7 +3070,7 @@ static void subdividenurb(Object *obedit, int number_cuts) bp++; } } - if (sel == (nu->pntsu * nu->pntsv) ) { /* subdivide entire nurb */ + if (sel == (nu->pntsu * nu->pntsv)) { /* subdivide entire nurb */ /* Global subdivision is a special case of partial * subdivision. Strange it is considered separately... */ @@ -3332,7 +3340,7 @@ static void findselectedNurbvert(ListBase *editnurb, Nurb **nu, BezTriple **bezt bezt1 = nu1->bezt; a = nu1->pntsu; while (a--) { - if ( (bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT) ) { + if ((bezt1->f1 & SELECT) || (bezt1->f2 & SELECT) || (bezt1->f3 & SELECT)) { if (*nu != NULL && *nu != nu1) { *nu = NULL; *bp = NULL; @@ -3803,7 +3811,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu /* first nurbs: u = resolu-1 selected */ - if (is_u_selected(nu1, nu1->pntsu - 1) ) { + if (is_u_selected(nu1, nu1->pntsu - 1)) { /* pass */ } else { @@ -3835,7 +3843,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu } /* 2nd nurbs: u = 0 selected */ - if (is_u_selected(nu2, 0) ) { + if (is_u_selected(nu2, 0)) { /* pass */ } else { @@ -4041,9 +4049,11 @@ static int make_segment_exec(bContext *C, wmOperator *op) if ((nu->flagu & CU_NURB_CYCLIC) == 0) { /* not cyclic */ if (nu->type == CU_BEZIER) { if (nu1 == NULL) { - if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt) ) nu1 = nu; + if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt)) { + nu1 = nu; + } else { - if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1])) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1]))) { nu1 = nu; BKE_nurb_direction_switch(nu); keyData_switchDirectionNurb(cu, nu); @@ -4051,23 +4061,27 @@ static int make_segment_exec(bContext *C, wmOperator *op) } } else if (nu2 == NULL) { - if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, nu->bezt)) { nu2 = nu; BKE_nurb_direction_switch(nu); keyData_switchDirectionNurb(cu, nu); } else { - if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1])) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, &(nu->bezt[nu->pntsu - 1]))) { nu2 = nu; } } } - else break; + else { + break; + } } else if (nu->pntsv == 1) { bp = nu->bp; if (nu1 == NULL) { - if (bp->f1 & SELECT) nu1 = nu; + if (bp->f1 & SELECT) { + nu1 = nu; + } else { bp = bp + (nu->pntsu - 1); if (bp->f1 & SELECT) { @@ -4090,7 +4104,9 @@ static int make_segment_exec(bContext *C, wmOperator *op) } } } - else break; + else { + break; + } } } } @@ -4421,7 +4437,7 @@ static int spin_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -4495,7 +4511,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3]) newnu->resolu = cu->resolu; newnu->flag |= CU_SMOOTH; } - else memcpy(newnu, nu, sizeof(Nurb)); + else { + memcpy(newnu, nu, sizeof(Nurb)); + } BLI_addtail(&editnurb->nurbs, newnu); set_actNurb(obedit, newnu); @@ -4609,7 +4627,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3]) bezt = newbezt; ok = 1; } - else bezt = NULL; + else { + bezt = NULL; + } if (bezt) { if (!newnu) nu->pntsu++; @@ -4687,7 +4707,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3]) bp = newbp; ok = 1; } - else bp = NULL; + else { + bp = NULL; + } if (bp) { if (mode == 'e') { @@ -4705,7 +4727,9 @@ static int addvert_Nurb(bContext *C, short mode, float location[3]) nu->pntsu++; BKE_nurb_knot_calc_u(nu); } - else BKE_nurb_knot_calc_u(newnu); + else { + BKE_nurb_knot_calc_u(newnu); + } } } @@ -4732,7 +4756,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) return addvert_Nurb(C, 0, location); } -static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -4761,7 +4785,7 @@ static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) copy_v3_v3(location, give_cursor(vc.scene, vc.v3d)); } - view3d_get_view_aligned_coordinate(&vc, location, event->mval, TRUE); + view3d_get_view_aligned_coordinate(vc.ar, location, event->mval, true); RNA_float_set_array(op->ptr, "location", location); } @@ -4864,7 +4888,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op) a = nu->pntsu; bezt = nu->bezt; while (a--) { - if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) { nu->flagu ^= CU_NURB_CYCLIC; break; } @@ -4915,7 +4939,7 @@ static int toggle_cyclic_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int toggle_cyclic_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int toggle_cyclic_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *obedit = CTX_data_edit_object(C); ListBase *editnurb = object_editcurve_get(obedit); @@ -4983,7 +5007,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) bezt = nu->bezt; a = nu->pntsu; while (a--) { - if ( (bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT) ) { + if ((bezt->f1 & SELECT) || (bezt->f2 & SELECT) || (bezt->f3 & SELECT)) { a = nu->pntsu; bezt = nu->bezt; while (a--) { @@ -5018,7 +5042,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return select_linked_exec(C, op); } @@ -5044,7 +5068,7 @@ void CURVE_OT_select_linked(wmOperatorType *ot) /***************** select linked pick operator ******************/ -static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); ViewContext vc; @@ -5333,7 +5357,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) BPoint *bp; BezTriple *bezt; int a; - short sel = 0, lastsel = 0; + short sel = 0, lastsel = false; short *selbpoints; if (obedit->type == OB_SURF) { @@ -5344,44 +5368,54 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) while (a--) { if ((bp->hide == 0) && (bp->f1 & SELECT)) { sel = 0; - + /* check if neighbors have been selected */ /* edges of surface are an exception */ - if ((a + 1) % nu->pntsu == 0) sel++; + if ((a + 1) % nu->pntsu == 0) { + sel++; + } else { bp--; if ((selbpoints[a + 1] == 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++; bp++; } - if ((a + 1) % nu->pntsu == 1) sel++; + if ((a + 1) % nu->pntsu == 1) { + sel++; + } else { bp++; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp--; } - if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) sel++; + if (a + 1 > nu->pntsu * nu->pntsv - nu->pntsu) { + sel++; + } else { bp -= nu->pntsu; if ((selbpoints[a + nu->pntsu] == 1) || ((bp->hide == 0) && (bp->f1 & SELECT))) sel++; bp += nu->pntsu; } - - if (a < nu->pntsu) sel++; + + if (a < nu->pntsu) { + sel++; + } else { bp += nu->pntsu; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp -= nu->pntsu; } - + if (sel != 4) { select_bpoint(bp, DESELECT, 1, VISIBLE); selbpoints[a] = 1; } } - else lastsel = 0; - + else { + lastsel = false; + } + bp++; } @@ -5390,26 +5424,29 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } else { for (nu = editnurb->first; nu; nu = nu->next) { - lastsel = 0; + lastsel = false; /* check what type of curve/nurb it is */ if (nu->type == CU_BEZIER) { a = nu->pntsu; bezt = nu->bezt; while (a--) { if ((bezt->hide == 0) && (bezt->f2 & SELECT)) { - if (lastsel == 1) sel = 1; - else sel = 0; - + sel = (lastsel == 1); + /* check if neighbors have been selected */ /* first and last are exceptions */ - if (a == nu->pntsu - 1) sel++; + if (a == nu->pntsu - 1) { + sel++; + } else { bezt--; if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++; bezt++; } - if (a == 0) sel++; + if (a == 0) { + sel++; + } else { bezt++; if ((bezt->hide == 0) && (bezt->f2 & SELECT)) sel++; @@ -5418,12 +5455,16 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) if (sel != 2) { select_beztriple(bezt, DESELECT, 1, VISIBLE); - lastsel = 1; + lastsel = true; + } + else { + lastsel = false; } - else lastsel = 0; } - else lastsel = 0; - + else { + lastsel = false; + } + bezt++; } } @@ -5436,28 +5477,36 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) else sel = 0; /* first and last are exceptions */ - if (a == nu->pntsu * nu->pntsv - 1) sel++; + if (a == nu->pntsu * nu->pntsv - 1) { + sel++; + } else { bp--; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp++; } - if (a == 0) sel++; + if (a == 0) { + sel++; + } else { bp++; if ((bp->hide == 0) && (bp->f1 & SELECT)) sel++; bp--; } - + if (sel != 2) { select_bpoint(bp, DESELECT, 1, VISIBLE); - lastsel = 1; + lastsel = true; + } + else { + lastsel = false; } - else lastsel = 0; } - else lastsel = 0; - + else { + lastsel = false; + } + bp++; } } @@ -5820,7 +5869,7 @@ static int delete_exec(bContext *C, wmOperator *op) int delta = 0; bezt = nu->bezt; for (a = 0; a < nu->pntsu; a++) { - if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) { memmove(bezt, bezt + 1, (nu->pntsu - a - 1) * sizeof(BezTriple)); keyIndex_delBezt(editnurb, bezt + delta); keyIndex_updateBezt(editnurb, bezt + 1, bezt, nu->pntsu - a - 1); @@ -5829,7 +5878,9 @@ static int delete_exec(bContext *C, wmOperator *op) type = 1; delta++; } - else bezt++; + else { + bezt++; + } } if (type) { bezt1 = (BezTriple *)MEM_mallocN((nu->pntsu) * sizeof(BezTriple), "delNurb"); @@ -5889,16 +5940,16 @@ static int delete_exec(bContext *C, wmOperator *op) if (nu->type == CU_BEZIER) { bezt = nu->bezt; for (a = 0; a < nu->pntsu - 1; a++) { - if (BEZSELECTED_HIDDENHANDLES(cu, bezt) ) { + if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) { bezt1 = bezt; bezt2 = bezt + 1; if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) { /* pass */ } else { /* maybe do not make cyclic */ - if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) ) { + if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) { bezt2 = bezt + (nu->pntsu - 1); - if ( (bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT) ) { + if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) { nu->flagu &= ~CU_NURB_CYCLIC; BKE_nurb_handles_calc(nu); WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); @@ -5925,7 +5976,7 @@ static int delete_exec(bContext *C, wmOperator *op) /* pass */ } else { /* maybe do not make cyclic */ - if (a == 0 && (nu->flagu & CU_NURB_CYCLIC) ) { + if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) { bp2 = bp + (nu->pntsu - 1); if (bp2->f1 & SELECT) { nu->flagu &= ~CU_NURB_CYCLIC; @@ -6046,7 +6097,7 @@ static int delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *obedit = CTX_data_edit_object(C); uiPopupMenu *pup; @@ -6187,10 +6238,12 @@ int join_curve_exec(bContext *C, wmOperator *UNUSED(op)) if (ob->totcol) { /* TODO, merge material lists */ CLAMP(newnu->mat_nr, 0, ob->totcol - 1); } - else newnu->mat_nr = 0; + else { + newnu->mat_nr = 0; + } BLI_addtail(&tempbase, newnu); - if ( (bezt = newnu->bezt) ) { + if ((bezt = newnu->bezt)) { a = newnu->pntsu; while (a--) { mul_m4_v3(cmat, bezt->vec[0]); @@ -6200,7 +6253,7 @@ int join_curve_exec(bContext *C, wmOperator *UNUSED(op)) } BKE_nurb_handles_calc(newnu); } - if ( (bp = newnu->bp) ) { + if ((bp = newnu->bp)) { a = newnu->pntsu * nu->pntsv; while (a--) { mul_m4_v3(cmat, bp->vec); @@ -6653,14 +6706,18 @@ static int curvesurf_prim_add(bContext *C, wmOperator *op, int type, int isSurf) if (type & CU_PRIM_PATH) cu->flag |= CU_PATH | CU_3D; } - else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + else { + DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + } } else { /* adding surface */ if (obedit == NULL || obedit->type != OB_SURF) { obedit = ED_object_add_type(C, OB_SURF, loc, rot, TRUE, layer); newob = 1; } - else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + else { + DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + } } /* rename here, the undo stack checks name for valid undo pushes */ diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index af6b90a9958..63444c5c17e 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -405,7 +405,7 @@ static int paste_file_exec(bContext *C, wmOperator *op) return retval; } -static int paste_file_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int paste_file_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (RNA_struct_property_is_set(op->ptr, "filepath")) return paste_file_exec(C, op); @@ -1221,16 +1221,16 @@ static int insert_text_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int insert_text_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; EditFont *ef = cu->editfont; static int accentcode = 0; - uintptr_t ascii = evt->ascii; - int alt = evt->alt, shift = evt->shift, ctrl = evt->ctrl; - int event = evt->type, val = evt->val; + uintptr_t ascii = event->ascii; + int alt = event->alt, shift = event->shift, ctrl = event->ctrl; + int event_type = event->type, event_val = event->val; wchar_t inserted_text[2] = {0}; if (RNA_struct_property_is_set(op->ptr, "text")) @@ -1243,26 +1243,26 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) } /* tab should exit editmode, but we allow it to be typed using modifier keys */ - if (event == TABKEY) { + if (event_type == TABKEY) { if ((alt || ctrl || shift) == 0) return OPERATOR_PASS_THROUGH; else ascii = 9; } - if (event == BACKSPACEKEY) { + if (event_type == BACKSPACEKEY) { if (alt && cu->len != 0 && cu->pos > 0) accentcode = 1; return OPERATOR_PASS_THROUGH; } - if (val && (ascii || evt->utf8_buf[0])) { + if (event_val && (ascii || event->utf8_buf[0])) { /* handle case like TAB (== 9) */ if ( (ascii > 31 && ascii < 254 && ascii != 127) || (ascii == 13) || (ascii == 10) || (ascii == 8) || - (evt->utf8_buf[0])) + (event->utf8_buf[0])) { if (accentcode) { @@ -1272,8 +1272,8 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) } accentcode = 0; } - else if (evt->utf8_buf[0]) { - BLI_strncpy_wchar_from_utf8(inserted_text, evt->utf8_buf, 1); + else if (event->utf8_buf[0]) { + BLI_strncpy_wchar_from_utf8(inserted_text, event->utf8_buf, 1); ascii = inserted_text[0]; insert_into_textbuf(obedit, ascii); accentcode = 0; @@ -1307,7 +1307,7 @@ static int insert_text_invoke(bContext *C, wmOperator *op, wmEvent *evt) } /* reset property? */ - if (val == 0) + if (event_val == 0) accentcode = 0; return OPERATOR_FINISHED; @@ -1643,7 +1643,7 @@ static int font_open_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { VFont *vfont = NULL; char *path; diff --git a/source/blender/editors/datafiles/SConscript b/source/blender/editors/datafiles/SConscript index c17ab386fe6..d4e6ed4aff8 100644 --- a/source/blender/editors/datafiles/SConscript +++ b/source/blender/editors/datafiles/SConscript @@ -35,75 +35,75 @@ incs = "" # generated data files import os sources.extend(( - os.path.join(env['DATA_SOURCES'], "bfont.pfb.c"), - os.path.join(env['DATA_SOURCES'], "bfont.ttf.c"), - os.path.join(env['DATA_SOURCES'], "bmonofont.ttf.c"), + os.path.join(env['DATA_SOURCES'], "bfont.pfb.c"), + os.path.join(env['DATA_SOURCES'], "bfont.ttf.c"), + os.path.join(env['DATA_SOURCES'], "bmonofont.ttf.c"), - os.path.join(env['DATA_SOURCES'], "splash.png.c"), - os.path.join(env['DATA_SOURCES'], "blender_icons16.png.c"), - os.path.join(env['DATA_SOURCES'], "blender_icons32.png.c"), - os.path.join(env['DATA_SOURCES'], "prvicons.png.c"), + os.path.join(env['DATA_SOURCES'], "splash.png.c"), + os.path.join(env['DATA_SOURCES'], "blender_icons16.png.c"), + os.path.join(env['DATA_SOURCES'], "blender_icons32.png.c"), + os.path.join(env['DATA_SOURCES'], "prvicons.png.c"), - os.path.join(env['DATA_SOURCES'], "startup.blend.c"), - os.path.join(env['DATA_SOURCES'], "preview.blend.c"), - os.path.join(env['DATA_SOURCES'], "preview_cycles.blend.c"), - - os.path.join(env['DATA_SOURCES'], "add.png.c"), - os.path.join(env['DATA_SOURCES'], "blob.png.c"), - os.path.join(env['DATA_SOURCES'], "blur.png.c"), - os.path.join(env['DATA_SOURCES'], "clay.png.c"), - os.path.join(env['DATA_SOURCES'], "claystrips.png.c"), - os.path.join(env['DATA_SOURCES'], "clone.png.c"), - os.path.join(env['DATA_SOURCES'], "crease.png.c"), - os.path.join(env['DATA_SOURCES'], "darken.png.c"), - os.path.join(env['DATA_SOURCES'], "draw.png.c"), - os.path.join(env['DATA_SOURCES'], "fill.png.c"), - os.path.join(env['DATA_SOURCES'], "flatten.png.c"), - os.path.join(env['DATA_SOURCES'], "grab.png.c"), - os.path.join(env['DATA_SOURCES'], "inflate.png.c"), - os.path.join(env['DATA_SOURCES'], "layer.png.c"), - os.path.join(env['DATA_SOURCES'], "lighten.png.c"), - os.path.join(env['DATA_SOURCES'], "mask.png.c"), - os.path.join(env['DATA_SOURCES'], "mix.png.c"), - os.path.join(env['DATA_SOURCES'], "multiply.png.c"), - os.path.join(env['DATA_SOURCES'], "nudge.png.c"), - os.path.join(env['DATA_SOURCES'], "pinch.png.c"), - os.path.join(env['DATA_SOURCES'], "scrape.png.c"), - os.path.join(env['DATA_SOURCES'], "smear.png.c"), - os.path.join(env['DATA_SOURCES'], "smooth.png.c"), - os.path.join(env['DATA_SOURCES'], "snake_hook.png.c"), - os.path.join(env['DATA_SOURCES'], "soften.png.c"), - os.path.join(env['DATA_SOURCES'], "subtract.png.c"), - os.path.join(env['DATA_SOURCES'], "texdraw.png.c"), - os.path.join(env['DATA_SOURCES'], "thumb.png.c"), - os.path.join(env['DATA_SOURCES'], "twist.png.c"), - os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"), - - os.path.join(env['DATA_SOURCES'], "mc01.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc02.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc03.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc04.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc05.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc06.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc07.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc08.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc09.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc10.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc11.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc12.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc13.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc14.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc15.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc16.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc17.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc18.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc19.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc20.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc21.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc22.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc23.jpg.c"), - os.path.join(env['DATA_SOURCES'], "mc24.jpg.c"), + os.path.join(env['DATA_SOURCES'], "startup.blend.c"), + os.path.join(env['DATA_SOURCES'], "preview.blend.c"), + os.path.join(env['DATA_SOURCES'], "preview_cycles.blend.c"), - )) + os.path.join(env['DATA_SOURCES'], "add.png.c"), + os.path.join(env['DATA_SOURCES'], "blob.png.c"), + os.path.join(env['DATA_SOURCES'], "blur.png.c"), + os.path.join(env['DATA_SOURCES'], "clay.png.c"), + os.path.join(env['DATA_SOURCES'], "claystrips.png.c"), + os.path.join(env['DATA_SOURCES'], "clone.png.c"), + os.path.join(env['DATA_SOURCES'], "crease.png.c"), + os.path.join(env['DATA_SOURCES'], "darken.png.c"), + os.path.join(env['DATA_SOURCES'], "draw.png.c"), + os.path.join(env['DATA_SOURCES'], "fill.png.c"), + os.path.join(env['DATA_SOURCES'], "flatten.png.c"), + os.path.join(env['DATA_SOURCES'], "grab.png.c"), + os.path.join(env['DATA_SOURCES'], "inflate.png.c"), + os.path.join(env['DATA_SOURCES'], "layer.png.c"), + os.path.join(env['DATA_SOURCES'], "lighten.png.c"), + os.path.join(env['DATA_SOURCES'], "mask.png.c"), + os.path.join(env['DATA_SOURCES'], "mix.png.c"), + os.path.join(env['DATA_SOURCES'], "multiply.png.c"), + os.path.join(env['DATA_SOURCES'], "nudge.png.c"), + os.path.join(env['DATA_SOURCES'], "pinch.png.c"), + os.path.join(env['DATA_SOURCES'], "scrape.png.c"), + os.path.join(env['DATA_SOURCES'], "smear.png.c"), + os.path.join(env['DATA_SOURCES'], "smooth.png.c"), + os.path.join(env['DATA_SOURCES'], "snake_hook.png.c"), + os.path.join(env['DATA_SOURCES'], "soften.png.c"), + os.path.join(env['DATA_SOURCES'], "subtract.png.c"), + os.path.join(env['DATA_SOURCES'], "texdraw.png.c"), + os.path.join(env['DATA_SOURCES'], "thumb.png.c"), + os.path.join(env['DATA_SOURCES'], "twist.png.c"), + os.path.join(env['DATA_SOURCES'], "vertexdraw.png.c"), + + os.path.join(env['DATA_SOURCES'], "mc01.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc02.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc03.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc04.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc05.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc06.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc07.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc08.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc09.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc10.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc11.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc12.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc13.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc14.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc15.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc16.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc17.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc18.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc19.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc20.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc21.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc22.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc23.jpg.c"), + os.path.join(env['DATA_SOURCES'], "mc24.jpg.c"), + + )) env.BlenderLib ( 'bf_editor_datafiles', sources, Split(incs), [], libtype=['core', 'player'], priority=[235, 30] ) diff --git a/source/blender/editors/gpencil/gpencil_buttons.c b/source/blender/editors/gpencil/gpencil_buttons.c index 0aa109a0aef..19c1bc34f5c 100644 --- a/source/blender/editors/gpencil/gpencil_buttons.c +++ b/source/blender/editors/gpencil/gpencil_buttons.c @@ -86,6 +86,29 @@ static void gp_ui_dellayer_cb(bContext *C, void *gpd, void *gpl) WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); } +/* move layer up */ +static void gp_ui_layer_up_cb(bContext *C, void *gpd_v, void *gpl_v) +{ + bGPdata *gpd = gpd_v; + bGPDlayer *gpl = gpl_v; + + BLI_remlink(&gpd->layers, gpl); + BLI_insertlinkbefore(&gpd->layers, gpl->prev, gpl); + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); +} + +/* move layer down */ +static void gp_ui_layer_down_cb(bContext *C, void *gpd_v, void *gpl_v) +{ + bGPdata *gpd = gpd_v; + bGPDlayer *gpl = gpl_v; + + BLI_remlink(&gpd->layers, gpl); + BLI_insertlinkafter(&gpd->layers, gpl->next, gpl); + + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); +} /* ------- Drawing Code ------- */ @@ -174,6 +197,18 @@ static void gp_drawui_layer(uiLayout *layout, bGPdata *gpd, bGPDlayer *gpl, cons /* name */ uiItemR(sub, &ptr, "info", 0, "", ICON_NONE); + /* move up/down */ + if (gpl->prev) { + but = uiDefIconBut(block, BUT, 0, ICON_TRIA_UP, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Move layer up")); + uiButSetFunc(but, gp_ui_layer_up_cb, gpd, gpl); + } + if (gpl->next) { + but = uiDefIconBut(block, BUT, 0, ICON_TRIA_DOWN, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Move layer down")); + uiButSetFunc(but, gp_ui_layer_down_cb, gpd, gpl); + } + /* delete 'button' */ uiBlockSetEmboss(block, UI_EMBOSSN); /* right-align ............................... */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 46815450bf2..bc68ad8869a 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -277,6 +277,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] int mval_prj[2]; float rvec[3], dvec[3]; float mval_f[2]; + float zfac; /* Current method just converts each point in screen-coordinates to * 3D-coordinates using the 3D-cursor as reference. In general, this @@ -288,12 +289,13 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] */ gp_get_3d_reference(p, rvec); + zfac = ED_view3d_calc_zfac(p->ar->regiondata, rvec, NULL); /* method taken from editview.c - mouse_cursor() */ /* TODO, use ED_view3d_project_float_global */ if (ED_view3d_project_int_global(p->ar, rvec, mval_prj, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { VECSUB2D(mval_f, mval_prj, mval); - ED_view3d_win_to_delta(p->ar, mval_f, dvec); + ED_view3d_win_to_delta(p->ar, mval_f, dvec, zfac); sub_v3_v3v3(out, rvec, dvec); } else { @@ -1237,13 +1239,6 @@ static void gp_paint_initstroke(tGPsdata *p, short paintmode) switch (p->sa->spacetype) { case SPACE_VIEW3D: { - RegionView3D *rv3d = p->ar->regiondata; - float rvec[3]; - - /* get reference point for 3d space placement */ - gp_get_3d_reference(p, rvec); - initgrabz(rv3d, rvec[0], rvec[1], rvec[2]); - p->gpd->sbuffer_sflag |= GP_STROKE_3DSPACE; } break; @@ -1551,7 +1546,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) } /* handle draw event */ -static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) +static void gpencil_draw_apply_event(wmOperator *op, const wmEvent *event) { tGPsdata *p = op->customdata; PointerRNA itemptr; @@ -1689,7 +1684,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) /* ------------------------------- */ /* start of interactive drawing part of operator */ -static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = NULL; wmWindow *win = CTX_wm_window(C); @@ -1800,7 +1795,7 @@ static void gpencil_stroke_end(wmOperator *op) } /* events handling during interactive drawing part of operator */ -static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) +static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) { tGPsdata *p = op->customdata; int estate = OPERATOR_PASS_THROUGH; /* default exit state - pass through to support MMB view nav, etc. */ diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 31f89063f05..39d1e283f54 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -129,7 +129,7 @@ void glaRasterPosSafe2f(float x, float y, float known_good_x, float known_good_y void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect); /** - * Functions like a limited glDrawPixels, but actually draws the + * glaDrawPixelsTex - Functions like a limited glDrawPixels, but actually draws the * image using textures, which can be tremendously faster on low-end * cards, and also avoids problems with the raster position being * clipped when offscreen. The routine respects the glPixelZoom values, @@ -141,9 +141,17 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo * 1-to-1 mapping to screen space. */ -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect); +void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect); -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY); +/** + * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef. + * only RGBA + * needs glaDefine2DArea to be set. + */ +void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect); + + +void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY); /* 2D Drawing Assistance */ diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index 414d2075bf6..625ef27f4f7 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -298,11 +298,14 @@ typedef enum eAnimFilter_Flags { #define SEL_MASKLAY(masklay) (masklay->flag & SELECT) - /* NLA only */ #define SEL_NLT(nlt) (nlt->flag & NLATRACK_SELECTED) #define EDITABLE_NLT(nlt) ((nlt->flag & NLATRACK_PROTECTED) == 0) + +/* AnimData - NLA mostly... */ +#define SEL_ANIMDATA(adt) (adt->flag & ADT_UI_SELECTED) + /* -------------- Channel Defines -------------- */ /* channel heights */ diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 30ac360cab6..310b60f13e8 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -61,7 +61,7 @@ typedef struct EditBone { * normal bones when leaving editmode. */ void *temp; /* Used to store temporary data */ - char name[64]; /* MAX_NAME */ + char name[64]; /* MAXBONENAME */ float roll; /* Roll along axis. We'll ultimately use the axis/angle method * for determining the transformation matrix of the bone. The axis * is tail-head while roll provides the angle. Refer to Graphics @@ -135,6 +135,7 @@ void ED_armature_validate_active(struct bArmature *arm); void add_primitive_bone(struct Scene *scene, struct View3D *v3d, struct RegionView3D *rv3d); struct EditBone *ED_armature_edit_bone_add(struct bArmature *arm, const char *name); void ED_armature_edit_bone_remove(struct bArmature *arm, EditBone *exBone); +bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child); void transform_armature_mirror_update(struct Object *obedit); void ED_armature_origin_set(struct Scene *scene, struct Object *ob, float cursor[3], int centermode, int around); diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index d66cc49a5d0..66c1798f507 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -63,8 +63,6 @@ void load_editNurb(struct Object *obedit); void make_editNurb(struct Object *obedit); void free_editNurb(struct Object *obedit); -void BKE_curve_editNurb_free(struct Curve *cu); - int mouse_nurb(struct bContext *C, const int mval[2], int extend, int deselect, int toggle); struct Nurb *add_nurbs_primitive(struct bContext *C, struct Object *obedit, float mat[4][4], int type, int newob); diff --git a/source/blender/editors/include/ED_fileselect.h b/source/blender/editors/include/ED_fileselect.h index d45504b3325..b7d9f811349 100644 --- a/source/blender/editors/include/ED_fileselect.h +++ b/source/blender/editors/include/ED_fileselect.h @@ -31,10 +31,11 @@ #ifndef __ED_FILESELECT_H__ #define __ED_FILESELECT_H__ -struct SpaceFile; struct ARegion; struct FileSelectParams; +struct SpaceFile; struct bContext; +struct wmWindowManager; #define FILE_LAYOUT_HOR 1 #define FILE_LAYOUT_VER 2 @@ -99,9 +100,9 @@ void ED_fileselect_layout_tilepos(FileLayout *layout, int tile, int *x, int *y); void ED_operatormacros_file(void); -void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile); +void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile); -void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile); +void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile); int ED_file_extension_icon(const char *relname); diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index d3de2593b9d..e704b8f0bf3 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -172,17 +172,10 @@ void em_setup_viewcontext(struct bContext *C, struct ViewContext *vc); /* renam extern unsigned int bm_vertoffs, bm_solidoffs, bm_wireoffs; - /* mesh_ops.c */ void ED_operatortypes_mesh(void); void ED_operatormacros_mesh(void); void ED_keymap_mesh(struct wmKeyConfig *keyconf); -void ED_keymap_mesh(struct wmKeyConfig *keyconf); - - -/* spacetypes.c */ -void ED_spacetypes_init(void); - /* editmesh_tools.c (could be moved) */ void EMBM_project_snap_verts(struct bContext *C, struct ARegion *ar, struct BMEditMesh *em); @@ -193,13 +186,14 @@ void paintface_flush_flags(struct Object *ob); int paintface_mouse_select(struct bContext *C, struct Object *ob, const int mval[2], int extend, int deselect, int toggle); int do_paintface_box_select(struct ViewContext *vc, struct rcti *rect, int select, int extend); void paintface_deselect_all_visible(struct Object *ob, int action, short flush_flags); -void paintface_select_linked(struct bContext *C, struct Object *ob, int mval[2], int mode); +void paintface_select_linked(struct bContext *C, struct Object *ob, const int mval[2], int mode); int paintface_minmax(struct Object *ob, float r_min[3], float r_max[3]); void paintface_hide(struct Object *ob, const int unselected); void paintface_reveal(struct Object *ob); void paintvert_deselect_all_visible(struct Object *ob, int action, short flush_flags); +void paintvert_select_ungrouped(struct Object *ob, short extend, short flush_flags); void paintvert_flush_flags(struct Object *ob); /* mirrtopo */ diff --git a/source/blender/editors/include/ED_numinput.h b/source/blender/editors/include/ED_numinput.h index 126ea13f0b2..e7d80d96f89 100644 --- a/source/blender/editors/include/ED_numinput.h +++ b/source/blender/editors/include/ED_numinput.h @@ -61,7 +61,7 @@ void initNumInput(NumInput *n); void outputNumInput(NumInput *n, char *str); short hasNumInput(NumInput *n); void applyNumInput(NumInput *n, float *vec); -char handleNumInput(NumInput *n, struct wmEvent *event); +char handleNumInput(NumInput *n, const struct wmEvent *event); #define NUM_MODAL_INCREMENT_UP 18 #define NUM_MODAL_INCREMENT_DOWN 19 diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index 72208a8e93d..d073eaa5607 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -71,7 +71,6 @@ void ED_region_visible_rect(struct ARegion *ar, struct rcti *rect); /* spaces */ -void ED_spacetypes_init(void); void ED_spacetypes_keymap(struct wmKeyConfig *keyconf); int ED_area_header_switchbutton(const struct bContext *C, struct uiBlock *block, int yco); int ED_area_header_standardbuttons(const struct bContext *C, struct uiBlock *block, int yco); diff --git a/source/blender/editors/include/ED_sequencer.h b/source/blender/editors/include/ED_sequencer.h index 23d173aebdc..21477a72014 100644 --- a/source/blender/editors/include/ED_sequencer.h +++ b/source/blender/editors/include/ED_sequencer.h @@ -31,7 +31,7 @@ struct Scene; struct Sequence; struct SpaceSeq; -void ED_sequencer_select_sequence_single(struct Scene *scene, struct Sequence *seq, int deselect_all); +void ED_sequencer_select_sequence_single(struct Scene *scene, struct Sequence *seq, bool deselect_all); void ED_sequencer_deselect_all(struct Scene *scene); int ED_space_sequencer_maskedit_mask_poll(struct bContext *C); diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index c8521cb194a..a40cf90f7ad 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -34,6 +34,8 @@ struct ARegionType; struct bContext; +void ED_spacetypes_init(void); + /* the pluginnable API for export to editors */ /* calls for registering default spaces */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index a41aaca15bd..6101d03b946 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -151,7 +151,7 @@ void Transform_Properties(struct wmOperatorType *ot, int flags); /* view3d manipulators */ -int BIF_do_manipulator(struct bContext *C, struct wmEvent *event, struct wmOperator *op); +int BIF_do_manipulator(struct bContext *C, const struct wmEvent *event, struct wmOperator *op); void BIF_draw_manipulator(const struct bContext *C); /* Snapping */ @@ -177,12 +177,12 @@ typedef enum SnapMode { #define SNAP_MIN_DISTANCE 30 -int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode); -int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode); -int snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); -int snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); -int snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); -int snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); +bool peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode); +bool peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode); +bool snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); +bool snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); +bool snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); +bool snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); #endif diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index d89d66dd62c..470bbe616cf 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -39,7 +39,6 @@ struct BMVert; struct BPoint; struct Base; struct BezTriple; -struct BezTriple; struct BoundBox; struct EditBone; struct ImBuf; @@ -47,7 +46,6 @@ struct MVert; struct Main; struct MetaElem; struct Nurb; -struct Nurb; struct Object; struct RegionView3D; struct Scene; @@ -174,52 +172,58 @@ void pose_foreachScreenBone( /* view3d_project.c */ -void ED_view3d_project_float_v2_m4(const struct ARegion *a, const float co[3], float r_co[2], float mat[4][4]); -void ED_view3d_project_float_v3_m4(struct ARegion *a, const float co[3], float r_co[3], float mat[4][4]); +void ED_view3d_project_float_v2_m4(const struct ARegion *ar, const float co[3], float r_co[2], float mat[4][4]); +void ED_view3d_project_float_v3_m4(const struct ARegion *ar, const float co[3], float r_co[3], float mat[4][4]); -eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base); +eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base); /* *** short *** */ -eV3DProjStatus ED_view3d_project_short_ex(struct ARegion *ar, float perspmat[4][4], const int is_local, +eV3DProjStatus ED_view3d_project_short_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local, const float co[3], short r_co[2], const eV3DProjTest flag); -eV3DProjStatus ED_view3d_project_short_global(struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag); -eV3DProjStatus ED_view3d_project_short_object(struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_short_global(const struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_short_object(const struct ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag); /* *** int *** */ -eV3DProjStatus ED_view3d_project_int_ex(struct ARegion *ar, float perspmat[4][4], const int is_local, +eV3DProjStatus ED_view3d_project_int_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local, const float co[3], int r_co[2], const eV3DProjTest flag); -eV3DProjStatus ED_view3d_project_int_global(struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag); -eV3DProjStatus ED_view3d_project_int_object(struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_int_global(const struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_int_object(const struct ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag); /* *** float *** */ -eV3DProjStatus ED_view3d_project_float_ex(struct ARegion *ar, float perspmat[4][4], const int is_local, - const float co[3], float r_co[2], const eV3DProjTest flag); -eV3DProjStatus ED_view3d_project_float_global(struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); -eV3DProjStatus ED_view3d_project_float_object(struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); - -int initgrabz(struct RegionView3D *rv3d, float x, float y, float z); -void ED_view3d_win_to_ray(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]); -void ED_view3d_global_to_vector(struct RegionView3D *rv3d, const float coord[3], float vec[3]); -void ED_view3d_win_to_3d(struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); -void ED_view3d_win_to_delta(struct ARegion *ar, const float mval[2], float out[3]); -void ED_view3d_win_to_vector(struct ARegion *ar, const float mval[2], float out[3]); -void ED_view3d_win_to_segment(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); -int ED_view3d_win_to_segment_clip(struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); -void ED_view3d_ob_project_mat_get(struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); +eV3DProjStatus ED_view3d_project_float_ex(const struct ARegion *ar, float perspmat[4][4], const bool is_local, + const float co[3], float r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); +eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); + +float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); +void ED_view3d_win_to_ray(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]); +void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coord[3], float vec[3]); +void ED_view3d_win_to_3d(const struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); +void ED_view3d_win_to_delta(const struct ARegion *ar, const float mval[2], float out[3], const float zfac); +void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]); +void ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); +int ED_view3d_win_to_segment_clip(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]); +void ED_view3d_ob_project_mat_get(const struct RegionView3D *v3d, struct Object *ob, float pmat[4][4]); void ED_view3d_unproject(struct bglMats *mats, float out[3], const float x, const float y, const float z); /* end */ -int ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, float *clipsta, float *clipend); -int ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, struct rctf *viewplane, float *clipsta, float *clipend); -void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, struct rctf *viewborder_r, short no_shift); -void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, struct View3D *v3d, struct RegionView3D *rv3d, float size_r[2]); +bool ED_view3d_clip_range_get(struct View3D *v3d, struct RegionView3D *rv3d, + float *r_clipsta, float *r_clipend, const bool use_ortho_factor); +bool ED_view3d_viewplane_get(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, + struct rctf *r_viewplane, float *r_clipsta, float *r_clipend); +void ED_view3d_calc_camera_border(struct Scene *scene, struct ARegion *ar, + struct View3D *v3d, struct RegionView3D *rv3d, + struct rctf *viewborder_r, const bool no_shift); +void ED_view3d_calc_camera_border_size(struct Scene *scene, struct ARegion *ar, + struct View3D *v3d, struct RegionView3D *rv3d, + float r_size[2]); void ED_view3d_clipping_calc(struct BoundBox *bb, float planes[4][4], struct bglMats *mats, const struct rcti *rect); void ED_view3d_clipping_local(struct RegionView3D *rv3d, float mat[4][4]); -int ED_view3d_clipping_test(struct RegionView3D *rv3d, const float vec[3], const int is_local); +int ED_view3d_clipping_test(struct RegionView3D *rv3d, const float co[3], const bool is_local); void ED_view3d_clipping_set(struct RegionView3D *rv3d); void ED_view3d_clipping_enable(void); void ED_view3d_clipping_disable(void); @@ -255,7 +259,8 @@ short view3d_opengl_select(struct ViewContext *vc, unsigned int *buffer, unsigne void view3d_set_viewcontext(struct bContext *C, struct ViewContext *vc); void view3d_operator_needs_opengl(const struct bContext *C); void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar); -int view3d_get_view_aligned_coordinate(struct ViewContext *vc, float fp[3], const int mval[2], const short do_fallback); +bool view3d_get_view_aligned_coordinate(struct ARegion *ar, float fp[3], const int mval[2], const bool do_fallback); +void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data); void view3d_get_transformation(const struct ARegion *ar, struct RegionView3D *rv3d, struct Object *ob, struct bglMats *mats); /* XXX should move to BLI_math */ @@ -285,7 +290,7 @@ void ED_view3d_offscreen_sky_color_get(struct Scene *scene, float sky_color[3]); struct Base *ED_view3d_give_base_under_cursor(struct bContext *C, const int mval[2]); void ED_view3d_quadview_update(struct ScrArea *sa, struct ARegion *ar, short do_clip); void ED_view3d_update_viewmat(struct Scene *scene, struct View3D *v3d, struct ARegion *ar, float viewmat[4][4], float winmat[4][4]); -int ED_view3d_lock(struct RegionView3D *rv3d); +bool ED_view3d_lock(struct RegionView3D *rv3d); uint64_t ED_view3d_datamask(struct Scene *scene, struct View3D *v3d); uint64_t ED_view3d_screen_datamask(struct bScreen *screen); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 450d97eb20e..2ac66fb1919 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -87,6 +87,7 @@ enum { TH_TRANSFORM, TH_VERTEX, TH_VERTEX_SELECT, + TH_VERTEX_UNREFERENCED, TH_VERTEX_SIZE, TH_OUTLINE_WIDTH, TH_EDGE, diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 2c17a629ed4..4f0d788d733 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -231,7 +231,9 @@ static void ui_text_bounds_block(uiBlock *block, float offset) nextcol = 1; col++; } - else nextcol = 0; + else { + nextcol = 0; + } bt->rect.xmin = x1addval; bt->rect.xmax = bt->rect.xmin + i + block->bounds; @@ -1461,6 +1463,8 @@ double ui_get_but_val(uiBut *but) if (but->rnaprop) { prop = but->rnaprop; + BLI_assert(but->rnaindex != -1); + switch (RNA_property_type(prop)) { case PROP_BOOLEAN: if (RNA_property_array_check(prop)) @@ -1642,6 +1646,9 @@ static double ui_get_but_scale_unit(uiBut *but, double value) if (unit_type == PROP_UNIT_LENGTH) { return value * (double)unit->scale_length; } + else if (unit_type == PROP_UNIT_CAMERA) { + return value * (double)unit->scale_length; + } else if (unit_type == PROP_UNIT_AREA) { return value * pow(unit->scale_length, 2); } @@ -1674,18 +1681,28 @@ void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen) } } -static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, int pad) +/** + * \param float_precision Override the button precision. + */ +static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double value, int pad, int float_precision) { UnitSettings *unit = but->block->unit; int do_split = unit->flag & USER_UNIT_OPT_SPLIT; int unit_type = uiButGetUnitType(but); - int precision = but->a2; + int precision; if (unit->scale_length < 0.0001f) unit->scale_length = 1.0f; // XXX do_versions - /* Sanity checks */ - if (precision > PRECISION_FLOAT_MAX) precision = PRECISION_FLOAT_MAX; - else if (precision == 0) precision = 2; + /* Use precision override? */ + if (float_precision == -1) { + /* Sanity checks */ + precision = (int)but->a2; + if (precision > PRECISION_FLOAT_MAX) precision = PRECISION_FLOAT_MAX; + else if (precision == 0) precision = 2; + } + else { + precision = float_precision; + } bUnit_AsString(str, len_max, ui_get_but_scale_unit(but, value), precision, unit->system, RNA_SUBTYPE_UNIT_VALUE(unit_type), do_split, pad); @@ -1706,8 +1723,10 @@ static float ui_get_but_step_unit(uiBut *but, float step_default) } } - -void ui_get_but_string(uiBut *but, char *str, size_t maxlen) +/** + * \param float_precision For number buttons the precission to use or -1 to fallback to the button default. + */ +void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision) { if (but->rnaprop && ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) { PropertyType type; @@ -1779,10 +1798,10 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) if (ui_is_but_float(but)) { if (ui_is_but_unit(but)) { - ui_get_but_string_unit(but, str, maxlen, value, 0); + ui_get_but_string_unit(but, str, maxlen, value, 0, float_precision); } else { - const int prec = ui_but_float_precision(but, value); + const int prec = (float_precision == -1) ? ui_but_float_precision(but, value) : float_precision; BLI_snprintf(str, maxlen, "%.*f", prec, value); } } @@ -1790,6 +1809,10 @@ void ui_get_but_string(uiBut *but, char *str, size_t maxlen) BLI_snprintf(str, maxlen, "%d", (int)value); } } +void ui_get_but_string(uiBut *but, char *str, const size_t maxlen) +{ + ui_get_but_string_ex(but, str, maxlen, -1); +} #ifdef WITH_PYTHON @@ -1984,7 +2007,8 @@ static double soft_range_round_down(double value, double max) return newmax; } -void ui_set_but_soft_range(uiBut *but, double value) +/* note: this could be split up into functions which handle arrays and not */ +static void ui_set_but_soft_range(uiBut *but) { /* ideally we would not limit this but practically, its more then * enough worst case is very long vectors wont use a smart soft-range @@ -1993,14 +2017,14 @@ void ui_set_but_soft_range(uiBut *but, double value) if (but->rnaprop) { const PropertyType type = RNA_property_type(but->rnaprop); double softmin, softmax /*, step, precision*/; - double value_min = value; - double value_max = value; + double value_min; + double value_max; /* clamp button range to something reasonable in case * we get -inf/inf from RNA properties */ if (type == PROP_INT) { + const bool is_array = RNA_property_array_check(but->rnaprop); int imin, imax, istep; - const int array_len = RNA_property_array_length(&but->rnapoin, but->rnaprop); RNA_property_int_ui_range(&but->rnapoin, but->rnaprop, &imin, &imax, &istep); softmin = (imin == INT_MIN) ? -1e4 : imin; @@ -2008,16 +2032,19 @@ void ui_set_but_soft_range(uiBut *but, double value) /*step = istep;*/ /*UNUSED*/ /*precision = 1;*/ /*UNUSED*/ - if (array_len >= 2) { + if (is_array) { int value_range[2]; RNA_property_int_get_array_range(&but->rnapoin, but->rnaprop, value_range); value_min = (double)value_range[0]; value_max = (double)value_range[1]; } + else { + value_min = value_max = (double)RNA_property_int_get(&but->rnapoin, but->rnaprop); + } } else if (type == PROP_FLOAT) { + const bool is_array = RNA_property_array_check(but->rnaprop); float fmin, fmax, fstep, fprecision; - const int array_len = RNA_property_array_length(&but->rnapoin, but->rnaprop); RNA_property_float_ui_range(&but->rnapoin, but->rnaprop, &fmin, &fmax, &fstep, &fprecision); softmin = (fmin == -FLT_MAX) ? (float)-1e4 : fmin; @@ -2025,15 +2052,19 @@ void ui_set_but_soft_range(uiBut *but, double value) /*step = fstep;*/ /*UNUSED*/ /*precision = fprecision;*/ /*UNUSED*/ - if (array_len >= 2) { + if (is_array) { float value_range[2]; RNA_property_float_get_array_range(&but->rnapoin, but->rnaprop, value_range); value_min = (double)value_range[0]; value_max = (double)value_range[1]; } + else { + value_min = value_max = (double)RNA_property_float_get(&but->rnapoin, but->rnaprop); + } } - else + else { return; + } /* if the value goes out of the soft/max range, adapt the range */ if (value_min + 1e-10 < softmin) { @@ -2260,8 +2291,7 @@ void ui_check_but(uiBut *but) /* only update soft range while not editing */ if (but->rnaprop && !(but->editval || but->editstr || but->editvec)) { - UI_GET_BUT_VALUE_INIT(but, value); - ui_set_but_soft_range(but, value); + ui_set_but_soft_range(but); } /* test for min and max, icon sliders, etc */ @@ -2345,7 +2375,7 @@ void ui_check_but(uiBut *but) /* support length type buttons */ else if (ui_is_but_unit(but)) { char new_str[sizeof(but->drawstr)]; - ui_get_but_string_unit(but, new_str, sizeof(new_str), value, TRUE); + ui_get_but_string_unit(but, new_str, sizeof(new_str), value, TRUE, -1); BLI_snprintf(but->drawstr, sizeof(but->drawstr), "%s%s", but->str, new_str); } else { @@ -2530,7 +2560,9 @@ static void ui_block_do_align_but(uiBut *first, short nr) else flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_LEFT; } - else flag = UI_BUT_ALIGN_TOP; + else { + flag = UI_BUT_ALIGN_TOP; + } } } else if (buts_are_horiz(but, next)) { @@ -2550,7 +2582,9 @@ static void ui_block_do_align_but(uiBut *first, short nr) if (bt == NULL || bt->alignnr != nr) flag = UI_BUT_ALIGN_TOP | UI_BUT_ALIGN_RIGHT; } } - else flag |= UI_BUT_ALIGN_LEFT; + else { + flag |= UI_BUT_ALIGN_LEFT; + } } else { if (cols == 0) { @@ -2712,8 +2746,8 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, const char *str, but->retval = retval; slen = strlen(str); - if (slen >= UI_MAX_NAME_STR - 1) { - but->str = MEM_mallocN(slen + 2, "ui_def_but str"); /* why +2 ? */ + if (slen >= UI_MAX_NAME_STR) { + but->str = MEM_mallocN(slen + 1, "ui_def_but str"); } else { but->str = but->strdata; @@ -3016,7 +3050,7 @@ static uiBut *ui_def_but_operator_ptr(uiBlock *block, int type, wmOperatorType * } #if 0 /* UNUSED */ -static uiBut *UNUSED_FUNCTION(ui_def_but_operator) (uiBlock * block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip) +static uiBut *UNUSED_FUNCTION(ui_def_but_operator) (uiBlock *block, int type, const char *opname, int opcontext, const char *str, int x, int y, short width, short height, const char *tip) { wmOperatorType *ot = WM_operatortype_find(opname, 0); if (str == NULL && ot == NULL) str = opname; diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index e19e89af5da..5486e12c6bf 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -97,7 +97,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r } glVertex2f(maxx, miny + rad); } - else glVertex2f(maxx, miny); + else { + glVertex2f(maxx, miny); + } /* corner right-top */ if (roundboxtype & UI_CNR_TOP_RIGHT) { @@ -107,7 +109,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r } glVertex2f(maxx - rad, maxy); } - else glVertex2f(maxx, maxy); + else { + glVertex2f(maxx, maxy); + } /* corner left-top */ if (roundboxtype & UI_CNR_TOP_LEFT) { @@ -117,7 +121,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r } glVertex2f(minx, maxy - rad); } - else glVertex2f(minx, maxy); + else { + glVertex2f(minx, maxy); + } /* corner left-bottom */ if (roundboxtype & UI_CNR_BOTTOM_LEFT) { @@ -127,7 +133,9 @@ void uiDrawBox(int mode, float minx, float miny, float maxx, float maxy, float r } glVertex2f(minx + rad, miny); } - else glVertex2f(minx, miny); + else { + glVertex2f(minx, miny); + } glEnd(); } @@ -381,16 +389,7 @@ void uiRoundRect(float minx, float miny, float maxx, float maxy, float rad) /* (old, used in outliner) plain antialiased filled box */ void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad) { - float color[4]; - - if (roundboxtype & UI_RB_ALPHA) { - glGetFloatv(GL_CURRENT_COLOR, color); - color[3] = 0.5; - glColor4fv(color); - glEnable(GL_BLEND); - } - - ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad); + ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA); } @@ -454,8 +453,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w float facy = (float)h / (float)ibuf->y; glPixelZoom(facx, facy); } - glaDrawPixelsSafe((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); - //glaDrawPixelsTex((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); glPixelZoom(1.0f, 1.0f); @@ -1301,8 +1299,10 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect) glEndList(); } - else glCallList(displist); - + else { + glCallList(displist); + } + /* restore */ glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); @@ -1602,7 +1602,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wc tmpibuf = BKE_tracking_sample_pattern(scopes->frame_width, scopes->frame_height, scopes->track_search, scopes->track, - &scopes->undist_marker, scopes->use_track_mask, + &scopes->undist_marker, TRUE, scopes->use_track_mask, width, height, scopes->track_pos); if (tmpibuf) { diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index e0d6c293be5..12a6343c7e7 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -235,14 +235,13 @@ void ui_pan_to_scroll(const wmEvent *event, int *type, int *val) BLI_assert(*type == MOUSEPAN); /* sign differs, reset */ - if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0)) + if ((dy > 0 && lastdy < 0) || (dy < 0 && lastdy > 0)) { lastdy = dy; + } else { lastdy += dy; if (ABS(lastdy) > (int)UI_UNIT_Y) { - int dy = event->prevy - event->y; - if (U.uiflag2 & USER_TRACKPAD_NATURAL) dy = -dy; @@ -804,8 +803,6 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const * button we mouse over is X or Y aligned, then lock the mouse to that axis after. */ if (drag_info->xy_lock[0] == false && drag_info->xy_lock[1] == false) { - ARegion *ar = CTX_wm_region(C); - /* first store the buttons original coords */ uiBut *but = ui_but_find_mouse_over(ar, xy_input[0], xy_input[1]); if (but) { @@ -1402,7 +1399,11 @@ static void ui_but_copy_paste(bContext *C, uiBut *but, uiHandleButtonData *data, /* pass */ } else if (mode == 'c') { - ui_get_but_string(but, buf, sizeof(buf)); + /* Get many decimal places, then strip trailing zeros. + * note: too high values start to give strange results (6 or so is ok) */ + ui_get_but_string_ex(but, buf, sizeof(buf), 6); + BLI_str_rstrip_float_zero(buf, '\0'); + WM_clipboard_text_set(buf, 0); } else { @@ -1984,6 +1985,10 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) data->str = MEM_callocN(sizeof(char) * data->maxlen + 1, "textedit str"); ui_get_but_string(but, data->str, data->maxlen); + if (ui_is_but_float(but) && !ui_is_but_unit(but)) { + BLI_str_rstrip_float_zero(data->str, '\0'); + } + if (ELEM3(but->type, NUM, NUMABS, NUMSLI)) { ui_convert_to_unit_alt_name(but, data->str, data->maxlen); } @@ -2327,7 +2332,7 @@ static void ui_numedit_begin(uiBut *but, uiHandleButtonData *data) data->coba = (ColorBand *)but->poin; but->editcoba = data->coba; } - else if (ELEM3(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE)) { + else if (ELEM4(but->type, BUT_NORMAL, HSVCUBE, HSVCIRCLE, COLOR)) { ui_get_but_vectorf(but, data->origvec); copy_v3_v3(data->vec, data->origvec); but->editvec = data->vec; @@ -3149,9 +3154,6 @@ static bool ui_numedit_but_SLI(uiBut *but, uiHandleButtonData *data, BLI_rctf_clamp_pt_v(&but->rect, data->ungrab_mval); } #endif - if (is_horizontal == false) { - mx_fl = my_fl; - } /* done correcting mouse */ @@ -5013,7 +5015,7 @@ static int ui_but_menu(bContext *C, uiBut *but) uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); if (but->rnapoin.data && but->rnaprop) { - short is_anim = RNA_property_animateable(&but->rnapoin, but->rnaprop); + bool is_anim = RNA_property_animateable(&but->rnapoin, but->rnaprop); /* second slower test, saved people finding keyframe items in menus when its not possible */ if (is_anim) @@ -6294,7 +6296,7 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) { uiHandleButtonData *data = but->active; - const uiButtonActivateType state_orig = data->state; + const uiHandleButtonState state_orig = data->state; uiBlock *block; ARegion *ar; int retval; @@ -6466,9 +6468,9 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) * This is needed to make sure if a button was active, * it stays active while the mouse is over it. * This avoids adding mousemoves, see: [#33466] */ - if (ELEM(state_orig, BUTTON_ACTIVATE, BUTTON_ACTIVATE_OVER)) { + if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT)) { if (ui_but_find_mouse_over(ar, event->x, event->y) == but) { - button_activate_init(C, ar, but, state_orig); + button_activate_init(C, ar, but, BUTTON_ACTIVATE_OVER); } } } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 086e9dad895..09686d7b416 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -47,6 +47,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_fileops_types.h" #include "DNA_brush_types.h" #include "DNA_dynamicpaint_types.h" @@ -703,10 +704,8 @@ static void init_iconfile_list(struct ListBase *list) { IconFile *ifile; struct direntry *dir; - int restoredir = 1; /* restore to current directory */ int totfile, i, index = 1; const char *icondir; - char olddir[FILE_MAX]; list->first = list->last = NULL; icondir = BLI_get_folder(BLENDER_DATAFILES, "icons"); @@ -714,12 +713,7 @@ static void init_iconfile_list(struct ListBase *list) if (icondir == NULL) return; - /* since BLI_dir_contents changes the current working directory, restore it - * back to old value afterwards */ - if (!BLI_current_working_dir(olddir, sizeof(olddir))) - restoredir = 0; totfile = BLI_dir_contents(icondir, &dir); - if (restoredir && !chdir(olddir)) {} /* fix warning about checking return value */ for (i = 0; i < totfile; i++) { if ((dir[i].type & S_IFREG)) { @@ -766,18 +760,8 @@ static void init_iconfile_list(struct ListBase *list) } } } - - /* free temporary direntry structure that's been created by BLI_dir_contents() */ - i = totfile - 1; - - for (; i >= 0; i--) { - MEM_freeN(dir[i].relname); - MEM_freeN(dir[i].path); - if (dir[i].string) { - MEM_freeN(dir[i].string); - } - } - free(dir); + + BLI_free_filelist(dir, totfile); dir = NULL; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 9093e8f8d30..6065fcfe574 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -394,7 +394,8 @@ extern void ui_set_but_vectorf(uiBut *but, const float vec[3]); extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rcti *rect, const float mx, const float my); -extern void ui_get_but_string(uiBut *but, char *str, size_t maxlen); +extern void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision); +extern void ui_get_but_string(uiBut *but, char *str, const size_t maxlen); extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen); extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str); extern int ui_get_but_string_max_length(uiBut *but); @@ -402,8 +403,6 @@ extern int ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char extern void ui_set_but_default(struct bContext *C, short all); -extern void ui_set_but_soft_range(uiBut *but, double value); - extern void ui_check_but(uiBut *but); extern int ui_is_but_float(uiBut *but); extern int ui_is_but_bool(uiBut *but); @@ -523,7 +522,7 @@ extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiB /* interface_widgets.c */ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad); +void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha); void ui_draw_menu_back(struct uiStyle *style, uiBlock *block, rcti *rect); uiWidgetColors *ui_tooltip_get_theme(void); void ui_draw_tooltip_background(uiStyle *UNUSED(style), uiBlock * block, rcti * rect); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 1e95b4df762..2ca26ae5317 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -1567,7 +1567,7 @@ void uiItemM(uiLayout *layout, bContext *UNUSED(C), const char *menuname, const } if (!name) { - name = IFACE_(mt->label); + name = CTX_IFACE_(mt->translation_context, mt->label); } if (layout->root->type == UI_LAYOUT_MENU && !icon) @@ -2369,6 +2369,7 @@ uiLayout *uiLayoutAbsolute(uiLayout *layout, int align) litem->active = 1; litem->enabled = 1; litem->context = layout->context; + litem->redalert = layout->redalert; BLI_addtail(&layout->items, litem); uiBlockSetCurLayout(layout->root->block, litem); @@ -2396,6 +2397,7 @@ uiLayout *uiLayoutOverlap(uiLayout *layout) litem->active = 1; litem->enabled = 1; litem->context = layout->context; + litem->redalert = layout->redalert; BLI_addtail(&layout->items, litem); uiBlockSetCurLayout(layout->root->block, litem); @@ -2415,6 +2417,7 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align) split->litem.enabled = 1; split->litem.context = layout->context; split->litem.space = layout->root->style->columnspace; + split->litem.redalert = layout->redalert; split->litem.w = layout->w; split->percentage = percentage; BLI_addtail(&layout->items, split); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 3298859ee0c..145deb35667 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -239,7 +239,7 @@ static void eyedropper_color_sample_accum(bContext *C, Eyedropper *eye, int mx, } /* main modal status check */ -static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event) +static int eyedropper_modal(bContext *C, wmOperator *op, const wmEvent *event) { Eyedropper *eye = (Eyedropper *)op->customdata; @@ -285,7 +285,7 @@ static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event) } /* Modal Operator init */ -static int eyedropper_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int eyedropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { /* init */ if (eyedropper_init(C, op)) { @@ -853,7 +853,7 @@ static int editsource_exec(bContext *C, wmOperator *op) ED_region_do_draw(C, ar); for (BLI_ghashIterator_init(&ghi, ui_editsource_info->hash); - !BLI_ghashIterator_isDone(&ghi); + BLI_ghashIterator_notDone(&ghi); BLI_ghashIterator_step(&ghi)) { uiBut *but_key = BLI_ghashIterator_getKey(&ghi); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index e466c481151..a741ea432a5 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -191,7 +191,7 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar) Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int *open) { Panel *pa, *patab, *palast, *panext; - char *drawname = pt->label; + const char *drawname = CTX_IFACE_(pt->translation_context, pt->label); char *idname = pt->idname; char *tabname = pt->idname; char *hookname = NULL; @@ -469,7 +469,7 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, rcti *r Panel *panel = block->panel; rcti hrect; int pnl_icons; - const char *activename = IFACE_(panel->drawname[0] ? panel->drawname : panel->panelname); + const char *activename = panel->drawname[0] ? panel->drawname : panel->panelname; /* + 0.001f to avoid flirting with float inaccuracy */ if (panel->control & UI_PNL_CLOSE) pnl_icons = (panel->labelofs + 2 * PNL_ICON + 5) / block->aspect + 0.001f; diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 03c127f33c8..febd1820e5c 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -663,9 +663,9 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) /* since the text has beens caled already, the size of tooltips is defined now */ /* here we try to figure out the right location */ if (butregion) { - float ofsx = rect_fl.xmin, ofsy = rect_fl.ymax; - ui_block_to_window_fl(butregion, but->block, &ofsx, &ofsy); - BLI_rctf_translate(&rect_fl, ofsx - rect_fl.xmin, ofsy - rect_fl.ymax); + float ofsx_fl = rect_fl.xmin, ofsy_fl = rect_fl.ymax; + ui_block_to_window_fl(butregion, but->block, &ofsx_fl, &ofsy_fl); + BLI_rctf_translate(&rect_fl, ofsx_fl - rect_fl.xmin, ofsy_fl - rect_fl.ymax); } BLI_rcti_rctf_copy(&rect_i, &rect_fl); diff --git a/source/blender/editors/interface/interface_style.c b/source/blender/editors/interface/interface_style.c index ef24ea951e3..dd4886a7243 100644 --- a/source/blender/editors/interface/interface_style.c +++ b/source/blender/editors/interface/interface_style.c @@ -216,7 +216,7 @@ void uiStyleFontDrawRotated(uiFontStyle *fs, rcti *rect, const char *str) /* rotate counter-clockwise for now (assumes left-to-right language)*/ xofs += height; yofs = BLF_width(fs->uifont_id, str) + 5; - angle = 90.0f; + angle = (float)M_PI / 2.0f; /* translate rect to vertical */ txtrect.xmin = rect->xmin - BLI_rcti_size_y(rect); @@ -330,6 +330,8 @@ void uiStyleInit(void) { uiFont *font = U.uifonts.first; uiStyle *style = U.uistyles.first; + int monofont_size = datatoc_bmonofont_ttf_size; + unsigned char *monofont_ttf = (unsigned char *)datatoc_bmonofont_ttf; /* recover from uninitialized dpi */ if (U.dpi == 0) @@ -400,15 +402,33 @@ void uiStyleInit(void) ui_style_new(&U.uistyles, "Default Style", UIFONT_DEFAULT); } +#ifdef WITH_INTERNATIONAL + /* use unicode font for text editor and interactive console */ + if (U.transopts & USER_DOTRANSLATE) { + monofont_ttf = BLF_get_unifont_mono(&monofont_size); + + if (!monofont_ttf) { + /* fall back if not found */ + monofont_size = datatoc_bmonofont_ttf_size; + monofont_ttf = (unsigned char *)datatoc_bmonofont_ttf; + } + } + + /* reload */ + BLF_unload("monospace"); + blf_mono_font = -1; + blf_mono_font_render = -1; +#endif + /* XXX, this should be moved into a style, but for now best only load the monospaced font once. */ if (blf_mono_font == -1) - blf_mono_font = BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); + blf_mono_font = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size); BLF_size(blf_mono_font, 12 * U.pixelsize, 72); /* second for rendering else we get threading problems */ if (blf_mono_font_render == -1) - blf_mono_font_render = BLF_load_mem_unique("monospace", (unsigned char *)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); + blf_mono_font_render = BLF_load_mem_unique("monospace", monofont_ttf, monofont_size); BLF_size(blf_mono_font_render, 12 * U.pixelsize, 72 ); } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 83540cef9fc..afb44101910 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -281,11 +281,13 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) if (id->flag & LIB_FAKEUSER) id_us_plus(id); else id_us_min(id); } - else return; + else { + return; + } break; case UI_ID_LOCAL: if (id) { - if (id_make_local(id, 0)) { + if (id_make_local(id, false)) { /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template->ptr, template->prop); RNA_property_pointer_set(&template->ptr, template->prop, idptr); @@ -465,7 +467,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str else { but = uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local")); - if (!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib)) + if (!id_make_local(id, true /* test */) || (idfrom && idfrom->lib)) uiButSetFlag(but, UI_BUT_DISABLED); } @@ -483,7 +485,7 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); if (/* test only */ - (id_copy(id, NULL, 1) == FALSE) || + (id_copy(id, NULL, true) == false) || (idfrom && idfrom->lib) || (editable == FALSE) || /* object in editmode - don't change data */ @@ -676,7 +678,7 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co const char *text) { PropertyRNA *propID, *propType; - uiLayout *row; + uiLayout *split, *row, *sub; /* get properties... */ propID = RNA_struct_find_property(ptr, propname); @@ -692,22 +694,34 @@ void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, co } /* Start drawing UI Elements using standard defines */ - row = uiLayoutRow(layout, TRUE); + split = uiLayoutSplit(layout, 0.33f, FALSE); /* NOTE: split amount here needs to be synced with normal labels */ + + /* FIRST PART ................................................ */ + row = uiLayoutRow(split, FALSE); /* Label - either use the provided text, or will become "ID-Block:" */ if (text) { if (text[0]) uiItemL(row, text, ICON_NONE); } - else + else { uiItemL(row, IFACE_("ID-Block:"), ICON_NONE); + } + + /* SECOND PART ................................................ */ + row = uiLayoutRow(split, TRUE); /* ID-Type Selector - just have a menu of icons */ - /* FIXME: the icon-only setting doesn't work when we supply a blank name */ - uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + sub = uiLayoutRow(row, TRUE); /* HACK: special group just for the enum, otherwise we */ + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); /* we get ugly layout with text included too... */ + + uiItemFullR(sub, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE); /* ID-Block Selector - just use pointer widget... */ - uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE); + sub = uiLayoutRow(row, TRUE); /* HACK: special group to counteract the effects of the previous */ + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */ + + uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE); } /********************* RNA Path Builder Template ********************/ @@ -2135,10 +2149,10 @@ static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labe uiLayoutRow(layout, TRUE); uiBlockSetNFunc(block, curvemap_buttons_update, MEM_dupallocN(cb), cumap); - bt = uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &cmp->x, bounds.xmin, bounds.xmax, 1, 5, ""); - bt = uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, - &cmp->y, bounds.ymin, bounds.ymax, 1, 5, ""); + uiDefButF(block, NUM, 0, "X", 0, 2 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, + &cmp->x, bounds.xmin, bounds.xmax, 1, 5, ""); + uiDefButF(block, NUM, 0, "Y", 0, 1 * UI_UNIT_Y, UI_UNIT_X * 10, UI_UNIT_Y, + &cmp->y, bounds.ymin, bounds.ymax, 1, 5, ""); } /* black/white levels */ @@ -2727,7 +2741,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char { GHashIterator *iter = WM_operatortype_iter(); - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(iter); if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index dd7b1d0ee06..78b6d2541fd 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -218,13 +218,16 @@ void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y glDisable(GL_BLEND); } -void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad) +void ui_draw_anti_roundbox(int mode, float minx, float miny, float maxx, float maxy, float rad, bool use_alpha) { float color[4]; int j; glEnable(GL_BLEND); glGetFloatv(GL_CURRENT_COLOR, color); + if (use_alpha) { + color[3] = 0.5f; + } color[3] *= 0.125f; glColor4fv(color); @@ -1289,7 +1292,9 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB else if ((but->block->flag & UI_BLOCK_LOOP) && (but->type == BUT)) { ui_text_clip_left(fstyle, but, rect); } - else but->ofs = 0; + else { + but->ofs = 0; + } /* check for button text label */ if (but->type == ICONTEXTROW) { diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index acea6e133f4..09122737373 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -279,6 +279,8 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->vertex; break; case TH_VERTEX_SELECT: cp = ts->vertex_select; break; + case TH_VERTEX_UNREFERENCED: + cp = ts->vertex_unreferenced; break; case TH_VERTEX_SIZE: cp = &ts->vertex_size; break; case TH_OUTLINE_WIDTH: @@ -445,7 +447,6 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_HANDLE_VERTEX_SIZE: cp = &ts->handle_vertex_size; break; - case TH_DOPESHEET_CHANNELOB: cp = ts->ds_channel; break; @@ -718,6 +719,8 @@ void ui_theme_init_default(void) /* space view3d */ btheme->tv3d.panelcolors.show_back = FALSE; btheme->tv3d.panelcolors.show_header = FALSE; + rgba_char_args_set_fl(btheme->tv3d.panelcolors.back, 0.45, 0.45, 0.45, 0.5); + rgba_char_args_set_fl(btheme->tv3d.panelcolors.header, 0, 0, 0, 0.01); rgba_char_args_set_fl(btheme->tv3d.back, 0.225, 0.225, 0.225, 1.0); rgba_char_args_set(btheme->tv3d.text, 0, 0, 0, 255); rgba_char_args_set(btheme->tv3d.text_hi, 255, 255, 255, 255); @@ -742,6 +745,7 @@ void ui_theme_init_default(void) rgba_char_args_set(btheme->tv3d.transform, 0xff, 0xff, 0xff, 255); rgba_char_args_set(btheme->tv3d.vertex, 0, 0, 0, 255); rgba_char_args_set(btheme->tv3d.vertex_select, 255, 133, 0, 255); + rgba_char_args_set(btheme->tv3d.vertex_unreferenced, 0, 0, 0, 255); btheme->tv3d.vertex_size = 3; btheme->tv3d.outline_width = 1; rgba_char_args_set(btheme->tv3d.edge, 0x0, 0x0, 0x0, 255); @@ -1376,7 +1380,7 @@ void init_userdef_do_versions(void) /* signal for derivedmesh to use colorband */ /* run in case this was on and is now off in the user prefs [#28096] */ - vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL); + vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced); if (bmain->versionfile <= 191) { strcpy(U.sounddir, "/"); diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index ad6428c7e80..8a6de9a549b 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -457,8 +457,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, int resize, int mask_ if (ABS(winx - v2d->oldwinx) > ABS(winy - v2d->oldwiny)) do_y = FALSE; else do_x = FALSE; } - else if (winRatio > 1.0f) do_x = FALSE; - else do_x = TRUE; + else if (winRatio > 1.0f) { + do_x = FALSE; + } + else { + do_x = TRUE; + } } do_cur = do_x; /* do_win = do_y; */ /* UNUSED */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index daa78957231..e283bd1351a 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -187,7 +187,7 @@ static int view_pan_exec(bContext *C, wmOperator *op) } /* set up modal operator and relevant settings */ -static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *window = CTX_wm_window(C); v2dViewPanData *vpd; @@ -231,7 +231,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */ -static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) +static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) { v2dViewPanData *vpd = op->customdata; @@ -700,7 +700,7 @@ static int view_zoomin_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoomin_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoomin_invoke(bContext *C, wmOperator *op, const wmEvent *event) { v2dViewZoomData *vzd; @@ -769,7 +769,7 @@ static int view_zoomout_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoomout_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoomout_invoke(bContext *C, wmOperator *op, const wmEvent *event) { v2dViewZoomData *vzd; @@ -924,7 +924,7 @@ static int view_zoomdrag_exec(bContext *C, wmOperator *op) } /* set up modal operator and relevant settings */ -static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoomdrag_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *window = CTX_wm_window(C); v2dViewZoomData *vzd; @@ -1005,7 +1005,7 @@ static int view_zoomdrag_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* handle user input - calculations of mouse-movement need to be done here, not in the apply callback! */ -static int view_zoomdrag_modal(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoomdrag_modal(bContext *C, wmOperator *op, const wmEvent *event) { v2dViewZoomData *vzd = op->customdata; View2D *v2d = vzd->v2d; @@ -1328,7 +1328,7 @@ void UI_view2d_smooth_view(bContext *C, ARegion *ar, } /* only meant for timer usage */ -static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int view2d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; @@ -1488,7 +1488,7 @@ static short mouse_in_scroller_handle(int mouse, int sc_min, int sc_max, int sh_ } /* initialize customdata for scroller manipulation operator */ -static void scroller_activate_init(bContext *C, wmOperator *op, wmEvent *event, short in_scroller) +static void scroller_activate_init(bContext *C, wmOperator *op, const wmEvent *event, short in_scroller) { v2dScrollerMove *vsm; View2DScrollers *scrollers; @@ -1637,7 +1637,7 @@ static void scroller_activate_apply(bContext *C, wmOperator *op) } /* handle user input for scrollers - calculations of mouse-movement need to be done here, not in the apply callback! */ -static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event) +static int scroller_activate_modal(bContext *C, wmOperator *op, const wmEvent *event) { v2dScrollerMove *vsm = op->customdata; @@ -1707,7 +1707,7 @@ static int scroller_activate_modal(bContext *C, wmOperator *op, wmEvent *event) /* a click (or click drag in progress) should have occurred, so check if it happened in scrollbar */ -static int scroller_activate_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int scroller_activate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); View2D *v2d = &ar->v2d; diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index 4908c101a7c..c673e0fb2b0 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -56,7 +56,7 @@ #include "io_collada.h" -static int wm_collada_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_collada_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!RNA_struct_property_is_set(op->ptr, "filepath")) { char filepath[FILE_MAX]; @@ -95,6 +95,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) int triangulate; int use_object_instantiation; int sort_by_name; + int export_transformation_type; int second_life; if (!RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -115,14 +116,15 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) deform_bones_only = RNA_boolean_get(op->ptr, "deform_bones_only"); include_uv_textures = RNA_boolean_get(op->ptr, "include_uv_textures"); - include_material_textures= RNA_boolean_get(op->ptr, "include_material_textures"); + include_material_textures = RNA_boolean_get(op->ptr, "include_material_textures"); use_texture_copies = RNA_boolean_get(op->ptr, "use_texture_copies"); active_uv_only = RNA_boolean_get(op->ptr, "active_uv_only"); - triangulate = RNA_boolean_get(op->ptr, "triangulate"); - use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); - sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); - second_life = RNA_boolean_get(op->ptr, "second_life"); + triangulate = RNA_boolean_get(op->ptr, "triangulate"); + use_object_instantiation = RNA_boolean_get(op->ptr, "use_object_instantiation"); + sort_by_name = RNA_boolean_get(op->ptr, "sort_by_name"); + export_transformation_type = RNA_enum_get(op->ptr, "export_transformation_type_selection"); + second_life = RNA_boolean_get(op->ptr, "second_life"); /* get editmode results */ ED_object_exit_editmode(C, 0); /* 0 = does not exit editmode */ @@ -145,6 +147,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) triangulate, use_object_instantiation, sort_by_name, + export_transformation_type, second_life)) { return OPERATOR_FINISHED; @@ -224,6 +227,12 @@ static void uiCollada_exportSettings(uiLayout *layout, PointerRNA *imfptr) uiItemR(row, imfptr, "triangulate", 0, NULL, ICON_NONE); row = uiLayoutRow(box, FALSE); uiItemR(row, imfptr, "use_object_instantiation", 0, NULL, ICON_NONE); + + row = uiLayoutRow(box, FALSE); + split = uiLayoutSplit(row, 0.6f, UI_LAYOUT_ALIGN_RIGHT); + uiItemL(split, IFACE_("Transformation Type"), ICON_NONE); + uiItemR(split, imfptr, "export_transformation_type_selection", 0, "", ICON_NONE); + row = uiLayoutRow(box, FALSE); uiItemR(row, imfptr, "sort_by_name", 0, NULL, ICON_NONE); @@ -245,6 +254,13 @@ void WM_OT_collada_export(wmOperatorType *ot) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem prop_bc_export_transformation_type[] = { + {BC_TRANSFORMATION_TYPE_MATRIX, "matrix", 0, "Matrix", "Use <matrix> to specify transformations"}, + {BC_TRANSFORMATION_TYPE_TRANSROTLOC, "transrotloc", 0, "TransRotLoc", "Use <translate>, <rotate>, <scale> to specify transformations"}, + {BC_TRANSFORMATION_TYPE_BOTH, "both", 0, "Both", "Use <matrix> AND <translate>, <rotate>, <scale> to specify transformations"}, + {0, NULL, 0, NULL, NULL} + }; + ot->name = "Export COLLADA"; ot->description = "Save a Collada file"; ot->idname = "WM_OT_collada_export"; @@ -308,6 +324,12 @@ void WM_OT_collada_export(wmOperatorType *ot) RNA_def_boolean(ot->srna, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); + RNA_def_int(ot->srna, "export_transformation_type", 0, INT_MIN, INT_MAX, + "Transform", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); + + RNA_def_enum(ot->srna, "export_transformation_type_selection", prop_bc_export_transformation_type, 0, + "Transform", "Transformation type for translation, scale and rotation"); + RNA_def_boolean(ot->srna, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life"); } diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 77abe43bba7..33a6aa2d43d 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -629,7 +629,7 @@ static int add_vertex_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int add_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int add_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -703,7 +703,7 @@ static int add_feather_vertex_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int add_feather_vertex_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int add_feather_vertex_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index 0a996c11f14..ff8e27ac264 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -438,7 +438,7 @@ static int slide_point_check_initial_feather(MaskSpline *spline) return TRUE; } -static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) +static void *slide_point_customdata(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -525,7 +525,7 @@ static void *slide_point_customdata(bContext *C, wmOperator *op, wmEvent *event) return customdata; } -static int slide_point_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int slide_point_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SlidePointData *slidedata = slide_point_customdata(C, op, event); @@ -634,7 +634,7 @@ static void free_slide_point_data(SlidePointData *data) MEM_freeN(data); } -static int slide_point_modal(bContext *C, wmOperator *op, wmEvent *event) +static int slide_point_modal(bContext *C, wmOperator *op, const wmEvent *event) { SlidePointData *data = (SlidePointData *)op->customdata; BezTriple *bezt = &data->point->bezt; diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index cd1a47754f8..ccc2fad5f52 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -361,7 +361,7 @@ static int select_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } -static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); @@ -689,7 +689,7 @@ void MASK_OT_select_circle(wmOperatorType *ot) RNA_def_int(ot->srna, "gesture_mode", 0, INT_MIN, INT_MAX, "Gesture Mode", "", INT_MIN, INT_MAX); } -static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int mask_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index b51d55aaf0e..a76872d6e30 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -26,6 +26,7 @@ set(INC ../../blenlib ../../blenloader ../../bmesh + ../../gpu ../../imbuf ../../makesdna ../../makesrna @@ -43,6 +44,7 @@ set(SRC editmesh_add.c editmesh_bvh.c editmesh_knife.c + editmesh_knife_project.c editmesh_loopcut.c editmesh_rip.c editmesh_select.c diff --git a/source/blender/editors/mesh/editface.c b/source/blender/editors/mesh/editface.c index 7ddf2b54a88..260d01d726a 100644 --- a/source/blender/editors/mesh/editface.c +++ b/source/blender/editors/mesh/editface.c @@ -294,7 +294,7 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind MEM_freeN(linkflag); } -void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]), int mode) +void paintface_select_linked(bContext *UNUSED(C), Object *ob, const int UNUSED(mval[2]), int mode) { Mesh *me; unsigned int index = 0; @@ -525,7 +525,9 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in else mpoly_sel->flag |= ME_FACE_SEL; } - else mpoly_sel->flag |= ME_FACE_SEL; + else { + mpoly_sel->flag |= ME_FACE_SEL; + } /* image window redraw */ @@ -568,7 +570,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend) ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect); rt = ibuf->rect; - glReadPixels(rect->xmin + vc->ar->winrct.xmin, rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); + view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf); a = sx * sy; @@ -710,6 +712,37 @@ void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags) } } +void paintvert_select_ungrouped(Object *ob, short extend, short flush_flags) +{ + Mesh *me = BKE_mesh_from_object(ob); + MVert *mv; + MDeformVert *dv; + int a, tot; + + if (me == NULL || me->dvert == NULL) { + return; + } + + if (!extend) { + paintvert_deselect_all_visible(ob, SEL_DESELECT, FALSE); + } + + dv = me->dvert; + tot = me->totvert; + + for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) { + if ((mv->flag & ME_HIDE) == 0) { + if (dv->dw == NULL) { + /* if null weight then not grouped */ + mv->flag |= SELECT; + } + } + } + + if (flush_flags) { + paintvert_flush_flags(ob); + } +} /* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */ /* note, this is not the best place for the function to be but moved diff --git a/source/blender/editors/mesh/editmesh_add.c b/source/blender/editors/mesh/editmesh_add.c index a356f9fca7f..174715495f6 100644 --- a/source/blender/editors/mesh/editmesh_add.c +++ b/source/blender/editors/mesh/editmesh_add.c @@ -32,15 +32,14 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "RNA_define.h" -#include "RNA_access.h" - #include "BLI_math.h" #include "BKE_context.h" #include "BKE_library.h" #include "BKE_tessmesh.h" +#include "RNA_define.h" +#include "RNA_access.h" #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index d7dbe3506b1..b5b6a92cbf5 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -37,6 +37,7 @@ #include "BLI_blenlib.h" #include "BLI_array.h" +#include "BLI_linklist.h" #include "BLI_math.h" #include "BLI_smallhash.h" #include "BLI_memarena.h" @@ -90,7 +91,8 @@ typedef struct KnifeVert { ListBase faces; float co[3], cageco[3], sco[3]; /* sco is screen coordinates for cageco */ - short flag, draw, isface, inspace; + bool is_face, in_space; + bool draw; } KnifeVert; typedef struct Ref { @@ -102,9 +104,9 @@ typedef struct KnifeEdge { KnifeVert *v1, *v2; BMFace *basef; /* face to restrict face fill to */ ListBase faces; - int draw; - BMEdge *e, *oe; /* non-NULL if this is an original edge */ + BMEdge *e /* , *e_old */; /* non-NULL if this is an original edge */ + bool draw; } KnifeEdge; typedef struct BMEdgeHit { @@ -128,7 +130,7 @@ typedef struct KnifePosData { KnifeVert *vert; KnifeEdge *edge; BMFace *bmface; - int is_space; + bool is_space; float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */ } KnifePosData; @@ -137,7 +139,8 @@ typedef struct KnifePosData { typedef struct KnifeTool_OpData { ARegion *ar; /* region that knifetool was activated in */ void *draw_handle; /* for drawing preview loop */ - ViewContext vc; + ViewContext vc; /* note: _don't_ use 'mval', instead use the one we define below */ + float mval[2]; /* mouse value with snapping applied */ //bContext *C; Object *ob; @@ -173,12 +176,15 @@ typedef struct KnifeTool_OpData { KnifeColors colors; + /* run by the UI or not */ + bool is_interactive; + /* operatpr options */ - char cut_through; /* preference, can be modified at runtime (that feature may go) */ - char only_select; /* set on initialization */ - char select_result; /* set on initialization */ + bool cut_through; /* preference, can be modified at runtime (that feature may go) */ + bool only_select; /* set on initialization */ + bool select_result; /* set on initialization */ - short is_ortho; + bool is_ortho; float ortho_extent; float clipsta, clipend; @@ -189,8 +195,10 @@ typedef struct KnifeTool_OpData { MODE_PANNING } mode; - int snap_midpoints, prevmode, extend; - int ignore_edge_snapping, ignore_vert_snapping; + int prevmode; + bool snap_midpoints, extend; + bool ignore_edge_snapping; + bool ignore_vert_snapping; enum { ANGLE_FREE, @@ -228,14 +236,16 @@ static void knife_update_header(bContext *C, KnifeTool_OpData *kcd) ED_area_headerprint(CTX_wm_area(C), header); } +#if 0 BLI_INLINE int round_ftoi(float x) { return x > 0.0f ? (int)(x + 0.5f) : (int)(x - 0.5f); } +#endif -static void knife_project_v3(KnifeTool_OpData *kcd, const float co[3], float sco[3]) +static void knife_project_v3(const KnifeTool_OpData *kcd, const float co[3], float sco[3]) { - ED_view3d_project_float_v3_m4(kcd->ar, co, sco, kcd->projmat); + ED_view3d_project_float_v3_m4(kcd->ar, co, sco, (float (*)[4])kcd->projmat); } static void knife_pos_data_clear(KnifePosData *kpd) @@ -245,8 +255,7 @@ static void knife_pos_data_clear(KnifePosData *kpd) kpd->vert = NULL; kpd->edge = NULL; kpd->bmface = NULL; - kpd->mval[0] = 0.0f; - kpd->mval[1] = 0.0f; + zero_v2(kpd->mval); } static ListBase *knife_empty_list(KnifeTool_OpData *kcd) @@ -494,7 +503,7 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge) return; - kfe->draw = 1; + kfe->draw = true; if (kcd->prev.vert) { kfe->v1 = kcd->prev.vert; @@ -505,9 +514,9 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) else { kfe->v1 = new_knife_vert(kcd, kcd->prev.co, kcd->prev.co); kfe->v1->draw = kfe->draw = !kcd->prev.is_space; - kfe->v1->inspace = kcd->prev.is_space; + kfe->v1->in_space = kcd->prev.is_space; kfe->draw = !kcd->prev.is_space; - kfe->v1->isface = 1; + kfe->v1->is_face = true; if (kfe->v1->draw && kcd->prev.bmface) knife_append_list(kcd, &kfe->v1->faces, kcd->prev.bmface); } @@ -522,13 +531,13 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) else { kfe->v2 = new_knife_vert(kcd, kcd->curr.co, kcd->curr.co); kfe->v2->draw = !kcd->curr.is_space; - kfe->v2->isface = 1; - kfe->v2->inspace = kcd->curr.is_space; + kfe->v2->is_face = true; + kfe->v2->in_space = kcd->curr.is_space; if (kfe->v2->draw && kcd->curr.bmface) knife_append_list(kcd, &kfe->v2->faces, kcd->curr.bmface); if (kcd->curr.is_space) - kfe->draw = 0; + kfe->draw = false; kcd->curr.vert = kfe->v2; } @@ -632,11 +641,10 @@ static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, K KnifeEdge *kfenew; kfenew = new_knife_edge(kcd); - kfenew->draw = 1; kfenew->basef = f; kfenew->v1 = v1; kfenew->v2 = v2; - kfenew->draw = 1; + kfenew->draw = true; knife_add_to_vert_edges(kcd, kfenew); @@ -650,7 +658,7 @@ static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace * BMFace *f; Ref *r; - if (kfv->isface && facef) { + if (kfv->is_face && facef) { knife_append_list(kcd, lst, facef); } else if (kfv->v) { @@ -689,7 +697,7 @@ static void knife_cut_through(KnifeTool_OpData *kcd) ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL}; Ref *r, *r2; KnifeEdge **splitkfe; - int i, j, found; + int i, j; if (!kcd->totlinehit) { /* if no linehits then no interesting back face stuff to do */ @@ -727,15 +735,15 @@ static void knife_cut_through(KnifeTool_OpData *kcd) /* For each face incident to firstv, * find the first following linehit (if any) sharing that face and connect */ for (r = firstfaces.first; r; r = r->next) { + bool found = false; f = r->ref; - found = 0; for (j = 0, lh2 = kcd->linehits; j < kcd->totlinehit && !found; j++, lh2++) { kfe2 = lh2->kfe; for (r2 = kfe2->faces.first; r2; r2 = r2->next) { if (r2->ref == f) { v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]); knife_add_single_cut_through(kcd, firstv, v2, f); - found = 1; + found = true; break; } } @@ -757,8 +765,8 @@ static void knife_cut_through(KnifeTool_OpData *kcd) /* For each face attached to edge for this linehit, * find the first following linehit (if any) sharing that face and connect */ for (r = kfe->faces.first; r; r = r->next) { + bool found = false; f = r->ref; - found = 0; for (j = i + 1, lh2 = lh + 1; j < kcd->totlinehit && !found; j++, lh2++) { kfe2 = lh2->kfe; for (r2 = kfe2->faces.first; r2; r2 = r2->next) { @@ -766,7 +774,7 @@ static void knife_cut_through(KnifeTool_OpData *kcd) v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]); v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]); knife_add_single_cut_through(kcd, v1, v2, f); - found = 1; + found = true; break; } } @@ -890,7 +898,7 @@ static void knife_finish_cut(KnifeTool_OpData *UNUSED(kcd)) } -static void knifetool_draw_angle_snapping(KnifeTool_OpData *kcd) +static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd) { bglMats mats; double u[3], u1[2], u2[2], v1[3], v2[3], dx, dy; @@ -1006,7 +1014,7 @@ static void knife_init_colors(KnifeColors *colors) static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) { View3D *v3d = CTX_wm_view3d(C); - KnifeTool_OpData *kcd = arg; + const KnifeTool_OpData *kcd = arg; if (v3d->zbuf) glDisable(GL_DEPTH_TEST); @@ -1062,7 +1070,7 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) if (kcd->totlinehit > 0) { const float vthresh4 = kcd->vthresh / 4.0f; - const float vthresh4_squared = vthresh4 * vthresh4; + const float vthresh4_sq = vthresh4 * vthresh4; BMEdgeHit *lh; int i; @@ -1082,12 +1090,12 @@ static void knifetool_draw(const bContext *C, ARegion *UNUSED(ar), void *arg) knife_project_v3(kcd, lh->kfe->v2->cageco, sv2); knife_project_v3(kcd, lh->cagehit, lh->schit); - if (len_squared_v2v2(lh->schit, sv1) < vthresh4_squared) { + if (len_squared_v2v2(lh->schit, sv1) < vthresh4_sq) { copy_v3_v3(lh->cagehit, lh->kfe->v1->cageco); glVertex3fv(lh->cagehit); lh->v = lh->kfe->v1; } - else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_squared) { + else if (len_squared_v2v2(lh->schit, sv2) < vthresh4_sq) { copy_v3_v3(lh->cagehit, lh->kfe->v2->cageco); glVertex3fv(lh->cagehit); lh->v = lh->kfe->v2; @@ -1179,7 +1187,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, /* for comparing distances, error of intersection depends on triangle scale. * need to scale down before squaring for accurate comparison */ const float depsilon = (FLT_EPSILON / 2.0f) * len_v3_tri_side_max(v1, v2, v3); - const float depsilon_squared = depsilon * depsilon; + const float depsilon_sq = depsilon * depsilon; copy_v3_v3(cos + 0, v1); copy_v3_v3(cos + 3, v2); @@ -1213,14 +1221,14 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda); - if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_squared) { + if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_sq) { continue; } - if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_squared) { + if (kcd->prev.vert && len_squared_v3v3(kcd->prev.vert->cageco, p) < depsilon_sq) { continue; } - if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_squared || - len_squared_v3v3(kcd->curr.cage, p) < depsilon_squared) + if (len_squared_v3v3(kcd->prev.cage, p) < depsilon_sq || + len_squared_v3v3(kcd->curr.cage, p) < depsilon_sq) { continue; } @@ -1266,8 +1274,8 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, if (!hitf && !BLI_smallhash_haskey(ehash, (intptr_t)kfe)) { BMEdgeHit hit; - if (len_squared_v3v3(p, kcd->curr.co) < depsilon_squared || - len_squared_v3v3(p, kcd->prev.co) < depsilon_squared) + if (len_squared_v3v3(p, kcd->curr.co) < depsilon_sq || + len_squared_v3v3(p, kcd->prev.co) < depsilon_sq) { continue; } @@ -1381,7 +1389,7 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) knife_project_v3(kcd, v1, s1); knife_project_v3(kcd, v2, s2); - if (len_v2v2(s1, s2) < 1) + if (len_squared_v2v2(s1, s2) < 1) return; /* unproject screen line */ @@ -1481,7 +1489,7 @@ static void knife_input_ray_segment(KnifeTool_OpData *kcd, const float mval[2], mul_m4_v3(kcd->ob->imat, r_origin_ofs); } -static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], int *is_space) +static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float cageco[3], bool *is_space) { BMFace *f; float dist = KMAXDIST; @@ -1499,13 +1507,15 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float *is_space = !f; if (!f) { - /* try to use backbuffer selection method if ray casting failed */ - f = EDBM_face_find_nearest(&kcd->vc, &dist); + if (kcd->is_interactive) { + /* try to use backbuffer selection method if ray casting failed */ + f = EDBM_face_find_nearest(&kcd->vc, &dist); - /* cheat for now; just put in the origin instead - * of a true coordinate on the face. - * This just puts a point 1.0f infront of the view. */ - add_v3_v3v3(co, origin, ray); + /* cheat for now; just put in the origin instead + * of a true coordinate on the face. + * This just puts a point 1.0f infront of the view. */ + add_v3_v3v3(co, origin, ray); + } } return f; @@ -1513,18 +1523,21 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float /* find the 2d screen space density of vertices within a radius. used to scale snapping * distance for picking edges/verts.*/ -static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius) +static int knife_sample_screen_density(KnifeTool_OpData *kcd, const float radius) { BMFace *f; - int is_space; + bool is_space; float co[3], cageco[3], sco[3]; + BLI_assert(kcd->is_interactive == true); + f = knife_find_closest_face(kcd, co, cageco, &is_space); if (f && !is_space) { + const float radius_sq = radius * radius; ListBase *lst; Ref *ref; - float dis; + float dis_sq; int c = 0; knife_project_v3(kcd, cageco, sco); @@ -1539,8 +1552,8 @@ static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius) knife_project_v3(kcd, kfv->cageco, kfv->sco); - dis = len_v2v2(kfv->sco, sco); - if (dis < radius) { + dis_sq = len_squared_v2v2(kfv->sco, sco); + if (dis_sq < radius_sq) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) { c++; @@ -1563,7 +1576,14 @@ static int knife_sample_screen_density(KnifeTool_OpData *kcd, float radius) * surrounding mesh (in screen space)*/ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize) { - float density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f); + float density; + + if (kcd->is_interactive) { + density = (float)knife_sample_screen_density(kcd, maxsize * 2.0f); + } + else { + density = 1.0f; + } if (density < 1.0f) density = 1.0f; @@ -1572,7 +1592,7 @@ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize) } /* p is closest point on edge to the mouse cursor */ -static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, int *is_space) +static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, bool *is_space) { BMFace *f; float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->ethresh); @@ -1668,7 +1688,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo /* find a vertex near the mouse cursor, if it exists */ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], float cagep[3], BMFace **fptr, - int *is_space) + bool *is_space) { BMFace *f; float co[3], cageco[3], sco[3], maxdist = knife_snap_size(kcd, kcd->vthresh); @@ -1684,10 +1704,11 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo kcd->curr.bmface = f; if (f) { + const float maxdist_sq = maxdist * maxdist; ListBase *lst; Ref *ref; KnifeVert *curv = NULL; - float dis, curdis = FLT_MAX; + float dis_sq, curdis_sq = FLT_MAX; knife_project_v3(kcd, cageco, sco); @@ -1701,17 +1722,17 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo knife_project_v3(kcd, kfv->cageco, kfv->sco); - dis = len_v2v2(kfv->sco, sco); - if (dis < curdis && dis < maxdist) { + dis_sq = len_squared_v2v2(kfv->sco, sco); + if (dis_sq < curdis_sq && dis_sq < maxdist_sq) { if (kcd->vc.rv3d->rflag & RV3D_CLIPPING) { if (ED_view3d_clipping_test(kcd->vc.rv3d, kfv->cageco, TRUE) == 0) { curv = kfv; - curdis = dis; + curdis_sq = dis_sq; } } else { curv = kfv; - curdis = dis; + curdis_sq = dis_sq; } } } @@ -1747,7 +1768,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo return NULL; } -/* update both kcd->curr.mval and kcd->vc.mval to snap to required angle */ +/* update both kcd->curr.mval and kcd->mval to snap to required angle */ static void knife_snap_angle(KnifeTool_OpData *kcd) { float dx, dy; @@ -1784,16 +1805,14 @@ static void knife_snap_angle(KnifeTool_OpData *kcd) kcd->curr.mval[0] = kcd->prev.mval[0]; } - kcd->vc.mval[0] = round_ftoi(kcd->curr.mval[0]); - kcd->vc.mval[1] = round_ftoi(kcd->curr.mval[1]); + copy_v2_v2(kcd->mval, kcd->curr.mval); } /* update active knife edge/vert pointers */ static int knife_update_active(KnifeTool_OpData *kcd) { knife_pos_data_clear(&kcd->curr); - kcd->curr.mval[0] = (float)kcd->vc.mval[0]; - kcd->curr.mval[1] = (float)kcd->vc.mval[1]; + copy_v2_v2(kcd->curr.mval, kcd->mval); if (kcd->angle_snapping != ANGLE_FREE && kcd->mode == MODE_DRAGGING) knife_snap_angle(kcd); @@ -1994,14 +2013,14 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) i++; if (kfe->e && kfe->v1->v == kfe->e->v1 && kfe->v2->v == kfe->e->v2) { - kfe->oe = kfe->e; + kfe->e_old = kfe->e; continue; } j++; if (kfe->e) { - kfe->oe = kfe->e; + kfe->e_old = kfe->e; BMO_elem_flag_enable(bm, kfe->e, DEL); BMO_elem_flag_disable(bm, kfe->e, BOUNDARY); @@ -2027,13 +2046,13 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) if (!kfe->v1 || !kfe->v2 || kfe->v1->inspace || kfe->v2->inspace) continue; - if (!(kfe->oe && kfe->v1->v == kfe->oe->v1 && kfe->v2->v == kfe->oe->v2)) + if (!(kfe->e_old && kfe->v1->v == kfe->e_old->v1 && kfe->v2->v == kfe->e_old->v2)) continue; k++; BMO_elem_flag_enable(bm, kfe->e, BOUNDARY); - kfe->oe = kfe->e; + kfe->e_old = kfe->e; for (ref = kfe->faces.first; ref; ref = ref->next) { f = ref->ref; @@ -2096,7 +2115,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) if (sf_vert->poly_nr > 1 && sf_vert_last->poly_nr > 1) { ScanFillEdge *sf_edge; sf_edge = BLI_scanfill_edge_add(&sf_ctx, sf_vert_last, sf_vert); - if (entry->kfe->oe) + if (entry->kfe->e_old) sf_edge->f = SF_EDGE_BOUNDARY; /* mark as original boundary edge */ BMO_elem_flag_disable(bm, entry->kfe->e->v1, DEL); @@ -2239,15 +2258,15 @@ static void sort_by_frac_along(ListBase *lst, BMEdge *e) /* The chain so far goes from an instantiated vertex to kfv (some may be reversed). * If possible, complete the chain to another instantiated vertex and return 1, else return 0. * The visited hash says which KnifeVert's have already been tried, not including kfv. */ -static int find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited, - ListBase *chain) +static bool find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fedges, SmallHash *visited, + ListBase *chain) { Ref *r; KnifeEdge *kfe; KnifeVert *kfv_other; if (kfv->v) - return TRUE; + return true; BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL); /* Try all possible next edges. Could either go through fedges @@ -2264,22 +2283,22 @@ static int find_chain_search(KnifeTool_OpData *kcd, KnifeVert *kfv, ListBase *fe if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) { knife_append_list(kcd, chain, kfe); if (find_chain_search(kcd, kfv_other, fedges, visited, chain)) - return TRUE; + return true; BLI_remlink(chain, chain->last); } } - return FALSE; + return false; } static ListBase *find_chain_from_vertex(KnifeTool_OpData *kcd, KnifeEdge *kfe, BMVert *v, ListBase *fedges) { SmallHash visited_, *visited = &visited_; ListBase *ans; - int found; + bool found; ans = knife_empty_list(kcd); knife_append_list(kcd, ans, kfe); - found = 0; + found = false; BLI_smallhash_init(visited); if (kfe->v1->v == v) { BLI_smallhash_insert(visited, (uintptr_t)(kfe->v1), NULL); @@ -2340,15 +2359,15 @@ static ListBase *find_chain(KnifeTool_OpData *kcd, ListBase *fedges) /* The hole so far goes from kfvfirst to kfv (some may be reversed). * If possible, complete the hole back to kfvfirst and return 1, else return 0. * The visited hash says which KnifeVert's have already been tried, not including kfv or kfvfirst. */ -static int find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges, - SmallHash *visited, ListBase *hole) +static bool find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVert *kfv, ListBase *fedges, + SmallHash *visited, ListBase *hole) { Ref *r; KnifeEdge *kfe, *kfelast; KnifeVert *kfv_other; if (kfv == kfvfirst) - return TRUE; + return true; BLI_smallhash_insert(visited, (uintptr_t)kfv, NULL); kfelast = ((Ref *)hole->last)->ref; @@ -2366,11 +2385,11 @@ static int find_hole_search(KnifeTool_OpData *kcd, KnifeVert *kfvfirst, KnifeVer if (kfv_other && !BLI_smallhash_haskey(visited, (uintptr_t)kfv_other)) { knife_append_list(kcd, hole, kfe); if (find_hole_search(kcd, kfvfirst, kfv_other, fedges, visited, hole)) - return TRUE; + return true; BLI_remlink(hole, hole->last); } } - return FALSE; + return false; } /* Find a hole (simple cycle with no instantiated vertices). @@ -2381,10 +2400,10 @@ static ListBase *find_hole(KnifeTool_OpData *kcd, ListBase *fedges) Ref *r, *ref; KnifeEdge *kfe; SmallHash visited_, *visited = &visited_; - int found; + bool found; ans = NULL; - found = FALSE; + found = false; for (r = fedges->first; r && !found; r = r->next) { kfe = r->ref; @@ -2853,10 +2872,8 @@ static void knife_make_cuts(KnifeTool_OpData *kcd) #endif /* called on tool confirmation */ -static void knifetool_finish(wmOperator *op) +static void knifetool_finish_ex(KnifeTool_OpData *kcd) { - KnifeTool_OpData *kcd = op->customdata; - #if SCANFILL_CUTS knifenet_fill_faces(kcd); #else @@ -2866,19 +2883,10 @@ static void knifetool_finish(wmOperator *op) EDBM_mesh_normals_update(kcd->em); EDBM_update_generic(kcd->em, TRUE, TRUE); } - -/* copied from paint_image.c */ -static int project_knife_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend) +static void knifetool_finish(wmOperator *op) { - int orth = ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend); - - if (orth) { /* only needed for ortho */ - float fac = 2.0f / ((*clipend) - (*clipsta)); - *clipsta *= fac; - *clipend *= fac; - } - - return orth; + KnifeTool_OpData *kcd = op->customdata; + knifetool_finish_ex(kcd); } static void knife_recalc_projmat(KnifeTool_OpData *kcd) @@ -2887,22 +2895,22 @@ static void knife_recalc_projmat(KnifeTool_OpData *kcd) ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, kcd->projmat); //mult_m4_m4m4(kcd->projmat, kcd->vc.rv3d->winmat, kcd->vc.rv3d->viewmat); - kcd->is_ortho = project_knife_view_clip(kcd->vc.v3d, kcd->vc.rv3d, - &kcd->clipsta, &kcd->clipend); + kcd->is_ortho = ED_view3d_clip_range_get(kcd->vc.v3d, kcd->vc.rv3d, + &kcd->clipsta, &kcd->clipend, true); } /* called when modal loop selection is done... */ -static void knifetool_exit(bContext *C, wmOperator *op) +static void knifetool_exit_ex(bContext *C, KnifeTool_OpData *kcd) { - KnifeTool_OpData *kcd = op->customdata; - if (!kcd) return; - WM_cursor_restore(CTX_wm_window(C)); + if (kcd->is_interactive) { + WM_cursor_restore(CTX_wm_window(C)); - /* deactivate the extra drawing stuff in 3D-View */ - ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle); + /* deactivate the extra drawing stuff in 3D-View */ + ED_region_draw_cb_exit(kcd->ar->type, kcd->draw_handle); + } /* free the custom data */ BLI_mempool_destroy(kcd->refs); @@ -2927,6 +2935,11 @@ static void knifetool_exit(bContext *C, wmOperator *op) /* destroy kcd itself */ MEM_freeN(kcd); +} +static void knifetool_exit(bContext *C, wmOperator *op) +{ + KnifeTool_OpData *kcd = op->customdata; + knifetool_exit_ex(C, kcd); op->customdata = NULL; } @@ -2944,35 +2957,36 @@ static void cage_mapped_verts_callback(void *userData, int index, const float co } } -static void knifetool_update_mval(KnifeTool_OpData *kcd, int mval_i[2]) +static void knifetool_update_mval(KnifeTool_OpData *kcd, const float mval[2]) { knife_recalc_projmat(kcd); - kcd->vc.mval[0] = mval_i[0]; - kcd->vc.mval[1] = mval_i[1]; + copy_v2_v2(kcd->mval, mval); if (knife_update_active(kcd)) { ED_region_tag_redraw(kcd->ar); } } +static void knifetool_update_mval_i(KnifeTool_OpData *kcd, const int mval_i[2]) +{ + float mval[2] = {UNPACK2(mval_i)}; + knifetool_update_mval(kcd, mval); +} + /* called when modal loop selection gets set up... */ -static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut)) +static void knifetool_init(bContext *C, KnifeTool_OpData *kcd, + const bool only_select, const bool cut_through, const bool is_interactive) { - KnifeTool_OpData *kcd; Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); DerivedMesh *cage, *final; SmallHash shash; void *data[3]; - const short only_select = RNA_boolean_get(op->ptr, "only_selected"); - - /* alloc new customdata */ - kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), "knifetool Modal Op Data"); /* assign the drawing handle for drawing preview line... */ kcd->ob = obedit; kcd->ar = CTX_wm_region(C); - kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW); + em_setup_viewcontext(C, &kcd->vc); kcd->em = BMEdit_FromObject(kcd->ob); @@ -2998,7 +3012,7 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut)) kcd->vthresh = KMAXDIST - 1; kcd->ethresh = KMAXDIST; - kcd->extend = 1; + kcd->extend = true; knife_recalc_projmat(kcd); @@ -3013,7 +3027,8 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut)) kcd->kedgefacemap = BLI_ghash_ptr_new("knife origvertmap"); /* cut all the way through the mesh if use_occlude_geometry button not pushed */ - kcd->cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry"); + kcd->is_interactive = is_interactive; + kcd->cut_through = cut_through; kcd->only_select = only_select; /* can't usefully select resulting edges in face mode */ @@ -3022,9 +3037,11 @@ static int knifetool_init(bContext *C, wmOperator *op, int UNUSED(do_cut)) knife_pos_data_clear(&kcd->curr); knife_pos_data_clear(&kcd->prev); - knife_init_colors(&kcd->colors); + if (is_interactive) { + kcd->draw_handle = ED_region_draw_cb_activate(kcd->ar->type, knifetool_draw, kcd, REGION_DRAW_POST_VIEW); - return 1; + knife_init_colors(&kcd->colors); + } } static int knifetool_cancel(bContext *C, wmOperator *op) @@ -3034,21 +3051,25 @@ static int knifetool_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int knifetool_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int knifetool_invoke(bContext *C, wmOperator *op, const wmEvent *event) { + const bool only_select = RNA_boolean_get(op->ptr, "only_selected"); + const bool cut_through = !RNA_boolean_get(op->ptr, "use_occlude_geometry"); + KnifeTool_OpData *kcd; view3d_operator_needs_opengl(C); - if (!knifetool_init(C, op, 0)) - return OPERATOR_CANCELLED; + /* alloc new customdata */ + kcd = op->customdata = MEM_callocN(sizeof(KnifeTool_OpData), __func__); + + knifetool_init(C, kcd, only_select, cut_through, true); /* add a modal handler for this operator - handles loop selection */ WM_cursor_modal(CTX_wm_window(C), BC_KNIFECURSOR); WM_event_add_modal_handler(C, op); - kcd = op->customdata; - knifetool_update_mval(kcd, evt->mval); + knifetool_update_mval_i(kcd, event->mval); knife_update_header(C, kcd); @@ -3119,11 +3140,11 @@ wmKeyMap *knifetool_modal_keymap(wmKeyConfig *keyconf) return keymap; } -static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) +static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); KnifeTool_OpData *kcd = op->customdata; - int do_refresh = FALSE; + bool do_refresh = false; if (!obedit || obedit->type != OB_MESH || BMEdit_FromObject(obedit) != kcd->em) { knifetool_exit(C, op); @@ -3158,7 +3179,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; case KNF_MODAL_MIDPOINT_ON: - kcd->snap_midpoints = 1; + kcd->snap_midpoints = true; knife_recalc_projmat(kcd); knife_update_active(kcd); @@ -3167,7 +3188,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) do_refresh = TRUE; break; case KNF_MODAL_MIDPOINT_OFF: - kcd->snap_midpoints = 0; + kcd->snap_midpoints = false; knife_recalc_projmat(kcd); knife_update_active(kcd); @@ -3177,13 +3198,13 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) break; case KNF_MODEL_IGNORE_SNAP_ON: ED_region_tag_redraw(kcd->ar); - kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 1; + kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = true; knife_update_header(C, kcd); do_refresh = TRUE; break; case KNF_MODEL_IGNORE_SNAP_OFF: ED_region_tag_redraw(kcd->ar); - kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = 0; + kcd->ignore_vert_snapping = kcd->ignore_edge_snapping = false; knife_update_header(C, kcd); do_refresh = TRUE; break; @@ -3241,7 +3262,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) case MOUSEMOVE: /* mouse moved somewhere to select another loop */ if (kcd->mode != MODE_PANNING) { - knifetool_update_mval(kcd, event->mval); + knifetool_update_mval_i(kcd, event->mval); } break; @@ -3251,7 +3272,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, wmEvent *event) if (do_refresh) { /* we don't really need to update mval, * but this happens to be the best way to refresh at the moment */ - knifetool_update_mval(kcd, event->mval); + knifetool_update_mval_i(kcd, event->mval); } /* keep going until the user confirms */ @@ -3277,3 +3298,229 @@ void MESH_OT_knife_tool(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_occlude_geometry", TRUE, "Occlude Geometry", "Only cut the front most geometry"); RNA_def_boolean(ot->srna, "only_selected", FALSE, "Only Selected", "Only cut selected geometry"); } + + +/* -------------------------------------------------------------------- */ +/* Knife tool as a utility function + * that can be used for internal slicing operations */ + +/** + * Return a point inside the face. + * + * tessellation here seems way overkill, + * but without this its very hard to know of a point is inside the face + */ +static void edvm_mesh_knife_face_point(BMFace *f, float r_cent[3]) +{ + int tottri = f->len - 2; + BMLoop **loops = BLI_array_alloca(loops, f->len); + int (*index)[3] = BLI_array_alloca(index, tottri); + int j; + + float const *best_co[3] = {NULL}; + float best_area = -1.0f; + bool ok = false; + + tottri = BM_face_calc_tessellation(f, loops, index); + BLI_assert(tottri <= f->len - 2); + + for (j = 0; j < tottri; j++) { + const float *p1 = loops[index[j][0]]->v->co; + const float *p2 = loops[index[j][1]]->v->co; + const float *p3 = loops[index[j][2]]->v->co; + float area; + + float cross[3]; + cross_v3_v3v3(cross, p2, p3); + area = fabsf(dot_v3v3(p1, cross)); + if (area > best_area) { + best_co[0] = p1; + best_co[1] = p2; + best_co[2] = p3; + best_area = area; + ok = true; + } + } + + if (ok) { + mid_v3_v3v3v3(r_cent, best_co[0], best_co[1], best_co[2]); + } + else { + mid_v3_v3v3v3(r_cent, loops[0]->v->co, loops[1]->v->co, loops[2]->v->co); + } +} + +static bool edbm_mesh_knife_face_isect(ARegion *ar, LinkNode *polys, BMFace *f, float projmat[4][4]) +{ + float cent_ss[2]; + float cent[3]; + + edvm_mesh_knife_face_point(f, cent); + + ED_view3d_project_float_v2_m4(ar, cent, cent_ss, projmat); + + /* check */ + { + LinkNode *p = polys; + int isect = 0; + + while (p) { + const float (*mval_fl)[2] = p->link; + const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl); + isect += (int)isect_point_poly_v2(cent_ss, mval_fl, mval_tot - 1); + p = p->next; + } + + if (isect % 2) { + return true; + } + } + + return false; +} + +/** + * \param use_tag When set, tag all faces inside the polylines. + */ +void EDBM_mesh_knife(bContext *C, LinkNode *polys, bool use_tag) +{ + KnifeTool_OpData *kcd; + + view3d_operator_needs_opengl(C); + + /* init */ + { + const bool only_select = false; + const bool cut_through = false; + const bool is_interactive = false; /* can enable for testing */ + + kcd = MEM_callocN(sizeof(KnifeTool_OpData), __func__); + + knifetool_init(C, kcd, only_select, cut_through, is_interactive); + + kcd->ignore_edge_snapping = true; + kcd->ignore_vert_snapping = true; + + if (use_tag) { + BM_mesh_elem_hflag_enable_all(kcd->em->bm, BM_EDGE, BM_ELEM_TAG, false); + } + } + + /* execute */ + { + LinkNode *p = polys; + + knife_recalc_projmat(kcd); + + while (p) { + const float (*mval_fl)[2] = p->link; + const int mval_tot = MEM_allocN_len(mval_fl) / sizeof(*mval_fl); + int i; + + for (i = 0; i < mval_tot; i++) { + knifetool_update_mval(kcd, mval_fl[i]); + if (i == 0) { + knife_start_cut(kcd); + kcd->mode = MODE_DRAGGING; + } + else { + knife_add_cut(kcd); + } + } + knife_finish_cut(kcd); + kcd->mode = MODE_IDLE; + p = p->next; + } + } + + /* finish */ + { + knifetool_finish_ex(kcd); + + /* tag faces inside! */ + if (use_tag) { + BMesh *bm = kcd->em->bm; + float projmat[4][4]; + + BMEdge *e; + BMIter iter; + + bool keep_search; + + ED_view3d_ob_project_mat_get(kcd->ar->regiondata, kcd->ob, projmat); + + /* use face-loop tag to store if we have intersected */ +#define F_ISECT_IS_UNKNOWN(f) BM_elem_flag_test(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG) +#define F_ISECT_SET_UNKNOWN(f) BM_elem_flag_enable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG) +#define F_ISECT_SET_OUTSIDE(f) BM_elem_flag_disable(BM_FACE_FIRST_LOOP(f), BM_ELEM_TAG) + { + BMFace *f; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + F_ISECT_SET_UNKNOWN(f); + BM_elem_flag_disable(f, BM_ELEM_TAG); + } + } + + /* tag all faces linked to cut edges */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + /* check are we tagged?, then we are an original face */ + if (BM_elem_flag_test(e, BM_ELEM_TAG) == false) { + BMFace *f; + BMIter fiter; + BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { + if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + } + } + } + + /* expand tags for faces which are not cut, but are inside the polys */ + do { + BMFace *f; + keep_search = false; + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_TAG) == false && (F_ISECT_IS_UNKNOWN(f))) { + /* am I connected to a tagged face via an un-tagged edge (ie, not across a cut) */ + BMLoop *l_first = BM_FACE_FIRST_LOOP(f); + BMLoop *l_iter = l_first; + bool found = false; + + do { + if (BM_elem_flag_test(l_iter->e, BM_ELEM_TAG) != false) { + /* now check if the adjacent faces is tagged */ + BMLoop *l_radial_iter = l_iter->radial_next; + if (l_radial_iter != l_iter) { + do { + if (BM_elem_flag_test(l_radial_iter->f, BM_ELEM_TAG)) { + found = true; + } + } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter && (found == false)); + } + } + } while ((l_iter = l_iter->next) != l_first && (found == false)); + + if (found) { + if (edbm_mesh_knife_face_isect(kcd->ar, polys, f, projmat)) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + keep_search = true; + } + else { + /* don't loose time on this face again, set it as outside */ + F_ISECT_SET_OUTSIDE(f); + } + } + } + } + } while (keep_search); + +#undef F_ISECT_IS_UNKNOWN +#undef F_ISECT_SET_UNKNOWN +#undef F_ISECT_SET_OUTSIDE + + } + + knifetool_exit_ex(C, kcd); + kcd = NULL; + } +} diff --git a/source/blender/editors/mesh/editmesh_knife_project.c b/source/blender/editors/mesh/editmesh_knife_project.c new file mode 100644 index 00000000000..c581ce5a2e8 --- /dev/null +++ b/source/blender/editors/mesh/editmesh_knife_project.c @@ -0,0 +1,168 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2007 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mesh/editmesh_knife_project.c + * \ingroup edmesh + */ + +#include "DNA_curve_types.h" +#include "DNA_scene_types.h" +#include "DNA_object_types.h" +#include "DNA_screen_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" + +#include "BKE_library.h" +#include "BKE_mesh.h" +#include "BKE_context.h" +#include "BKE_curve.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_tessmesh.h" +#include "BKE_report.h" + +#include "MEM_guardedalloc.h" + +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_view3d.h" + +#include "mesh_intern.h" + + +static LinkNode *knifeproject_poly_from_object(ARegion *ar, Scene *scene, Object *ob, LinkNode *polys) +{ + DerivedMesh *dm; + bool dm_needsFree; + + if (ob->type == OB_MESH || ob->derivedFinal) { + dm = ob->derivedFinal ? ob->derivedFinal : mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm_needsFree = false; + } + else if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { + dm = CDDM_from_curve(ob); + dm_needsFree = true; + } + else { + dm = NULL; + } + + if (dm) { + ListBase nurbslist = {NULL, NULL}; + float projmat[4][4]; + + BKE_mesh_to_curve_nurblist(dm, &nurbslist, 0); /* wire */ + BKE_mesh_to_curve_nurblist(dm, &nurbslist, 1); /* boundary */ + + ED_view3d_ob_project_mat_get(ar->regiondata, ob, projmat); + + if (nurbslist.first) { + Nurb *nu; + for (nu = nurbslist.first; nu; nu = nu->next) { + if (nu->bp) { + int a; + BPoint *bp; + bool is_cyclic = (nu->flagu & CU_NURB_CYCLIC) != 0; + float (*mval)[2] = MEM_mallocN(sizeof(*mval) * (nu->pntsu + is_cyclic), __func__); + + for (bp = nu->bp, a = 0; a < nu->pntsu; a++, bp++) { + ED_view3d_project_float_v3_m4(ar, bp->vec, mval[a], projmat); + } + if (is_cyclic) { + copy_v2_v2(mval[a], mval[0]); + } + + BLI_linklist_prepend(&polys, mval); + } + } + } + + BKE_nurbList_free(&nurbslist); + + if (dm_needsFree) { + dm->release(dm); + } + } + + + return polys; +} + +static int knifeproject_exec(bContext *C, wmOperator *op) +{ + ARegion *ar = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); + + LinkNode *polys = NULL; + + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + if (ob != obedit) { + polys = knifeproject_poly_from_object(ar, scene, ob, polys); + } + } + CTX_DATA_END; + + if (polys) { + EDBM_mesh_knife(C, polys, true); + + /* select only tagged faces */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_TAG); + + BM_mesh_select_mode_flush(em->bm); + + BLI_linklist_freeN(polys); + + return OPERATOR_FINISHED; + } + else { + BKE_report(op->reports, RPT_ERROR, "No other selected objects found to use for projection"); + return OPERATOR_CANCELLED; + } +} + +void MESH_OT_knife_project(wmOperatorType *ot) +{ + /* description */ + ot->name = "Knife Project"; + ot->idname = "MESH_OT_knife_project"; + ot->description = "Use other objects outlines & boundaries to project knife cuts"; + + /* callbacks */ + ot->exec = knifeproject_exec; + ot->poll = ED_operator_editmesh_view3d; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; +} + diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 83542915ec2..5b9864ca239 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -385,7 +385,7 @@ static int ringcut_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int ringcut_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); Object *obedit = CTX_data_edit_object(C); @@ -405,8 +405,7 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) WM_event_add_modal_handler(C, op); lcd = op->customdata; - lcd->vc.mval[0] = evt->mval[0]; - lcd->vc.mval[1] = evt->mval[1]; + copy_v2_v2_int(lcd->vc.mval, event->mval); edge = EDBM_edge_find_nearest(&lcd->vc, &dist); if (edge != lcd->eed) { @@ -419,7 +418,7 @@ static int ringcut_invoke(bContext *C, wmOperator *op, wmEvent *evt) return OPERATOR_RUNNING_MODAL; } -static int loopcut_modal(bContext *C, wmOperator *op, wmEvent *event) +static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event) { float smoothness = RNA_float_get(op->ptr, "smoothness"); int cuts = RNA_int_get(op->ptr, "number_cuts"); diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 6cbf5e88cee..8198e088e5a 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -33,9 +33,6 @@ #include "DNA_object_types.h" -#include "RNA_define.h" -#include "RNA_access.h" - #include "BLI_math.h" #include "BLI_array.h" @@ -43,6 +40,9 @@ #include "BKE_report.h" #include "BKE_tessmesh.h" +#include "RNA_define.h" +#include "RNA_access.h" + #include "WM_types.h" #include "ED_mesh.h" @@ -499,16 +499,9 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); } else { - if (v_shared == f_verts[0]) { - BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; - BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; - BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); - } - else { - BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; - BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; - BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); - } + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[0]->e, l_iter), l_iter); l_iter = l_iter->next; + BM_elem_attrs_copy(bm, bm, BM_edge_other_loop(ulp->l_pair[1]->e, l_iter), l_iter); } } @@ -538,7 +531,7 @@ static int edbm_rip_call_edgesplit(BMEditMesh *em, wmOperator *op) /** * This is the main vert ripping function (rip when one vertex is selected) */ -static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *event) { const int do_fill = RNA_boolean_get(op->ptr, "use_fill"); UnorderedLoopPair *fill_uloop_pairs = NULL; @@ -860,7 +853,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, wmEvent *event) /** * This is the main edge ripping function */ -static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, const wmEvent *event) { const int do_fill = RNA_boolean_get(op->ptr, "use_fill"); UnorderedLoopPair *fill_uloop_pairs = NULL; @@ -988,7 +981,7 @@ static int edbm_rip_invoke__edge(bContext *C, wmOperator *op, wmEvent *event) } /* based on mouse cursor position, it defines how is being ripped */ -static int edbm_rip_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 1016c08e1c4..a1c302c6a63 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -66,6 +66,8 @@ #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "GPU_extensions.h" + #include "mesh_intern.h" #include "UI_resources.h" @@ -253,6 +255,9 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short dr = buf->rect; + if (vc->rv3d->gpuoffscreen) + GPU_offscreen_bind(vc->rv3d->gpuoffscreen); + /* draw the mask */ glDisable(GL_DEPTH_TEST); @@ -270,6 +275,9 @@ int EDBM_backbuf_border_mask_init(ViewContext *vc, const int mcords[][2], short glFinish(); /* to be sure readpixels sees mask */ + if (vc->rv3d->gpuoffscreen) + GPU_offscreen_unbind(vc->rv3d->gpuoffscreen); + /* grab mask */ bufmask = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); @@ -308,8 +316,10 @@ int EDBM_backbuf_circle_init(ViewContext *vc, short xs, short ys, short rads) return 0; } } - else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) return 0; - + else if (vc->v3d->drawtype < OB_SOLID || (vc->v3d->flag & V3D_ZBUF_SELECT) == 0) { + return 0; + } + xmin = xs - rads; xmax = xs + rads; ymin = ys - rads; ymax = ys + rads; buf = view3d_read_backbuf(vc, xmin, ymin, xmax, ymax); @@ -932,7 +942,7 @@ static int edbm_select_mode_exec(bContext *C, wmOperator *op) } } -static int edbm_select_mode_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_select_mode_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* detecting these options based on shift/ctrl here is weak, but it's done * to make this work when clicking buttons or menus */ @@ -1084,7 +1094,7 @@ void MESH_OT_loop_multi_select(wmOperatorType *ot) /* ***************** loop select (non modal) ************** */ -static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short deselect, short toggle, short ring) +static void mouse_mesh_loop(bContext *C, const int mval[2], short extend, short deselect, short toggle, short ring) { ViewContext vc; BMEditMesh *em; @@ -1171,7 +1181,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele /* Select the face of eed which is the nearest of mouse. */ BMFace *f, *efa = NULL; BMIter iterf; - float best_dist = MAXFLOAT; + float best_dist = FLT_MAX; /* We can't be sure this has already been set... */ ED_view3d_init_mats_rv3d(vc.obedit, vc.rv3d); @@ -1203,7 +1213,7 @@ static void mouse_mesh_loop(bContext *C, int mval[2], short extend, short desele } } -static int edbm_select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { view3d_operator_needs_opengl(C); @@ -1754,7 +1764,7 @@ static int mouse_mesh_shortest_path_face(ViewContext *vc) /* ******************* operator for edge and face tag ****************** */ -static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ViewContext vc; BMEditMesh *em; @@ -2252,7 +2262,7 @@ static void linked_limit_default(bContext *C, wmOperator *op) } } -static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); ViewContext vc; @@ -2995,6 +3005,59 @@ void MESH_OT_select_random(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); } +static int edbm_select_ungrouped_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BMEdit_FromObject(obedit); + BMVert *eve; + BMIter iter; + + if (!em->selectmode == SCE_SELECT_VERTEX) { + BKE_report(op->reports, RPT_ERROR, "Does not work out of vertex selection mode"); + return OPERATOR_CANCELLED; + } + + if (obedit->defbase.first == NULL) { + BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); + return OPERATOR_CANCELLED; + } + + if (!RNA_boolean_get(op->ptr, "extend")) { + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + } + + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { + MDeformVert *dv = CustomData_bmesh_get(&em->bm->vdata, eve->head.data, CD_MDEFORMVERT); + /* no dv or dv set with no weight */ + if (dv == NULL || (dv && dv->dw == NULL)) { + BM_vert_select_set(em->bm, eve, true); + } + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void MESH_OT_select_ungrouped(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Ungrouped"; + ot->idname = "MESH_OT_select_ungrouped"; + ot->description = "Select vertices without a group"; + + /* api callbacks */ + ot->exec = edbm_select_ungrouped_exec; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); +} + static int edbm_select_next_loop_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index c35f942cf33..36a1d30c85e 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -39,10 +39,6 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "RNA_define.h" -#include "RNA_access.h" -#include "RNA_enum_types.h" - #include "BLI_blenlib.h" #include "BLI_noise.h" #include "BLI_math.h" @@ -59,6 +55,10 @@ #include "BKE_main.h" #include "BKE_tessmesh.h" +#include "RNA_define.h" +#include "RNA_access.h" +#include "RNA_enum_types.h" + #include "WM_api.h" #include "WM_types.h" @@ -77,6 +77,8 @@ #include "mesh_intern.h" +#define USE_FACE_CREATE_SEL_EXTEND + #define MVAL_PIXEL_MARGIN 5.0f /* allow accumulated normals to form a new direction but don't @@ -333,10 +335,7 @@ static short edbm_extrude_edge(Object *obedit, BMEditMesh *em, const char hflag, mult_m4_m4m4(mtx, imtx, obedit->obmat); } - for (edge = BM_iter_new(&iter, bm, BM_EDGES_OF_MESH, NULL); - edge; - edge = BM_iter_step(&iter)) - { + BM_ITER_MESH (edge, &iter, bm, BM_EDGES_OF_MESH) { if (BM_elem_flag_test(edge, hflag) && BM_edge_is_boundary(edge) && BM_elem_flag_test(edge->l->f, hflag)) @@ -779,7 +778,7 @@ void MESH_OT_select_interior_faces(wmOperatorType *ot) } /* *************** add-click-mesh (extrude) operator ************** */ -static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewContext vc; BMVert *v1; @@ -863,7 +862,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent copy_v3_v3(min, cent); mul_m4_v3(vc.obedit->obmat, min); /* view space */ - view3d_get_view_aligned_coordinate(&vc, min, event->mval, TRUE); + view3d_get_view_aligned_coordinate(vc.ar, min, event->mval, true); mul_m4_v3(vc.obedit->imat, min); // back in object space sub_v3_v3(min, cent); @@ -912,7 +911,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, wmEvent BMOIter oiter; copy_v3_v3(min, curs); - view3d_get_view_aligned_coordinate(&vc, min, event->mval, FALSE); + view3d_get_view_aligned_coordinate(vc.ar, min, event->mval, false); invert_m4_m4(vc.obedit->imat, vc.obedit->obmat); mul_m4_v3(vc.obedit->imat, min); // back in object space @@ -1099,6 +1098,140 @@ static int edbm_add_edge_face__smooth_get(BMesh *bm) return (vote_on_smooth[0] < vote_on_smooth[1]); } +#ifdef USE_FACE_CREATE_SEL_EXTEND +/** + * Function used to get a fixed number of edges linked to a vertex that passes a test function. + * This is used so we can request all boundary edges connected to a vertex for eg. + */ +static int edbm_add_edge_face_exec__vert_edge_lookup(BMVert *v, BMEdge *e_used, BMEdge **e_arr, const int e_arr_len, + bool (* func)(BMEdge *)) +{ + BMIter iter; + BMEdge *e_iter; + int i = 0; + BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_iter, BM_ELEM_HIDDEN) == false) { + if ((e_used == NULL) || (e_used != e_iter)) { + if (func(e_iter)) { + e_arr[i++] = e_iter; + if (i >= e_arr_len) { + break; + } + } + } + } + } + return i; +} + +static BMElem *edbm_add_edge_face_exec__tricky_extend_sel(BMesh *bm) +{ + BMIter iter; + bool found = false; + + if (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0) { + /* first look for 2 boundary edges */ + BMVert *v; + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { + found = true; + break; + } + } + + if (found) { + BMEdge *ed_pair[3]; + if ( + ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_wire) == 2) && + (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) || + + ((edbm_add_edge_face_exec__vert_edge_lookup(v, NULL, ed_pair, 3, BM_edge_is_boundary) == 2) && + (BM_edge_share_face_check(ed_pair[0], ed_pair[1]) == false)) + ) + { + BMEdge *e_other = BM_edge_exists(BM_edge_other_vert(ed_pair[0], v), + BM_edge_other_vert(ed_pair[1], v)); + BM_edge_select_set(bm, ed_pair[0], true); + BM_edge_select_set(bm, ed_pair[1], true); + if (e_other) { + BM_edge_select_set(bm, e_other, true); + } + return (BMElem *)v; + } + } + } + else if (bm->totvertsel == 2 && bm->totedgesel == 1 && bm->totfacesel == 0) { + /* first look for 2 boundary edges */ + BMEdge *e; + + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + if (BM_elem_flag_test(e, BM_ELEM_SELECT)) { + found = true; + break; + } + } + if (found) { + BMEdge *ed_pair_v1[2]; + BMEdge *ed_pair_v2[2]; + if ( + ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_wire) == 1) && + (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_wire) == 1) && + (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) && + (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) || + + ((edbm_add_edge_face_exec__vert_edge_lookup(e->v1, e, ed_pair_v1, 2, BM_edge_is_boundary) == 1) && + (edbm_add_edge_face_exec__vert_edge_lookup(e->v2, e, ed_pair_v2, 2, BM_edge_is_boundary) == 1) && + (BM_edge_share_face_check(e, ed_pair_v1[0]) == false) && + (BM_edge_share_face_check(e, ed_pair_v2[0]) == false)) + ) + { + BMVert *v1_other = BM_edge_other_vert(ed_pair_v1[0], e->v1); + BMVert *v2_other = BM_edge_other_vert(ed_pair_v2[0], e->v2); + BMEdge *e_other = (v1_other != v2_other) ? BM_edge_exists(v1_other, v2_other) : NULL; + BM_edge_select_set(bm, ed_pair_v1[0], true); + BM_edge_select_set(bm, ed_pair_v2[0], true); + if (e_other) { + BM_edge_select_set(bm, e_other, true); + } + return (BMElem *)e; + } + } + } + + return NULL; +} +static void edbm_add_edge_face_exec__tricky_finalize_sel(BMesh *bm, BMElem *ele_desel, BMFace *f) +{ + /* now we need to find the edge that isnt connected to this element */ + BM_select_history_clear(bm); + + if (ele_desel->head.htype == BM_VERT) { + BMLoop *l = BM_face_vert_share_loop(f, (BMVert *)ele_desel); + BLI_assert(f->len == 3); + BM_face_select_set(bm, f, false); + BM_vert_select_set(bm, (BMVert *)ele_desel, false); + + BM_edge_select_set(bm, l->next->e, true); + BM_select_history_store(bm, l->next->e); + } + else { + BMLoop *l = BM_face_edge_share_loop(f, (BMEdge *)ele_desel); + BLI_assert(f->len == 4 || f->len == 3); + BM_face_select_set(bm, f, false); + BM_edge_select_set(bm, (BMEdge *)ele_desel, false); + if (f->len == 4) { + BM_edge_select_set(bm, l->next->next->e, true); + BM_select_history_store(bm, l->next->next->e); + } + else { + BM_vert_select_set(bm, l->next->next->v, true); + BM_select_history_store(bm, l->next->next->v); + } + } +} +#endif /* USE_FACE_CREATE_SEL_EXTEND */ + static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) { BMOperator bmop; @@ -1107,6 +1240,15 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) const short use_smooth = edbm_add_edge_face__smooth_get(em->bm); /* when this is used to dissolve we could avoid this, but checking isnt too slow */ +#ifdef USE_FACE_CREATE_SEL_EXTEND + BMElem *ele_desel; + BMFace *ele_desel_face; + + /* be extra clever, figure out if a partial selection should be extended so we can create geometry + * with single vert or single edge selection */ + ele_desel = edbm_add_edge_face_exec__tricky_extend_sel(em->bm); +#endif + if (!EDBM_op_init(em, &bmop, op, "contextual_create geom=%hfev mat_nr=%i use_smooth=%b", BM_ELEM_SELECT, em->mat_nr, use_smooth)) @@ -1115,8 +1257,22 @@ static int edbm_add_edge_face_exec(bContext *C, wmOperator *op) } BMO_op_exec(em->bm, &bmop); - BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, TRUE); - BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, TRUE); + +#ifdef USE_FACE_CREATE_SEL_EXTEND + /* normally we would want to leave the new geometry selected, + * but being able to press F many times to add geometry is too useful! */ + if (ele_desel && + (BMO_slot_buffer_count(bmop.slots_out, "faces.out") == 1) && + (ele_desel_face = BMO_slot_buffer_get_first(bmop.slots_out, "faces.out"))) + { + edbm_add_edge_face_exec__tricky_finalize_sel(em->bm, ele_desel, ele_desel_face); + } + else +#endif + { + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "edges.out", BM_EDGE, BM_ELEM_SELECT, true); + } if (!EDBM_op_finish(em, &bmop, op, TRUE)) { return OPERATOR_CANCELLED; @@ -1355,7 +1511,7 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int edbm_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int edbm_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { WM_cursor_wait(1); edbm_duplicate_exec(C, op); @@ -2005,12 +2161,22 @@ static int merge_firstlast(BMEditMesh *em, int first, int uvmerge, wmOperator *w BMVert *mergevert; BMEditSelection *ese; + /* operator could be called directly from shortcut or python, + * so do extra check for data here + */ + /* do sanity check in mergemenu in edit.c ?*/ if (first == 0) { + if (!em->bm->selected.last || ((BMEditSelection *)em->bm->selected.last)->htype != BM_VERT) + return OPERATOR_CANCELLED; + ese = em->bm->selected.last; mergevert = (BMVert *)ese->ele; } else { + if (!em->bm->selected.first || ((BMEditSelection *)em->bm->selected.first)->htype != BM_VERT) + return OPERATOR_CANCELLED; + ese = em->bm->selected.first; mergevert = (BMVert *)ese->ele; } @@ -2293,8 +2459,12 @@ static int edbm_select_vertex_path_exec(bContext *C, wmOperator *op) if (!BM_elem_flag_test(eve, BM_ELEM_SELECT) || BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) continue; - if (svert == NULL) svert = eve; - else if (evert == NULL) evert = eve; + if (svert == NULL) { + svert = eve; + } + else if (evert == NULL) { + evert = eve; + } else { /* more than two vertices are selected, * show warning message and cancel operator */ @@ -3225,6 +3395,16 @@ static int edbm_separate_exec(bContext *C, wmOperator *op) Base *base = CTX_data_active_base(C); BMEditMesh *em = BMEdit_FromObject(base->object); + if (type == 0) { + if ((em->bm->totvertsel == 0) && + (em->bm->totedgesel == 0) && + (em->bm->totfacesel == 0)) + { + BKE_report(op->reports, RPT_ERROR, "Nothing selected"); + return OPERATOR_CANCELLED; + } + } + /* editmode separate */ if (type == 0) retval = mesh_separate_selected(bmain, scene, base, em->bm); else if (type == 1) retval = mesh_separate_material(bmain, scene, base, em->bm); @@ -3689,7 +3869,7 @@ static int edbm_spin_exec(bContext *C, wmOperator *op) } /* get center and axis, in global coords */ -static int edbm_spin_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int edbm_spin_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -3759,9 +3939,10 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) /* find two vertices with valence count == 1, more or less is wrong */ v1 = NULL; v2 = NULL; - for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter)) { + + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { valence = 0; - for (eed = BM_iter_new(&eiter, em->bm, BM_EDGES_OF_VERT, eve); eed; eed = BM_iter_step(&eiter)) { + BM_ITER_ELEM (eed, &eiter, eve, BM_EDGES_OF_VERT) { if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { valence++; } @@ -3812,7 +3993,7 @@ static int edbm_screw_exec(bContext *C, wmOperator *op) } /* get center and axis, in global coords */ -static int edbm_screw_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int edbm_screw_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -4505,7 +4686,7 @@ static int edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop int action = RNA_enum_get(ptr, "type"); /* Only show seed for randomize action! */ - if (strcmp(prop_id, "seed") == 0) { + if (STREQ(prop_id, "seed")) { if (action == SRT_RANDOMIZE) return TRUE; else @@ -4513,7 +4694,7 @@ static int edbm_sort_elements_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop } /* Hide seed for reverse and randomize actions! */ - if (strcmp(prop_id, "reverse") == 0) { + if (STREQ(prop_id, "reverse")) { if (ELEM(action, SRT_RANDOMIZE, SRT_REVERSE)) return FALSE; else @@ -4804,7 +4985,7 @@ static int edbm_bevel_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_bevel_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* TODO make modal keymap (see fly mode) */ RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -4841,7 +5022,7 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) +static float edbm_bevel_mval_factor(wmOperator *op, const wmEvent *event) { BevelData *opdata = op->customdata; int use_dist = TRUE; @@ -4880,7 +5061,7 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) return factor; } -static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_bevel_modal(bContext *C, wmOperator *op, const wmEvent *event) { BevelData *opdata = op->customdata; int segments = RNA_int_get(op->ptr, "segments"); @@ -5186,7 +5367,7 @@ static int edbm_inset_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_inset_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); InsetData *opdata; @@ -5216,7 +5397,7 @@ static int edbm_inset_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int edbm_inset_modal(bContext *C, wmOperator *op, wmEvent *event) +static int edbm_inset_modal(bContext *C, wmOperator *op, const wmEvent *event) { InsetData *opdata = op->customdata; diff --git a/source/blender/editors/mesh/mesh_data.c b/source/blender/editors/mesh/mesh_data.c index 0c9a5aab537..99f526f95f3 100644 --- a/source/blender/editors/mesh/mesh_data.c +++ b/source/blender/editors/mesh/mesh_data.c @@ -36,6 +36,7 @@ #include "DNA_scene_types.h" #include "DNA_view3d_types.h" +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "BLI_array.h" #include "BLI_math.h" @@ -570,7 +571,7 @@ void MESH_OT_uv_texture_add(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -884,7 +885,7 @@ void ED_mesh_update(Mesh *mesh, bContext *C, int calc_edges, int calc_tessface) } if (calc_edges || ((mesh->totpoly || mesh->totface) && mesh->totedge == 0)) - BKE_mesh_calc_edges(mesh, calc_edges); + BKE_mesh_calc_edges(mesh, calc_edges, true); if (calc_tessface) { if (tessface_input == FALSE) { diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index fe4917acdac..5dab022dd2f 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -48,6 +48,7 @@ struct wmKeyConfig; struct wmKeyMap; struct wmOperator; struct wmOperatorType; +struct LinkNode; /* ******************** editmesh_utils.c */ @@ -77,7 +78,6 @@ int EDBM_op_init(struct BMEditMesh *em, struct BMOperator *bmop, int EDBM_op_finish(struct BMEditMesh *em, struct BMOperator *bmop, struct wmOperator *op, const int report); -void EDBM_flag_disable_all(struct BMEditMesh *em, const char hflag); void EDBM_stats_update(struct BMEditMesh *em); /* ******************** editface.c */ @@ -128,6 +128,7 @@ void MESH_OT_select_shortest_path(struct wmOperatorType *ot); void MESH_OT_select_similar(struct wmOperatorType *ot); void MESH_OT_select_mode(struct wmOperatorType *ot); void MESH_OT_select_random(struct wmOperatorType *ot); +void MESH_OT_select_ungrouped(struct wmOperatorType *ot); void MESH_OT_loop_multi_select(struct wmOperatorType *ot); void MESH_OT_mark_seam(struct wmOperatorType *ot); void MESH_OT_mark_sharp(struct wmOperatorType *ot); @@ -211,6 +212,8 @@ void MESH_OT_edgering_select(struct wmOperatorType *ot); void MESH_OT_loopcut(struct wmOperatorType *ot); void MESH_OT_knife_tool(struct wmOperatorType *ot); +void MESH_OT_knife_project(wmOperatorType *ot); + void MESH_OT_bevel(struct wmOperatorType *ot); void MESH_OT_bridge_edge_loops(struct wmOperatorType *ot); @@ -228,4 +231,6 @@ void MESH_OT_navmesh_face_add(struct wmOperatorType *ot); void MESH_OT_navmesh_reset(struct wmOperatorType *ot); void MESH_OT_navmesh_clear(struct wmOperatorType *ot); +void EDBM_mesh_knife(struct bContext *C, struct LinkNode *polys, bool use_tag); + #endif /* __MESH_INTERN_H__ */ diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 140681304b2..cf3877a8d93 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -59,6 +59,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_select_linked); WM_operatortype_append(MESH_OT_select_linked_pick); WM_operatortype_append(MESH_OT_select_random); + WM_operatortype_append(MESH_OT_select_ungrouped); WM_operatortype_append(MESH_OT_hide); WM_operatortype_append(MESH_OT_reveal); WM_operatortype_append(MESH_OT_select_face_by_sides); @@ -155,6 +156,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_select_nth); WM_operatortype_append(MESH_OT_vert_connect); WM_operatortype_append(MESH_OT_knife_tool); + WM_operatortype_append(MESH_OT_knife_project); WM_operatortype_append(MESH_OT_bevel); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index 378f6374336..3d4d204299f 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -789,7 +789,9 @@ static intptr_t mesh_octree_find_index(MocNode **bt, MVert *mvert, const float c return (*bt)->index[a]; } } - else return -1; + else { + return -1; + } } if ( (*bt)->next) return mesh_octree_find_index(&(*bt)->next, mvert, co); diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index 6c056df5a38..6781624aec6 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -254,7 +254,7 @@ static int duplicate_metaelems_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int duplicate_metaelems_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int duplicate_metaelems_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { int retv = duplicate_metaelems_exec(C, op); diff --git a/source/blender/editors/metaball/mball_ops.c b/source/blender/editors/metaball/mball_ops.c index f91d57424a1..8c705aac0d2 100644 --- a/source/blender/editors/metaball/mball_ops.c +++ b/source/blender/editors/metaball/mball_ops.c @@ -28,17 +28,17 @@ * \ingroup edmeta */ +#include "BLI_utildefines.h" + #include "RNA_access.h" +#include "WM_api.h" +#include "WM_types.h" + #include "ED_mball.h" #include "ED_screen.h" #include "ED_object.h" -#include "BLI_utildefines.h" - -#include "WM_api.h" -#include "WM_types.h" - #include "mball_intern.h" void ED_operatortypes_metaball(void) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 997cbb71683..dbb0d55a2b1 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -49,11 +49,13 @@ #include "DNA_vfont_types.h" #include "DNA_actuator_types.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" -#include "BLI_utildefines.h" + +#include "BLF_translation.h" #include "BKE_anim.h" #include "BKE_animsys.h" @@ -662,7 +664,9 @@ static int object_armature_add_exec(bContext *C, wmOperator *op) ED_object_enter_editmode(C, 0); newob = 1; } - else DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + else { + DAG_id_tag_update(&obedit->id, OB_RECALC_DATA); + } if (obedit == NULL) { BKE_report(op->reports, RPT_ERROR, "Cannot create editmode armature"); @@ -736,7 +740,7 @@ void OBJECT_OT_empty_add(wmOperatorType *ot) ED_object_add_generic_props(ot, FALSE); } -static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int empty_drop_named_image_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Base *base = NULL; Image *ima = NULL; @@ -872,6 +876,7 @@ void OBJECT_OT_lamp_add(wmOperatorType *ot) /* properties */ ot->prop = RNA_def_enum(ot->srna, "type", lamp_type_items, 0, "Type", ""); + RNA_def_property_translation_context(ot->prop, BLF_I18NCONTEXT_ID_LAMP); ED_object_add_generic_props(ot, FALSE); } @@ -1482,7 +1487,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; } - BKE_mesh_from_curve(scene, newob); + BKE_mesh_to_curve(scene, newob); if (newob->type == OB_CURVE) BKE_object_free_modifiers(newob); /* after derivedmesh calls! */ diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index a680230fb32..dc54207b4e6 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -138,7 +138,9 @@ static int multiresbake_check(bContext *C, wmOperator *op) } } } - else ok = 0; + else { + ok = 0; + } if (!ok) { BKE_report(op->reports, RPT_ERROR, "Multires data baking requires multi-resolution object"); @@ -696,7 +698,7 @@ static void bake_freejob(void *bkv) } /* catch esc */ -static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int objects_bake_render_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { /* no running blender, remove handler and pass through */ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_BAKE_TEXTURE)) @@ -719,7 +721,7 @@ static int is_multires_bake(Scene *scene) return 0; } -static int objects_bake_render_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(_event)) +static int objects_bake_render_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event)) { Scene *scene = CTX_data_scene(C); int result = OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_constraint.c b/source/blender/editors/object/object_constraint.c index 1bed7d7dd11..8e2a87c7c64 100644 --- a/source/blender/editors/object/object_constraint.c +++ b/source/blender/editors/object/object_constraint.c @@ -435,7 +435,9 @@ static void test_constraints(Object *owner, bPoseChannel *pchan) curcon->flag |= CONSTRAINT_DISABLE; } } - else curcon->flag |= CONSTRAINT_DISABLE; + else { + curcon->flag |= CONSTRAINT_DISABLE; + } } } else if (curcon->type == CONSTRAINT_TYPE_CAMERASOLVER) { @@ -645,7 +647,7 @@ static int stretchto_reset_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int stretchto_reset_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int stretchto_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return stretchto_reset_exec(C, op); @@ -691,7 +693,7 @@ static int limitdistance_reset_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int limitdistance_reset_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int limitdistance_reset_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return limitdistance_reset_exec(C, op); @@ -827,7 +829,7 @@ static int childof_set_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int childof_set_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int childof_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return childof_set_inverse_exec(C, op); @@ -874,7 +876,7 @@ static int childof_clear_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int childof_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return childof_clear_inverse_exec(C, op); @@ -991,7 +993,7 @@ static int followpath_path_animate_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int followpath_path_animate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int followpath_path_animate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { /* hook up invoke properties for figuring out which constraint we're dealing with */ if (edit_constraint_invoke_properties(C, op)) { @@ -1049,7 +1051,7 @@ static int objectsolver_set_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int objectsolver_set_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return objectsolver_set_inverse_exec(C, op); @@ -1095,7 +1097,7 @@ static int objectsolver_clear_inverse_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int objectsolver_clear_inverse_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return objectsolver_clear_inverse_exec(C, op); @@ -1231,7 +1233,7 @@ static int constraint_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int constraint_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int constraint_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return constraint_move_down_exec(C, op); @@ -1280,7 +1282,7 @@ static int constraint_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int constraint_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int constraint_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_constraint_invoke_properties(C, op)) return constraint_move_up_exec(C, op); @@ -1848,7 +1850,7 @@ void POSE_OT_constraint_add_with_targets(wmOperatorType *ot) // TODO: should these be here, or back in editors/armature/poseobject.c again? /* present menu with options + validation for targets to use */ -static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int pose_ik_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C)); bPoseChannel *pchan = BKE_pose_channel_active(ob); diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index b94c9e940dc..ca57ab76c57 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -1012,7 +1012,7 @@ static void copy_attr(Main *bmain, Scene *scene, View3D *v3d, short event) DAG_relations_tag_update(bmain); } -static void UNUSED_FUNCTION(copy_attr_menu) (Main * bmain, Scene * scene, View3D * v3d) +static void UNUSED_FUNCTION(copy_attr_menu) (Main *bmain, Scene *scene, View3D *v3d) { Object *ob; short event; @@ -1132,7 +1132,7 @@ void ED_objects_recalculate_paths(bContext *C, Scene *scene) /* show popup to determine settings */ -static int object_calculate_paths_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = CTX_data_active_object(C); @@ -1358,7 +1358,7 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) /* ********************** */ -static void UNUSED_FUNCTION(image_aspect) (Scene * scene, View3D * v3d) +static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) { /* all selected objects with an image map: scale in image aspect */ Base *base; diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index a302aa65fd0..163a869613b 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -138,6 +138,7 @@ void OBJECT_OT_hook_recenter(struct wmOperatorType *ot); /* object_lattice.c */ void LATTICE_OT_select_all(struct wmOperatorType *ot); +void LATTICE_OT_select_ungrouped(struct wmOperatorType *ot); void LATTICE_OT_make_regular(struct wmOperatorType *ot); void LATTICE_OT_flip(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_lattice.c b/source/blender/editors/object/object_lattice.c index c9eae776ac7..053f1ffabd0 100644 --- a/source/blender/editors/object/object_lattice.c +++ b/source/blender/editors/object/object_lattice.c @@ -53,6 +53,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_deform.h" +#include "BKE_report.h" #include "ED_lattice.h" #include "ED_object.h" @@ -255,6 +256,58 @@ void LATTICE_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } +/************************** Select Ungrouped Verts Operator *************************/ + +static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt; + MDeformVert *dv; + BPoint *bp; + int a, tot; + + if (obedit->defbase.first == NULL || lt->dvert == NULL) { + BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); + return OPERATOR_CANCELLED; + } + + if (!RNA_boolean_get(op->ptr, "extend")) { + ED_setflagsLatt(obedit, 0); + } + + dv = lt->dvert; + tot = lt->pntsu * lt->pntsv * lt->pntsw; + + for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) { + if (bp->hide == 0) { + if (dv->dw == NULL) { + bp->f1 |= SELECT; + } + } + } + + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + + return OPERATOR_FINISHED; +} + +void LATTICE_OT_select_ungrouped(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Ungrouped"; + ot->idname = "LATTICE_OT_select_ungrouped"; + ot->description = "Select vertices without a group"; + + /* api callbacks */ + ot->exec = lattice_select_ungrouped_exec; + ot->poll = ED_operator_editlattice; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); +} + /************************** Make Regular Operator *************************/ static int make_regular_poll(bContext *C) diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 8d29813e2ac..d66620c2ff6 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -892,7 +892,7 @@ static int modifier_remove_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int modifier_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return modifier_remove_exec(C, op); @@ -931,7 +931,7 @@ static int modifier_move_up_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_up_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int modifier_move_up_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return modifier_move_up_exec(C, op); @@ -970,7 +970,7 @@ static int modifier_move_down_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_move_down_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int modifier_move_down_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return modifier_move_down_exec(C, op); @@ -1012,7 +1012,7 @@ static int modifier_apply_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int modifier_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return modifier_apply_exec(C, op); @@ -1061,7 +1061,7 @@ static int modifier_convert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int modifier_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return modifier_convert_exec(C, op); @@ -1100,7 +1100,7 @@ static int modifier_copy_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int modifier_copy_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int modifier_copy_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return modifier_copy_exec(C, op); @@ -1149,7 +1149,7 @@ static int multires_higher_levels_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int multires_higher_levels_delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return multires_higher_levels_delete_exec(C, op); @@ -1199,7 +1199,7 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_subdivide_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int multires_subdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return multires_subdivide_exec(C, op); @@ -1263,7 +1263,7 @@ static int multires_reshape_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_reshape_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int multires_reshape_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return multires_reshape_exec(C, op); @@ -1314,7 +1314,7 @@ static int multires_external_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_external_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int multires_external_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = ED_object_active_context(C); MultiresModifierData *mmd; @@ -1410,7 +1410,7 @@ static int multires_base_apply_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int multires_base_apply_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int multires_base_apply_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return multires_base_apply_exec(C, op); @@ -1834,7 +1834,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int skin_armature_create_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int skin_armature_create_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return skin_armature_create_exec(C, op); @@ -1927,7 +1927,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int meshdeform_bind_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int meshdeform_bind_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return meshdeform_bind_exec(C, op); @@ -1975,7 +1975,7 @@ static int explode_refresh_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int explode_refresh_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int explode_refresh_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return explode_refresh_exec(C, op); @@ -2191,7 +2191,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int ocean_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int ocean_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_modifier_invoke_properties(C, op)) return ocean_bake_exec(C, op); diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index e5aaaffade8..594dfd6e271 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -211,6 +211,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_shape_key_move); WM_operatortype_append(LATTICE_OT_select_all); + WM_operatortype_append(LATTICE_OT_select_ungrouped); WM_operatortype_append(LATTICE_OT_make_regular); WM_operatortype_append(LATTICE_OT_flip); @@ -364,7 +365,7 @@ void ED_keymap_object(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", XKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "use_global", TRUE); - WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, 0, 0); + kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "use_global", FALSE); kmi = WM_keymap_add_item(keymap, "OBJECT_OT_delete", DELKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "use_global", TRUE); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index f9dde043607..6039ff6d34b 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -215,7 +215,7 @@ static int vertex_parent_set_exec(bContext *C, wmOperator *op) } } - if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3)) ) { + if (v4 || !((v1 && v2 == 0 && v3 == 0) || (v1 && v2 && v3))) { BKE_report(op->reports, RPT_ERROR, "Select either 1 or 3 vertices to parent to"); return OPERATOR_CANCELLED; } @@ -286,7 +286,7 @@ void OBJECT_OT_vertex_parent_set(wmOperatorType *ot) /********************** Make Proxy Operator *************************/ /* set the object to proxify */ -static int make_proxy_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int make_proxy_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); Object *ob = ED_object_active_context(C); @@ -299,7 +299,7 @@ static int make_proxy_invoke(bContext *C, wmOperator *op, wmEvent *evt) if (ob->dup_group && ob->dup_group->id.lib) { /* gives menu with list of objects in group */ //proxy_group_objects_menu(C, op, ob, ob->dup_group); - WM_enum_search_invoke(C, op, evt); + WM_enum_search_invoke(C, op, event); return OPERATOR_CANCELLED; } @@ -608,8 +608,10 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object cu->flag |= CU_PATH | CU_FOLLOW; BKE_displist_make_curveTypes(scene, par, 0); /* force creation of path data */ } - else cu->flag |= CU_FOLLOW; - + else { + cu->flag |= CU_FOLLOW; + } + /* if follow, add F-Curve for ctime (i.e. "eval_time") so that path-follow works */ if (partype == PAR_FOLLOW) { /* get or create F-Curve */ @@ -797,7 +799,7 @@ static int parent_set_exec(bContext *C, wmOperator *op) } -static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { Object *ob = ED_object_active_context(C); uiPopupMenu *pup = uiPupMenuBegin(C, IFACE_("Set Parent To"), ICON_NONE); @@ -1227,7 +1229,7 @@ static unsigned int move_to_layer_init(bContext *C, wmOperator *op) return lay; } -static int move_to_layer_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int move_to_layer_invoke(bContext *C, wmOperator *op, const wmEvent *event) { View3D *v3d = CTX_wm_view3d(C); if (v3d && v3d->localvd) { @@ -1541,6 +1543,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); + WM_event_add_notifier(C, NC_OBJECT, NULL); return OPERATOR_FINISHED; } @@ -1928,11 +1931,11 @@ static void make_local_makelocalmaterial(Material *ma) AnimData *adt; int b; - id_make_local(&ma->id, 0); + id_make_local(&ma->id, false); for (b = 0; b < MAX_MTEX; b++) if (ma->mtex[b] && ma->mtex[b]->tex) - id_make_local(&ma->mtex[b]->tex->id, 0); + id_make_local(&ma->mtex[b]->tex->id, false); adt = BKE_animdata_from_id(&ma->id); if (adt) BKE_animdata_make_local(adt); @@ -1958,7 +1961,7 @@ static int make_local_exec(bContext *C, wmOperator *op) int a, b, mode = RNA_enum_get(op->ptr, "type"); if (mode == MAKE_LOCAL_ALL) { - BKE_library_make_local(bmain, NULL, 0); /* NULL is all libs */ + BKE_library_make_local(bmain, NULL, false); /* NULL is all libs */ WM_event_add_notifier(C, NC_WINDOW, NULL); return OPERATOR_FINISHED; } @@ -1968,7 +1971,7 @@ static int make_local_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Object *, ob, selected_objects) { if (ob->id.lib) - id_make_local(&ob->id, 0); + id_make_local(&ob->id, false); } CTX_DATA_END; @@ -1986,7 +1989,7 @@ static int make_local_exec(bContext *C, wmOperator *op) id = ob->data; if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) { - id_make_local(id, 0); + id_make_local(id, false); adt = BKE_animdata_from_id(id); if (adt) BKE_animdata_make_local(adt); @@ -2002,7 +2005,7 @@ static int make_local_exec(bContext *C, wmOperator *op) } for (psys = ob->particlesystem.first; psys; psys = psys->next) - id_make_local(&psys->part->id, 0); + id_make_local(&psys->part->id, false); adt = BKE_animdata_from_id(&ob->id); if (adt) BKE_animdata_make_local(adt); @@ -2017,7 +2020,7 @@ static int make_local_exec(bContext *C, wmOperator *op) for (b = 0; b < MAX_MTEX; b++) if (la->mtex[b] && la->mtex[b]->tex) - id_make_local(&la->mtex[b]->tex->id, 0); + id_make_local(&la->mtex[b]->tex->id, false); } else { for (a = 0; a < ob->totcol; a++) { @@ -2130,7 +2133,7 @@ void OBJECT_OT_make_single_user(wmOperatorType *ot) RNA_def_boolean(ot->srna, "animation", 0, "Object Animation", "Make animation data local to each object"); } -static int drop_named_material_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int drop_named_material_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Base *base = ED_view3d_give_base_under_cursor(C, event->mval); Material *ma; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 3fa6c301fcb..80d494a6a07 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -795,8 +795,8 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) if (centermode == ORIGIN_TO_CURSOR) { /* done */ } else if (centermode == ORIGIN_TO_CENTER_OF_MASS) { BKE_mesh_center_centroid(me, cent); } - else if (around == V3D_CENTROID) { BKE_mesh_center_median(me, cent); } - else { BKE_mesh_center_bounds(me, cent); } + else if (around == V3D_CENTROID) { BKE_mesh_center_median(me, cent); } + else { BKE_mesh_center_bounds(me, cent); } negate_v3_v3(cent_neg, cent); BKE_mesh_translate(me, cent_neg, 1); @@ -808,9 +808,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ } + if (centermode == ORIGIN_TO_CURSOR) { /* done */ } else if (around == V3D_CENTROID) { BKE_curve_center_median(cu, cent); } - else { BKE_curve_center_bounds(cu, cent); } + else { BKE_curve_center_bounds(cu, cent); } /* don't allow Z change if curve is 2D */ if ((ob->type == OB_CURVE) && !(cu->flag & CU_3D)) @@ -889,9 +889,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ob->type == OB_MBALL) { MetaBall *mb = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ } + if (centermode == ORIGIN_TO_CURSOR) { /* done */ } else if (around == V3D_CENTROID) { BKE_mball_center_median(mb, cent); } - else { BKE_mball_center_bounds(mb, cent); } + else { BKE_mball_center_bounds(mb, cent); } negate_v3_v3(cent_neg, cent); BKE_mball_translate(mb, cent_neg); @@ -910,9 +910,9 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) else if (ob->type == OB_LATTICE) { Lattice *lt = ob->data; - if (centermode == ORIGIN_TO_CURSOR) { /* done */ } + if (centermode == ORIGIN_TO_CURSOR) { /* done */ } else if (around == V3D_CENTROID) { BKE_lattice_center_median(lt, cent); } - else { BKE_lattice_center_bounds(lt, cent); } + else { BKE_lattice_center_bounds(lt, cent); } negate_v3_v3(cent_neg, cent); BKE_lattice_translate(lt, cent_neg, 1); diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index ef882b2486b..5abbb7124c0 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1037,7 +1037,7 @@ static void vgroup_duplicate(Object *ob) BLI_snprintf(name, sizeof(name), "%s_copy", dg->name); } else { - BLI_snprintf(name, sizeof(name), "%s", dg->name); + BLI_strncpy(name, dg->name, sizeof(name)); } cdg = defgroup_duplicate(dg); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 31079de275e..329f1f67c4a 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -430,15 +430,6 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection, (GLint *)data->mats.viewport, &ux, &uy, &uz); -#if 0 /* works well but too slow on some systems [#23118] */ - screen_co[0] += (short)data->vc.ar->winrct.xmin; - screen_co[1] += (short)data->vc.ar->winrct.ymin; - - /* PE_set_view3d_data calls this. no need to call here */ - /* view3d_validate_backbuf(&data->vc); */ - glReadPixels(screen_co[0], screen_co[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); -#else /* faster to use depths, these are calculated in PE_set_view3d_data */ - /* check if screen_co is within bounds because brush_cut uses out of screen coords */ if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) { BLI_assert(vd && vd->depths); @@ -447,7 +438,6 @@ static int key_test_depth(PEData *data, const float co[3], const int screen_co[2 } else return 0; -#endif if ((float)uz - 0.00001f > depth) return 0; @@ -1555,7 +1545,7 @@ static int select_linked_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int select_linked_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RNA_int_set_array(op->ptr, "location", event->mval); return select_linked_exec(C, op); @@ -3476,6 +3466,7 @@ typedef struct BrushEdit { int first; int lastmouse[2]; + float zfac; /* optional cached view settings to avoid setting on every mousemove */ PEData data; @@ -3498,7 +3489,6 @@ static int brush_edit_init(bContext *C, wmOperator *op) INIT_MINMAX(min, max); PE_minmax(scene, min, max); mid_v3_v3v3(min, min, max); - initgrabz(ar->regiondata, min[0], min[1], min[2]); bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit"); bedit->first= 1; @@ -3508,6 +3498,8 @@ static int brush_edit_init(bContext *C, wmOperator *op) bedit->ob= ob; bedit->edit= edit; + bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL); + /* cache view depths and settings for re-use */ PE_set_view3d_data(C, &bedit->data); @@ -3587,7 +3579,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) invert_m4_m4(ob->imat, ob->obmat); - ED_view3d_win_to_delta(ar, mval_f, vec); + ED_view3d_win_to_delta(ar, mval_f, vec, bedit->zfac); data.dvec= vec; foreach_mouse_hit_key(&data, brush_comb, selected); @@ -3757,7 +3749,7 @@ static int brush_edit_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void brush_edit_apply_event(bContext *C, wmOperator *op, wmEvent *event) +static void brush_edit_apply_event(bContext *C, wmOperator *op, const wmEvent *event) { PointerRNA itemptr; float mouse[2]; @@ -3774,7 +3766,7 @@ static void brush_edit_apply_event(bContext *C, wmOperator *op, wmEvent *event) brush_edit_apply(C, op, &itemptr); } -static int brush_edit_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int brush_edit_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!brush_edit_init(C, op)) return OPERATOR_CANCELLED; @@ -3786,7 +3778,7 @@ static int brush_edit_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int brush_edit_modal(bContext *C, wmOperator *op, wmEvent *event) +static int brush_edit_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index fc55b2b5915..df723b06259 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -679,18 +679,15 @@ static int fluid_init_filepaths(Object *fsDomain, char *targetDir, char *targetF if (fileCfg) { dirExist = 1; fclose(fileCfg); // remove cfg dummy from directory test - BLI_delete(targetFile, 0, 0); + BLI_delete(targetFile, false, false); } if (targetDir[0] == '\0' || (!dirExist)) { - char blendDir[FILE_MAX]; char blendFile[FILE_MAX]; // invalid dir, reset to current/previous - BLI_strncpy(blendDir, G.main->name, FILE_MAX); - BLI_splitdirstring(blendDir, blendFile); + BLI_split_file_part(G.main->name, blendFile, sizeof(blendFile)); BLI_replace_extension(blendFile, FILE_MAX, ""); /* strip .blend */ - BLI_snprintf(newSurfdataPath, FILE_MAX, "//fluidsimdata/%s_%s_", blendFile, fsDomain->id.name); BLI_snprintf(debugStrBuffer, 256, "fluidsimBake::error - warning resetting output dir to '%s'\n", newSurfdataPath); @@ -852,9 +849,9 @@ static void fluidsim_delete_until_lastframe(FluidsimSettings *fss, const char *r curFrame++; if ((exists = BLI_exists(targetFile))) { - BLI_delete(targetFile, 0, 0); - BLI_delete(targetFileVel, 0, 0); - BLI_delete(previewFile, 0, 0); + BLI_delete(targetFile, false, false); + BLI_delete(targetFileVel, false, false); + BLI_delete(previewFile, false, false); } } while (exists); @@ -1130,7 +1127,7 @@ static int fluidsimBake(bContext *UNUSED(C), ReportList *UNUSED(reports), Object /***************************** Operators ******************************/ -static int fluid_bake_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int fluid_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { /* only one bake job at a time */ if (WM_jobs_test(CTX_wm_manager(C), CTX_data_scene(C), WM_JOB_TYPE_OBJECT_SIM_FLUID)) diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index 51a66886c6e..2ede7047b74 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -27,9 +27,9 @@ * \ingroup edphys */ - #include <stdlib.h> +#include "BLI_utildefines.h" #include "RNA_access.h" @@ -39,8 +39,6 @@ #include "ED_physics.h" #include "ED_object.h" -#include "BLI_utildefines.h" - #include "physics_intern.h" // own include diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 6bcdf6e07aa..9c03c6173a5 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -44,6 +44,8 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -374,61 +376,61 @@ typedef struct rbMaterialDensityItem { * 3) http://www.avlandesign.com/density_metal.htm */ static rbMaterialDensityItem RB_MATERIAL_DENSITY_TABLE[] = { - {"Air", 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */ - {"Acrylic", 1400.0f}, - {"Asphalt (Crushed)", 721.0f}, - {"Bark", 240.0f}, - {"Beans (Cocoa)", 593.0f}, - {"Beans (Soy)", 721.0f}, - {"Brick (Pressed)", 2400.0f}, - {"Brick (Common)", 2000.0f}, - {"Brick (Soft)", 1600.0f}, - {"Brass", 8216.0f}, - {"Bronze", 8860.0f}, - {"Carbon (Solid)", 2146.0f}, - {"Cardboard", 689.0f}, - {"Cast Iron", 7150.0f}, - //{"Cement", 1442.0f}, - {"Chalk (Solid)", 2499.0f}, - //{"Coffee (Fresh/Roast)", ~500}, - {"Concrete", 2320.0f}, - {"Charcoal", 208.0f}, - {"Cork", 240.0f}, - {"Copper", 8933.0f}, - {"Garbage", 481.0f}, - {"Glass (Broken)", 1940.0f}, - {"Glass (Solid)", 2190.0f}, - {"Gold", 19282.0f}, - {"Granite (Broken)", 1650.0f}, - {"Granite (Solid)", 2691.0f}, - {"Gravel", 2780.0f}, - {"Ice (Crushed)", 593.0f}, - {"Ice (Solid)", 919.0f}, - {"Iron", 7874.0f}, - {"Lead", 11342.0f}, - {"Limestone (Broken)", 1554.0f}, - {"Limestone (Solid)", 2611.0f}, - {"Marble (Broken)", 1570.0f}, - {"Marble (Solid)", 2563.0f}, - {"Paper", 1201.0f}, - {"Peanuts (Shelled)", 641.0f}, - {"Peanuts (Not Shelled)", 272.0f}, - {"Plaster", 849.0f}, - {"Plastic", 1200.0f}, - {"Polystyrene", 1050.0f}, - {"Rubber", 1522.0f}, - {"Silver", 10501.0f}, - {"Steel", 7860.0f}, - {"Stone", 2515.0f}, - {"Stone (Crushed)", 1602.0f}, - {"Timber", 610.0f} + {N_("Air"), 1.0f}, /* not quite; adapted from 1.43 for oxygen for use as default */ + {N_("Acrylic"), 1400.0f}, + {N_("Asphalt (Crushed)"), 721.0f}, + {N_("Bark"), 240.0f}, + {N_("Beans (Cocoa)"), 593.0f}, + {N_("Beans (Soy)"), 721.0f}, + {N_("Brick (Pressed)"), 2400.0f}, + {N_("Brick (Common)"), 2000.0f}, + {N_("Brick (Soft)"), 1600.0f}, + {N_("Brass"), 8216.0f}, + {N_("Bronze"), 8860.0f}, + {N_("Carbon (Solid)"), 2146.0f}, + {N_("Cardboard"), 689.0f}, + {N_("Cast Iron"), 7150.0f}, + /* {N_("Cement"), 1442.0f}, */ + {N_("Chalk (Solid)"), 2499.0f}, + /* {N_("Coffee (Fresh/Roast)"), ~500}, */ + {N_("Concrete"), 2320.0f}, + {N_("Charcoal"), 208.0f}, + {N_("Cork"), 240.0f}, + {N_("Copper"), 8933.0f}, + {N_("Garbage"), 481.0f}, + {N_("Glass (Broken)"), 1940.0f}, + {N_("Glass (Solid)"), 2190.0f}, + {N_("Gold"), 19282.0f}, + {N_("Granite (Broken)"), 1650.0f}, + {N_("Granite (Solid)"), 2691.0f}, + {N_("Gravel"), 2780.0f}, + {N_("Ice (Crushed)"), 593.0f}, + {N_("Ice (Solid)"), 919.0f}, + {N_("Iron"), 7874.0f}, + {N_("Lead"), 11342.0f}, + {N_("Limestone (Broken)"), 1554.0f}, + {N_("Limestone (Solid)"), 2611.0f}, + {N_("Marble (Broken)"), 1570.0f}, + {N_("Marble (Solid)"), 2563.0f}, + {N_("Paper"), 1201.0f}, + {N_("Peanuts (Shelled)"), 641.0f}, + {N_("Peanuts (Not Shelled)"), 272.0f}, + {N_("Plaster"), 849.0f}, + {N_("Plastic"), 1200.0f}, + {N_("Polystyrene"), 1050.0f}, + {N_("Rubber"), 1522.0f}, + {N_("Silver"), 10501.0f}, + {N_("Steel"), 7860.0f}, + {N_("Stone"), 2515.0f}, + {N_("Stone (Crushed)"), 1602.0f}, + {N_("Timber"), 610.0f} }; static const int NUM_RB_MATERIAL_PRESETS = sizeof(RB_MATERIAL_DENSITY_TABLE) / sizeof(rbMaterialDensityItem); /* dynamically generate list of items * - Although there is a runtime cost, this has a lower maintenance cost - * in the long run than other two-list solutions... + * in the long run than other two-list solutions... */ static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop), int *free) { @@ -441,14 +443,16 @@ static EnumPropertyItem *rigidbody_materials_itemf(bContext *UNUSED(C), PointerR for (i = 0; i < NUM_RB_MATERIAL_PRESETS; i++) { rbMaterialDensityItem *preset = &RB_MATERIAL_DENSITY_TABLE[i]; - item_tmp.identifier = item_tmp.name = preset->name; + item_tmp.identifier = preset->name; + item_tmp.name = IFACE_(preset->name); item_tmp.value = i; RNA_enum_item_add(&item, &totitem, &item_tmp); } /* add special "custom" entry to the end of the list */ { - item_tmp.identifier = item_tmp.name = "Custom"; + item_tmp.identifier = "Custom"; + item_tmp.name = IFACE_("Custom"); item_tmp.value = -1; RNA_enum_item_add(&item, &totitem, &item_tmp); } diff --git a/source/blender/editors/physics/rigidbody_world.c b/source/blender/editors/physics/rigidbody_world.c index babe32c74b2..b7430cb8a95 100644 --- a/source/blender/editors/physics/rigidbody_world.c +++ b/source/blender/editors/physics/rigidbody_world.c @@ -175,7 +175,7 @@ static int rigidbody_world_export_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(evt)) +static int rigidbody_world_export_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!RNA_struct_property_is_set(op->ptr, "relative_path")) RNA_boolean_set(op->ptr, "relative_path", (U.flag & USER_RELPATHS)); diff --git a/source/blender/editors/render/SConscript b/source/blender/editors/render/SConscript index 9d1de2fc700..25af8080d51 100644 --- a/source/blender/editors/render/SConscript +++ b/source/blender/editors/render/SConscript @@ -33,7 +33,7 @@ incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../gpu' incs += ' ../../makesrna ../../render/extern/include #/intern/elbeem/extern' -incs += ' ../../blenloader ../../bmesh' +incs += ' ../../blenloader ../../bmesh ../../blenfont' if env['OURPLATFORM'] == 'linux': cflags='-pthread' diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index deb6eaf2c22..b138bc63a68 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -39,6 +39,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "DNA_scene_types.h" #include "BKE_blender.h" @@ -281,38 +283,39 @@ static void make_renderinfo_string(RenderStats *rs, Scene *scene, char *str) megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); if (scene->lay & 0xFF000000) - spos += sprintf(spos, "Localview | "); + spos += sprintf(spos, IFACE_("Localview | ")); else if (scene->r.scemode & R_SINGLE_LAYER) - spos += sprintf(spos, "Single Layer | "); + spos += sprintf(spos, IFACE_("Single Layer | ")); - spos += sprintf(spos, "Frame:%d ", (scene->r.cfra)); + spos += sprintf(spos, IFACE_("Frame:%d "), (scene->r.cfra)); if (rs->statstr) { spos += sprintf(spos, "| %s ", rs->statstr); } else { - if (rs->totvert) spos += sprintf(spos, "Ve:%d ", rs->totvert); - if (rs->totface) spos += sprintf(spos, "Fa:%d ", rs->totface); - if (rs->tothalo) spos += sprintf(spos, "Ha:%d ", rs->tothalo); - if (rs->totstrand) spos += sprintf(spos, "St:%d ", rs->totstrand); - if (rs->totlamp) spos += sprintf(spos, "La:%d ", rs->totlamp); + if (rs->totvert) spos += sprintf(spos, IFACE_("Ve:%d "), rs->totvert); + if (rs->totface) spos += sprintf(spos, IFACE_("Fa:%d "), rs->totface); + if (rs->tothalo) spos += sprintf(spos, IFACE_("Ha:%d "), rs->tothalo); + if (rs->totstrand) spos += sprintf(spos, IFACE_("St:%d "), rs->totstrand); + if (rs->totlamp) spos += sprintf(spos, IFACE_("La:%d "), rs->totlamp); if (rs->mem_peak == 0.0f) - spos += sprintf(spos, "Mem:%.2fM (%.2fM, peak %.2fM) ", megs_used_memory, mmap_used_memory, megs_peak_memory); + spos += sprintf(spos, IFACE_("Mem:%.2fM (%.2fM, Peak %.2fM) "), + megs_used_memory, mmap_used_memory, megs_peak_memory); else - spos += sprintf(spos, "Mem:%.2fM, Peak: %.2fM ", rs->mem_used, rs->mem_peak); + spos += sprintf(spos, IFACE_("Mem:%.2fM, Peak: %.2fM "), rs->mem_used, rs->mem_peak); if (rs->curfield) - spos += sprintf(spos, "Field %d ", rs->curfield); + spos += sprintf(spos, IFACE_("Field %d "), rs->curfield); if (rs->curblur) - spos += sprintf(spos, "Blur %d ", rs->curblur); + spos += sprintf(spos, IFACE_("Blur %d "), rs->curblur); } BLI_timestr(rs->lastframetime, info_time_str); - spos += sprintf(spos, "Time:%s ", info_time_str); + spos += sprintf(spos, IFACE_("Time:%s "), info_time_str); if (rs->curfsa) - spos += sprintf(spos, "| Full Sample %d ", rs->curfsa); + spos += sprintf(spos, IFACE_("| Full Sample %d "), rs->curfsa); if (rs->infostr && rs->infostr[0]) spos += sprintf(spos, "| %s ", rs->infostr); @@ -462,7 +465,7 @@ static void render_drawlock(void *UNUSED(rjv), int lock) } /* catch esc */ -static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event) +static int screen_render_modal(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = (Scene *) op->customdata; @@ -481,7 +484,7 @@ static int screen_render_modal(bContext *C, wmOperator *op, wmEvent *event) } /* using context, starts job */ -static int screen_render_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int screen_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* new render clears all callbacks */ Main *mainp; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index ea18f2c8fbb..f47d737beca 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -638,7 +638,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) } -static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *event) +static int screen_opengl_render_modal(bContext *C, wmOperator *op, const wmEvent *event) { OGLRender *oglrender = op->customdata; int anim = RNA_boolean_get(op->ptr, "animation"); @@ -677,7 +677,7 @@ static int screen_opengl_render_modal(bContext *C, wmOperator *op, wmEvent *even return OPERATOR_RUNNING_MODAL; } -static int screen_opengl_render_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int screen_opengl_render_invoke(bContext *C, wmOperator *op, const wmEvent *event) { OGLRender *oglrender; int anim = RNA_boolean_get(op->ptr, "animation"); diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index dfc80e4cf51..7802e5460ff 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -110,7 +110,7 @@ ImBuf *get_brush_icon(Brush *brush) static const int flags = IB_rect | IB_multilayer | IB_metadata; char path[FILE_MAX]; - char *folder; + const char *folder; if (!(brush->icon_imbuf)) { if (brush->flag & BRUSH_CUSTOM_ICON) { @@ -188,8 +188,8 @@ typedef struct IconPreview { /* *************************** Preview for buttons *********************** */ -static Main *pr_main = NULL; -static Main *pr_main_cycles = NULL; +static Main *G_pr_main = NULL; +static Main *G_pr_main_cycles = NULL; #ifndef WITH_HEADLESS static Main *load_main_from_memory(char *blend, int blend_size) @@ -214,18 +214,18 @@ static Main *load_main_from_memory(char *blend, int blend_size) void ED_preview_init_dbase(void) { #ifndef WITH_HEADLESS - pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size); - pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size); + G_pr_main = load_main_from_memory(datatoc_preview_blend, datatoc_preview_blend_size); + G_pr_main_cycles = load_main_from_memory(datatoc_preview_cycles_blend, datatoc_preview_cycles_blend_size); #endif } void ED_preview_free_dbase(void) { - if (pr_main) - free_main(pr_main); + if (G_pr_main) + free_main(G_pr_main); - if (pr_main_cycles) - free_main(pr_main_cycles); + if (G_pr_main_cycles) + free_main(G_pr_main_cycles); } static int preview_mat_has_sss(Material *mat, bNodeTree *ntree) @@ -425,15 +425,16 @@ static Scene *preview_prepare_scene(Scene *scene, ID *id, int id_type, ShaderPre if (tex && sp->slot) mat->mtex[0]->which_output = sp->slot->which_output; - + + mat->mtex[0]->mapto &= ~MAP_ALPHA; + mat->alpha = 1.0f; + /* show alpha in this case */ if (tex == NULL || (tex->flag & TEX_PRV_ALPHA)) { - mat->mtex[0]->mapto |= MAP_ALPHA; - mat->alpha = 0.0f; - } - else { - mat->mtex[0]->mapto &= ~MAP_ALPHA; - mat->alpha = 1.0f; + if (!(tex && tex->type == TEX_IMAGE && (tex->imaflag & (TEX_USEALPHA | TEX_CALCALPHA)) == 0)) { + mat->mtex[0]->mapto |= MAP_ALPHA; + mat->alpha = 0.0f; + } } } } @@ -670,8 +671,10 @@ static void shader_preview_render(ShaderPreview *sp, ID *id, int split, int firs if (first) sizex = sp->sizex / 2; else sizex = sp->sizex - sp->sizex / 2; } - else sizex = sp->sizex; - + else { + sizex = sp->sizex; + } + /* we have to set preview variables first */ sce = preview_get_scene(pr_main); if (sce) { @@ -1025,7 +1028,7 @@ static void icon_preview_startjob_all_sizes(void *customdata, short *stop, short sp->pr_method = PR_ICON_RENDER; sp->pr_rect = cur_size->rect; sp->id = ip->id; - sp->pr_main = pr_main; + sp->pr_main = G_pr_main; common_preview_startjob(sp, stop, do_update, progress); shader_preview_free(sp); @@ -1128,9 +1131,9 @@ void ED_preview_shader_job(const bContext *C, void *owner, ID *id, ID *parent, M /* hardcoded preview .blend for cycles/internal, this should be solved * once with custom preview .blend path for external engines */ if (BKE_scene_use_new_shading_nodes(scene)) - sp->pr_main = pr_main_cycles; + sp->pr_main = G_pr_main_cycles; else - sp->pr_main = pr_main; + sp->pr_main = G_pr_main; if (ob && ob->totcol) copy_v4_v4(sp->col, ob->col); else sp->col[0] = sp->col[1] = sp->col[2] = sp->col[3] = 1.0f; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index aa1edb1c1b1..decc5b131ae 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -1327,7 +1327,7 @@ static int envmap_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int envmap_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int envmap_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { //Scene *scene= CTX_data_scene(C); diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 16d7923baff..a467b053443 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -394,8 +394,6 @@ static void texture_changed(Main *bmain, Tex *tex) if (dm && totmaterial && material) { for (a = 0; a < *totmaterial; a++) { - Material *ma; - if (ob->matbits && ob->matbits[a]) ma = ob->mat[a]; else diff --git a/source/blender/editors/render/render_view.c b/source/blender/editors/render/render_view.c index 8b2ac740e47..186d0d20623 100644 --- a/source/blender/editors/render/render_view.c +++ b/source/blender/editors/render/render_view.c @@ -275,7 +275,7 @@ void RENDER_OT_view_cancel(struct wmOperatorType *ot) /************************* show render viewer *****************/ -static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int render_view_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { wmWindow *wincur = CTX_wm_window(C); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 1b7cd4a6d20..2d6e8d0ada0 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -67,6 +67,8 @@ #include "screen_intern.h" +extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */ + /* general area and region code */ static void region_draw_emboss(ARegion *ar, rcti *scirct) @@ -245,8 +247,6 @@ static void draw_azone_plus(float x1, float y1, float x2, float y2) static void region_draw_azone_tab_plus(AZone *az) { - extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */ - glEnable(GL_BLEND); /* add code to draw region hidden as 'too small' */ @@ -321,8 +321,6 @@ static void region_draw_azone_tab(AZone *az) static void region_draw_azone_tria(AZone *az) { - extern void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3); /* xxx temp */ - glEnable(GL_BLEND); //UI_GetThemeColor3fv(TH_HEADER, col); glColor4f(0.0f, 0.0f, 0.0f, 0.35f); @@ -590,7 +588,7 @@ static void area_azone_initialize(bScreen *screen, ScrArea *sa) BLI_rcti_init(&az->rect, az->x1, az->x2, az->y1, az->y2); } -#define AZONEPAD_EDGE (0.2f * U.widget_unit) +#define AZONEPAD_EDGE (0.1f * U.widget_unit) #define AZONEPAD_ICON (0.45f * U.widget_unit) static void region_azone_edge(AZone *az, ARegion *ar) { @@ -599,22 +597,22 @@ static void region_azone_edge(AZone *az, ARegion *ar) az->x1 = ar->winrct.xmin; az->y1 = ar->winrct.ymax - AZONEPAD_EDGE; az->x2 = ar->winrct.xmax; - az->y2 = ar->winrct.ymax; + az->y2 = ar->winrct.ymax + AZONEPAD_EDGE; break; case AE_BOTTOM_TO_TOPLEFT: az->x1 = ar->winrct.xmin; az->y1 = ar->winrct.ymin + AZONEPAD_EDGE; az->x2 = ar->winrct.xmax; - az->y2 = ar->winrct.ymin; + az->y2 = ar->winrct.ymin - AZONEPAD_EDGE; break; case AE_LEFT_TO_TOPRIGHT: - az->x1 = ar->winrct.xmin; + az->x1 = ar->winrct.xmin - AZONEPAD_EDGE; az->y1 = ar->winrct.ymin; az->x2 = ar->winrct.xmin + AZONEPAD_EDGE; az->y2 = ar->winrct.ymax; break; case AE_RIGHT_TO_TOPLEFT: - az->x1 = ar->winrct.xmax; + az->x1 = ar->winrct.xmax + AZONEPAD_EDGE; az->y1 = ar->winrct.ymin; az->x2 = ar->winrct.xmax - AZONEPAD_EDGE; az->y2 = ar->winrct.ymax; @@ -1071,7 +1069,9 @@ static void region_rect_recursive(wmWindow *win, ScrArea *sa, ARegion *ar, rcti if (G.debug & G_DEBUG) printf("region quadsplit failed\n"); } - else quad = 1; + else { + quad = 1; + } } if (quad) { if (quad == 1) { /* left bottom */ @@ -1746,7 +1746,9 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char * /* uiScalePanels(ar, BLI_rctf_size_x(&v2d->cur)); break; */ } - else break; + else { + break; + } } diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 105c2dc88d1..8501b53afae 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -482,7 +482,7 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, void *rect, float scaleX, float scaleY) +void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY) { unsigned char *uc_rect = (unsigned char *) rect; float *f_rect = (float *)rect; @@ -503,6 +503,7 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, /* don't want nasty border artifacts */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, zoomfilter); #ifdef __APPLE__ /* workaround for os x 10.5/10.6 driver bug: http://lists.apple.com/archives/Mac-opengl/2008/Jul/msg00117.html */ @@ -560,10 +561,10 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, glEnable(GL_TEXTURE_2D); glBegin(GL_QUADS); glTexCoord2f((float)(0 + offset_left) / tex_w, (float)(0 + offset_bot) / tex_h); - glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * xzoom); + glVertex2f(rast_x + (float)offset_left * xzoom, rast_y + (float)offset_bot * yzoom); glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(0 + offset_bot) / tex_h); - glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * xzoom); + glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)offset_bot * yzoom); glTexCoord2f((float)(subpart_w - offset_right) / tex_w, (float)(subpart_h - offset_top) / tex_h); glVertex2f(rast_x + (float)(subpart_w - offset_right) * xzoom * scaleX, rast_y + (float)(subpart_h - offset_top) * yzoom * scaleY); @@ -585,9 +586,9 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, #endif } -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, void *rect) +void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect) { - glaDrawPixelsTexScaled(x, y, img_w, img_h, format, rect, 1.0f, 1.0f); + glaDrawPixelsTexScaled(x, y, img_w, img_h, format, zoomfilter, rect, 1.0f, 1.0f); } void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect) @@ -669,6 +670,22 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo } } +/* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */ +void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect) +{ + if (U.image_gpubuffer_limit) { + /* Megapixels, use float math to prevent overflow */ + float img_size = ((float)img_w * (float)img_h) / (1024.0f * 1024.0f); + + if (U.image_gpubuffer_limit > (int)img_size) { + glColor4f(1.0, 1.0, 1.0, 1.0); + glaDrawPixelsTex(x, y, img_w, img_h, format, zoomfilter, rect); + return; + } + } + glaDrawPixelsSafe(x, y, img_w, img_h, img_w, GL_RGBA, format, rect); +} + /* 2D Drawing Assistance */ void glaDefine2DArea(rcti *screen_rect) @@ -807,7 +824,9 @@ void bglBegin(int mode) pointhack = floor(value[0] + 0.5f); if (pointhack > 4) pointhack = 4; } - else glBegin(mode); + else { + glBegin(mode); + } } } @@ -835,7 +854,9 @@ void bglVertex3fv(const float vec[3]) glRasterPos3fv(vec); glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot); } - else glVertex3fv(vec); + else { + glVertex3fv(vec); + } break; } } @@ -848,7 +869,9 @@ void bglVertex3f(float x, float y, float z) glRasterPos3f(x, y, z); glBitmap(pointhack, pointhack, (float)pointhack / 2.0f, (float)pointhack / 2.0f, 0.0, 0.0, Squaredot); } - else glVertex3f(x, y, z); + else { + glVertex3f(x, y, z); + } break; } } @@ -861,7 +884,9 @@ void bglVertex2fv(const float vec[2]) glRasterPos2fv(vec); glBitmap(pointhack, pointhack, (float)pointhack / 2, pointhack / 2, 0.0, 0.0, Squaredot); } - else glVertex2fv(vec); + else { + glVertex2fv(vec); + } break; } } diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 7c22dff1b01..6045bdfebfe 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -194,7 +194,9 @@ void removenotused_scrverts(bScreen *sc) BLI_remlink(&sc->vertbase, sv); MEM_freeN(sv); } - else sv->flag = 0; + else { + sv->flag = 0; + } sv = svn; } } @@ -250,7 +252,9 @@ void removenotused_scredges(bScreen *sc) BLI_remlink(&sc->edgebase, se); MEM_freeN(se); } - else se->flag = 0; + else { + se->flag = 0; + } se = sen; } } @@ -1133,8 +1137,12 @@ void ED_screens_initialize(wmWindowManager *wm) void ED_region_exit(bContext *C, ARegion *ar) { + wmWindowManager *wm = CTX_wm_manager(C); ARegion *prevar = CTX_wm_region(C); + if (ar->type && ar->type->exit) + ar->type->exit(wm, ar); + CTX_wm_region_set(C, ar); WM_event_remove_handlers(C, &ar->handlers); if (ar->swinid) @@ -1153,18 +1161,12 @@ void ED_region_exit(bContext *C, ARegion *ar) void ED_area_exit(bContext *C, ScrArea *sa) { + wmWindowManager *wm = CTX_wm_manager(C); ScrArea *prevsa = CTX_wm_area(C); ARegion *ar; - if (sa->spacetype == SPACE_FILE) { - SpaceLink *sl = sa->spacedata.first; - if (sl && sl->spacetype == SPACE_FILE) { - ED_fileselect_exit(C, (SpaceFile *)sl); - } - } - else if (sa->spacetype == SPACE_VIEW3D) { - ED_render_engine_area_exit(sa); - } + if (sa->type && sa->type->exit) + sa->type->exit(wm, sa); CTX_wm_area_set(C, sa); for (ar = sa->regionbase.first; ar; ar = ar->next) diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index fcd0968d52f..1906a3259a9 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -644,7 +644,7 @@ static void actionzone_apply(bContext *C, wmOperator *op, int type) wm_event_add(win, &event); } -static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) { AZone *az = is_in_area_actionzone(CTX_wm_area(C), &event->x); sActionzoneData *sad; @@ -674,7 +674,7 @@ static int actionzone_invoke(bContext *C, wmOperator *op, wmEvent *event) } -static int actionzone_modal(bContext *C, wmOperator *op, wmEvent *event) +static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) { sActionzoneData *sad = op->customdata; int deltax, deltay; @@ -769,7 +769,7 @@ typedef struct sAreaSwapData { ScrArea *sa1, *sa2; } sAreaSwapData; -static int area_swap_init(wmOperator *op, wmEvent *event) +static int area_swap_init(wmOperator *op, const wmEvent *event) { sAreaSwapData *sd = NULL; sActionzoneData *sad = event->customdata; @@ -800,7 +800,7 @@ static int area_swap_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int area_swap_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!area_swap_init(op, event)) @@ -814,7 +814,7 @@ static int area_swap_invoke(bContext *C, wmOperator *op, wmEvent *event) } -static int area_swap_modal(bContext *C, wmOperator *op, wmEvent *event) +static int area_swap_modal(bContext *C, wmOperator *op, const wmEvent *event) { sActionzoneData *sad = op->customdata; @@ -866,7 +866,7 @@ static void SCREEN_OT_area_swap(wmOperatorType *ot) /* *********** Duplicate area as new window operator ****************** */ /* operator callback */ -static int area_dupli_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int area_dupli_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *newwin, *win; bScreen *newsc, *sc; @@ -1100,7 +1100,7 @@ static int area_move_exec(bContext *C, wmOperator *op) } /* interaction callback */ -static int area_move_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int area_move_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RNA_int_set(op->ptr, "x", event->x); RNA_int_set(op->ptr, "y", event->y); @@ -1125,7 +1125,7 @@ static int area_move_cancel(bContext *C, wmOperator *op) } /* modal callback for while moving edges */ -static int area_move_modal(bContext *C, wmOperator *op, wmEvent *event) +static int area_move_modal(bContext *C, wmOperator *op, const wmEvent *event) { sAreaMoveData *md = op->customdata; int delta, x, y; @@ -1382,7 +1382,7 @@ static void area_split_exit(bContext *C, wmOperator *op) /* UI callback, adds new handler */ -static int area_split_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int area_split_invoke(bContext *C, wmOperator *op, const wmEvent *event) { sAreaSplitData *sd; int dir; @@ -1514,7 +1514,7 @@ static int area_split_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int area_split_modal(bContext *C, wmOperator *op, wmEvent *event) +static int area_split_modal(bContext *C, wmOperator *op, const wmEvent *event) { sAreaSplitData *sd = (sAreaSplitData *)op->customdata; float fac; @@ -1697,7 +1697,7 @@ static int area_max_regionsize(ScrArea *sa, ARegion *scalear, AZEdge edge) return dist; } -static int region_scale_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int region_scale_invoke(bContext *C, wmOperator *op, const wmEvent *event) { sActionzoneData *sad = event->customdata; AZone *az; @@ -1795,7 +1795,7 @@ static void region_scale_toggle_hidden(bContext *C, RegionMoveData *rmd) region_scale_validate_size(rmd); } -static int region_scale_modal(bContext *C, wmOperator *op, wmEvent *event) +static int region_scale_modal(bContext *C, wmOperator *op, const wmEvent *event) { RegionMoveData *rmd = op->customdata; int delta; @@ -2318,7 +2318,7 @@ static int area_join_exec(bContext *C, wmOperator *op) } /* interaction callback */ -static int area_join_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int area_join_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type == EVT_ACTIONZONE_AREA) { @@ -2374,7 +2374,7 @@ static int area_join_cancel(bContext *C, wmOperator *op) } /* modal callback while selecting area (space) that will be removed */ -static int area_join_modal(bContext *C, wmOperator *op, wmEvent *event) +static int area_join_modal(bContext *C, wmOperator *op, const wmEvent *event) { bScreen *sc = CTX_wm_screen(C); sAreaJoinData *jd = (sAreaJoinData *)op->customdata; @@ -2490,7 +2490,7 @@ static void SCREEN_OT_area_join(wmOperatorType *ot) /* ******************************* */ -static int screen_area_options_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int screen_area_options_invoke(bContext *C, wmOperator *op, const wmEvent *event) { uiPopupMenu *pup; uiLayout *layout; @@ -2604,7 +2604,7 @@ static void SCREEN_OT_repeat_last(wmOperatorType *ot) } -static int repeat_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int repeat_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { wmWindowManager *wm = CTX_wm_manager(C); wmOperator *lastop; @@ -2661,7 +2661,7 @@ static void SCREEN_OT_repeat_history(wmOperatorType *ot) /* ********************** redo operator ***************************** */ -static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int redo_last_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { wmOperator *lastop = WM_operator_last_redo(C); @@ -2958,7 +2958,7 @@ void ED_screens_header_tools_menu_create(bContext *C, uiLayout *layout, void *UN } } -static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int header_toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; @@ -3071,7 +3071,7 @@ static int match_region_with_redraws(int spacetype, int regiontype, int redraws) return 0; } -static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { bScreen *screen = CTX_wm_screen(C); @@ -3421,7 +3421,7 @@ static void SCREEN_OT_back_to_previous(struct wmOperatorType *ot) /* *********** show user pref window ****** */ -static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int userpref_show_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { wmWindow *win = CTX_wm_window(C); rcti rect; @@ -3696,7 +3696,7 @@ void region_blend_start(bContext *C, ScrArea *sa, ARegion *ar) } /* timer runs in win->handlers, so it cannot use context to find area/region */ -static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int region_blend_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { RegionAlphaInfo *rgi; wmTimer *timer = event->customdata; @@ -3820,7 +3820,7 @@ static void keymap_modal_set(wmKeyConfig *keyconf) } -static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int open_file_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) { if (drag->icon == ICON_FILE_BLEND) diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 9cde62e8302..0fbb4c25e78 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -204,7 +204,7 @@ static int screenshot_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int screenshot_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int screenshot_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (screenshot_data_create(C, op)) { if (RNA_struct_property_is_set(op->ptr, "filepath")) diff --git a/source/blender/editors/sculpt_paint/CMakeLists.txt b/source/blender/editors/sculpt_paint/CMakeLists.txt index 5bed31e2e52..0899fb97a2a 100644 --- a/source/blender/editors/sculpt_paint/CMakeLists.txt +++ b/source/blender/editors/sculpt_paint/CMakeLists.txt @@ -23,6 +23,7 @@ set(INC ../uvedit ../../blenkernel ../../blenlib + ../../blenfont ../../blenloader ../../bmesh ../../gpu @@ -43,6 +44,7 @@ set(SRC paint_hide.c paint_image.c paint_image_2d.c + paint_image_proj.c paint_mask.c paint_ops.c paint_stroke.c @@ -57,4 +59,8 @@ set(SRC sculpt_intern.h ) +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + blender_add_lib(bf_editor_sculpt_paint "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/editors/sculpt_paint/SConscript b/source/blender/editors/sculpt_paint/SConscript index 6767e06f65b..d10666de637 100644 --- a/source/blender/editors/sculpt_paint/SConscript +++ b/source/blender/editors/sculpt_paint/SConscript @@ -31,7 +31,7 @@ sources = env.Glob('*.c') defs = [] -incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' +incs = '../include ../../blenlib ../../blenfont ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include' incs += ' ../../gpu ../../makesrna ../../blenloader ../../bmesh ../uvedit' @@ -47,4 +47,7 @@ if env['OURPLATFORM'] == 'linuxcross': if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + env.BlenderLib ( 'bf_editors_sculpt_paint', sources, Split(incs), defines=defs, libtype=['core'], priority=[40] ) diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index ffea5af74a3..8d9cbbbcf11 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -207,14 +207,14 @@ static int load_tex(Brush *br, ViewContext *vc) x = (float)i / size; y = (float)j / size; - x -= 0.5f; - y -= 0.5f; - if (br->mtex.brush_map_mode == MTEX_MAP_MODE_TILED) { x *= vc->ar->winx / radius; y *= vc->ar->winy / radius; } else { + x -= 0.5f; + y -= 0.5f; + x *= 2; y *= 2; } @@ -345,14 +345,14 @@ static int sculpt_get_brush_geometry(bContext *C, ViewContext *vc, { Scene *scene = CTX_data_scene(C); Paint *paint = paint_get_active_from_context(C); - float window[2]; + float mouse[2]; int hit; - window[0] = x + vc->ar->winrct.xmin; - window[1] = y + vc->ar->winrct.ymin; + mouse[0] = x; + mouse[1] = y; if (vc->obact->sculpt && vc->obact->sculpt->pbvh && - sculpt_stroke_get_location(C, location, window)) + sculpt_stroke_get_location(C, location, mouse)) { Brush *brush = paint_brush(paint); *pixel_radius = @@ -420,8 +420,7 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) { /* brush rotation */ glTranslatef(0.5, 0.5, 0); - glRotatef((double)RAD2DEGF((brush->flag & BRUSH_RAKE) ? - ups->last_angle : ups->special_rotation), + glRotatef((double)RAD2DEGF(ups->brush_rotation), 0.0, 0.0, 1.0); glTranslatef(-0.5f, -0.5f, 0); @@ -434,11 +433,10 @@ static void paint_draw_alpha_overlay(UnifiedPaintSettings *ups, Brush *brush, if (ups->draw_anchored) { const float *aim = ups->anchored_initial_mouse; - const rcti *win = &vc->ar->winrct; - quad.xmin = aim[0] - ups->anchored_size - win->xmin; - quad.ymin = aim[1] - ups->anchored_size - win->ymin; - quad.xmax = aim[0] + ups->anchored_size - win->xmin; - quad.ymax = aim[1] + ups->anchored_size - win->ymin; + quad.xmin = aim[0] - ups->anchored_size; + quad.ymin = aim[1] - ups->anchored_size; + quad.xmax = aim[0] + ups->anchored_size; + quad.ymax = aim[1] + ups->anchored_size; } else { const int radius = BKE_brush_size_get(vc->scene, brush); @@ -537,38 +535,22 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) * mouse over too, not just during a stroke */ view3d_set_viewcontext(C, &vc); + if (brush->flag & BRUSH_RAKE) + /* here, translation contains the mouse coordinates. */ + paint_calculate_rake_rotation(ups, translation); + + /* draw overlay */ + paint_draw_alpha_overlay(ups, brush, &vc, x, y); + /* TODO: as sculpt and other paint modes are unified, this * special mode of drawing will go away */ if (vc.obact->sculpt) { float location[3]; int pixel_radius, hit; - /* this is probably here so that rake takes into - * account the brush movements before the stroke - * starts, but this doesn't really belong in draw code - * TODO) */ - { - const float u = 0.5f; - const float v = 1 - u; - const float r = 20; - - const float dx = ups->last_x - x; - const float dy = ups->last_y - y; - - if (dx * dx + dy * dy >= r * r) { - ups->last_angle = atan2(dx, dy); - - ups->last_x = u * ups->last_x + v * x; - ups->last_y = u * ups->last_y + v * y; - } - } - /* test if brush is over the mesh */ hit = sculpt_get_brush_geometry(C, &vc, x, y, &pixel_radius, location); - /* draw overlay */ - paint_draw_alpha_overlay(ups, brush, &vc, x, y); - if (BKE_brush_use_locked_size(scene, brush)) BKE_brush_size_set(scene, brush, pixel_radius); @@ -590,8 +572,8 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused)) if (ups->draw_anchored) { final_radius = ups->anchored_size; - translation[0] = ups->anchored_initial_mouse[0] - vc.ar->winrct.xmin; - translation[1] = ups->anchored_initial_mouse[1] - vc.ar->winrct.ymin; + translation[0] = ups->anchored_initial_mouse[0]; + translation[1] = ups->anchored_initial_mouse[1]; } } diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index d50261a3b98..14eb358f20f 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -424,7 +424,7 @@ static int hide_show_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int hide_show_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int hide_show_invoke(bContext *C, wmOperator *op, const wmEvent *event) { PartialVisArea area = RNA_enum_get(op->ptr, "area"); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index edeb66d9281..144dfa948d0 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -101,298 +101,8 @@ #include "paint_intern.h" -/* Defines and Structs */ -/* FTOCHAR as inline function */ -BLI_INLINE unsigned char f_to_char(const float val) -{ - return FTOCHAR(val); -} - - -#define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f) - -#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ - (c)[0] = f_to_char((f)[0]); \ - (c)[1] = f_to_char((f)[1]); \ - (c)[2] = f_to_char((f)[2]); \ -} (void)0 -#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \ - (c)[0] = f_to_char((f)[0]); \ - (c)[1] = f_to_char((f)[1]); \ - (c)[2] = f_to_char((f)[2]); \ - (c)[3] = f_to_char((f)[3]); \ -} (void)0 -#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \ - (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ - (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ - (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ -} (void)0 -#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \ - (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ - (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ - (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ - (f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]); \ -} (void)0 - -#define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b) - #define IMAPAINT_TILE_BITS 6 #define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) -#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS) - -static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint); - - -typedef struct ImagePaintState { - SpaceImage *sima; - View2D *v2d; - Scene *scene; - bScreen *screen; - - Brush *brush; - short tool, blend; - Image *image; - ImBuf *canvas; - ImBuf *clonecanvas; - char *warnpackedfile; - char *warnmultifile; - - /* viewport texture paint only, but _not_ project paint */ - Object *ob; - int faceindex; - float uv[2]; - int do_facesel; - - DerivedMesh *dm; - int dm_totface; - int dm_release; - - MFace *dm_mface; - MTFace *dm_mtface; -} ImagePaintState; - -typedef struct ImagePaintPartialRedraw { - int x1, y1, x2, y2; /* XXX, could use 'rcti' */ - int enabled; -} ImagePaintPartialRedraw; - -typedef struct ImagePaintRegion { - int destx, desty; - int srcx, srcy; - int width, height; -} ImagePaintRegion; - -/* ProjectionPaint defines */ - -/* approx the number of buckets to have under the brush, - * used with the brush size to set the ps->buckets_x and ps->buckets_y value. - * - * When 3 - a brush should have ~9 buckets under it at once - * ...this helps for threading while painting as well as - * avoiding initializing pixels that wont touch the brush */ -#define PROJ_BUCKET_BRUSH_DIV 4 - -#define PROJ_BUCKET_RECT_MIN 4 -#define PROJ_BUCKET_RECT_MAX 256 - -#define PROJ_BOUNDBOX_DIV 8 -#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV) - -//#define PROJ_DEBUG_PAINT 1 -//#define PROJ_DEBUG_NOSEAMBLEED 1 -//#define PROJ_DEBUG_PRINT_CLIP 1 -#define PROJ_DEBUG_WINCLIP 1 - -/* projectFaceSeamFlags options */ -//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */ -//#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */ -#define PROJ_FACE_SEAM1 (1 << 0) /* If this face has a seam on any of its edges */ -#define PROJ_FACE_SEAM2 (1 << 1) -#define PROJ_FACE_SEAM3 (1 << 2) -#define PROJ_FACE_SEAM4 (1 << 3) - -#define PROJ_FACE_NOSEAM1 (1 << 4) -#define PROJ_FACE_NOSEAM2 (1 << 5) -#define PROJ_FACE_NOSEAM3 (1 << 6) -#define PROJ_FACE_NOSEAM4 (1 << 7) - -#define PROJ_SRC_VIEW 1 -#define PROJ_SRC_IMAGE_CAM 2 -#define PROJ_SRC_IMAGE_VIEW 3 - -#define PROJ_VIEW_DATA_ID "view_data" -#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */ - - -/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams - * as this number approaches 1.0f the likelihood increases of float precision errors where - * it is occluded by an adjacent face */ -#define PROJ_FACE_SCALE_SEAM 0.99f - -#define PROJ_BUCKET_NULL 0 -#define PROJ_BUCKET_INIT (1 << 0) -// #define PROJ_BUCKET_CLONE_INIT (1<<1) - -/* used for testing doubles, if a point is on a line etc */ -#define PROJ_GEOM_TOLERANCE 0.00075f - -/* vert flags */ -#define PROJ_VERT_CULL 1 - -/* This is mainly a convenience struct used so we can keep an array of images we use - * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread - * because 'partRedrawRect' and 'touch' values would not be thread safe */ -typedef struct ProjPaintImage { - Image *ima; - ImBuf *ibuf; - ImagePaintPartialRedraw *partRedrawRect; - void **undoRect; /* only used to build undo tiles after painting */ - int touch; -} ProjPaintImage; - -/* Main projection painting struct passed to all projection painting functions */ -typedef struct ProjPaintState { - View3D *v3d; - RegionView3D *rv3d; - ARegion *ar; - Scene *scene; - int source; /* PROJ_SRC_**** */ - - Brush *brush; - short tool, blend; - Object *ob; - /* end similarities with ImagePaintState */ - - DerivedMesh *dm; - int dm_totface; - int dm_totvert; - int dm_release; - - MVert *dm_mvert; - MFace *dm_mface; - MTFace *dm_mtface; - MTFace *dm_mtface_clone; /* other UV map, use for cloning between layers */ - MTFace *dm_mtface_stencil; - - /* projection painting only */ - MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the first item is sometimes used for non threaded cases too */ - LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */ - LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */ - unsigned char *bucketFlags; /* store if the bucks have been initialized */ -#ifndef PROJ_DEBUG_NOSEAMBLEED - char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ - float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ - LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ -#endif - char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ - int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ - int buckets_y; - - ProjPaintImage *projImages; - - int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */ - - int image_tot; /* size of projectImages array */ - - float (*screenCoords)[4]; /* verts projected into floating point screen space */ - - float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */ - float screenMax[2]; - float screen_width; /* Calculated from screenMin & screenMax */ - float screen_height; - int winx, winy; /* from the carea or from the projection render */ - - /* options for projection painting */ - int do_layer_clone; - int do_layer_stencil; - int do_layer_stencil_inv; - - short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/ - short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */ - short do_mask_normal; /* mask out pixels based on their normals */ - short do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */ - float normal_angle; /* what angle to mask at*/ - float normal_angle_inner; - float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ - - short is_ortho; - bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */ - short is_texbrush; /* only to avoid running */ -#ifndef PROJ_DEBUG_NOSEAMBLEED - float seam_bleed_px; -#endif - /* clone vars */ - float cloneOffset[2]; - - float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ - float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */ - float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ - float clipsta, clipend; - - /* reproject vars */ - Image *reproject_image; - ImBuf *reproject_ibuf; - - - /* threads */ - int thread_tot; - int bucketMin[2]; - int bucketMax[2]; - int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */ -} ProjPaintState; - -typedef union pixelPointer { - float *f_pt; /* float buffer */ - unsigned int *uint_pt; /* 2 ways to access a char buffer */ - unsigned char *ch_pt; -} PixelPointer; - -typedef union pixelStore { - unsigned char ch[4]; - unsigned int uint; - float f[4]; -} PixelStore; - -typedef struct ProjPixel { - float projCoSS[2]; /* the floating point screen projection of this pixel */ - float worldCoSS[3]; - /* Only used when the airbrush is disabled. - * Store the max mask value to avoid painting over an area with a lower opacity - * with an advantage that we can avoid touching the pixel at all, if the - * new mask value is lower then mask_max */ - unsigned short mask_max; - - /* for various reasons we may want to mask out painting onto this pixel */ - unsigned short mask; - - short x_px, y_px; - - PixelStore origColor; - PixelStore newColor; - PixelPointer pixel; - - short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */ - unsigned char bb_cell_index; -} ProjPixel; - -typedef struct ProjPixelClone { - struct ProjPixel __pp; - PixelStore clonepx; -} ProjPixelClone; - -/* blur, store surrounding colors */ -#define PROJ_PIXEL_SOFTEN_TOT 4 -/* blur picking offset (in screenspace) */ -#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f - -static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = { - {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, - { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX}, - { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX}, - { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, -}; - -/* Finish projection painting structs */ typedef struct UndoImageTile { struct UndoImageTile *next, *prev; @@ -411,8 +121,21 @@ typedef struct UndoImageTile { char gen_type; } UndoImageTile; +/* this is a static resource for non-globality, + * Maybe it should be exposed as part of the + * paint operation, but for now just give a public interface */ static ImagePaintPartialRedraw imapaintpartial = {0, 0, 0, 0, 0}; +ImagePaintPartialRedraw *get_imapaintpartial(void) +{ + return &imapaintpartial; +} + +void set_imapaintpartial(struct ImagePaintPartialRedraw *ippr) +{ + imapaintpartial = *ippr; +} + /* UNDO */ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int restore) @@ -433,7 +156,7 @@ static void undo_copy_tile(UndoImageTile *tile, ImBuf *tmpibuf, ImBuf *ibuf, int tile->y * IMAPAINT_TILE_SIZE, 0, 0, IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE); } -static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile) +void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int x_tile, int y_tile) { ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_IMAGE); UndoImageTile *tile; @@ -472,7 +195,7 @@ static void *image_undo_push_tile(Image *ima, ImBuf *ibuf, ImBuf **tmpibuf, int return tile->rect.pt; } -static void image_undo_restore(bContext *C, ListBase *lb) +void image_undo_restore(bContext *C, ListBase *lb) { Main *bmain = CTX_data_main(C); Image *ima = NULL; @@ -481,7 +204,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) tmpibuf = IMB_allocImBuf(IMAPAINT_TILE_SIZE, IMAPAINT_TILE_SIZE, 32, IB_rectfloat | IB_rect); - + for (tile = lb->first; tile; tile = tile->next) { short use_float; @@ -538,7 +261,7 @@ static void image_undo_restore(bContext *C, ListBase *lb) IMB_freeImBuf(tmpibuf); } -static void image_undo_free(ListBase *lb) +void image_undo_free(ListBase *lb) { UndoImageTile *tile; @@ -546,3839 +269,14 @@ static void image_undo_free(ListBase *lb) MEM_freeN(tile->rect.pt); } -/* get active image for face depending on old/new shading system */ - -static Image *imapaint_face_image(const ImagePaintState *s, int face_index) -{ - Image *ima; - - if (BKE_scene_use_new_shading_nodes(s->scene)) { - MFace *mf = &s->dm_mface[face_index]; - ED_object_get_active_image(s->ob, mf->mat_nr + 1, &ima, NULL, NULL); - } - else { - MTFace *tf = &s->dm_mtface[face_index]; - ima = tf->tpage; - } - - return ima; -} - -static Image *project_paint_face_image(const ProjPaintState *ps, MTFace *dm_mtface, int face_index) -{ - Image *ima; - - if (ps->do_new_shading_nodes) { /* cached BKE_scene_use_new_shading_nodes result */ - MFace *mf = ps->dm_mface + face_index; - ED_object_get_active_image(ps->ob, mf->mat_nr + 1, &ima, NULL, NULL); - } - else { - ima = dm_mtface[face_index].tpage; - } - - return ima; -} - -/* fast projection bucket array lookup, use the safe version for bound checking */ -static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2]) -{ - /* If we were not dealing with screenspace 2D coords we could simple do... - * ps->bucketRect[x + (y*ps->buckets_y)] */ - - /* please explain? - * projCoSS[0] - ps->screenMin[0] : zero origin - * ... / ps->screen_width : range from 0.0 to 1.0 - * ... * ps->buckets_x : use as a bucket index - * - * Second multiplication does similar but for vertical offset - */ - return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) + - (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x); -} - -static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2]) -{ - int bucket_index = project_bucket_offset(ps, projCoSS); - - if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) { - return -1; - } - else { - return bucket_index; - } -} - -/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */ -static void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3]) -{ - float wtot_inv, wtot; - - w[0] = area_tri_signed_v2(v2, v3, co) / v1[3]; - w[1] = area_tri_signed_v2(v3, v1, co) / v2[3]; - w[2] = area_tri_signed_v2(v1, v2, co) / v3[3]; - wtot = w[0] + w[1] + w[2]; - - if (wtot != 0.0f) { - wtot_inv = 1.0f / wtot; - - w[0] = w[0] * wtot_inv; - w[1] = w[1] * wtot_inv; - w[2] = w[2] * wtot_inv; - } - else /* dummy values for zero area face */ - w[0] = w[1] = w[2] = 1.0f / 3.0f; -} - -static float VecZDepthOrtho(const float pt[2], - const float v1[3], const float v2[3], const float v3[3], - float w[3]) -{ - barycentric_weights_v2(v1, v2, v3, pt, w); - return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]); -} - -static float VecZDepthPersp(const float pt[2], - const float v1[4], const float v2[4], const float v3[4], - float w[3]) -{ - float wtot_inv, wtot; - float w_tmp[3]; - - barycentric_weights_v2_persp(v1, v2, v3, pt, w); - /* for the depth we need the weights to match what - * barycentric_weights_v2 would return, in this case its easiest just to - * undo the 4th axis division and make it unit-sum - * - * don't call barycentric_weights_v2() because our callers expect 'w' - * to be weighted from the perspective */ - w_tmp[0] = w[0] * v1[3]; - w_tmp[1] = w[1] * v2[3]; - w_tmp[2] = w[2] * v3[3]; - - wtot = w_tmp[0] + w_tmp[1] + w_tmp[2]; - - if (wtot != 0.0f) { - wtot_inv = 1.0f / wtot; - - w_tmp[0] = w_tmp[0] * wtot_inv; - w_tmp[1] = w_tmp[1] * wtot_inv; - w_tmp[2] = w_tmp[2] * wtot_inv; - } - else /* dummy values for zero area face */ - w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f; - /* done mimicing barycentric_weights_v2() */ - - return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[2]); -} - - -/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */ -static int project_paint_PickFace(const ProjPaintState *ps, float pt[2], float w[3], int *side) -{ - LinkNode *node; - float w_tmp[3]; - float *v1, *v2, *v3, *v4; - int bucket_index; - int face_index; - int best_side = -1; - int best_face_index = -1; - float z_depth_best = FLT_MAX, z_depth; - MFace *mf; - - bucket_index = project_bucket_offset_safe(ps, pt); - if (bucket_index == -1) - return -1; - - - - /* we could return 0 for 1 face buckets, as long as this function assumes - * that the point its testing is only every originated from an existing face */ - - for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { - face_index = GET_INT_FROM_POINTER(node->link); - mf = ps->dm_mface + face_index; - - v1 = ps->screenCoords[mf->v1]; - v2 = ps->screenCoords[mf->v2]; - v3 = ps->screenCoords[mf->v3]; - - if (isect_point_tri_v2(pt, v1, v2, v3)) { - if (ps->is_ortho) z_depth = VecZDepthOrtho(pt, v1, v2, v3, w_tmp); - else z_depth = VecZDepthPersp(pt, v1, v2, v3, w_tmp); - - if (z_depth < z_depth_best) { - best_face_index = face_index; - best_side = 0; - z_depth_best = z_depth; - copy_v3_v3(w, w_tmp); - } - } - else if (mf->v4) { - v4 = ps->screenCoords[mf->v4]; - - if (isect_point_tri_v2(pt, v1, v3, v4)) { - if (ps->is_ortho) z_depth = VecZDepthOrtho(pt, v1, v3, v4, w_tmp); - else z_depth = VecZDepthPersp(pt, v1, v3, v4, w_tmp); - - if (z_depth < z_depth_best) { - best_face_index = face_index; - best_side = 1; - z_depth_best = z_depth; - copy_v3_v3(w, w_tmp); - } - } - } - } - - *side = best_side; - return best_face_index; /* will be -1 or a valid face */ -} - -/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */ -static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y) -{ - /* use */ - *x = (float)fmodf(uv[0], 1.0f); - *y = (float)fmodf(uv[1], 1.0f); - - if (*x < 0.0f) *x += 1.0f; - if (*y < 0.0f) *y += 1.0f; - - *x = *x * ibuf_x - 0.5f; - *y = *y * ibuf_y - 0.5f; -} - -/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */ -static int project_paint_PickColor(const ProjPaintState *ps, float pt[2], float *rgba_fp, unsigned char *rgba, const int interp) -{ - float w[3], uv[2]; - int side; - int face_index; - MTFace *tf; - Image *ima; - ImBuf *ibuf; - int xi, yi; - - - face_index = project_paint_PickFace(ps, pt, w, &side); - - if (face_index == -1) - return 0; - - tf = ps->dm_mtface + face_index; - - if (side == 0) { - interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[1], tf->uv[2], w); - } - else { /* QUAD */ - interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); - } - - ima = project_paint_face_image(ps, ps->dm_mtface, face_index); - ibuf = ima->ibufs.first; /* we must have got the imbuf before getting here */ - if (!ibuf) return 0; - - if (interp) { - float x, y; - uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y); - - if (ibuf->rect_float) { - if (rgba_fp) { - bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y); - } - else { - float rgba_tmp_f[4]; - bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y); - IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f); - } - } - else { - if (rgba) { - bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y); - } - else { - unsigned char rgba_tmp[4]; - bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y); - IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp); - } - } - } - else { - //xi = (int)((uv[0]*ibuf->x) + 0.5f); - //yi = (int)((uv[1]*ibuf->y) + 0.5f); - //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0; - - /* wrap */ - xi = ((int)(uv[0] * ibuf->x)) % ibuf->x; - if (xi < 0) xi += ibuf->x; - yi = ((int)(uv[1] * ibuf->y)) % ibuf->y; - if (yi < 0) yi += ibuf->y; - - - if (rgba) { - if (ibuf->rect_float) { - float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4); - IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp); - } - else { - *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4)); - } - } - - if (rgba_fp) { - if (ibuf->rect_float) { - copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4))); - } - else { - char *tmp_ch = ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4); - IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch); - } - } - } - return 1; -} - -/* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test) - * return... - * 0 : no occlusion - * -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad) - * 1 : occluded - * 2 : occluded with w[3] weights set (need to know in some cases) */ - -static int project_paint_occlude_ptv(float pt[3], float v1[4], float v2[4], float v3[4], float w[3], int is_ortho) -{ - /* if all are behind us, return false */ - if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2]) - return 0; - - /* do a 2D point in try intersection */ - if (!isect_point_tri_v2(pt, v1, v2, v3)) - return 0; /* we know there is */ - - - /* From here on we know there IS an intersection */ - /* if ALL of the verts are infront of us then we know it intersects ? */ - if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) { - return 1; - } - else { - /* we intersect? - find the exact depth at the point of intersection */ - /* Is this point is occluded by another face? */ - if (is_ortho) { - if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2; - } - else { - if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2; - } - } - return -1; -} - - -static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace *mf, - float pt[3], float v1[4], float v2[4], float v3[4], - const int side) -{ - float w[3], wco[3]; - int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho); - - if (ret <= 0) - return ret; - - if (ret == 1) { /* weights not calculated */ - if (ps->is_ortho) barycentric_weights_v2(v1, v2, v3, pt, w); - else barycentric_weights_v2_persp(v1, v2, v3, pt, w); - } - - /* Test if we're in the clipped area, */ - if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); - else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); - - if (!ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { - return 1; - } - - return -1; -} - - -/* Check if a screenspace location is occluded by any other faces - * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison - * and doesn't need to be correct in relation to X and Y coords (this is the case in perspective view) */ -static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, float pixelScreenCo[4]) -{ - MFace *mf; - int face_index; - int isect_ret; - float w[3]; /* not needed when clipping */ - const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; - - /* we could return 0 for 1 face buckets, as long as this function assumes - * that the point its testing is only every originated from an existing face */ - - for (; bucketFace; bucketFace = bucketFace->next) { - face_index = GET_INT_FROM_POINTER(bucketFace->link); - - if (orig_face != face_index) { - mf = ps->dm_mface + face_index; - if (do_clip) - isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0); - else - isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho); - - /* Note, if (isect_ret == -1) then we don't want to test the other side of the quad */ - if (isect_ret == 0 && mf->v4) { - if (do_clip) - isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1); - else - isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho); - } - if (isect_ret >= 1) { - /* TODO - we may want to cache the first hit, - * it is not possible to swap the face order in the list anymore */ - return 1; - } - } - } - return 0; -} - -/* basic line intersection, could move to math_geom.c, 2 points with a horiz line - * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */ -#define ISECT_TRUE 1 -#define ISECT_TRUE_P1 2 -#define ISECT_TRUE_P2 3 -static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect) -{ - float y_diff; - - if (y_level == p1[1]) { /* are we touching the first point? - no interpolation needed */ - *x_isect = p1[0]; - return ISECT_TRUE_P1; - } - if (y_level == p2[1]) { /* are we touching the second point? - no interpolation needed */ - *x_isect = p2[0]; - return ISECT_TRUE_P2; - } - - y_diff = fabsf(p1[1] - p2[1]); /* yuck, horizontal line, we cant do much here */ - - if (y_diff < 0.000001f) { - *x_isect = (p1[0] + p2[0]) * 0.5f; - return ISECT_TRUE; - } - - if (p1[1] > y_level && p2[1] < y_level) { - *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff; /*(p1[1]-p2[1]);*/ - return ISECT_TRUE; - } - else if (p1[1] < y_level && p2[1] > y_level) { - *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff; /*(p2[1]-p1[1]);*/ - return ISECT_TRUE; - } - else { - return 0; - } -} - -static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect) -{ - float x_diff; - - if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */ - *y_isect = p1[1]; - return ISECT_TRUE_P1; - } - if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */ - *y_isect = p2[1]; - return ISECT_TRUE_P2; - } - - x_diff = fabsf(p1[0] - p2[0]); /* yuck, horizontal line, we cant do much here */ - - if (x_diff < 0.000001f) { /* yuck, vertical line, we cant do much here */ - *y_isect = (p1[0] + p2[0]) * 0.5f; - return ISECT_TRUE; - } - - if (p1[0] > x_level && p2[0] < x_level) { - *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff; /*(p1[0]-p2[0]);*/ - return ISECT_TRUE; - } - else if (p1[0] < x_level && p2[0] > x_level) { - *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff; /*(p2[0]-p1[0]);*/ - return ISECT_TRUE; - } - else { - return 0; - } -} - -/* simple func use for comparing UV locations to check if there are seams. - * Its possible this gives incorrect results, when the UVs for 1 face go into the next - * tile, but do not do this for the adjacent face, it could return a false positive. - * This is so unlikely that Id not worry about it. */ -#ifndef PROJ_DEBUG_NOSEAMBLEED -static int cmp_uv(const float vec2a[2], const float vec2b[2]) -{ - /* if the UV's are not between 0.0 and 1.0 */ - float xa = (float)fmodf(vec2a[0], 1.0f); - float ya = (float)fmodf(vec2a[1], 1.0f); - - float xb = (float)fmodf(vec2b[0], 1.0f); - float yb = (float)fmodf(vec2b[1], 1.0f); - - if (xa < 0.0f) xa += 1.0f; - if (ya < 0.0f) ya += 1.0f; - - if (xb < 0.0f) xb += 1.0f; - if (yb < 0.0f) yb += 1.0f; - - return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ? 1 : 0; -} -#endif - -/* set min_px and max_px to the image space bounds of the UV coords - * return zero if there is no area in the returned rectangle */ -#ifndef PROJ_DEBUG_NOSEAMBLEED -static int pixel_bounds_uv( - const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2], - rcti *bounds_px, - const int ibuf_x, const int ibuf_y, - int is_quad - ) -{ - float min_uv[2], max_uv[2]; /* UV bounds */ - - INIT_MINMAX2(min_uv, max_uv); - - minmax_v2v2_v2(min_uv, max_uv, uv1); - minmax_v2v2_v2(min_uv, max_uv, uv2); - minmax_v2v2_v2(min_uv, max_uv, uv3); - if (is_quad) - minmax_v2v2_v2(min_uv, max_uv, uv4); - - bounds_px->xmin = (int)(ibuf_x * min_uv[0]); - bounds_px->ymin = (int)(ibuf_y * min_uv[1]); - - bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1; - bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1; - - /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ - - /* face uses no UV area when quantized to pixels? */ - return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1; -} -#endif - -static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot) -{ - float min_uv[2], max_uv[2]; /* UV bounds */ - - if (tot == 0) { - return 0; - } - - INIT_MINMAX2(min_uv, max_uv); - - while (tot--) { - minmax_v2v2_v2(min_uv, max_uv, (*uv)); - uv++; - } - - bounds_px->xmin = (int)(ibuf_x * min_uv[0]); - bounds_px->ymin = (int)(ibuf_y * min_uv[1]); - - bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1; - bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1; - - /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ - - /* face uses no UV area when quantized to pixels? */ - return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1; -} - -#ifndef PROJ_DEBUG_NOSEAMBLEED - -/* This function returns 1 if this face has a seam along the 2 face-vert indices - * 'orig_i1_fidx' and 'orig_i2_fidx' */ -static int check_seam(const ProjPaintState *ps, const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx, int *other_face, int *orig_fidx) -{ - LinkNode *node; - int face_index; - unsigned int i1, i2; - int i1_fidx = -1, i2_fidx = -1; /* index in face */ - MFace *mf; - MTFace *tf; - const MFace *orig_mf = ps->dm_mface + orig_face; - const MTFace *orig_tf = ps->dm_mtface + orig_face; - - /* vert indices from face vert order indices */ - i1 = (*(&orig_mf->v1 + orig_i1_fidx)); - i2 = (*(&orig_mf->v1 + orig_i2_fidx)); - - for (node = ps->vertFaces[i1]; node; node = node->next) { - face_index = GET_INT_FROM_POINTER(node->link); - - if (face_index != orig_face) { - mf = ps->dm_mface + face_index; - /* could check if the 2 faces images match here, - * but then there wouldn't be a way to return the opposite face's info */ - - - /* We need to know the order of the verts in the adjacent face - * set the i1_fidx and i2_fidx to (0,1,2,3) */ - if (mf->v1 == i1) i1_fidx = 0; - else if (mf->v2 == i1) i1_fidx = 1; - else if (mf->v3 == i1) i1_fidx = 2; - else if (mf->v4 && mf->v4 == i1) i1_fidx = 3; - - if (mf->v1 == i2) i2_fidx = 0; - else if (mf->v2 == i2) i2_fidx = 1; - else if (mf->v3 == i2) i2_fidx = 2; - else if (mf->v4 && mf->v4 == i2) i2_fidx = 3; - - /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */ - if (i2_fidx != -1) { - Image *tpage = project_paint_face_image(ps, ps->dm_mtface, face_index); - Image *orig_tpage = project_paint_face_image(ps, ps->dm_mtface, orig_face); - - /* This IS an adjacent face!, now lets check if the UVs are ok */ - tf = ps->dm_mtface + face_index; - - /* set up the other face */ - *other_face = face_index; - *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx; - - /* first test if they have the same image */ - if ((orig_tpage == tpage) && - cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) && - cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) ) - { - // printf("SEAM (NONE)\n"); - return 0; - - } - else { - // printf("SEAM (UV GAP)\n"); - return 1; - } - } - } - } - // printf("SEAM (NO FACE)\n"); - *other_face = -1; - return 1; -} - -/* Calculate outset UV's, this is not the same as simply scaling the UVs, - * since the outset coords are a margin that keep an even distance from the original UV's, - * note that the image aspect is taken into account */ -static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler, const int ibuf_x, const int ibuf_y, const int is_quad) -{ - float a1, a2, a3, a4 = 0.0f; - float puv[4][2]; /* pixelspace uv's */ - float no1[2], no2[2], no3[2], no4[2]; /* normals */ - float dir1[2], dir2[2], dir3[2], dir4[2]; - float ibuf_inv[2]; - - ibuf_inv[0] = 1.0f / (float)ibuf_x; - ibuf_inv[1] = 1.0f / (float)ibuf_y; - - /* make UV's in pixel space so we can */ - puv[0][0] = orig_uv[0][0] * ibuf_x; - puv[0][1] = orig_uv[0][1] * ibuf_y; - - puv[1][0] = orig_uv[1][0] * ibuf_x; - puv[1][1] = orig_uv[1][1] * ibuf_y; - - puv[2][0] = orig_uv[2][0] * ibuf_x; - puv[2][1] = orig_uv[2][1] * ibuf_y; - - if (is_quad) { - puv[3][0] = orig_uv[3][0] * ibuf_x; - puv[3][1] = orig_uv[3][1] * ibuf_y; - } - - /* face edge directions */ - sub_v2_v2v2(dir1, puv[1], puv[0]); - sub_v2_v2v2(dir2, puv[2], puv[1]); - normalize_v2(dir1); - normalize_v2(dir2); - - if (is_quad) { - sub_v2_v2v2(dir3, puv[3], puv[2]); - sub_v2_v2v2(dir4, puv[0], puv[3]); - normalize_v2(dir3); - normalize_v2(dir4); - } - else { - sub_v2_v2v2(dir3, puv[0], puv[2]); - normalize_v2(dir3); - } - - /* TODO - angle_normalized_v2v2(...) * (M_PI/180.0f) - * This is incorrect. Its already given radians but without it wont work. - * need to look into a fix - campbell */ - if (is_quad) { - a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * ((float)M_PI / 180.0f)); - a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f)); - a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f)); - a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * ((float)M_PI / 180.0f)); - } - else { - a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * ((float)M_PI / 180.0f)); - a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f)); - a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f)); - } - - if (is_quad) { - sub_v2_v2v2(no1, dir4, dir1); - sub_v2_v2v2(no2, dir1, dir2); - sub_v2_v2v2(no3, dir2, dir3); - sub_v2_v2v2(no4, dir3, dir4); - normalize_v2(no1); - normalize_v2(no2); - normalize_v2(no3); - normalize_v2(no4); - mul_v2_fl(no1, a1 * scaler); - mul_v2_fl(no2, a2 * scaler); - mul_v2_fl(no3, a3 * scaler); - mul_v2_fl(no4, a4 * scaler); - add_v2_v2v2(outset_uv[0], puv[0], no1); - add_v2_v2v2(outset_uv[1], puv[1], no2); - add_v2_v2v2(outset_uv[2], puv[2], no3); - add_v2_v2v2(outset_uv[3], puv[3], no4); - mul_v2_v2(outset_uv[0], ibuf_inv); - mul_v2_v2(outset_uv[1], ibuf_inv); - mul_v2_v2(outset_uv[2], ibuf_inv); - mul_v2_v2(outset_uv[3], ibuf_inv); - } - else { - sub_v2_v2v2(no1, dir3, dir1); - sub_v2_v2v2(no2, dir1, dir2); - sub_v2_v2v2(no3, dir2, dir3); - normalize_v2(no1); - normalize_v2(no2); - normalize_v2(no3); - mul_v2_fl(no1, a1 * scaler); - mul_v2_fl(no2, a2 * scaler); - mul_v2_fl(no3, a3 * scaler); - add_v2_v2v2(outset_uv[0], puv[0], no1); - add_v2_v2v2(outset_uv[1], puv[1], no2); - add_v2_v2v2(outset_uv[2], puv[2], no3); - - mul_v2_v2(outset_uv[0], ibuf_inv); - mul_v2_v2(outset_uv[1], ibuf_inv); - mul_v2_v2(outset_uv[2], ibuf_inv); - } -} - -/* - * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4 - * 1<<i - where i is (0-3) - * - * If we're multithreadng, make sure threads are locked when this is called - */ -static void project_face_seams_init(const ProjPaintState *ps, const int face_index, const int is_quad) -{ - int other_face, other_fidx; /* vars for the other face, we also set its flag */ - int fidx1 = is_quad ? 3 : 2; - int fidx2 = 0; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */ - - do { - if ((ps->faceSeamFlags[face_index] & (1 << fidx1 | 16 << fidx1)) == 0) { - if (check_seam(ps, face_index, fidx1, fidx2, &other_face, &other_fidx)) { - ps->faceSeamFlags[face_index] |= 1 << fidx1; - if (other_face != -1) - ps->faceSeamFlags[other_face] |= 1 << other_fidx; - } - else { - ps->faceSeamFlags[face_index] |= 16 << fidx1; - if (other_face != -1) - ps->faceSeamFlags[other_face] |= 16 << other_fidx; /* second 4 bits for disabled */ - } - } - - fidx2 = fidx1; - } while (fidx1--); -} -#endif // PROJ_DEBUG_NOSEAMBLEED - - -/* Converts a UV location to a 3D screenspace location - * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo - * - * This is used for finding a pixels location in screenspace for painting */ -static void screen_px_from_ortho( - float uv[2], - float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */ - float uv1co[2], float uv2co[2], float uv3co[2], - float pixelScreenCo[4], - float w[3]) -{ - barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w); - interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w); -} - -/* same as screen_px_from_ortho except we need to take into account - * the perspective W coord for each vert */ -static void screen_px_from_persp( - float uv[2], - float v1co[4], float v2co[4], float v3co[4], /* screenspace coords */ - float uv1co[2], float uv2co[2], float uv3co[2], - float pixelScreenCo[4], - float w[3]) -{ - - float wtot_inv, wtot; - barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w); - - /* re-weight from the 4th coord of each screen vert */ - w[0] *= v1co[3]; - w[1] *= v2co[3]; - w[2] *= v3co[3]; - - wtot = w[0] + w[1] + w[2]; - - if (wtot > 0.0f) { - wtot_inv = 1.0f / wtot; - w[0] *= wtot_inv; - w[1] *= wtot_inv; - w[2] *= wtot_inv; - } - else { - w[0] = w[1] = w[2] = 1.0f / 3.0f; /* dummy values for zero area face */ - } - /* done re-weighting */ - - interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w); -} - -static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], int side, unsigned char rgba_ub[4], float rgba_f[4]) -{ - float *uvCo1, *uvCo2, *uvCo3; - float uv_other[2], x, y; - - uvCo1 = (float *)tf_other->uv[0]; - if (side == 1) { - uvCo2 = (float *)tf_other->uv[2]; - uvCo3 = (float *)tf_other->uv[3]; - } - else { - uvCo2 = (float *)tf_other->uv[1]; - uvCo3 = (float *)tf_other->uv[2]; - } - - interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)w); - - /* use */ - uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); - - - if (ibuf_other->rect_float) { /* from float to float */ - bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y); - } - else { /* from char to float */ - bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y); - } - -} - -/* run this outside project_paint_uvpixel_init since pixels with mask 0 don't need init */ -static float project_paint_uvpixel_mask( - const ProjPaintState *ps, - const int face_index, - const int side, - const float w[3]) -{ - float mask; - - /* Image Mask */ - if (ps->do_layer_stencil) { - /* another UV maps image is masking this one's */ - ImBuf *ibuf_other; - Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index); - const MTFace *tf_other = ps->dm_mtface_stencil + face_index; - - if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { - /* BKE_image_acquire_ibuf - TODO - this may be slow */ - unsigned char rgba_ub[4]; - float rgba_f[4]; - - project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f); - - if (ibuf_other->rect_float) { /* from float to float */ - mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) / 3.0f) * rgba_f[3]; - } - else { /* from char to float */ - mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f); - } - - BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); - - if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ - mask = (1.0f - mask); - - if (mask == 0.0f) { - return 0.0f; - } - } - else { - return 0.0f; - } - } - else { - mask = 1.0f; - } - - /* calculate mask */ - if (ps->do_mask_normal) { - MFace *mf = &ps->dm_mface[face_index]; - float no[3], angle; - if (mf->flag & ME_SMOOTH) { - short *no1, *no2, *no3; - no1 = ps->dm_mvert[mf->v1].no; - if (side == 1) { - no2 = ps->dm_mvert[mf->v3].no; - no3 = ps->dm_mvert[mf->v4].no; - } - else { - no2 = ps->dm_mvert[mf->v2].no; - no3 = ps->dm_mvert[mf->v3].no; - } - - no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0]; - no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1]; - no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2]; - normalize_v3(no); - } - else { - /* incase the */ -#if 1 - /* normalizing per pixel isn't optimal, we could cache or check ps->*/ - if (mf->v4) - normal_quad_v3(no, - ps->dm_mvert[mf->v1].co, - ps->dm_mvert[mf->v2].co, - ps->dm_mvert[mf->v3].co, - ps->dm_mvert[mf->v4].co); - else - normal_tri_v3(no, - ps->dm_mvert[mf->v1].co, - ps->dm_mvert[mf->v2].co, - ps->dm_mvert[mf->v3].co); -#else - /* don't use because some modifiers dont have normal data (subsurf for eg) */ - copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, face_index, CD_NORMAL)); -#endif - } - - /* now we can use the normal as a mask */ - if (ps->is_ortho) { - angle = angle_normalized_v3v3((float *)ps->viewDir, no); - } - else { - /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */ - float viewDirPersp[3]; - float *co1, *co2, *co3; - co1 = ps->dm_mvert[mf->v1].co; - if (side == 1) { - co2 = ps->dm_mvert[mf->v3].co; - co3 = ps->dm_mvert[mf->v4].co; - } - else { - co2 = ps->dm_mvert[mf->v2].co; - co3 = ps->dm_mvert[mf->v3].co; - } - - /* Get the direction from the viewPoint to the pixel and normalize */ - viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0])); - viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1])); - viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2])); - normalize_v3(viewDirPersp); - - angle = angle_normalized_v3v3(viewDirPersp, no); - } - - if (angle >= ps->normal_angle) { - return 0.0f; /* outsize the normal limit*/ - } - else if (angle > ps->normal_angle_inner) { - mask *= (ps->normal_angle - angle) / ps->normal_angle_range; - } /* otherwise no mask normal is needed, were within the limit */ - } - - /* This only works when the opacity dosnt change while painting, stylus pressure messes with this - * so don't use it. */ - // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush); - - return mask; -} - -static int project_paint_pixel_sizeof(const short tool) -{ - if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) { - return sizeof(ProjPixelClone); - } - else { - return sizeof(ProjPixel); - } -} - - -/* run this function when we know a bucket's, face's pixel can be initialized, - * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ -static ProjPixel *project_paint_uvpixel_init( - const ProjPaintState *ps, - MemArena *arena, - const ImBuf *ibuf, - short x_px, short y_px, - const float mask, - const int face_index, - const int image_index, - const float pixelScreenCo[4], - const float world_spaceCo[3], - const int side, - const float w[3]) -{ - ProjPixel *projPixel; - - /* wrap pixel location */ - x_px = x_px % ibuf->x; - if (x_px < 0) x_px += ibuf->x; - y_px = y_px % ibuf->y; - if (y_px < 0) y_px += ibuf->y; - - BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool)); - projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof); - //memset(projPixel, 0, size); - - if (ibuf->rect_float) { - projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4); - projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; - projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; - projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; - projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; - } - else { - projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4)); - projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt; - } - - /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */ - if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { - copy_v3_v3(projPixel->worldCoSS, world_spaceCo); - } - - copy_v2_v2(projPixel->projCoSS, pixelScreenCo); - - projPixel->x_px = x_px; - projPixel->y_px = y_px; - - projPixel->mask = (unsigned short)(mask * 65535); - projPixel->mask_max = 0; - - /* which bounding box cell are we in?, needed for undo */ - projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + - ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV; - - /* done with view3d_project_float inline */ - if (ps->tool == PAINT_TOOL_CLONE) { - if (ps->dm_mtface_clone) { - ImBuf *ibuf_other; - Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index); - const MTFace *tf_other = ps->dm_mtface_clone + face_index; - - if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { - /* BKE_image_acquire_ibuf - TODO - this may be slow */ - - if (ibuf->rect_float) { - if (ibuf_other->rect_float) { /* from float to float */ - project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f); - } - else { /* from char to float */ - unsigned char rgba_ub[4]; - project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL); - IMAPAINT_CHAR_RGBA_TO_FLOAT(((ProjPixelClone *)projPixel)->clonepx.f, rgba_ub); - } - } - else { - if (ibuf_other->rect_float) { /* float to char */ - float rgba[4]; - project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba); - IMAPAINT_FLOAT_RGBA_TO_CHAR(((ProjPixelClone *)projPixel)->clonepx.ch, rgba); - } - else { /* char to char */ - project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); - } - } - - BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); - } - else { - if (ibuf->rect_float) { - ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; - } - else { - ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; - } - } - - } - else { - float co[2]; - sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset); - - /* no need to initialize the bucket, we're only checking buckets faces and for this - * the faces are already initialized in project_paint_delayed_face_init(...) */ - if (ibuf->rect_float) { - if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) { - ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */ - } - } - else { - if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) { - ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */ - } - } - } - } - -#ifdef PROJ_DEBUG_PAINT - if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0; - else projPixel->pixel.ch_pt[0] = 0; -#endif - projPixel->image_index = image_index; - - return projPixel; -} - -static int line_clip_rect2f( - rctf *rect, - const float l1[2], const float l2[2], - float l1_clip[2], float l2_clip[2]) -{ - /* first account for horizontal, then vertical lines */ - /* horiz */ - if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_TOLERANCE) { - /* is the line out of range on its Y axis? */ - if (l1[1] < rect->ymin || l1[1] > rect->ymax) { - return 0; - } - /* line is out of range on its X axis */ - if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) { - return 0; - } - - - if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/ - if (BLI_rctf_isect_pt_v(rect, l1)) { - copy_v2_v2(l1_clip, l1); - copy_v2_v2(l2_clip, l2); - return 1; - } - else { - return 0; - } - } - - copy_v2_v2(l1_clip, l1); - copy_v2_v2(l2_clip, l2); - CLAMP(l1_clip[0], rect->xmin, rect->xmax); - CLAMP(l2_clip[0], rect->xmin, rect->xmax); - return 1; - } - else if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) { - /* is the line out of range on its X axis? */ - if (l1[0] < rect->xmin || l1[0] > rect->xmax) { - return 0; - } - - /* line is out of range on its Y axis */ - if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) { - return 0; - } - - if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/ - if (BLI_rctf_isect_pt_v(rect, l1)) { - copy_v2_v2(l1_clip, l1); - copy_v2_v2(l2_clip, l2); - return 1; - } - else { - return 0; - } - } - - copy_v2_v2(l1_clip, l1); - copy_v2_v2(l2_clip, l2); - CLAMP(l1_clip[1], rect->ymin, rect->ymax); - CLAMP(l2_clip[1], rect->ymin, rect->ymax); - return 1; - } - else { - float isect; - short ok1 = 0; - short ok2 = 0; - - /* Done with vertical lines */ - - /* are either of the points inside the rectangle ? */ - if (BLI_rctf_isect_pt_v(rect, l1)) { - copy_v2_v2(l1_clip, l1); - ok1 = 1; - } - - if (BLI_rctf_isect_pt_v(rect, l2)) { - copy_v2_v2(l2_clip, l2); - ok2 = 1; - } - - /* line inside rect */ - if (ok1 && ok2) return 1; - - /* top/bottom */ - if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) { - if (l1[1] < l2[1]) { /* line 1 is outside */ - l1_clip[0] = isect; - l1_clip[1] = rect->ymin; - ok1 = 1; - } - else { - l2_clip[0] = isect; - l2_clip[1] = rect->ymin; - ok2 = 2; - } - } - - if (ok1 && ok2) return 1; - - if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) { - if (l1[1] > l2[1]) { /* line 1 is outside */ - l1_clip[0] = isect; - l1_clip[1] = rect->ymax; - ok1 = 1; - } - else { - l2_clip[0] = isect; - l2_clip[1] = rect->ymax; - ok2 = 2; - } - } - - if (ok1 && ok2) return 1; - - /* left/right */ - if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) { - if (l1[0] < l2[0]) { /* line 1 is outside */ - l1_clip[0] = rect->xmin; - l1_clip[1] = isect; - ok1 = 1; - } - else { - l2_clip[0] = rect->xmin; - l2_clip[1] = isect; - ok2 = 2; - } - } - - if (ok1 && ok2) return 1; - - if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) { - if (l1[0] > l2[0]) { /* line 1 is outside */ - l1_clip[0] = rect->xmax; - l1_clip[1] = isect; - ok1 = 1; - } - else { - l2_clip[0] = rect->xmax; - l2_clip[1] = isect; - ok2 = 2; - } - } - - if (ok1 && ok2) { - return 1; - } - else { - return 0; - } - } -} - - - -/* scale the quad & tri about its center - * scaling by PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the - * edge of the face but slightly inside it occlusion tests don't return hits on adjacent faces */ -#ifndef PROJ_DEBUG_NOSEAMBLEED -static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset) -{ - float cent[3]; - cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) / 4.0f; - cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f; - cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 4.0f; - - sub_v3_v3v3(insetCos[0], origCos[0], cent); - sub_v3_v3v3(insetCos[1], origCos[1], cent); - sub_v3_v3v3(insetCos[2], origCos[2], cent); - sub_v3_v3v3(insetCos[3], origCos[3], cent); - - mul_v3_fl(insetCos[0], inset); - mul_v3_fl(insetCos[1], inset); - mul_v3_fl(insetCos[2], inset); - mul_v3_fl(insetCos[3], inset); - - add_v3_v3(insetCos[0], cent); - add_v3_v3(insetCos[1], cent); - add_v3_v3(insetCos[2], cent); - add_v3_v3(insetCos[3], cent); -} - - -static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset) -{ - float cent[3]; - cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f; - cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f; - cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.0f; - - sub_v3_v3v3(insetCos[0], origCos[0], cent); - sub_v3_v3v3(insetCos[1], origCos[1], cent); - sub_v3_v3v3(insetCos[2], origCos[2], cent); - - mul_v3_fl(insetCos[0], inset); - mul_v3_fl(insetCos[1], inset); - mul_v3_fl(insetCos[2], inset); - - add_v3_v3(insetCos[0], cent); - add_v3_v3(insetCos[1], cent); - add_v3_v3(insetCos[2], cent); -} -#endif //PROJ_DEBUG_NOSEAMBLEED - -static float len_squared_v2v2_alt(const float *v1, const float v2_1, const float v2_2) -{ - float x, y; - - x = v1[0] - v2_1; - y = v1[1] - v2_2; - return x * x + y * y; -} - -/* note, use a squared value so we can use len_squared_v2v2 - * be sure that you have done a bounds check first or this may fail */ -/* only give bucket_bounds as an arg because we need it elsewhere */ -static int project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds) -{ - - /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect - * so we only need to test if the center is inside the vertical or horizontal bounds on either axis, - * this is even less work then an intersection test - */ -#if 0 - if (BLI_rctf_isect_pt_v(bucket_bounds, cent)) - return 1; -#endif - - if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) || - (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1])) - { - return 1; - } - - /* out of bounds left */ - if (cent[0] < bucket_bounds->xmin) { - /* lower left out of radius test */ - if (cent[1] < bucket_bounds->ymin) { - return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0; - } - /* top left test */ - else if (cent[1] > bucket_bounds->ymax) { - return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0; - } - } - else if (cent[0] > bucket_bounds->xmax) { - /* lower right out of radius test */ - if (cent[1] < bucket_bounds->ymin) { - return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0; - } - /* top right test */ - else if (cent[1] > bucket_bounds->ymax) { - return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0; - } - } - - return 0; -} - - - -/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp() - * in ortho view this function gives good results when bucket_bounds are outside the triangle - * however in some cases, perspective view will mess up with faces that have minimal screenspace area - * (viewed from the side) - * - * for this reason its not reliable in this case so we'll use the Simple Barycentric' - * funcs that only account for points inside the triangle. - * however switching back to this for ortho is always an option */ - -static void rect_to_uvspace_ortho( - rctf *bucket_bounds, - float *v1coSS, float *v2coSS, float *v3coSS, - float *uv1co, float *uv2co, float *uv3co, - float bucket_bounds_uv[4][2], - const int flip) -{ - float uv[2]; - float w[3]; - - /* get the UV space bounding box */ - uv[0] = bucket_bounds->xmax; - uv[1] = bucket_bounds->ymin; - barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w); - - //uv[0] = bucket_bounds->xmax; // set above - uv[1] = bucket_bounds->ymax; - barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w); - - uv[0] = bucket_bounds->xmin; - //uv[1] = bucket_bounds->ymax; // set above - barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w); - - //uv[0] = bucket_bounds->xmin; // set above - uv[1] = bucket_bounds->ymin; - barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w); -} - -/* same as above but use barycentric_weights_v2_persp */ -static void rect_to_uvspace_persp( - rctf *bucket_bounds, - float *v1coSS, float *v2coSS, float *v3coSS, - float *uv1co, float *uv2co, float *uv3co, - float bucket_bounds_uv[4][2], - const int flip - ) -{ - float uv[2]; - float w[3]; - - /* get the UV space bounding box */ - uv[0] = bucket_bounds->xmax; - uv[1] = bucket_bounds->ymin; - barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w); - - //uv[0] = bucket_bounds->xmax; // set above - uv[1] = bucket_bounds->ymax; - barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w); - - uv[0] = bucket_bounds->xmin; - //uv[1] = bucket_bounds->ymax; // set above - barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w); - - //uv[0] = bucket_bounds->xmin; // set above - uv[1] = bucket_bounds->ymin; - barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); - interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w); -} - -/* This works as we need it to but we can save a few steps and not use it */ - -#if 0 -static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2]) -{ - float v1[2], v2[2]; - - v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1]; - v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1]; - - return -atan2(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]); -} -#endif - -#define ISECT_1 (1) -#define ISECT_2 (1 << 1) -#define ISECT_3 (1 << 2) -#define ISECT_4 (1 << 3) -#define ISECT_ALL3 ((1 << 3) - 1) -#define ISECT_ALL4 ((1 << 4) - 1) - -/* limit must be a fraction over 1.0f */ -static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit) -{ - return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) / (area_tri_v2(v1, v2, v3))) < limit; -} - -/* Clip the face by a bucket and set the uv-space bucket_bounds_uv - * so we have the clipped UV's to do pixel intersection tests with - * */ -static int float_z_sort_flip(const void *p1, const void *p2) -{ - return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1); -} - -static int float_z_sort(const void *p1, const void *p2) -{ - return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1); -} - -static void project_bucket_clip_face( - const int is_ortho, - rctf *bucket_bounds, - float *v1coSS, float *v2coSS, float *v3coSS, - float *uv1co, float *uv2co, float *uv3co, - float bucket_bounds_uv[8][2], - int *tot) -{ - int inside_bucket_flag = 0; - int inside_face_flag = 0; - const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); - - float bucket_bounds_ss[4][2]; - - /* get the UV space bounding box */ - inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS); - inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1; - inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2; - - if (inside_bucket_flag == ISECT_ALL3) { - /* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */ - if (flip) { /* facing the back? */ - copy_v2_v2(bucket_bounds_uv[0], uv3co); - copy_v2_v2(bucket_bounds_uv[1], uv2co); - copy_v2_v2(bucket_bounds_uv[2], uv1co); - } - else { - copy_v2_v2(bucket_bounds_uv[0], uv1co); - copy_v2_v2(bucket_bounds_uv[1], uv2co); - copy_v2_v2(bucket_bounds_uv[2], uv3co); - } - - *tot = 3; - return; - } - - /* get the UV space bounding box */ - /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */ - bucket_bounds_ss[0][0] = bucket_bounds->xmax; - bucket_bounds_ss[0][1] = bucket_bounds->ymin; - inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0); - - bucket_bounds_ss[1][0] = bucket_bounds->xmax; - bucket_bounds_ss[1][1] = bucket_bounds->ymax; - inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0); - - bucket_bounds_ss[2][0] = bucket_bounds->xmin; - bucket_bounds_ss[2][1] = bucket_bounds->ymax; - inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0); - - bucket_bounds_ss[3][0] = bucket_bounds->xmin; - bucket_bounds_ss[3][1] = bucket_bounds->ymin; - inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0); - - if (inside_face_flag == ISECT_ALL4) { - /* bucket is totally inside the screenspace face, we can safely use weights */ - - if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip); - else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip); - - *tot = 4; - return; - } - else { - /* The Complicated Case! - * - * The 2 cases above are where the face is inside the bucket or the bucket is inside the face. - * - * we need to make a convex polyline from the intersection between the screenspace face - * and the bucket bounds. - * - * There are a number of ways this could be done, currently it just collects all intersecting verts, - * and line intersections, then sorts them clockwise, this is a lot easier then evaluating the geometry to - * do a correct clipping on both shapes. */ - - - /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */ - - - - /* Maximum possible 6 intersections when using a rectangle and triangle */ - float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */ - float v1_clipSS[2], v2_clipSS[2]; - float w[3]; - - /* calc center */ - float cent[2] = {0.0f, 0.0f}; - /*float up[2] = {0.0f, 1.0f};*/ - int i; - short doubles; - - (*tot) = 0; - - if (inside_face_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; } - if (inside_face_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; } - if (inside_face_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; } - if (inside_face_flag & ISECT_4) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; } - - if (inside_bucket_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], v1coSS); (*tot)++; } - if (inside_bucket_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], v2coSS); (*tot)++; } - if (inside_bucket_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], v3coSS); (*tot)++; } - - if ((inside_bucket_flag & (ISECT_1 | ISECT_2)) != (ISECT_1 | ISECT_2)) { - if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) { - if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } - if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } - } - } - - if ((inside_bucket_flag & (ISECT_2 | ISECT_3)) != (ISECT_2 | ISECT_3)) { - if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) { - if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } - if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } - } - } - - if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) { - if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) { - if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } - if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } - } - } - - - if ((*tot) < 3) { /* no intersections to speak of */ - *tot = 0; - return; - } - - /* now we have all points we need, collect their angles and sort them clockwise */ - - for (i = 0; i < (*tot); i++) { - cent[0] += isectVCosSS[i][0]; - cent[1] += isectVCosSS[i][1]; - } - cent[0] = cent[0] / (float)(*tot); - cent[1] = cent[1] / (float)(*tot); - - - - /* Collect angles for every point around the center point */ - - -#if 0 /* uses a few more cycles then the above loop */ - for (i = 0; i < (*tot); i++) { - isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]); - } -#endif - - v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */ - v1_clipSS[1] = cent[1] + 1.0f; - - for (i = 0; i < (*tot); i++) { - v2_clipSS[0] = isectVCosSS[i][0] - cent[0]; - v2_clipSS[1] = isectVCosSS[i][1] - cent[1]; - isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0], v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]); - } - - if (flip) qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip); - else qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort); - - /* remove doubles */ - /* first/last check */ - if (fabsf(isectVCosSS[0][0] - isectVCosSS[(*tot) - 1][0]) < PROJ_GEOM_TOLERANCE && - fabsf(isectVCosSS[0][1] - isectVCosSS[(*tot) - 1][1]) < PROJ_GEOM_TOLERANCE) - { - (*tot)--; - } - - /* its possible there is only a few left after remove doubles */ - if ((*tot) < 3) { - // printf("removed too many doubles A\n"); - *tot = 0; - return; - } - - doubles = TRUE; - while (doubles == TRUE) { - doubles = FALSE; - for (i = 1; i < (*tot); i++) { - if (fabsf(isectVCosSS[i - 1][0] - isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE && - fabsf(isectVCosSS[i - 1][1] - isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE) - { - int j; - for (j = i + 1; j < (*tot); j++) { - isectVCosSS[j - 1][0] = isectVCosSS[j][0]; - isectVCosSS[j - 1][1] = isectVCosSS[j][1]; - } - doubles = TRUE; /* keep looking for more doubles */ - (*tot)--; - } - } - } - - /* its possible there is only a few left after remove doubles */ - if ((*tot) < 3) { - // printf("removed too many doubles B\n"); - *tot = 0; - return; - } - - - if (is_ortho) { - for (i = 0; i < (*tot); i++) { - barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w); - interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); - } - } - else { - for (i = 0; i < (*tot); i++) { - barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w); - interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); - } - } - } - -#ifdef PROJ_DEBUG_PRINT_CLIP - /* include this at the bottom of the above function to debug the output */ - - { - /* If there are ever any problems, */ - float test_uv[4][2]; - int i; - if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip); - else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip); - printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1], test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]); - - printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]); - - printf("["); - for (i = 0; i < (*tot); i++) { - printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]); - } - printf("]),\\\n"); - } -#endif -} - -/* - * # This script creates faces in a blender scene from printed data above. - * - * project_ls = [ - * ...(output from above block)... - * ] - * - * from Blender import Scene, Mesh, Window, sys, Mathutils - * - * import bpy - * - * V = Mathutils.Vector - * - * def main(): - * sce = bpy.data.scenes.active - * - * for item in project_ls: - * bb = item[0] - * uv = item[1] - * poly = item[2] - * - * me = bpy.data.meshes.new() - * ob = sce.objects.new(me) - * - * me.verts.extend([V(bb[0]).xyz, V(bb[1]).xyz, V(bb[2]).xyz, V(bb[3]).xyz]) - * me.faces.extend([(0,1,2,3),]) - * me.verts.extend([V(uv[0]).xyz, V(uv[1]).xyz, V(uv[2]).xyz]) - * me.faces.extend([(4,5,6),]) - * - * vs = [V(p).xyz for p in poly] - * print len(vs) - * l = len(me.verts) - * me.verts.extend(vs) - * - * i = l - * while i < len(me.verts): - * ii = i + 1 - * if ii == len(me.verts): - * ii = l - * me.edges.extend([i, ii]) - * i += 1 - * - * if __name__ == '__main__': - * main() - */ - - -#undef ISECT_1 -#undef ISECT_2 -#undef ISECT_3 -#undef ISECT_4 -#undef ISECT_ALL3 -#undef ISECT_ALL4 - - -/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise - * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */ -static int IsectPoly2Df(const float pt[2], float uv[][2], const int tot) -{ - int i; - if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f) - return 0; - - for (i = 1; i < tot; i++) { - if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f) - return 0; - - } - - return 1; -} -static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) -{ - int i; - int side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f); - - for (i = 1; i < tot; i++) { - if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side) - return 0; - - } - - return 1; -} - -/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket. - * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */ -static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v) -{ - /* Projection vars, to get the 3D locations into screen space */ - MemArena *arena = ps->arena_mt[thread_index]; - LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index; - LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index]; - - const MFace *mf = ps->dm_mface + face_index; - const MTFace *tf = ps->dm_mtface + face_index; - - /* UV/pixel seeking data */ - int x; /* Image X-Pixel */ - int y; /* Image Y-Pixel */ - float mask; - float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */ - - int side; - float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ - - float *vCo[4]; /* vertex screenspace coords */ - - float w[3], wco[3]; - - float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */ - float pixelScreenCo[4]; - bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; - - rcti bounds_px; /* ispace bounds */ - /* vars for getting uvspace bounds */ - - float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */ - float xhalfpx, yhalfpx; - const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y; - - int has_x_isect = 0, has_isect = 0; /* for early loop exit */ - - int i1, i2, i3; - - float uv_clip[8][2]; - int uv_clip_tot; - const short is_ortho = ps->is_ortho; - const short do_backfacecull = ps->do_backfacecull; - const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; - - vCo[0] = ps->dm_mvert[mf->v1].co; - vCo[1] = ps->dm_mvert[mf->v2].co; - vCo[2] = ps->dm_mvert[mf->v3].co; - - - /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel - * this is done so we can avoid offsetting all the pixels by 0.5 which causes - * problems when wrapping negative coords */ - xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 3.0f)) / ibuf_xf; - yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 4.0f)) / ibuf_yf; - - /* Note about (PROJ_GEOM_TOLERANCE/x) above... - * Needed to add this offset since UV coords are often quads aligned to pixels. - * In this case pixels can be exactly between 2 triangles causing nasty - * artifacts. - * - * This workaround can be removed and painting will still work on most cases - * but since the first thing most people try is painting onto a quad- better make it work. - */ - - - - tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx; - tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx; - - tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx; - tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx; - - tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx; - tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx; - - if (mf->v4) { - vCo[3] = ps->dm_mvert[mf->v4].co; - - tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx; - tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx; - side = 1; - } - else { - side = 0; - } - - do { - if (side == 1) { - i1 = 0; i2 = 2; i3 = 3; - } - else { - i1 = 0; i2 = 1; i3 = 2; - } - - uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1]; - uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2]; - uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3]; - - v1coSS = ps->screenCoords[(*(&mf->v1 + i1))]; - v2coSS = ps->screenCoords[(*(&mf->v1 + i2))]; - v3coSS = ps->screenCoords[(*(&mf->v1 + i3))]; - - /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ - project_bucket_clip_face( - is_ortho, bucket_bounds, - v1coSS, v2coSS, v3coSS, - uv1co, uv2co, uv3co, - uv_clip, &uv_clip_tot - ); - - /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */ -#if 0 - if (uv_clip_tot > 6) { - printf("this should never happen! %d\n", uv_clip_tot); - } -#endif - - if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) { - - if (clamp_u) { - CLAMP(bounds_px.xmin, 0, ibuf->x); - CLAMP(bounds_px.xmax, 0, ibuf->x); - } - - if (clamp_v) { - CLAMP(bounds_px.ymin, 0, ibuf->y); - CLAMP(bounds_px.ymax, 0, ibuf->y); - } - - /* clip face and */ - - has_isect = 0; - for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { - //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; - uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */ - - has_x_isect = 0; - for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { - //uv[0] = (((float)x) + 0.5f) / ibuf->x; - uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */ - - /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work, - * could check the poly direction but better to do this */ - if ((do_backfacecull == TRUE && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) || - (do_backfacecull == FALSE && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) - { - - has_x_isect = has_isect = 1; - - if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); - else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); - - /* a pity we need to get the worldspace pixel location here */ - if (do_clip || do_3d_mapping) { - interp_v3_v3v3v3(wco, ps->dm_mvert[(*(&mf->v1 + i1))].co, ps->dm_mvert[(*(&mf->v1 + i2))].co, ps->dm_mvert[(*(&mf->v1 + i3))].co, w); - if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { - continue; /* Watch out that no code below this needs to run */ - } - } - - /* Is this UV visible from the view? - raytrace */ - /* project_paint_PickFace is less complex, use for testing */ - //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) { - if ((ps->do_occlude == FALSE) || - !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) - { - mask = project_paint_uvpixel_mask(ps, face_index, side, w); - - if (mask > 0.0f) { - BLI_linklist_prepend_arena( - bucketPixelNodes, - project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, - image_index, pixelScreenCo, wco, side, w), - arena - ); - } - } - - } -//#if 0 - else if (has_x_isect) { - /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ - break; - } -//#endif - } - - -#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */ - /* no intersection for this entire row, after some intersection above means we can quit now */ - if (has_x_isect == 0 && has_isect) { - break; - } -#endif - } - } - } while (side--); - - - -#ifndef PROJ_DEBUG_NOSEAMBLEED - if (ps->seam_bleed_px > 0.0f) { - int face_seam_flag; - - if (ps->thread_tot > 1) - BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ - - face_seam_flag = ps->faceSeamFlags[face_index]; - - /* are any of our edges un-initialized? */ - if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_NOSEAM1)) == 0 || - (face_seam_flag & (PROJ_FACE_SEAM2 | PROJ_FACE_NOSEAM2)) == 0 || - (face_seam_flag & (PROJ_FACE_SEAM3 | PROJ_FACE_NOSEAM3)) == 0 || - (face_seam_flag & (PROJ_FACE_SEAM4 | PROJ_FACE_NOSEAM4)) == 0) - { - project_face_seams_init(ps, face_index, mf->v4); - face_seam_flag = ps->faceSeamFlags[face_index]; - //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4); - } - - if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) { - - if (ps->thread_tot > 1) - BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ - - } - else { - /* we have a seam - deal with it! */ - - /* Now create new UV's for the seam face */ - float (*outset_uv)[2] = ps->faceSeamUVs[face_index]; - float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */ - - float *vCoSS[4]; /* vertex screenspace coords */ - - float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */ - float edge_verts_inset_clip[2][3]; - int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */ - - float seam_subsection[4][2]; - float fac1, fac2, ftot; - - - if (outset_uv[0][0] == FLT_MAX) /* first time initialize */ - uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4); - - /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */ - if (ps->thread_tot > 1) - BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ - - vCoSS[0] = ps->screenCoords[mf->v1]; - vCoSS[1] = ps->screenCoords[mf->v2]; - vCoSS[2] = ps->screenCoords[mf->v3]; - if (mf->v4) - vCoSS[3] = ps->screenCoords[mf->v4]; - - /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */ - if (is_ortho) { - if (mf->v4) scale_quad(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM); - else scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM); - } - else { - if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM); - else scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM); - } - - side = 0; /* for triangles this wont need to change */ - - for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) { - if (mf->v4) fidx2 = (fidx1 == 3) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) */ - else fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2) -> (1,2,0) */ - - if ((face_seam_flag & (1 << fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */ - line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])) - { - - ftot = len_v2v2(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */ - - if (ftot > 0.0f) { /* avoid div by zero */ - if (mf->v4) { - if (fidx1 == 2 || fidx2 == 2) side = 1; - else side = 0; - } - - fac1 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[0]) / ftot; - fac2 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[1]) / ftot; - - interp_v2_v2v2(seam_subsection[0], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac1); - interp_v2_v2v2(seam_subsection[1], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac2); - - interp_v2_v2v2(seam_subsection[2], outset_uv[fidx1], outset_uv[fidx2], fac2); - interp_v2_v2v2(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1); - - /* if the bucket_clip_edges values Z values was kept we could avoid this - * Inset needs to be added so occlusion tests wont hit adjacent faces */ - interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1); - interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2); - - - if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, 1)) { - /* bounds between the seam rect and the uvspace bucket pixels */ - - has_isect = 0; - for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { - // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; - uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */ - - has_x_isect = 0; - for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { - //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x; - uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */ - - /* test we're inside uvspace bucket and triangle bounds */ - if (isect_point_quad_v2(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) { - float fac; - - /* We need to find the closest point along the face edge, - * getting the screen_px_from_*** wont work because our actual location - * is not relevant, since we are outside the face, Use VecLerpf to find - * our location on the side of the face's UV */ -#if 0 - if (is_ortho) screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo); - else screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo); -#endif - - /* Since this is a seam we need to work out where on the line this pixel is */ - //fac = line_point_factor_v2(uv, uv_seam_quad[0], uv_seam_quad[1]); - - fac = line_point_factor_v2(uv, seam_subsection[0], seam_subsection[1]); - if (fac < 0.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[0]); } - else if (fac > 1.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[1]); } - else { interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); } - - if (!is_ortho) { - pixelScreenCo[3] = 1.0f; - mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */ - pixelScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * pixelScreenCo[0] / pixelScreenCo[3]; - pixelScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * pixelScreenCo[1] / pixelScreenCo[3]; - pixelScreenCo[2] = pixelScreenCo[2] / pixelScreenCo[3]; /* Use the depth for bucket point occlusion */ - } - - if ((ps->do_occlude == FALSE) || - !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) - { - /* Only bother calculating the weights if we intersect */ - if (ps->do_mask_normal || ps->dm_mtface_clone) { -#if 1 - /* get the UV on the line since we want to copy the pixels from there for bleeding */ - float uv_close[2]; - float uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); - if (uv_fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]); - else if (uv_fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]); - - if (side) { - barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv_close, w); - } - else { - barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], uv_close, w); - } -#else /* this is buggy with quads, don't use for now */ - - /* Cheat, we know where we are along the edge so work out the weights from that */ - uv_fac = fac1 + (uv_fac * (fac2 - fac1)); - - w[0] = w[1] = w[2] = 0.0; - if (side) { - w[fidx1 ? fidx1 - 1 : 0] = 1.0f - uv_fac; - w[fidx2 ? fidx2 - 1 : 0] = uv_fac; - } - else { - w[fidx1] = 1.0f - uv_fac; - w[fidx2] = uv_fac; - } -#endif - } - - /* a pity we need to get the worldspace pixel location here */ - if (do_clip || do_3d_mapping) { - if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); - else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); - - if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { - continue; /* Watch out that no code below this needs to run */ - } - } - - mask = project_paint_uvpixel_mask(ps, face_index, side, w); - - if (mask > 0.0f) { - BLI_linklist_prepend_arena( - bucketPixelNodes, - project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w), - arena - ); - } - - } - } - else if (has_x_isect) { - /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ - break; - } - } - -#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */ - /* no intersection for this entire row, after some intersection above means we can quit now */ - if (has_x_isect == 0 && has_isect) { - break; - } -#endif - } - } - } - } - } - } - } -#endif // PROJ_DEBUG_NOSEAMBLEED -} - - -/* takes floating point screenspace min/max and returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */ -static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2]) -{ - /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */ - /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f is always truncated to 1, is this really correct?? - jwilkins */ - bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f); /* these offsets of 0.5 and 1.5 seem odd but they are correct */ - bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f); - - bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f); - bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f); - - /* in case the rect is outside the mesh 2d bounds */ - CLAMP(bucketMin[0], 0, ps->buckets_x); - CLAMP(bucketMin[1], 0, ps->buckets_y); - - CLAMP(bucketMax[0], 0, ps->buckets_x); - CLAMP(bucketMax[1], 0, ps->buckets_y); -} - -/* set bucket_bounds to a screen space-aligned floating point bound-box */ -static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds) -{ - bucket_bounds->xmin = ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)); /* left */ - bucket_bounds->xmax = ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)); /* right */ - - bucket_bounds->ymin = ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)); /* bottom */ - bucket_bounds->ymax = ps->screenMin[1] + ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)); /* top */ -} - -/* Fill this bucket with pixels from the faces that intersect it. - * - * have bucket_bounds as an argument so we don't need to give bucket_x/y the rect function needs */ -static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds) -{ - LinkNode *node; - int face_index, image_index = 0; - ImBuf *ibuf = NULL; - Image *tpage_last = NULL, *tpage; - Image *ima = NULL; - - if (ps->image_tot == 1) { - /* Simple loop, no context switching */ - ibuf = ps->projImages[0].ibuf; - ima = ps->projImages[0].ima; - - for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { - project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); - } - } - else { - - /* More complicated loop, switch between images */ - for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { - face_index = GET_INT_FROM_POINTER(node->link); - - /* Image context switching */ - tpage = project_paint_face_image(ps, ps->dm_mtface, face_index); - if (tpage_last != tpage) { - tpage_last = tpage; - - for (image_index = 0; image_index < ps->image_tot; image_index++) { - if (ps->projImages[image_index].ima == tpage_last) { - ibuf = ps->projImages[image_index].ibuf; - ima = ps->projImages[image_index].ima; - break; - } - } - } - /* context switching done */ - - project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); - } - } - - ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT; -} - - -/* We want to know if a bucket and a face overlap in screen-space - * - * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels - * calculated when it might not be needed later, (at the moment at least) - * obviously it shouldn't have bugs though */ - -static int project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf) -{ - /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */ - rctf bucket_bounds; - float p1[2], p2[2], p3[2], p4[2]; - float *v, *v1, *v2, *v3, *v4 = NULL; - int fidx; - - project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds); - - /* Is one of the faces verts in the bucket bounds? */ - - fidx = mf->v4 ? 3 : 2; - do { - v = ps->screenCoords[(*(&mf->v1 + fidx))]; - if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) { - return 1; - } - } while (fidx--); - - v1 = ps->screenCoords[mf->v1]; - v2 = ps->screenCoords[mf->v2]; - v3 = ps->screenCoords[mf->v3]; - if (mf->v4) { - v4 = ps->screenCoords[mf->v4]; - } - - p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin; - p2[0] = bucket_bounds.xmin; p2[1] = bucket_bounds.ymax; - p3[0] = bucket_bounds.xmax; p3[1] = bucket_bounds.ymax; - p4[0] = bucket_bounds.xmax; p4[1] = bucket_bounds.ymin; - - if (mf->v4) { - if (isect_point_quad_v2(p1, v1, v2, v3, v4) || - isect_point_quad_v2(p2, v1, v2, v3, v4) || - isect_point_quad_v2(p3, v1, v2, v3, v4) || - isect_point_quad_v2(p4, v1, v2, v3, v4) || - - /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */ - (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3) || isect_line_line_v2(p1, p2, v3, v4)) || - (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3) || isect_line_line_v2(p2, p3, v3, v4)) || - (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3) || isect_line_line_v2(p3, p4, v3, v4)) || - (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3) || isect_line_line_v2(p4, p1, v3, v4))) - { - return 1; - } - } - else { - if (isect_point_tri_v2(p1, v1, v2, v3) || - isect_point_tri_v2(p2, v1, v2, v3) || - isect_point_tri_v2(p3, v1, v2, v3) || - isect_point_tri_v2(p4, v1, v2, v3) || - /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */ - (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3)) || - (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3)) || - (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3)) || - (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3))) - { - return 1; - } - } - - return 0; -} - -/* Add faces to the bucket but don't initialize its pixels - * TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */ -static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const int face_index) -{ - float min[2], max[2], *vCoSS; - int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */ - int fidx, bucket_x, bucket_y; - int has_x_isect = -1, has_isect = 0; /* for early loop exit */ - MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */ - - INIT_MINMAX2(min, max); - - fidx = mf->v4 ? 3 : 2; - do { - vCoSS = ps->screenCoords[*(&mf->v1 + fidx)]; - minmax_v2v2_v2(min, max, vCoSS); - } while (fidx--); - - project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax); - - for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) { - has_x_isect = 0; - for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) { - if (project_bucket_face_isect(ps, bucket_x, bucket_y, mf)) { - int bucket_index = bucket_x + (bucket_y * ps->buckets_x); - BLI_linklist_prepend_arena( - &ps->bucketFaces[bucket_index], - SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */ - arena - ); - - has_x_isect = has_isect = 1; - } - else if (has_x_isect) { - /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ - break; - } - } - - /* no intersection for this entire row, after some intersection above means we can quit now */ - if (has_x_isect == 0 && has_isect) { - break; - } - } - -#ifndef PROJ_DEBUG_NOSEAMBLEED - if (ps->seam_bleed_px > 0.0f) { - if (!mf->v4) { - ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged edge */ - } - **ps->faceSeamUVs[face_index] = FLT_MAX; /* set as uninitialized */ - } -#endif -} - -static int project_paint_view_clip(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend) -{ - int orth = ED_view3d_clip_range_get(v3d, rv3d, clipsta, clipend); - - if (orth) { /* only needed for ortho */ - float fac = 2.0f / ((*clipend) - (*clipsta)); - *clipsta *= fac; - *clipend *= fac; - } - - return orth; -} - -/* run once per stroke before projection painting */ -static void project_paint_begin(ProjPaintState *ps) -{ - /* Viewport vars */ - float mat[3][3]; - - float no[3]; - - float *projScreenCo; /* Note, we could have 4D vectors are only needed for */ - float projMargin; - - /* Image Vars - keep track of images we have used */ - LinkNode *image_LinkList = NULL; - LinkNode *node; - - ProjPaintImage *projIma; - Image *tpage_last = NULL, *tpage; - - /* Face vars */ - MFace *mf; - MTFace *tf; - - int a, i; /* generic looping vars */ - int image_index = -1, face_index; - MVert *mv; - - MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */ - - const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush); - - /* ---- end defines ---- */ - - if (ps->source == PROJ_SRC_VIEW) - ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */ - - /* paint onto the derived mesh */ - - /* Workaround for subsurf selection, try the display mesh first */ - if (ps->source == PROJ_SRC_IMAGE_CAM) { - /* using render mesh, assume only camera was rendered from */ - ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); - ps->dm_release = TRUE; - } - else if (ps->ob->derivedFinal && CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE)) { - ps->dm = ps->ob->derivedFinal; - ps->dm_release = FALSE; - } - else { - ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); - ps->dm_release = TRUE; - } - - if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE) ) { - - if (ps->dm_release) - ps->dm->release(ps->dm); - - ps->dm = NULL; - return; - } - - ps->dm_mvert = ps->dm->getVertArray(ps->dm); - ps->dm_mface = ps->dm->getTessFaceArray(ps->dm); - ps->dm_mtface = ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE); - - ps->dm_totvert = ps->dm->getNumVerts(ps->dm); - ps->dm_totface = ps->dm->getNumTessFaces(ps->dm); - - /* use clone mtface? */ - - - /* Note, use the original mesh for getting the clone and mask layer index - * this avoids re-generating the derived mesh just to get the new index */ - if (ps->do_layer_clone) { - //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE); - int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); - if (layer_num != -1) - ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); - - if (ps->dm_mtface_clone == NULL || ps->dm_mtface_clone == ps->dm_mtface) { - ps->do_layer_clone = FALSE; - ps->dm_mtface_clone = NULL; - printf("ACK!\n"); - } - } - - if (ps->do_layer_stencil) { - //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE); - int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); - if (layer_num != -1) - ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); - - if (ps->dm_mtface_stencil == NULL || ps->dm_mtface_stencil == ps->dm_mtface) { - ps->do_layer_stencil = FALSE; - ps->dm_mtface_stencil = NULL; - } - } - - /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */ - if (ps->dm->type != DM_TYPE_CDDM) { - ps->dm_mvert = MEM_dupallocN(ps->dm_mvert); - ps->dm_mface = MEM_dupallocN(ps->dm_mface); - /* looks like these are ok for now.*/ -#if 0 - ps->dm_mtface = MEM_dupallocN(ps->dm_mtface); - ps->dm_mtface_clone = MEM_dupallocN(ps->dm_mtface_clone); - ps->dm_mtface_stencil = MEM_dupallocN(ps->dm_mtface_stencil); -#endif - } - - ps->viewDir[0] = 0.0f; - ps->viewDir[1] = 0.0f; - ps->viewDir[2] = 1.0f; - - { - float viewmat[4][4]; - float viewinv[4][4]; - - invert_m4_m4(ps->ob->imat, ps->ob->obmat); - - if (ps->source == PROJ_SRC_VIEW) { - /* normal drawing */ - ps->winx = ps->ar->winx; - ps->winy = ps->ar->winy; - - copy_m4_m4(viewmat, ps->rv3d->viewmat); - copy_m4_m4(viewinv, ps->rv3d->viewinv); - - ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat); - - ps->is_ortho = project_paint_view_clip(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend); - } - else { - /* re-projection */ - float winmat[4][4]; - float vmat[4][4]; - - ps->winx = ps->reproject_ibuf->x; - ps->winy = ps->reproject_ibuf->y; - - if (ps->source == PROJ_SRC_IMAGE_VIEW) { - /* image stores camera data, tricky */ - IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0); - IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID); - - float *array = (float *)IDP_Array(view_data); - - /* use image array, written when creating image */ - memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float); - memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float); - ps->clipsta = array[0]; - ps->clipend = array[1]; - ps->is_ortho = array[2] ? 1 : 0; - - invert_m4_m4(viewinv, viewmat); - } - else if (ps->source == PROJ_SRC_IMAGE_CAM) { - Object *cam_ob = ps->scene->camera; - CameraParams params; - - /* viewmat & viewinv */ - copy_m4_m4(viewinv, cam_ob->obmat); - normalize_m4(viewinv); - invert_m4_m4(viewmat, viewinv); - - /* window matrix, clipping and ortho */ - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, cam_ob); - BKE_camera_params_compute_viewplane(¶ms, ps->winx, ps->winy, 1.0f, 1.0f); - BKE_camera_params_compute_matrix(¶ms); - - copy_m4_m4(winmat, params.winmat); - ps->clipsta = params.clipsta; - ps->clipend = params.clipend; - ps->is_ortho = params.is_ortho; - } - - /* same as #ED_view3d_ob_project_mat_get */ - mult_m4_m4m4(vmat, viewmat, ps->ob->obmat); - mult_m4_m4m4(ps->projectMat, winmat, vmat); - } - - - /* viewDir - object relative */ - invert_m4_m4(ps->ob->imat, ps->ob->obmat); - copy_m3_m4(mat, viewinv); - mul_m3_v3(mat, ps->viewDir); - copy_m3_m4(mat, ps->ob->imat); - mul_m3_v3(mat, ps->viewDir); - normalize_v3(ps->viewDir); - - /* viewPos - object relative */ - copy_v3_v3(ps->viewPos, viewinv[3]); - copy_m3_m4(mat, ps->ob->imat); - mul_m3_v3(mat, ps->viewPos); - add_v3_v3(ps->viewPos, ps->ob->imat[3]); - } - - /* calculate vert screen coords - * run this early so we can calculate the x/y resolution of our bucket rect */ - INIT_MINMAX2(ps->screenMin, ps->screenMax); - - ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts"); - projScreenCo = *ps->screenCoords; - - if (ps->is_ortho) { - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) { - mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co); - - /* screen space, not clamped */ - projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0]; - projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1]; - minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); - } - } - else { - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) { - copy_v3_v3(projScreenCo, mv->co); - projScreenCo[3] = 1.0f; - - mul_m4_v4(ps->projectMat, projScreenCo); - - if (projScreenCo[3] > ps->clipsta) { - /* screen space, not clamped */ - projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3]; - projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3]; - projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */ - minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); - } - else { - /* TODO - deal with cases where 1 side of a face goes behind the view ? - * - * After some research this is actually very tricky, only option is to - * clip the derived mesh before painting, which is a Pain */ - projScreenCo[0] = FLT_MAX; - } - } - } - - /* If this border is not added we get artifacts for faces that - * have a parallel edge and at the bounds of the the 2D projected verts eg - * - a single screen aligned quad */ - projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f; - ps->screenMax[0] += projMargin; - ps->screenMin[0] -= projMargin; - projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f; - ps->screenMax[1] += projMargin; - ps->screenMin[1] -= projMargin; - - if (ps->source == PROJ_SRC_VIEW) { -#ifdef PROJ_DEBUG_WINCLIP - CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter)); - CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter)); - - CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter)); - CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter)); -#endif - } - else { /* re-projection, use bounds */ - ps->screenMin[0] = 0; - ps->screenMax[0] = (float)(ps->winx); - - ps->screenMin[1] = 0; - ps->screenMax[1] = (float)(ps->winy); - } - - /* only for convenience */ - ps->screen_width = ps->screenMax[0] - ps->screenMin[0]; - ps->screen_height = ps->screenMax[1] - ps->screenMin[1]; - - ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV)); - ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV)); - - /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */ - - /* really high values could cause problems since it has to allocate a few - * (ps->buckets_x*ps->buckets_y) sized arrays */ - CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); - CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); - - ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect"); - ps->bucketFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); - - ps->bucketFlags = (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); -#ifndef PROJ_DEBUG_NOSEAMBLEED - if (ps->seam_bleed_px > 0.0f) { - ps->vertFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces"); - ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags"); - ps->faceSeamUVs = MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs"); - } -#endif - - /* Thread stuff - * - * very small brushes run a lot slower multithreaded since the advantage with - * threads is being able to fill in multiple buckets at once. - * Only use threads for bigger brushes. */ - - if (ps->scene->r.mode & R_FIXED_THREADS) { - ps->thread_tot = ps->scene->r.threads; - } - else { - ps->thread_tot = BLI_system_thread_count(); - } - for (a = 0; a < ps->thread_tot; a++) { - ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena"); - } - - arena = ps->arena_mt[0]; - - if (ps->do_backfacecull && ps->do_mask_normal) { - float viewDirPersp[3]; - - ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags"); - - for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) { - normal_short_to_float_v3(no, mv->no); - - if (ps->is_ortho) { - if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ - ps->vertFlags[a] |= PROJ_VERT_CULL; - } - } - else { - sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co); - normalize_v3(viewDirPersp); - if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ - ps->vertFlags[a] |= PROJ_VERT_CULL; - } - } - } - } - - - for (face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) { - -#ifndef PROJ_DEBUG_NOSEAMBLEED - /* add face user if we have bleed enabled, set the UV seam flags later */ - /* annoying but we need to add all faces even ones we never use elsewhere */ - if (ps->seam_bleed_px > 0.0f) { - BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena); - BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena); - BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena); - if (mf->v4) { - BLI_linklist_prepend_arena(&ps->vertFaces[mf->v4], SET_INT_IN_POINTER(face_index), arena); - } - } -#endif - - tpage = project_paint_face_image(ps, ps->dm_mtface, face_index); - - if (tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) == 0 || mf->flag & ME_FACE_SEL)) { - - float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL; - - v1coSS = ps->screenCoords[mf->v1]; - v2coSS = ps->screenCoords[mf->v2]; - v3coSS = ps->screenCoords[mf->v3]; - if (mf->v4) { - v4coSS = ps->screenCoords[mf->v4]; - } - - - if (!ps->is_ortho) { - if (v1coSS[0] == FLT_MAX || - v2coSS[0] == FLT_MAX || - v3coSS[0] == FLT_MAX || - (mf->v4 && v4coSS[0] == FLT_MAX)) - { - continue; - } - } - -#ifdef PROJ_DEBUG_WINCLIP - /* ignore faces outside the view */ - if ( - (v1coSS[0] < ps->screenMin[0] && - v2coSS[0] < ps->screenMin[0] && - v3coSS[0] < ps->screenMin[0] && - (mf->v4 && v4coSS[0] < ps->screenMin[0])) || - - (v1coSS[0] > ps->screenMax[0] && - v2coSS[0] > ps->screenMax[0] && - v3coSS[0] > ps->screenMax[0] && - (mf->v4 && v4coSS[0] > ps->screenMax[0])) || - - (v1coSS[1] < ps->screenMin[1] && - v2coSS[1] < ps->screenMin[1] && - v3coSS[1] < ps->screenMin[1] && - (mf->v4 && v4coSS[1] < ps->screenMin[1])) || - - (v1coSS[1] > ps->screenMax[1] && - v2coSS[1] > ps->screenMax[1] && - v3coSS[1] > ps->screenMax[1] && - (mf->v4 && v4coSS[1] > ps->screenMax[1])) - ) - { - continue; - } - -#endif //PROJ_DEBUG_WINCLIP - - - if (ps->do_backfacecull) { - if (ps->do_mask_normal) { - /* Since we are interpolating the normals of faces, we want to make - * sure all the verts are pointing away from the view, - * not just the face */ - if ((ps->vertFlags[mf->v1] & PROJ_VERT_CULL) && - (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) && - (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) && - (mf->v4 == 0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL) - ) - { - continue; - } - } - else { - if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) { - continue; - } - - } - } - - if (tpage_last != tpage) { - - image_index = BLI_linklist_index(image_LinkList, tpage); - - if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ - BLI_linklist_append(&image_LinkList, tpage); - image_index = ps->image_tot; - ps->image_tot++; - } - - tpage_last = tpage; - } - - if (image_index != -1) { - /* Initialize the faces screen pixels */ - /* Add this to a list to initialize later */ - project_paint_delayed_face_init(ps, mf, face_index); - } - } - } - - /* build an array of images we use*/ - projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot); - - for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) { - projIma->ima = node->link; - projIma->touch = 0; - projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL); - projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); - memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); - } - - /* we have built the array, discard the linked list */ - BLI_linklist_free(image_LinkList, NULL); -} - -static void project_paint_begin_clone(ProjPaintState *ps, int mouse[2]) -{ - /* setup clone offset */ - if (ps->tool == PAINT_TOOL_CLONE) { - float projCo[4]; - copy_v3_v3(projCo, give_cursor(ps->scene, ps->v3d)); - mul_m4_v3(ps->ob->imat, projCo); - - projCo[3] = 1.0f; - mul_m4_v4(ps->projectMat, projCo); - ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projCo[0] / projCo[3]); - ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projCo[1] / projCo[3]); - } -} - -static void project_paint_end(ProjPaintState *ps) -{ - int a; - ProjPaintImage *projIma; - - /* build undo data from original pixel colors */ - if (U.uiflag & USER_GLOBALUNDO) { - ProjPixel *projPixel; - ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL; - LinkNode *pixel_node; - void *tilerect; - MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */ - - int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */ - int bucket_index; - int tile_index; - int x_round, y_round; - int x_tile, y_tile; - int is_float = -1; - - /* context */ - ProjPaintImage *last_projIma; - int last_image_index = -1; - int last_tile_width = 0; - - for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) { - int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y); - last_projIma->undoRect = (void **) BLI_memarena_alloc(arena, size); - memset(last_projIma->undoRect, 0, size); - last_projIma->ibuf->userflags |= IB_BITMAPDIRTY; - } - - for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) { - /* loop through all pixels */ - for (pixel_node = ps->bucketRect[bucket_index]; pixel_node; pixel_node = pixel_node->next) { - - /* ok we have a pixel, was it modified? */ - projPixel = (ProjPixel *)pixel_node->link; - - if (last_image_index != projPixel->image_index) { - /* set the context */ - last_image_index = projPixel->image_index; - last_projIma = ps->projImages + last_image_index; - last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x); - is_float = last_projIma->ibuf->rect_float ? 1 : 0; - } - - - if ((is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) || - (is_float == 1 && - (projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] || - projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] || - projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] || - projPixel->origColor.f[3] != projPixel->pixel.f_pt[3])) - ) - { - - x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS; - y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS; - - x_round = x_tile * IMAPAINT_TILE_SIZE; - y_round = y_tile * IMAPAINT_TILE_SIZE; - - tile_index = x_tile + y_tile * last_tile_width; - - if (last_projIma->undoRect[tile_index] == NULL) { - /* add the undo tile from the modified image, then write the original colors back into it */ - tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile); - } - else { - tilerect = last_projIma->undoRect[tile_index]; - } - - /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color - * because allocating the tiles along the way slows down painting */ - - if (is_float) { - float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4; - copy_v4_v4(rgba_fp, projPixel->origColor.f); - } - else { - ((unsigned int *)tilerect)[(projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE] = projPixel->origColor.uint; - } - } - } - } - - if (tmpibuf) IMB_freeImBuf(tmpibuf); - if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float); - } - /* done calculating undo data */ - - /* dereference used image buffers */ - for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { - BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); - } - - BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); - - MEM_freeN(ps->screenCoords); - MEM_freeN(ps->bucketRect); - MEM_freeN(ps->bucketFaces); - MEM_freeN(ps->bucketFlags); - -#ifndef PROJ_DEBUG_NOSEAMBLEED - if (ps->seam_bleed_px > 0.0f) { - MEM_freeN(ps->vertFaces); - MEM_freeN(ps->faceSeamFlags); - MEM_freeN(ps->faceSeamUVs); - } -#endif - - if (ps->vertFlags) MEM_freeN(ps->vertFlags); - - for (a = 0; a < ps->thread_tot; a++) { - BLI_memarena_free(ps->arena_mt[a]); - } - - /* copy for subsurf/multires, so throw away */ - if (ps->dm->type != DM_TYPE_CDDM) { - if (ps->dm_mvert) MEM_freeN(ps->dm_mvert); - if (ps->dm_mface) MEM_freeN(ps->dm_mface); - /* looks like these don't need copying */ -#if 0 - if (ps->dm_mtface) MEM_freeN(ps->dm_mtface); - if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone); - if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil); -#endif - } - - if (ps->dm_release) - ps->dm->release(ps->dm); -} - -/* 1 = an undo, -1 is a redo. */ -static void partial_redraw_array_init(ImagePaintPartialRedraw *pr) -{ - int tot = PROJ_BOUNDBOX_SQUARED; - while (tot--) { - pr->x1 = 10000000; - pr->y1 = 10000000; - - pr->x2 = -1; - pr->y2 = -1; - - pr->enabled = 1; - - pr++; - } -} - - -static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot) -{ - int touch = 0; - while (tot--) { - pr->x1 = min_ii(pr->x1, pr_other->x1); - pr->y1 = min_ii(pr->y1, pr_other->y1); - - pr->x2 = max_ii(pr->x2, pr_other->x2); - pr->y2 = max_ii(pr->y2, pr_other->y2); - - if (pr->x2 != -1) - touch = 1; - - pr++; pr_other++; - } - - return touch; -} - -/* Loop over all images on this mesh and update any we have touched */ -static int project_image_refresh_tagged(ProjPaintState *ps) -{ - ImagePaintPartialRedraw *pr; - ProjPaintImage *projIma; - int a, i; - int redraw = 0; - - - for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { - if (projIma->touch) { - /* look over each bound cell */ - for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) { - pr = &(projIma->partRedrawRect[i]); - if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ - imapaintpartial = *pr; - imapaint_image_update(NULL, projIma->ima, projIma->ibuf, 1); /*last 1 is for texpaint*/ - redraw = 1; - } - } - - projIma->touch = 0; /* clear for reuse */ - } - } - - return redraw; -} - -/* run this per painting onto each mouse location */ -static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2]) -{ - if (ps->source == PROJ_SRC_VIEW) { - float min_brush[2], max_brush[2]; - const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush); - - /* so we don't have a bucket bounds that is way too small to paint into */ - // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/ - - min_brush[0] = mval_f[0] - radius; - min_brush[1] = mval_f[1] - radius; - - max_brush[0] = mval_f[0] + radius; - max_brush[1] = mval_f[1] + radius; - - /* offset to make this a valid bucket index */ - project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax); - - /* mouse outside the model areas? */ - if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) { - return 0; - } - - ps->context_bucket_x = ps->bucketMin[0]; - ps->context_bucket_y = ps->bucketMin[1]; - } - else { /* reproject: PROJ_SRC_* */ - ps->bucketMin[0] = 0; - ps->bucketMin[1] = 0; - - ps->bucketMax[0] = ps->buckets_x; - ps->bucketMax[1] = ps->buckets_y; - - ps->context_bucket_x = 0; - ps->context_bucket_y = 0; - } - return 1; -} - - -static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2]) -{ - const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush); - - if (ps->thread_tot > 1) - BLI_lock_thread(LOCK_CUSTOM1); - - //printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y); - - for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) { - for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) { - - /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/ - project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds); - - if ((ps->source != PROJ_SRC_VIEW) || - project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds)) - { - *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x); - ps->context_bucket_x++; - - if (ps->thread_tot > 1) - BLI_unlock_thread(LOCK_CUSTOM1); - - return 1; - } - } - ps->context_bucket_x = ps->bucketMin[0]; - } - - if (ps->thread_tot > 1) - BLI_unlock_thread(LOCK_CUSTOM1); - return 0; -} - -/* Each thread gets one of these, also used as an argument to pass to project_paint_op */ -typedef struct ProjectHandle { - /* args */ - ProjPaintState *ps; - float prevmval[2]; - float mval[2]; - - /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */ - ProjPaintImage *projImages; /* array of partial redraws */ - - /* thread settings */ - int thread_index; - - struct ImagePool *pool; -} ProjectHandle; - -static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) -{ - /* this and other blending modes previously used >>8 instead of /255. both - * are not equivalent (>>8 is /256), and the former results in rounding - * errors that can turn colors black fast after repeated blending */ - const int mfac = 255 - fac; - - cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255; - cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255; - cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255; - cp[3] = (mfac * cp1[3] + fac * cp2[3]) / 255; -} - -static void blend_color_mix_float(float cp[4], const float cp1[4], const float cp2[4], const float fac) -{ - const float mfac = 1.0f - fac; - cp[0] = mfac * cp1[0] + fac * cp2[0]; - cp[1] = mfac * cp1[1] + fac * cp2[1]; - cp[2] = mfac * cp1[2] + fac * cp2[2]; - cp[3] = mfac * cp1[3] + fac * cp2[3]; -} - -static void blend_color_mix_accum(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) -{ - /* this and other blending modes previously used >>8 instead of /255. both - * are not equivalent (>>8 is /256), and the former results in rounding - * errors that can turn colors black fast after repeated blending */ - const int mfac = 255 - fac; - const int alpha = cp1[3] + ((fac * cp2[3]) / 255); - - cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255; - cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255; - cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255; - cp[3] = alpha > 255 ? 255 : alpha; -} -static void blend_color_mix_accum_float(float cp[4], const float cp1[4], const unsigned char cp2[4], const float fac) -{ - const float mfac = 1.0f - fac; - const float alpha = cp1[3] + (fac * (cp2[3] / 255.0f)); - - cp[0] = (mfac * cp1[0] + (fac * (cp2[0] / 255.0f))); - cp[1] = (mfac * cp1[1] + (fac * (cp2[1] / 255.0f))); - cp[2] = (mfac * cp1[2] + (fac * (cp2[2] / 255.0f))); - cp[3] = alpha > 1.0f ? 1.0f : alpha; -} - - -static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) -{ - if (ps->do_masking && mask < 1.0f) { - projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * 255), ps->blend); - blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); - } - else { - *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * mask * 255), ps->blend); - } -} - -static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) -{ - if (ps->do_masking && mask < 1.0f) { - IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend); - blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); - } - else { - IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha * mask, ps->blend); - } -} - -/* do_projectpaint_smear* - * - * note, mask is used to modify the alpha here, this is not correct since it allows - * accumulation of color greater then 'projPixel->mask' however in the case of smear its not - * really that important to be correct as it is with clone and painting - */ -static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels, float co[2]) -{ - unsigned char rgba_ub[4]; - - if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0) - return; - /* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */ - blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * mask * 255)); - BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena); -} - -static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *smearArena, LinkNode **smearPixels_f, float co[2]) -{ - float rgba[4]; - - if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0) - return; - - /* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */ - blend_color_mix_float(((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, alpha * mask); - BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena); -} - -/* do_projectpaint_soften for float & byte - */ -static float inv_pow2(float f) -{ - f = 1.0f - f; - f = f * f; - return 1.0f - f; -} - -static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels) -{ - unsigned int accum_tot = 0; - unsigned int i; - - float *rgba = projPixel->newColor.f; - - /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ - mask = inv_pow2(mask); - alpha = inv_pow2(alpha); - - /* rather then painting, accumulate surrounding colors */ - zero_v4(rgba); - - for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { - float co_ofs[2]; - float rgba_tmp[4]; - sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); - if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { - add_v4_v4(rgba, rgba_tmp); - accum_tot++; - } - } - - if (LIKELY(accum_tot != 0)) { - mul_v4_fl(rgba, 1.0f / (float)accum_tot); - blend_color_mix_float(rgba, projPixel->pixel.f_pt, rgba, alpha); - if (mask < 1.0f) blend_color_mix_float(rgba, projPixel->origColor.f, rgba, mask); - BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); - } -} - -static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, MemArena *softenArena, LinkNode **softenPixels) -{ - unsigned int accum_tot = 0; - unsigned int i; - - float rgba[4]; /* convert to byte after */ - - /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ - mask = inv_pow2(mask); - alpha = inv_pow2(alpha); - - /* rather then painting, accumulate surrounding colors */ - zero_v4(rgba); - - for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { - float co_ofs[2]; - float rgba_tmp[4]; - sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); - if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { - add_v4_v4(rgba, rgba_tmp); - accum_tot++; - } - } - - if (LIKELY(accum_tot != 0)) { - unsigned char *rgba_ub = projPixel->newColor.ch; - - mul_v4_fl(rgba, 1.0f / (float)accum_tot); - IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_ub, rgba); - - blend_color_mix(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * 255)); - if (mask != 1.0f) blend_color_mix(rgba_ub, projPixel->origColor.ch, rgba_ub, (int)(mask * 255)); - BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); - } -} - -BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3]) -{ - rgba_ub[0] = f_to_char(rgba[0] * rgb[0]); - rgba_ub[1] = f_to_char(rgba[1] * rgb[1]); - rgba_ub[2] = f_to_char(rgba[2] * rgb[2]); - rgba_ub[3] = f_to_char(rgba[3]); -} - -static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask) -{ - unsigned char rgba_ub[4]; - - if (ps->is_texbrush) { - rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb); - } - else { - IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb); - rgba_ub[3] = 255; - } - - if (ps->do_masking && mask < 1.0f) { - projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha * 255), ps->blend); - blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); - } - else { - *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha * mask * 255), ps->blend); - } -} - -static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float rgba[4], float alpha, float mask, int use_color_correction) -{ - if (ps->is_texbrush) { - /* rgba already holds a texture result here from higher level function */ - if (use_color_correction) { - float rgba_br[3]; - 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 { - if (use_color_correction) { - srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb); - } - else { - copy_v3_v3(rgba, ps->brush->rgb); - } - rgba[3] = 1.0; - } - - if (ps->do_masking && mask < 1.0f) { - IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend); - blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); - } - else { - IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha * mask, ps->blend); - } -} - - - -/* run this for single and multithreaded painting */ -static void *do_projectpaint_thread(void *ph_v) -{ - /* First unpack args from the struct */ - ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps; - ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages; - const float *lastpos = ((ProjectHandle *)ph_v)->prevmval; - const float *pos = ((ProjectHandle *)ph_v)->mval; - const int thread_index = ((ProjectHandle *)ph_v)->thread_index; - struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool; - /* Done with args from ProjectHandle */ - - LinkNode *node; - ProjPixel *projPixel; - Brush *brush = ps->brush; - - int last_index = -1; - ProjPaintImage *last_projIma = NULL; - ImagePaintPartialRedraw *last_partial_redraw_cell; - - float rgba[4], alpha, dist_nosqrt, dist; - - float falloff; - int bucket_index; - int is_floatbuf = 0; - int use_color_correction = FALSE; - const short tool = ps->tool; - rctf bucket_bounds; - - /* for smear only */ - float pos_ofs[2] = {0}; - float co[2]; - float mask = 1.0f; /* airbrush wont use mask */ - unsigned short mask_short; - const float radius = (float)BKE_brush_size_get(ps->scene, brush); - const float radius_squared = radius * radius; /* avoid a square root with every dist comparison */ - - short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA; - - LinkNode *smearPixels = NULL; - LinkNode *smearPixels_f = NULL; - MemArena *smearArena = NULL; /* mem arena for this brush projection only */ - - LinkNode *softenPixels = NULL; - LinkNode *softenPixels_f = NULL; - MemArena *softenArena = NULL; /* mem arena for this brush projection only */ - - if (tool == PAINT_TOOL_SMEAR) { - pos_ofs[0] = pos[0] - lastpos[0]; - pos_ofs[1] = pos[1] - lastpos[1]; - - smearArena = BLI_memarena_new(1 << 16, "paint smear arena"); - } - else if (tool == PAINT_TOOL_SOFTEN) { - softenArena = BLI_memarena_new(1 << 16, "paint soften arena"); - } - - /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */ - - while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) { - - /* Check this bucket and its faces are initialized */ - if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) { - /* No pixels initialized */ - project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds); - } - - if (ps->source != PROJ_SRC_VIEW) { - - /* Re-Projection, simple, no brushes! */ - - for (node = ps->bucketRect[bucket_index]; node; node = node->next) { - projPixel = (ProjPixel *)node->link; - - /* copy of code below */ - if (last_index != projPixel->image_index) { - last_index = projPixel->image_index; - last_projIma = projImages + last_index; - - last_projIma->touch = 1; - is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; - use_color_correction = TRUE; - } - /* end copy */ - - if (is_floatbuf) { - /* re-project buffer is assumed byte - TODO, allow float */ - bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, - projPixel->projCoSS[0], projPixel->projCoSS[1]); - if (projPixel->newColor.ch[3]) { - mask = ((float)projPixel->mask) / 65535.0f; - blend_color_mix_accum_float(projPixel->pixel.f_pt, projPixel->origColor.f, - projPixel->newColor.ch, (mask * (projPixel->newColor.ch[3] / 255.0f))); - } - } - else { - /* re-project buffer is assumed byte - TODO, allow float */ - bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, - projPixel->projCoSS[0], projPixel->projCoSS[1]); - if (projPixel->newColor.ch[3]) { - mask = ((float)projPixel->mask) / 65535.0f; - blend_color_mix_accum(projPixel->pixel.ch_pt, projPixel->origColor.ch, - projPixel->newColor.ch, (int)(mask * projPixel->newColor.ch[3])); - } - } - } - } - else { - /* Normal brush painting */ - - for (node = ps->bucketRect[bucket_index]; node; node = node->next) { - - projPixel = (ProjPixel *)node->link; - - dist_nosqrt = len_squared_v2v2(projPixel->projCoSS, pos); - - /*if (dist < radius) {*/ /* correct but uses a sqrtf */ - if (dist_nosqrt <= radius_squared) { - float samplecos[3]; - dist = sqrtf(dist_nosqrt); - - falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius); - - if (ps->is_texbrush) { - MTex *mtex = &brush->mtex; - if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { - sub_v2_v2v2(samplecos, projPixel->projCoSS, pos); - } - /* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */ - else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) - copy_v3_v3(samplecos, projPixel->worldCoSS); - else - copy_v3_v3(samplecos, projPixel->projCoSS); - } - - if (falloff > 0.0f) { - if (ps->is_texbrush) { - /* note, for clone and smear, we only use the alpha, could be a special function */ - BKE_brush_sample_tex(ps->scene, brush, samplecos, rgba, thread_index, pool); - alpha = rgba[3]; - } - else { - alpha = 1.0f; - } - - if (!ps->do_masking) { - /* for an aurbrush there is no real mask, so just multiply the alpha by it */ - alpha *= falloff * BKE_brush_alpha_get(ps->scene, brush); - mask = ((float)projPixel->mask) / 65535.0f; - } - else { - /* This brush dosnt accumulate so add some curve to the brushes falloff */ - falloff = 1.0f - falloff; - falloff = 1.0f - (falloff * falloff); - - mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff)); - if (mask_short > projPixel->mask_max) { - mask = ((float)mask_short) / 65535.0f; - projPixel->mask_max = mask_short; - } - else { - /*mask = ((float)projPixel->mask_max)/65535.0f;*/ - - /* Go onto the next pixel */ - continue; - } - } - - if (alpha > 0.0f) { - - /* copy of code above */ - if (last_index != projPixel->image_index) { - last_index = projPixel->image_index; - last_projIma = projImages + last_index; - - last_projIma->touch = 1; - is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; - use_color_correction = TRUE; - } - /* end copy */ - - last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index; - last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px); - last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px); - - last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1); - last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1); - - - switch (tool) { - case PAINT_TOOL_CLONE: - if (is_floatbuf) { - if (((ProjPixelClone *)projPixel)->clonepx.f[3]) { - do_projectpaint_clone_f(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */ - } - } - else { - if (((ProjPixelClone *)projPixel)->clonepx.ch[3]) { - do_projectpaint_clone(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */ - } - } - break; - case PAINT_TOOL_SMEAR: - sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs); - - if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co); - else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co); - break; - case PAINT_TOOL_SOFTEN: - if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, alpha, mask, softenArena, &softenPixels_f); - else do_projectpaint_soften(ps, projPixel, alpha, mask, softenArena, &softenPixels); - break; - default: - 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; - } - } - - if (lock_alpha) { - if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f[3]; - else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch[3]; - } - - /* done painting */ - } - } - } - } - } - - - if (tool == PAINT_TOOL_SMEAR) { - - for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */ - projPixel = node->link; - *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint; - } - - for (node = smearPixels_f; node; node = node->next) { - projPixel = node->link; - copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f); - } - - BLI_memarena_free(smearArena); - } - else if (tool == PAINT_TOOL_SOFTEN) { - - for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */ - projPixel = node->link; - *projPixel->pixel.uint_pt = projPixel->newColor.uint; - } - - for (node = softenPixels_f; node; node = node->next) { - projPixel = node->link; - copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f); - } - - BLI_memarena_free(softenArena); - } - - return NULL; -} - -static int project_paint_op(void *state, ImBuf *UNUSED(ibufb), const float lastpos[2], const float pos[2]) -{ - /* First unpack args from the struct */ - ProjPaintState *ps = (ProjPaintState *)state; - int touch_any = 0; - - ProjectHandle handles[BLENDER_MAX_THREADS]; - ListBase threads; - int a, i; - - struct ImagePool *pool; - - if (!project_bucket_iter_init(ps, pos)) { - return 0; - } - - if (ps->thread_tot > 1) - BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot); - - pool = BKE_image_pool_new(); - - /* get the threads running */ - for (a = 0; a < ps->thread_tot; a++) { - - /* set defaults in handles */ - //memset(&handles[a], 0, sizeof(BakeShade)); - - handles[a].ps = ps; - copy_v2_v2(handles[a].mval, pos); - copy_v2_v2(handles[a].prevmval, lastpos); - - /* thread specific */ - handles[a].thread_index = a; - - handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage)); - - memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage)); - - /* image bounds */ - for (i = 0; i < ps->image_tot; i++) { - handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); - memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); - } - - handles[a].pool = pool; - - if (ps->thread_tot > 1) - BLI_insert_thread(&threads, &handles[a]); - } - - if (ps->thread_tot > 1) /* wait for everything to be done */ - BLI_end_threads(&threads); - else - do_projectpaint_thread(&handles[0]); - - - BKE_image_pool_free(pool); - - /* move threaded bounds back into ps->projectPartialRedraws */ - for (i = 0; i < ps->image_tot; i++) { - int touch = 0; - for (a = 0; a < ps->thread_tot; a++) { - touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED); - } - - if (touch) { - ps->projImages[i].touch = 1; - touch_any = 1; - } - } - - return touch_any; -} - - -static int project_paint_sub_stroke(ProjPaintState *ps, BrushPainter *painter, const int UNUSED(prevmval_i[2]), const int mval_i[2], double time, float pressure) -{ - - /* Use mouse coords as floats for projection painting */ - float pos[2]; - - pos[0] = (float)(mval_i[0]); - pos[1] = (float)(mval_i[1]); - - // we may want to use this later - // BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0); - - if (BKE_brush_painter_paint(painter, project_paint_op, pos, time, pressure, ps, 0)) { - return 1; - } - else return 0; -} - - -static int project_paint_stroke(ProjPaintState *ps, BrushPainter *painter, const int prevmval_i[2], const int mval_i[2], double time, float pressure) -{ - int a, redraw; - - for (a = 0; a < ps->image_tot; a++) - partial_redraw_array_init(ps->projImages[a].partRedrawRect); - - redraw = project_paint_sub_stroke(ps, painter, prevmval_i, mval_i, time, pressure); - - if (project_image_refresh_tagged(ps)) - return redraw; - - return 0; -} - /* Imagepaint Partial Redraw & Dirty Region */ -static void imapaint_clear_partial_redraw(void) +void imapaint_clear_partial_redraw(void) { memset(&imapaintpartial, 0, sizeof(imapaintpartial)); } -static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) +void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, int h) { ImBuf *tmpibuf = NULL; int srcx = 0, srcy = 0, origx; @@ -4417,7 +315,7 @@ static void imapaint_dirty_region(Image *ima, ImBuf *ibuf, int x, int y, int w, IMB_freeImBuf(tmpibuf); } -static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) +void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, short texpaint) { if (imapaintpartial.x1 != imapaintpartial.x2 && imapaintpartial.y1 != imapaintpartial.y2) @@ -4438,447 +336,6 @@ static void imapaint_image_update(SpaceImage *sima, Image *image, ImBuf *ibuf, s } } -/* Image Paint Operations */ - -/* keep these functions in sync */ -static void imapaint_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const short is_torus, float r_rgb[3]) -{ - if (is_torus) { - x %= ibuf->x; - if (x < 0) x += ibuf->x; - y %= ibuf->y; - if (y < 0) y += ibuf->y; - } - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4; - IMAPAINT_FLOAT_RGB_COPY(r_rgb, rrgbf); - } - else { - char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4; - IMAPAINT_CHAR_RGB_TO_FLOAT(r_rgb, rrgb); - } -} -static void imapaint_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const short is_torus, const float rgb[3]) -{ - if (is_torus) { - x %= ibuf->x; - if (x < 0) x += ibuf->x; - y %= ibuf->y; - if (y < 0) y += ibuf->y; - } - - if (ibuf->rect_float) { - float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4; - IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb); - } - else { - char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4; - IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb); - } -} - -static int imapaint_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus) -{ - float inrgb[3]; - - // XXX: signed unsigned mismatch - if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) { - if (torus) imapaint_ibuf_rgb_get(ibuf, x, y, 1, inrgb); - else return 0; - } - else { - imapaint_ibuf_rgb_get(ibuf, x, y, 0, inrgb); - } - - outrgb[0] += inrgb[0]; - outrgb[1] += inrgb[1]; - outrgb[2] += inrgb[2]; - - return 1; -} - -static void imapaint_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus) -{ - int x, y, count, xi, yi, xo, yo; - int out_off[2], in_off[2], dim[2]; - float outrgb[3]; - - dim[0] = ibufb->x; - dim[1] = ibufb->y; - in_off[0] = pos[0]; - in_off[1] = pos[1]; - out_off[0] = out_off[1] = 0; - - if (!is_torus) { - IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0], - &out_off[1], &dim[0], &dim[1]); - - if ((dim[0] == 0) || (dim[1] == 0)) - return; - } - - for (y = 0; y < dim[1]; y++) { - for (x = 0; x < dim[0]; x++) { - /* get input pixel */ - xi = in_off[0] + x; - yi = in_off[1] + y; - - count = 1; - imapaint_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb); - - count += imapaint_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus); - count += imapaint_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus); - count += imapaint_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus); - - count += imapaint_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus); - count += imapaint_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus); - - count += imapaint_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus); - count += imapaint_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus); - count += imapaint_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus); - - mul_v3_fl(outrgb, 1.0f / (float)count); - - /* write into brush buffer */ - xo = out_off[0] + x; - yo = out_off[1] + y; - imapaint_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb); - } - } -} - -static void imapaint_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height) -{ - region->destx = destx; - region->desty = desty; - region->srcx = srcx; - region->srcy = srcy; - region->width = width; - region->height = height; -} - -static int imapaint_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf) -{ - int destx = region->destx; - int desty = region->desty; - int srcx = region->srcx; - int srcy = region->srcy; - int width = region->width; - int height = region->height; - int origw, origh, w, h, tot = 0; - - /* convert destination and source coordinates to be within image */ - destx = destx % dbuf->x; - if (destx < 0) destx += dbuf->x; - desty = desty % dbuf->y; - if (desty < 0) desty += dbuf->y; - srcx = srcx % sbuf->x; - if (srcx < 0) srcx += sbuf->x; - srcy = srcy % sbuf->y; - if (srcy < 0) srcy += sbuf->y; - - /* clip width of blending area to destination imbuf, to avoid writing the - * same pixel twice */ - origw = w = (width > dbuf->x) ? dbuf->x : width; - origh = h = (height > dbuf->y) ? dbuf->y : height; - - /* clip within image */ - IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h); - imapaint_set_region(®ion[tot++], destx, desty, srcx, srcy, w, h); - - /* do 3 other rects if needed */ - if (w < origw) - imapaint_set_region(®ion[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h); - if (h < origh) - imapaint_set_region(®ion[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h); - if ((w < origw) && (h < origh)) - imapaint_set_region(®ion[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h); - - return tot; -} - -static void imapaint_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos) -{ - ImagePaintRegion region[4]; - int a, tot; - - imapaint_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y); - tot = imapaint_torus_split_region(region, ibufb, ibuf); - - for (a = 0; a < tot; a++) - IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty, - region[a].srcx, region[a].srcy, - region[a].width, region[a].height, IMB_BLEND_COPY_RGB); -} - -static ImBuf *imapaint_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) -{ - /* note: allocImbuf returns zero'd memory, so regions outside image will - * have zero alpha, and hence not be blended onto the image */ - int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1]; - ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags); - - IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h); - IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h, - IMB_BLEND_COPY_RGB); - IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h, - IMB_BLEND_COPY_ALPHA); - - return clonebuf; -} - -static void imapaint_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[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 - * only the old style painting in the 3d view */ -static int imapaint_paint_op(void *state, ImBuf *ibufb, const float lastpos[2], const float pos[2]) -{ - ImagePaintState *s = ((ImagePaintState *)state); - ImBuf *clonebuf = NULL, *frombuf; - ImagePaintRegion region[4]; - short torus = s->brush->flag & BRUSH_TORUS; - short blend = s->blend; - float *offset = s->brush->clone.offset; - float liftpos[2]; - int bpos[2], blastpos[2], bliftpos[2]; - int a, tot; - - imapaint_convert_brushco(ibufb, pos, bpos); - - /* lift from canvas */ - if (s->tool == PAINT_TOOL_SOFTEN) { - imapaint_lift_soften(s->canvas, ibufb, bpos, torus); - } - else if (s->tool == PAINT_TOOL_SMEAR) { - if (lastpos[0] == pos[0] && lastpos[1] == pos[1]) - return 0; - - imapaint_convert_brushco(ibufb, lastpos, blastpos); - imapaint_lift_smear(s->canvas, ibufb, blastpos); - } - else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) { - liftpos[0] = pos[0] - offset[0] * s->canvas->x; - liftpos[1] = pos[1] - offset[1] * s->canvas->y; - - imapaint_convert_brushco(ibufb, liftpos, bliftpos); - clonebuf = imapaint_lift_clone(s->clonecanvas, ibufb, bliftpos); - } - - frombuf = (clonebuf) ? clonebuf : ibufb; - - if (torus) { - imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y); - tot = imapaint_torus_split_region(region, s->canvas, frombuf); - } - else { - imapaint_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y); - tot = 1; - } - - /* blend into canvas */ - for (a = 0; a < tot; a++) { - imapaint_dirty_region(s->image, s->canvas, - region[a].destx, region[a].desty, - region[a].width, region[a].height); - - IMB_rectblend(s->canvas, frombuf, - region[a].destx, region[a].desty, - region[a].srcx, region[a].srcy, - region[a].width, region[a].height, blend); - } - - if (clonebuf) IMB_freeImBuf(clonebuf); - - return 1; -} - -/* 3D TexturePaint */ - -static int texpaint_break_stroke(float *prevuv, float *fwuv, float *bkuv, float *uv) -{ - float d1[2], d2[2]; - float mismatch = len_v2v2(fwuv, uv); - float len1 = len_v2v2(prevuv, fwuv); - float len2 = len_v2v2(bkuv, uv); - - sub_v2_v2v2(d1, fwuv, prevuv); - sub_v2_v2v2(d2, uv, bkuv); - - return ((dot_v2v2(d1, d2) < 0.0f) || (mismatch > MAX2(len1, len2) * 2)); -} - -/* ImagePaint Common */ - -static int imapaint_canvas_set(ImagePaintState *s, Image *ima) -{ - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); - - /* verify that we can paint and set canvas */ - if (ima == NULL) { - return 0; - } - else if (ima->packedfile && ima->rr) { - s->warnpackedfile = ima->id.name + 2; - return 0; - } - else if (ibuf && ibuf->channels != 4) { - s->warnmultifile = ima->id.name + 2; - return 0; - } - else if (!ibuf || !(ibuf->rect || ibuf->rect_float)) - return 0; - - s->image = ima; - s->canvas = ibuf; - - /* set clone canvas */ - if (s->tool == PAINT_TOOL_CLONE) { - ima = s->brush->clone.image; - ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); - - if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { - BKE_image_release_ibuf(ima, ibuf, NULL); - BKE_image_release_ibuf(s->image, s->canvas, NULL); - return 0; - } - - s->clonecanvas = ibuf; - - /* temporarily add float rect for cloning */ - if (s->canvas->rect_float && !s->clonecanvas->rect_float) { - IMB_float_from_rect(s->clonecanvas); - } - else if (!s->canvas->rect_float && !s->clonecanvas->rect) - IMB_rect_from_float(s->clonecanvas); - } - - return 1; -} - -static void imapaint_canvas_free(ImagePaintState *s) -{ - BKE_image_release_ibuf(s->image, s->canvas, NULL); - BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL); -} - -static int imapaint_paint_sub_stroke(ImagePaintState *s, BrushPainter *painter, Image *image, short texpaint, float *uv, double time, int update, float pressure) -{ - ImBuf *ibuf = BKE_image_acquire_ibuf(image, s->sima ? &s->sima->iuser : NULL, NULL); - float pos[2]; - int is_data; - - if (!ibuf) - return 0; - - is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; - - pos[0] = uv[0] * ibuf->x; - pos[1] = uv[1] * ibuf->y; - - BKE_brush_painter_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0); - - /* OCIO_TODO: float buffers are now always linear, so always use color correction - * this should probably be changed when texture painting color space is supported - */ - if (BKE_brush_painter_paint(painter, imapaint_paint_op, pos, time, pressure, s, is_data == FALSE)) { - if (update) - imapaint_image_update(s->sima, image, ibuf, texpaint); - BKE_image_release_ibuf(image, ibuf, NULL); - return 1; - } - else { - BKE_image_release_ibuf(image, ibuf, NULL); - return 0; - } -} - -static int imapaint_paint_stroke(ViewContext *vc, ImagePaintState *s, BrushPainter *painter, short texpaint, const int prevmval[2], const int mval[2], double time, float pressure) -{ - Image *newimage = NULL; - float fwuv[2], bkuv[2], newuv[2]; - unsigned int newfaceindex; - int breakstroke = 0, redraw = 0; - - if (texpaint) { - /* pick new face and image */ - if (imapaint_pick_face(vc, mval, &newfaceindex, s->dm_totface) && - ((s->do_facesel == FALSE) || (s->dm_mface[newfaceindex].flag & ME_FACE_SEL))) - { - ImBuf *ibuf; - - newimage = imapaint_face_image(s, newfaceindex); - ibuf = BKE_image_acquire_ibuf(newimage, s->sima ? &s->sima->iuser : NULL, NULL); - - if (ibuf && ibuf->rect) - imapaint_pick_uv(s->scene, s->ob, newfaceindex, mval, newuv); - else { - newimage = NULL; - newuv[0] = newuv[1] = 0.0f; - } - - BKE_image_release_ibuf(newimage, ibuf, NULL); - } - else - newuv[0] = newuv[1] = 0.0f; - - /* see if stroke is broken, and if so finish painting in old position */ - if (s->image) { - imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv); - imapaint_pick_uv(s->scene, s->ob, newfaceindex, prevmval, bkuv); - - if (newimage == s->image) - breakstroke = texpaint_break_stroke(s->uv, fwuv, bkuv, newuv); - else - breakstroke = 1; - } - else - fwuv[0] = fwuv[1] = 0.0f; - - if (breakstroke) { - imapaint_pick_uv(s->scene, s->ob, s->faceindex, mval, fwuv); - redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, - fwuv, time, 1, pressure); - imapaint_clear_partial_redraw(); - BKE_brush_painter_break_stroke(painter); - } - - /* set new canvas */ - if (newimage && (newimage != s->image)) - if (!imapaint_canvas_set(s, newimage)) - newimage = NULL; - - /* paint in new image */ - if (newimage) { - if (breakstroke) - redraw |= imapaint_paint_sub_stroke(s, painter, newimage, - texpaint, bkuv, time, 0, pressure); - redraw |= imapaint_paint_sub_stroke(s, painter, newimage, texpaint, - newuv, time, 1, pressure); - } - - /* update state */ - s->image = newimage; - s->faceindex = newfaceindex; - s->uv[0] = newuv[0]; - s->uv[1] = newuv[1]; - } - else { - UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]); - redraw |= imapaint_paint_sub_stroke(s, painter, s->image, texpaint, newuv, - time, 1, pressure); - } - - if (redraw) - imapaint_clear_partial_redraw(); - - return redraw; -} - /************************ image paint poll ************************/ static Brush *image_paint_brush(bContext *C) @@ -4889,16 +346,6 @@ static Brush *image_paint_brush(bContext *C) return paint_brush(&settings->imapaint.paint); } -static Brush *uv_sculpt_brush(bContext *C) -{ - Scene *scene = CTX_data_scene(C); - ToolSettings *settings = scene->toolsettings; - - if (!settings->uvsculpt) - return NULL; - return paint_brush(&settings->uvsculpt->paint); -} - static int image_paint_poll(bContext *C) { Object *obact = CTX_data_active_object(C); @@ -4924,38 +371,6 @@ static int image_paint_poll(bContext *C) return 0; } -static int uv_sculpt_brush_poll(bContext *C) -{ - BMEditMesh *em; - int ret; - Object *obedit = CTX_data_edit_object(C); - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - ToolSettings *toolsettings = scene->toolsettings; - - if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH) - return 0; - - em = BMEdit_FromObject(obedit); - ret = EDBM_mtexpoly_check(em); - - if (ret && sima) { - ARegion *ar = CTX_wm_region(C); - if ((toolsettings->use_uv_sculpt) && ar->regiontype == RGN_TYPE_WINDOW) - return 1; - } - - return 0; -} - -static int image_paint_3d_poll(bContext *C) -{ - if (CTX_wm_region_view3d(C)) - return image_paint_poll(C); - - return 0; -} - static int image_paint_2d_clone_poll(bContext *C) { Brush *brush = image_paint_brush(C); @@ -4969,339 +384,173 @@ static int image_paint_2d_clone_poll(bContext *C) } /************************ paint operator ************************/ - -typedef enum PaintMode { +typedef enum TexPaintMode { PAINT_MODE_2D, - PAINT_MODE_3D, PAINT_MODE_3D_PROJECT -} PaintMode; +} TexPaintMode; typedef struct PaintOperation { - PaintMode mode; + TexPaintMode mode; - BrushPainter *painter; - ImagePaintState s; - ProjPaintState ps; + void *custom_paint; - int first; int prevmouse[2]; - int orig_brush_size; double starttime; ViewContext vc; wmTimer *timer; - - short restore_projection; } PaintOperation; -static void paint_redraw(bContext *C, ImagePaintState *s, int texpaint, int final) +void paint_brush_init_tex(Brush *brush) { - if (final) { - if (s->image && !(texpaint || (s->sima && s->sima->lock))) - GPU_free_image(s->image); - - /* compositor listener deals with updating */ - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image); - } - else { - if (!s->sima || !s->sima->lock) - ED_region_tag_redraw(CTX_wm_region(C)); - else - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image); + /* init mtex nodes */ + if (brush) { + MTex *mtex = &brush->mtex; + if (mtex->tex && mtex->tex->nodetree) + ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */ } } -/* initialize project paint settings from context */ -static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps) +void paint_brush_exit_tex(Brush *brush) { - Scene *scene = CTX_data_scene(C); - ToolSettings *settings = scene->toolsettings; - - /* brush */ - ps->brush = paint_brush(&settings->imapaint.paint); - if (ps->brush) { - Brush *brush = ps->brush; - ps->tool = brush->imagepaint_tool; - ps->blend = brush->blend; - - /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */ - ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW || - brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) ? false : true; - ps->is_texbrush = (brush->mtex.tex) ? 1 : 0; - } - else { - /* brush may be NULL*/ - ps->do_masking = false; - ps->is_texbrush = false; + if (brush) { + MTex *mtex = &brush->mtex; + if (mtex->tex && mtex->tex->nodetree) + ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1); } +} - /* sizeof(ProjPixel), since we alloc this a _lot_ */ - ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool); - BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel)); - - /* these can be NULL */ - ps->v3d = CTX_wm_view3d(C); - ps->rv3d = CTX_wm_region_view3d(C); - ps->ar = CTX_wm_region(C); - - ps->scene = scene; - ps->ob = ob; /* allow override of active object */ - - /* setup projection painting data */ - ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; - ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; - ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1; - ps->do_new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* only cache the value */ - - if (ps->tool == PAINT_TOOL_CLONE) - ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE); - - ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0; - ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0; - - -#ifndef PROJ_DEBUG_NOSEAMBLEED - ps->seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */ -#endif - if (ps->do_mask_normal) { - ps->normal_angle_inner = settings->imapaint.normal_angle; - ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f; +static void paint_redraw(const bContext *C, PaintOperation *pop, int final) +{ + if (pop->mode == PAINT_MODE_2D) { + paint_2d_redraw(C, pop->custom_paint, final); } else { - ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle; - } - - ps->normal_angle_inner *= (float)(M_PI_2 / 90); - ps->normal_angle *= (float)(M_PI_2 / 90); - ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner; - - if (ps->normal_angle_range <= 0.0f) - ps->do_mask_normal = FALSE; /* no need to do blending */ -} - -static void paint_brush_init_tex(Brush *brush) -{ - /* init mtex nodes */ - if (brush) { - MTex *mtex = &brush->mtex; - if (mtex->tex && mtex->tex->nodetree) - ntreeTexBeginExecTree(mtex->tex->nodetree, 1); /* has internal flag to detect it only does it once */ + if (final) { + /* compositor listener deals with updating */ + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, NULL); + } + else { + ED_region_tag_redraw(CTX_wm_region(C)); + } } - } -static int texture_paint_init(bContext *C, wmOperator *op) +static PaintOperation * texture_paint_init(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); ToolSettings *settings = scene->toolsettings; - Brush *brush = paint_brush(&settings->imapaint.paint); PaintOperation *pop = MEM_callocN(sizeof(PaintOperation), "PaintOperation"); /* caller frees */ + int mode = RNA_enum_get(op->ptr, "mode"); + view3d_set_viewcontext(C, &pop->vc); + + /* TODO Should avoid putting this here. Instead, last position should be requested + * from stroke system. */ + pop->prevmouse[0] = event->mval[0]; + pop->prevmouse[1] = event->mval[1]; - pop->first = 1; - op->customdata = pop; /* initialize from context */ if (CTX_wm_region_view3d(C)) { - pop->mode = PAINT_MODE_3D; - - if (!(settings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)) - pop->mode = PAINT_MODE_3D_PROJECT; - else - view3d_set_viewcontext(C, &pop->vc); + pop->mode = PAINT_MODE_3D_PROJECT; + pop->custom_paint = paint_proj_new_stroke(C, OBACT, pop->prevmouse, mode); } else { - pop->s.sima = CTX_wm_space_image(C); - pop->s.v2d = &CTX_wm_region(C)->v2d; + pop->mode = PAINT_MODE_2D; + pop->custom_paint = paint_2d_new_stroke(C, op); } - pop->s.scene = scene; - pop->s.screen = CTX_wm_screen(C); - - pop->s.brush = brush; - pop->s.tool = brush->imagepaint_tool; - if (pop->mode == PAINT_MODE_3D && (pop->s.tool == PAINT_TOOL_CLONE)) - pop->s.tool = PAINT_TOOL_DRAW; - pop->s.blend = brush->blend; - pop->orig_brush_size = BKE_brush_size_get(scene, brush); - - if (pop->mode != PAINT_MODE_2D) { - Object *ob = OBACT; - Mesh *me = BKE_mesh_from_object(ob); - - if (!me) { - return 0; - } - - pop->s.ob = ob; - pop->s.do_facesel = (me->editflag & ME_EDIT_PAINT_FACE_SEL) != 0; - - /* for non prohect paint we need */ - /* fill in derived mesh */ - if (ob->derivedFinal && CustomData_has_layer(&ob->derivedFinal->faceData, CD_MTFACE)) { - pop->s.dm = ob->derivedFinal; - pop->s.dm_release = FALSE; - } - else { - pop->s.dm = mesh_get_derived_final(pop->s.scene, ob, pop->s.scene->customdata_mask | CD_MASK_MTFACE); - pop->s.dm_release = TRUE; - } - - if (!CustomData_has_layer(&pop->s.dm->faceData, CD_MTFACE)) { - - if (pop->s.dm_release) - pop->s.dm->release(pop->s.dm); - - pop->s.dm = NULL; - return 0; - } - - pop->s.dm_mface = pop->s.dm->getTessFaceArray(pop->s.dm); - pop->s.dm_mtface = pop->s.dm->getTessFaceDataArray(pop->s.dm, CD_MTFACE); - pop->s.dm_totface = pop->s.dm->getNumTessFaces(pop->s.dm); - } - else { - pop->s.image = pop->s.sima->image; - - if (!imapaint_canvas_set(&pop->s, pop->s.image)) { - if (pop->s.warnmultifile) - BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint"); - if (pop->s.warnpackedfile) - BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted"); - - return 0; - } + if (!pop->custom_paint) { + MEM_freeN(pop); + return NULL; } - /* note, if we have no UVs on the derived mesh, then we must return here */ - if (pop->mode == PAINT_MODE_3D_PROJECT) { - - /* initialize all data from the context */ - project_state_init(C, OBACT, &pop->ps); - - /* needed so multiple threads don't try to initialize the brush at once (can leak memory) */ - curvemapping_initialize(pop->ps.brush->curve); - - paint_brush_init_tex(pop->ps.brush); - - pop->ps.source = PROJ_SRC_VIEW; - - if (pop->ps.ob == NULL || !(pop->ps.ob->lay & pop->ps.v3d->lay)) - return 0; - - /* Don't allow brush size below 2 */ - if (BKE_brush_size_get(scene, brush) < 2) - BKE_brush_size_set(scene, brush, 2); - - /* allocate and initialize spatial data structures */ - project_paint_begin(&pop->ps); - - if (pop->ps.dm == NULL) - return 0; - } - else { - paint_brush_init_tex(pop->s.brush); - } - settings->imapaint.flag |= IMAGEPAINT_DRAWING; undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name, image_undo_restore, image_undo_free); - /* create painter */ - pop->painter = BKE_brush_painter_new(scene, pop->s.brush); - { UnifiedPaintSettings *ups = &settings->unified_paint_settings; ups->draw_pressure = true; } - return 1; + return pop; } -static void paint_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) +static void paint_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) { - PaintOperation *pop = op->customdata; - float time, mousef[2]; + PaintOperation *pop = paint_stroke_mode_data(stroke); + Scene *scene = CTX_data_scene(C); + Brush *brush = paint_brush(&scene->toolsettings->imapaint.paint); + + /* initial brush values. Maybe it should be considered moving these to stroke system */ + float startsize = BKE_brush_size_get(scene, brush); + float startalpha = BKE_brush_alpha_get(scene, brush); + + float mousef[2]; float pressure; - int mouse[2], redraw; + int mouse[2], redraw, eraser; RNA_float_get_array(itemptr, "mouse", mousef); mouse[0] = (int)(mousef[0]); mouse[1] = (int)(mousef[1]); - time = RNA_float_get(itemptr, "time"); pressure = RNA_float_get(itemptr, "pressure"); + eraser = RNA_boolean_get(itemptr, "pen_flip"); - if (pop->first) - project_paint_begin_clone(&pop->ps, mouse); - - if (pop->mode == PAINT_MODE_3D) - view3d_operator_needs_opengl(C); + if (BKE_brush_use_alpha_pressure(scene, brush)) + BKE_brush_alpha_set(scene, brush, max_ff(0.0f, startalpha * pressure)); + if (BKE_brush_use_size_pressure(scene, brush)) + BKE_brush_size_set(scene, brush, max_ff(1.0f, startsize * pressure)); if (pop->mode == PAINT_MODE_3D_PROJECT) { - redraw = project_paint_stroke(&pop->ps, pop->painter, pop->prevmouse, mouse, time, pressure); - pop->prevmouse[0] = mouse[0]; - pop->prevmouse[1] = mouse[1]; - + redraw = paint_proj_stroke(C, pop->custom_paint, pop->prevmouse, mouse); } else { - redraw = imapaint_paint_stroke(&pop->vc, &pop->s, pop->painter, pop->mode == PAINT_MODE_3D, pop->prevmouse, mouse, time, pressure); - pop->prevmouse[0] = mouse[0]; - pop->prevmouse[1] = mouse[1]; + redraw = paint_2d_stroke(pop->custom_paint, pop->prevmouse, mouse, eraser); } - if (redraw) - paint_redraw(C, &pop->s, pop->mode == PAINT_MODE_3D, 0); + pop->prevmouse[0] = mouse[0]; + pop->prevmouse[1] = mouse[1]; - pop->first = 0; -} + /* restore brush values */ + BKE_brush_alpha_set(scene, brush, startalpha); + BKE_brush_size_set(scene, brush, startsize); + + + if (redraw) + paint_redraw(C, pop, 0); -static void paint_brush_exit_tex(Brush *brush) -{ - if (brush) { - MTex *mtex = &brush->mtex; - if (mtex->tex && mtex->tex->nodetree) - ntreeTexEndExecTree(mtex->tex->nodetree->execdata, 1); - } } -static void paint_exit(bContext *C, wmOperator *op) +static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke) { Scene *scene = CTX_data_scene(C); ToolSettings *settings = scene->toolsettings; - PaintOperation *pop = op->customdata; + PaintOperation *pop = paint_stroke_mode_data(stroke); + + paint_redraw(C, pop, 1); if (pop->timer) WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), pop->timer); - if (pop->restore_projection) - settings->imapaint.flag &= ~IMAGEPAINT_PROJECT_DISABLE; - settings->imapaint.flag &= ~IMAGEPAINT_DRAWING; - imapaint_canvas_free(&pop->s); - BKE_brush_painter_free(pop->painter); if (pop->mode == PAINT_MODE_3D_PROJECT) { - BKE_brush_size_set(scene, pop->ps.brush, pop->orig_brush_size); - paint_brush_exit_tex(pop->ps.brush); - - project_paint_end(&pop->ps); + paint_proj_stroke_done(pop->custom_paint); } else { - paint_brush_exit_tex(pop->s.brush); - - /* non projection 3d paint, could move into own function of more needs adding */ - if (pop->s.dm_release) - pop->s.dm->release(pop->s.dm); + paint_2d_stroke_done(pop->custom_paint); } - - paint_redraw(C, &pop->s, pop->mode == PAINT_MODE_3D, 1); + undo_paint_push_end(UNDO_PAINT_IMAGE); - + + /* duplicate warning, see texpaint_init if (pop->s.warnmultifile) BKE_reportf(op->reports, RPT_WARNING, "Image requires 4 color channels to paint: %s", pop->s.warnmultifile); if (pop->s.warnpackedfile) BKE_reportf(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted: %s", pop->s.warnpackedfile); - + */ MEM_freeN(pop); { @@ -5310,159 +559,69 @@ static void paint_exit(bContext *C, wmOperator *op) } } -static int paint_exec(bContext *C, wmOperator *op) +static int paint_stroke_test_start(bContext *UNUSED(C), wmOperator *UNUSED(op), const float UNUSED(mouse[2])) { - if (!texture_paint_init(C, op)) { - MEM_freeN(op->customdata); - return OPERATOR_CANCELLED; - } - - RNA_BEGIN (op->ptr, itemptr, "stroke") - { - paint_apply(C, op, &itemptr); - } - RNA_END; - - paint_exit(C, op); - - return OPERATOR_FINISHED; + return true; } -static void paint_apply_event(bContext *C, wmOperator *op, wmEvent *event) -{ - const Scene *scene = CTX_data_scene(C); - PaintOperation *pop = op->customdata; - PointerRNA itemptr; - float pressure, mousef[2]; - double time; - int tablet; - - time = PIL_check_seconds_timer(); - - tablet = 0; - pop->s.blend = pop->s.brush->blend; - - if (event->tablet_data) { - wmTabletData *wmtab = event->tablet_data; - - tablet = (wmtab->Active != EVT_TABLET_NONE); - pressure = wmtab->Pressure; - if (wmtab->Active == EVT_TABLET_ERASER) - pop->s.blend = IMB_BLEND_ERASE_ALPHA; - } - else { - BLI_assert(fabsf(WM_cursor_pressure(CTX_wm_window(C))) == 1.0f); - pressure = 1.0f; - } - - if (pop->first) { - 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 - * windows for some tablets, then we just skip first touch .. */ - if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush))) - return; - - /* This can be removed once fixed properly in - * BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) - * at zero pressure we should do nothing 1/2^12 is 0.0002 which is the sensitivity of the most sensitive pen tablet available */ - if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush))) - return; - - } - - /* fill in stroke */ - RNA_collection_add(op->ptr, "stroke", &itemptr); - - 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); - - /* apply */ - paint_apply(C, op, &itemptr); - - { - UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; - ups->pressure_value = pressure; - } -} -static int paint_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int paint_invoke(bContext *C, wmOperator *op, const wmEvent *event) { PaintOperation *pop; + struct PaintStroke *stroke; + int retval; - if (!texture_paint_init(C, op)) { - MEM_freeN(op->customdata); + if (!(pop = texture_paint_init(C, op, event))) { return OPERATOR_CANCELLED; } - paint_apply_event(C, op, event); - - pop = op->customdata; + stroke = op->customdata = paint_stroke_new(C, NULL, paint_stroke_test_start, + paint_stroke_update_step, + paint_stroke_done, event->type); + paint_stroke_set_mode_data(stroke, pop); + /* add modal handler */ WM_event_add_modal_handler(C, op); - if (pop->s.brush->flag & BRUSH_AIRBRUSH) - pop->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); + retval = op->type->modal(C, op, event); + OPERATOR_RETVAL_CHECK(retval); + BLI_assert(retval == OPERATOR_RUNNING_MODAL); return OPERATOR_RUNNING_MODAL; } -static int paint_modal(bContext *C, wmOperator *op, wmEvent *event) -{ - PaintOperation *pop = op->customdata; - - switch (event->type) { - case LEFTMOUSE: - case MIDDLEMOUSE: - case RIGHTMOUSE: // XXX hardcoded - paint_exit(C, op); - return OPERATOR_FINISHED; - case MOUSEMOVE: - case INBETWEEN_MOUSEMOVE: - paint_apply_event(C, op, event); - break; - case TIMER: - if (event->customdata == pop->timer) - paint_apply_event(C, op, event); - break; - } - - return OPERATOR_RUNNING_MODAL; -} - -static int paint_cancel(bContext *C, wmOperator *op) -{ - paint_exit(C, op); - - return OPERATOR_CANCELLED; -} void PAINT_OT_image_paint(wmOperatorType *ot) { + static EnumPropertyItem stroke_mode_items[] = { + {BRUSH_STROKE_NORMAL, "NORMAL", 0, "Normal", "Apply brush normally"}, + {BRUSH_STROKE_INVERT, "INVERT", 0, "Invert", "Invert action of brush for duration of stroke"}, + {0} + }; + /* identifiers */ ot->name = "Image Paint"; ot->idname = "PAINT_OT_image_paint"; ot->description = "Paint a stroke into the image"; - + /* api callbacks */ - ot->exec = paint_exec; ot->invoke = paint_invoke; - ot->modal = paint_modal; - ot->cancel = paint_cancel; + ot->modal = paint_stroke_modal; + /* ot->exec = paint_exec; <-- needs stroke property */ ot->poll = image_paint_poll; + ot->cancel = paint_stroke_cancel; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_BLOCKING; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_BLOCKING; + + RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL, + "Paint Stroke Mode", + "Action taken when a paint stroke is made"); - /* properties */ RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); } -static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) + +int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) { RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -5484,7 +643,7 @@ static int get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy) /************************ cursor drawing *******************************/ -static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)) +void brush_drawcursor_texpaint_uvsculpt(bContext *C, int x, int y, void *UNUSED(customdata)) { #define PX_SIZE_FADE_MAX 12.0f #define PX_SIZE_FADE_MIN 4.0f @@ -5560,7 +719,8 @@ static void toggle_paint_cursor(bContext *C, int enable) settings->imapaint.paintcursor = NULL; } else if (enable) - settings->imapaint.paintcursor = WM_paint_cursor_activate(wm, image_paint_poll, brush_drawcursor, NULL); + settings->imapaint.paintcursor = + WM_paint_cursor_activate(wm, image_paint_poll, brush_drawcursor_texpaint_uvsculpt, NULL); } /* enable the paint cursor if it isn't already. @@ -5587,32 +747,11 @@ void ED_space_image_paint_update(wmWindowManager *wm, ToolSettings *settings) if (!imapaint->paintcursor) { imapaint->paintcursor = WM_paint_cursor_activate(wm, image_paint_poll, - brush_drawcursor, NULL); + brush_drawcursor_texpaint_uvsculpt, NULL); } } } - -void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings) -{ - if (settings->use_uv_sculpt) { - if (!settings->uvsculpt) { - settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint"); - settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB; - settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS; - settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN; - } - - BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT); - - WM_paint_cursor_activate(wm, uv_sculpt_brush_poll, - brush_drawcursor, NULL); - } - else { - if (settings->uvsculpt) - settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH; - } -} /************************ grab clone operator ************************/ typedef struct GrabClone { @@ -5637,7 +776,7 @@ static int grab_clone_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int grab_clone_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Brush *brush = image_paint_brush(C); GrabClone *cmv; @@ -5653,7 +792,7 @@ static int grab_clone_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int grab_clone_modal(bContext *C, wmOperator *op, wmEvent *event) +static int grab_clone_modal(bContext *C, wmOperator *op, const wmEvent *event) { Brush *brush = image_paint_brush(C); ARegion *ar = CTX_wm_region(C); @@ -5728,7 +867,7 @@ static int sample_color_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sample_color_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RNA_int_set_array(op->ptr, "location", event->mval); sample_color_exec(C, op); @@ -5738,7 +877,7 @@ static int sample_color_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int sample_color_modal(bContext *C, wmOperator *op, wmEvent *event) +static int sample_color_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: @@ -5793,57 +932,6 @@ void PAINT_OT_sample_color(wmOperatorType *ot) RNA_def_int_vector(ot->srna, "location", 2, NULL, 0, INT_MAX, "Location", "Cursor location in region coordinates", 0, 16384); } -/******************** set clone cursor operator ********************/ - -static int set_clone_cursor_exec(bContext *C, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - float *cursor = give_cursor(scene, v3d); - - RNA_float_get_array(op->ptr, "location", cursor); - - ED_area_tag_redraw(CTX_wm_area(C)); - - return OPERATOR_FINISHED; -} - -static int set_clone_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) -{ - Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); - ARegion *ar = CTX_wm_region(C); - float location[3]; - - view3d_operator_needs_opengl(C); - - if (!ED_view3d_autodist(scene, ar, v3d, event->mval, location)) - return OPERATOR_CANCELLED; - - RNA_float_set_array(op->ptr, "location", location); - - return set_clone_cursor_exec(C, op); -} - -void PAINT_OT_clone_cursor_set(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Set Clone Cursor"; - ot->idname = "PAINT_OT_clone_cursor_set"; - ot->description = "Set the location of the clone cursor"; - - /* api callbacks */ - ot->exec = set_clone_cursor_exec; - ot->invoke = set_clone_cursor_invoke; - ot->poll = image_paint_3d_poll; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - RNA_def_float_vector(ot->srna, "location", 3, NULL, -FLT_MAX, FLT_MAX, "Location", "Cursor location in world space coordinates", -10000.0f, 10000.0f); -} - /******************** texture paint toggle operator ********************/ static int texture_paint_toggle_poll(bContext *C) @@ -5937,11 +1025,6 @@ int image_texture_paint_poll(bContext *C) return (texture_paint_poll(C) || image_paint_poll(C)); } -int uv_sculpt_poll(bContext *C) -{ - return uv_sculpt_brush_poll(C); -} - int facemask_paint_poll(bContext *C) { return paint_facesel_test(CTX_data_active_object(C)); @@ -5956,201 +1039,4 @@ int mask_paint_poll(bContext *C) { return paint_facesel_test(CTX_data_active_object(C)) || paint_vertsel_test(CTX_data_active_object(C)); } -/* use project paint to re-apply an image */ -static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) -{ - Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image")); - Scene *scene = CTX_data_scene(C); - ProjPaintState ps = {NULL}; - int orig_brush_size; - IDProperty *idgroup; - IDProperty *view_data = NULL; - - project_state_init(C, OBACT, &ps); - - if (ps.ob == NULL || ps.ob->type != OB_MESH) { - BKE_report(op->reports, RPT_ERROR, "No active mesh object"); - return OPERATOR_CANCELLED; - } - - if (image == NULL) { - BKE_report(op->reports, RPT_ERROR, "Image could not be found"); - return OPERATOR_CANCELLED; - } - - ps.reproject_image = image; - ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); - - if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) { - BKE_report(op->reports, RPT_ERROR, "Image data could not be found"); - return OPERATOR_CANCELLED; - } - - idgroup = IDP_GetProperties(&image->id, 0); - - if (idgroup) { - view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY); - - /* type check to make sure its ok */ - if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) { - BKE_report(op->reports, RPT_ERROR, "Image project data invalid"); - return OPERATOR_CANCELLED; - } - } - - if (view_data) { - /* image has stored view projection info */ - ps.source = PROJ_SRC_IMAGE_VIEW; - } - else { - ps.source = PROJ_SRC_IMAGE_CAM; - - if (scene->camera == NULL) { - BKE_report(op->reports, RPT_ERROR, "No active camera set"); - return OPERATOR_CANCELLED; - } - } - - /* override */ - ps.is_texbrush = 0; - ps.do_masking = false; - orig_brush_size = BKE_brush_size_get(scene, ps.brush); - BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */ - - ps.tool = PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */ - - scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING; - - undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name, - image_undo_restore, image_undo_free); - - /* allocate and initialize spatial data structures */ - project_paint_begin(&ps); - - if (ps.dm == NULL) { - BKE_brush_size_set(scene, ps.brush, orig_brush_size); - return OPERATOR_CANCELLED; - } - else { - float pos[2] = {0.0, 0.0}; - float lastpos[2] = {0.0, 0.0}; - int a; - - for (a = 0; a < ps.image_tot; a++) - partial_redraw_array_init(ps.projImages[a].partRedrawRect); - - project_paint_op(&ps, NULL, lastpos, pos); - - project_image_refresh_tagged(&ps); - - for (a = 0; a < ps.image_tot; a++) { - GPU_free_image(ps.projImages[a].ima); - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima); - } - } - - project_paint_end(&ps); - - scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING; - BKE_brush_size_set(scene, ps.brush, orig_brush_size); - - return OPERATOR_FINISHED; -} - -void PAINT_OT_project_image(wmOperatorType *ot) -{ - PropertyRNA *prop; - - /* identifiers */ - ot->name = "Project Image"; - ot->idname = "PAINT_OT_project_image"; - ot->description = "Project an edited render from the active camera back onto the object"; - - /* api callbacks */ - ot->invoke = WM_enum_search_invoke; - ot->exec = texture_paint_camera_project_exec; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", ""); - RNA_def_enum_funcs(prop, RNA_image_itemf); - ot->prop = prop; -} - -static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) -{ - Image *image; - ImBuf *ibuf; - char filename[FILE_MAX]; - - Scene *scene = CTX_data_scene(C); - ToolSettings *settings = scene->toolsettings; - int w = settings->imapaint.screen_grab_size[0]; - int h = settings->imapaint.screen_grab_size[1]; - int maxsize; - char err_out[256] = "unknown"; - - RNA_string_get(op->ptr, "filepath", filename); - - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize); - if (w > maxsize) w = maxsize; - if (h > maxsize) h = maxsize; - - ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, R_ALPHAPREMUL, err_out); - if (!ibuf) { - /* Mostly happens when OpenGL offscreen buffer was failed to create, */ - /* but could be other reasons. Should be handled in the future. nazgul */ - BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out); - return OPERATOR_CANCELLED; - } - - image = BKE_image_add_from_imbuf(ibuf); - - if (image) { - /* now for the trickyness. store the view projection here! - * re-projection will reuse this */ - View3D *v3d = CTX_wm_view3d(C); - RegionView3D *rv3d = CTX_wm_region_view3d(C); - - IDPropertyTemplate val; - IDProperty *idgroup = IDP_GetProperties(&image->id, 1); - IDProperty *view_data; - int orth; - float *array; - - val.array.len = PROJ_VIEW_DATA_SIZE; - val.array.type = IDP_FLOAT; - view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID); - - array = (float *)IDP_Array(view_data); - memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat) / sizeof(float); - memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat) / sizeof(float); - orth = project_paint_view_clip(v3d, rv3d, &array[0], &array[1]); - array[2] = orth ? 1.0f : 0.0f; /* using float for a bool is dodgy but since its an extra member in the array... easier then adding a single bool prop */ - - IDP_AddToGroup(idgroup, view_data); - - rename_id(&image->id, "image_view"); - } - - return OPERATOR_FINISHED; -} - -void PAINT_OT_image_from_view(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Image from View"; - ot->idname = "PAINT_OT_image_from_view"; - ot->description = "Make an image from the current 3D view for re-projection"; - - /* api callbacks */ - ot->exec = texture_paint_image_from_view_exec; - ot->poll = ED_operator_region_view3d_active; - - /* flags */ - ot->flag = OPTYPE_REGISTER; - - RNA_def_string_file_name(ot->srna, "filepath", "", FILE_MAX, "File Path", "Name of the file"); -} diff --git a/source/blender/editors/sculpt_paint/paint_image_2d.c b/source/blender/editors/sculpt_paint/paint_image_2d.c index 84250853f38..ed1b25d1b4e 100644 --- a/source/blender/editors/sculpt_paint/paint_image_2d.c +++ b/source/blender/editors/sculpt_paint/paint_image_2d.c @@ -35,17 +35,56 @@ #include "DNA_brush_types.h" #include "DNA_scene_types.h" +#include "DNA_space_types.h" +#include "DNA_object_types.h" +#include "BLI_math.h" + +#include "BKE_context.h" #include "BKE_brush.h" +#include "BKE_main.h" +#include "BKE_image.h" +#include "BKE_paint.h" +#include "BKE_report.h" -#include "BLI_math.h" +#include "ED_screen.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" +#include "IMB_colormanagement.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_view2d.h" #include "RE_shader_ext.h" - /* Brush Painting for 2D image editor */ +#include "GPU_draw.h" + +#include "paint_intern.h" + +/* Brush Painting for 2D image editor */ + +/* Defines and Structs */ +/* FTOCHAR as inline function */ +BLI_INLINE unsigned char f_to_char(const float val) +{ + return FTOCHAR(val); +} +#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ +} (void)0 + +#define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \ + (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ + (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ + (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ +} (void)0 + +#define IMAPAINT_FLOAT_RGB_COPY(a, b) copy_v3_v3(a, b) typedef struct BrushPainterCache { short enabled; @@ -57,38 +96,55 @@ typedef struct BrushPainterCache { int lastsize; float lastalpha; float lastjitter; + float last_rotation; ImBuf *ibuf; ImBuf *texibuf; ImBuf *maskibuf; } BrushPainterCache; -struct BrushPainter { +typedef struct BrushPainter { Scene *scene; Brush *brush; - float lastmousepos[2]; /* mouse position of last paint call */ - - float accumdistance; /* accumulated distance of brush since last paint op */ float lastpaintpos[2]; /* position of last paint op */ float startpaintpos[2]; /* position of first paint */ - double accumtime; /* accumulated time since last paint op (airbrush) */ - double lasttime; /* time of last update */ - - float lastpressure; - short firsttouch; /* first paint op */ - float startsize; - float startalpha; - float startjitter; - float startspacing; - BrushPainterCache cache; -}; +} BrushPainter; + +typedef struct ImagePaintRegion { + int destx, desty; + int srcx, srcy; + int width, height; +} ImagePaintRegion; + +typedef struct ImagePaintState { + BrushPainter *painter; + SpaceImage *sima; + View2D *v2d; + Scene *scene; + bScreen *screen; -BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush) + Brush *brush; + short tool, blend; + Image *image; + ImBuf *canvas; + ImBuf *clonecanvas; + char *warnpackedfile; + char *warnmultifile; + + /* viewport texture paint only, but _not_ project paint */ + Object *ob; + int faceindex; + float uv[2]; + int do_facesel; +} ImagePaintState; + + +static BrushPainter *brush_painter_2d_new(Scene *scene, Brush *brush) { BrushPainter *painter = MEM_callocN(sizeof(BrushPainter), "BrushPainter"); @@ -97,29 +153,11 @@ BrushPainter *BKE_brush_painter_new(Scene *scene, Brush *brush) painter->firsttouch = 1; painter->cache.lastsize = -1; /* force ibuf create in refresh */ - painter->startsize = BKE_brush_size_get(scene, brush); - painter->startalpha = BKE_brush_alpha_get(scene, brush); - painter->startjitter = brush->jitter; - painter->startspacing = brush->spacing; - return painter; } -static void brush_pressure_apply(BrushPainter *painter, Brush *brush, float pressure) -{ - if (BKE_brush_use_alpha_pressure(painter->scene, brush)) - BKE_brush_alpha_set(painter->scene, brush, max_ff(0.0f, painter->startalpha * pressure)); - if (BKE_brush_use_size_pressure(painter->scene, brush)) - BKE_brush_size_set(painter->scene, brush, max_ff(1.0f, painter->startsize * pressure)); - if (brush->flag & BRUSH_JITTER_PRESSURE) - brush->jitter = max_ff(0.0f, painter->startjitter * pressure); - if (brush->flag & BRUSH_SPACING_PRESSURE) - brush->spacing = max_ff(1.0f, painter->startspacing * (1.5f - pressure)); -} - - -void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short texonly, int size) +static void brush_painter_2d_require_imbuf(BrushPainter *painter, short flt, short texonly, int size) { if ((painter->cache.flt != flt) || (painter->cache.size != size) || ((painter->cache.texonly != texonly) && texonly)) @@ -142,22 +180,15 @@ void BKE_brush_painter_require_imbuf(BrushPainter *painter, short flt, short tex painter->cache.enabled = 1; } -void BKE_brush_painter_free(BrushPainter *painter) +static void brush_painter_2d_free(BrushPainter *painter) { - Brush *brush = painter->brush; - - BKE_brush_size_set(painter->scene, brush, painter->startsize); - BKE_brush_alpha_set(painter->scene, brush, painter->startalpha); - brush->jitter = painter->startjitter; - brush->spacing = painter->startspacing; - if (painter->cache.ibuf) IMB_freeImBuf(painter->cache.ibuf); if (painter->cache.texibuf) IMB_freeImBuf(painter->cache.texibuf); if (painter->cache.maskibuf) IMB_freeImBuf(painter->cache.maskibuf); MEM_freeN(painter); } -static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, +static void brush_painter_2d_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, int x, int y, int w, int h, int xt, int yt, const float pos[2]) { @@ -204,7 +235,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex_2D(scene, brush, xy, tf, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, tf, NULL); } bf[0] = tf[0] * mf[0]; @@ -235,7 +266,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, xy[0] = x + xoff; xy[1] = y + yoff; - BKE_brush_sample_tex_2D(scene, brush, xy, rgba, 0); + BKE_brush_sample_tex_2D(scene, brush, xy, rgba, NULL); rgba_float_to_uchar(t, rgba); } @@ -248,7 +279,7 @@ static void brush_painter_do_partial(BrushPainter *painter, ImBuf *oldtexibuf, } } -static void brush_painter_tiled_tex_partial_update(BrushPainter *painter, const float pos[2]) +static void brush_painter_2d_tiled_tex_partial_update(BrushPainter *painter, const float pos[2]) { const Scene *scene = painter->scene; Brush *brush = painter->brush; @@ -286,25 +317,26 @@ static void brush_painter_tiled_tex_partial_update(BrushPainter *painter, const /* blend existing texture in new position */ if ((x1 < x2) && (y1 < y2)) - brush_painter_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos); + brush_painter_2d_do_partial(painter, oldtexibuf, x1, y1, x2, y2, srcx, srcy, pos); if (oldtexibuf) IMB_freeImBuf(oldtexibuf); /* sample texture in new areas */ if ((0 < x1) && (0 < ibuf->y)) - brush_painter_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos); + brush_painter_2d_do_partial(painter, NULL, 0, 0, x1, ibuf->y, 0, 0, pos); if ((x2 < ibuf->x) && (0 < ibuf->y)) - brush_painter_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos); + brush_painter_2d_do_partial(painter, NULL, x2, 0, ibuf->x, ibuf->y, 0, 0, pos); if ((x1 < x2) && (0 < y1)) - brush_painter_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos); + brush_painter_2d_do_partial(painter, NULL, x1, 0, x2, y1, 0, 0, pos); if ((x1 < x2) && (y2 < ibuf->y)) - brush_painter_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos); + brush_painter_2d_do_partial(painter, NULL, x1, y2, x2, ibuf->y, 0, 0, pos); } -static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction) +static void brush_painter_2d_refresh_cache(BrushPainter *painter, const float pos[2], int use_color_correction) { const Scene *scene = painter->scene; + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; Brush *brush = painter->brush; BrushPainterCache *cache = &painter->cache; MTex *mtex = &brush->mtex; @@ -313,10 +345,16 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 const int diameter = 2 * BKE_brush_size_get(scene, brush); const float alpha = BKE_brush_alpha_get(scene, brush); const bool do_tiled = ELEM(brush->mtex.brush_map_mode, MTEX_MAP_MODE_TILED, MTEX_MAP_MODE_3D); + float rotation = -mtex->rot; + + if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { + rotation += ups->brush_rotation; + } if (diameter != cache->lastsize || alpha != cache->lastalpha || - brush->jitter != cache->lastjitter) + brush->jitter != cache->lastjitter || + rotation != cache->last_rotation) { if (cache->ibuf) { IMB_freeImBuf(cache->ibuf); @@ -332,7 +370,7 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 if (do_tiled) { BKE_brush_imbuf_new(scene, brush, flt, 3, size, &cache->maskibuf, use_color_correction); - brush_painter_tiled_tex_partial_update(painter, pos); + brush_painter_2d_tiled_tex_partial_update(painter, pos); } else BKE_brush_imbuf_new(scene, brush, flt, 2, size, &cache->ibuf, use_color_correction); @@ -340,221 +378,447 @@ static void brush_painter_refresh_cache(BrushPainter *painter, const float pos[2 cache->lastsize = diameter; cache->lastalpha = alpha; cache->lastjitter = brush->jitter; + cache->last_rotation = rotation; } else if (do_tiled && mtex && mtex->tex) { int dx = (int)painter->lastpaintpos[0] - (int)pos[0]; int dy = (int)painter->lastpaintpos[1] - (int)pos[1]; if ((dx != 0) || (dy != 0)) - brush_painter_tiled_tex_partial_update(painter, pos); + brush_painter_2d_tiled_tex_partial_update(painter, pos); } } -void BKE_brush_painter_break_stroke(BrushPainter *painter) +/* keep these functions in sync */ +static void paint_2d_ibuf_rgb_get(ImBuf *ibuf, int x, int y, const short is_torus, float r_rgb[3]) { - painter->firsttouch = 1; + if (is_torus) { + x %= ibuf->x; + if (x < 0) x += ibuf->x; + y %= ibuf->y; + if (y < 0) y += ibuf->y; + } + + if (ibuf->rect_float) { + float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4; + IMAPAINT_FLOAT_RGB_COPY(r_rgb, rrgbf); + } + else { + char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4; + IMAPAINT_CHAR_RGB_TO_FLOAT(r_rgb, rrgb); + } } +static void paint_2d_ibuf_rgb_set(ImBuf *ibuf, int x, int y, const short is_torus, const float rgb[3]) +{ + if (is_torus) { + x %= ibuf->x; + if (x < 0) x += ibuf->x; + y %= ibuf->y; + if (y < 0) y += ibuf->y; + } + if (ibuf->rect_float) { + float *rrgbf = ibuf->rect_float + (ibuf->x * y + x) * 4; + IMAPAINT_FLOAT_RGB_COPY(rrgbf, rgb); + } + else { + char *rrgb = (char *)ibuf->rect + (ibuf->x * y + x) * 4; + IMAPAINT_FLOAT_RGB_TO_CHAR(rrgb, rgb); + } +} -int BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, const float pos[2], double time, float pressure, - void *user, int use_color_correction) +static int paint_2d_ibuf_add_if(ImBuf *ibuf, unsigned int x, unsigned int y, float *outrgb, short torus) { - Scene *scene = painter->scene; - Brush *brush = painter->brush; - int totpaintops = 0; + float inrgb[3]; - if (pressure == 0.0f) { - if (painter->lastpressure) // XXX - hack, operator misses - pressure = painter->lastpressure; - else - pressure = 1.0f; /* zero pressure == not using tablet */ - } - if (painter->firsttouch) { - /* paint exactly once on first touch */ - painter->startpaintpos[0] = pos[0]; - painter->startpaintpos[1] = pos[1]; - - brush_pressure_apply(painter, brush, pressure); - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, pos, use_color_correction); - totpaintops += func(user, painter->cache.ibuf, pos, pos); - - painter->lasttime = time; - painter->firsttouch = 0; - painter->lastpaintpos[0] = pos[0]; - painter->lastpaintpos[1] = pos[1]; - } -#if 0 - else if (painter->brush->flag & BRUSH_AIRBRUSH) { - float spacing, step, paintpos[2], dmousepos[2], len; - double starttime, curtime = time; - - /* compute brush spacing adapted to brush size */ - spacing = brush->rate; //radius*brush->spacing * 0.01f; - - /* setup starting time, direction vector and accumulated time */ - starttime = painter->accumtime; - sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); - len = normalize_v2(dmousepos); - painter->accumtime += curtime - painter->lasttime; - - /* do paint op over unpainted time distance */ - while (painter->accumtime >= spacing) { - step = (spacing - starttime) * len; - paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step; - paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step; - - if (painter->cache.enabled) - brush_painter_refresh_cache(painter); - totpaintops += func(user, painter->cache.ibuf, - painter->lastpaintpos, paintpos); - - painter->lastpaintpos[0] = paintpos[0]; - painter->lastpaintpos[1] = paintpos[1]; - painter->accumtime -= spacing; - starttime -= spacing; - } - - painter->lasttime = curtime; + // XXX: signed unsigned mismatch + if ((x >= (unsigned int)(ibuf->x)) || (y >= (unsigned int)(ibuf->y))) { + if (torus) paint_2d_ibuf_rgb_get(ibuf, x, y, 1, inrgb); + else return 0; } -#endif else { - float startdistance, spacing, step, paintpos[2], dmousepos[2], finalpos[2]; - float t, len, press; - const int radius = BKE_brush_size_get(scene, brush); - - /* compute brush spacing adapted to brush radius, spacing may depend - * on pressure, so update it */ - brush_pressure_apply(painter, brush, painter->lastpressure); - spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; - - /* setup starting distance, direction vector and accumulated distance */ - startdistance = painter->accumdistance; - sub_v2_v2v2(dmousepos, pos, painter->lastmousepos); - len = normalize_v2(dmousepos); - painter->accumdistance += len; - - if (brush->flag & BRUSH_SPACE) { - /* do paint op over unpainted distance */ - while ((len > 0.0f) && (painter->accumdistance >= spacing)) { - step = spacing - startdistance; - paintpos[0] = painter->lastmousepos[0] + dmousepos[0] * step; - paintpos[1] = painter->lastmousepos[1] + dmousepos[1] * step; - - t = step / len; - press = (1.0f - t) * painter->lastpressure + t * pressure; - brush_pressure_apply(painter, brush, press); - spacing = max_ff(1.0f, radius) * brush->spacing * 0.01f; - - BKE_brush_jitter_pos(scene, brush, paintpos, finalpos); - - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos, use_color_correction); - - totpaintops += - func(user, painter->cache.ibuf, painter->lastpaintpos, finalpos); - - painter->lastpaintpos[0] = paintpos[0]; - painter->lastpaintpos[1] = paintpos[1]; - painter->accumdistance -= spacing; - startdistance -= spacing; - } - } - else { - BKE_brush_jitter_pos(scene, brush, pos, finalpos); + paint_2d_ibuf_rgb_get(ibuf, x, y, 0, inrgb); + } - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos, use_color_correction); + outrgb[0] += inrgb[0]; + outrgb[1] += inrgb[1]; + outrgb[2] += inrgb[2]; - totpaintops += func(user, painter->cache.ibuf, pos, finalpos); + return 1; +} - painter->lastpaintpos[0] = pos[0]; - painter->lastpaintpos[1] = pos[1]; - painter->accumdistance = 0; - } +static void paint_2d_lift_soften(ImBuf *ibuf, ImBuf *ibufb, int *pos, const short is_torus) +{ + int x, y, count, xi, yi, xo, yo; + int out_off[2], in_off[2], dim[2]; + float outrgb[3]; + + dim[0] = ibufb->x; + dim[1] = ibufb->y; + in_off[0] = pos[0]; + in_off[1] = pos[1]; + out_off[0] = out_off[1] = 0; + + if (!is_torus) { + IMB_rectclip(ibuf, ibufb, &in_off[0], &in_off[1], &out_off[0], + &out_off[1], &dim[0], &dim[1]); + + if ((dim[0] == 0) || (dim[1] == 0)) + return; + } - /* do airbrush paint ops, based on the number of paint ops left over - * from regular painting. this is a temporary solution until we have - * accurate time stamps for mouse move events */ - if (brush->flag & BRUSH_AIRBRUSH) { - double curtime = time; - double painttime = brush->rate * totpaintops; + for (y = 0; y < dim[1]; y++) { + for (x = 0; x < dim[0]; x++) { + /* get input pixel */ + xi = in_off[0] + x; + yi = in_off[1] + y; - painter->accumtime += curtime - painter->lasttime; - if (painter->accumtime <= painttime) - painter->accumtime = 0.0; - else - painter->accumtime -= painttime; + count = 1; + paint_2d_ibuf_rgb_get(ibuf, xi, yi, is_torus, outrgb); - while (painter->accumtime >= (double)brush->rate) { - brush_pressure_apply(painter, brush, pressure); + count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi - 1, outrgb, is_torus); + count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi, outrgb, is_torus); + count += paint_2d_ibuf_add_if(ibuf, xi - 1, yi + 1, outrgb, is_torus); - BKE_brush_jitter_pos(scene, brush, pos, finalpos); + count += paint_2d_ibuf_add_if(ibuf, xi, yi - 1, outrgb, is_torus); + count += paint_2d_ibuf_add_if(ibuf, xi, yi + 1, outrgb, is_torus); - if (painter->cache.enabled) - brush_painter_refresh_cache(painter, finalpos, use_color_correction); + count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi - 1, outrgb, is_torus); + count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi, outrgb, is_torus); + count += paint_2d_ibuf_add_if(ibuf, xi + 1, yi + 1, outrgb, is_torus); - totpaintops += - func(user, painter->cache.ibuf, painter->lastmousepos, finalpos); - painter->accumtime -= (double)brush->rate; - } + mul_v3_fl(outrgb, 1.0f / (float)count); - painter->lasttime = curtime; + /* write into brush buffer */ + xo = out_off[0] + x; + yo = out_off[1] + y; + paint_2d_ibuf_rgb_set(ibufb, xo, yo, 0, outrgb); } } +} - painter->lastmousepos[0] = pos[0]; - painter->lastmousepos[1] = pos[1]; - painter->lastpressure = pressure; +static void paint_2d_set_region(ImagePaintRegion *region, int destx, int desty, int srcx, int srcy, int width, int height) +{ + region->destx = destx; + region->desty = desty; + region->srcx = srcx; + region->srcy = srcy; + region->width = width; + region->height = height; +} + +static int paint_2d_torus_split_region(ImagePaintRegion region[4], ImBuf *dbuf, ImBuf *sbuf) +{ + int destx = region->destx; + int desty = region->desty; + int srcx = region->srcx; + int srcy = region->srcy; + int width = region->width; + int height = region->height; + int origw, origh, w, h, tot = 0; + + /* convert destination and source coordinates to be within image */ + destx = destx % dbuf->x; + if (destx < 0) destx += dbuf->x; + desty = desty % dbuf->y; + if (desty < 0) desty += dbuf->y; + srcx = srcx % sbuf->x; + if (srcx < 0) srcx += sbuf->x; + srcy = srcy % sbuf->y; + if (srcy < 0) srcy += sbuf->y; + + /* clip width of blending area to destination imbuf, to avoid writing the + * same pixel twice */ + origw = w = (width > dbuf->x) ? dbuf->x : width; + origh = h = (height > dbuf->y) ? dbuf->y : height; + + /* clip within image */ + IMB_rectclip(dbuf, sbuf, &destx, &desty, &srcx, &srcy, &w, &h); + paint_2d_set_region(®ion[tot++], destx, desty, srcx, srcy, w, h); + + /* do 3 other rects if needed */ + if (w < origw) + paint_2d_set_region(®ion[tot++], (destx + w) % dbuf->x, desty, (srcx + w) % sbuf->x, srcy, origw - w, h); + if (h < origh) + paint_2d_set_region(®ion[tot++], destx, (desty + h) % dbuf->y, srcx, (srcy + h) % sbuf->y, w, origh - h); + if ((w < origw) && (h < origh)) + paint_2d_set_region(®ion[tot++], (destx + w) % dbuf->x, (desty + h) % dbuf->y, (srcx + w) % sbuf->x, (srcy + h) % sbuf->y, origw - w, origh - h); + + return tot; +} - BKE_brush_alpha_set(scene, brush, painter->startalpha); - BKE_brush_size_set(scene, brush, painter->startsize); - brush->jitter = painter->startjitter; - brush->spacing = painter->startspacing; +static void paint_2d_lift_smear(ImBuf *ibuf, ImBuf *ibufb, int *pos) +{ + ImagePaintRegion region[4]; + int a, tot; + + paint_2d_set_region(region, 0, 0, pos[0], pos[1], ibufb->x, ibufb->y); + tot = paint_2d_torus_split_region(region, ibufb, ibuf); + + for (a = 0; a < tot; a++) + IMB_rectblend(ibufb, ibuf, region[a].destx, region[a].desty, + region[a].srcx, region[a].srcy, + region[a].width, region[a].height, IMB_BLEND_COPY_RGB); +} - return totpaintops; +static ImBuf *paint_2d_lift_clone(ImBuf *ibuf, ImBuf *ibufb, int *pos) +{ + /* note: allocImbuf returns zero'd memory, so regions outside image will + * have zero alpha, and hence not be blended onto the image */ + int w = ibufb->x, h = ibufb->y, destx = 0, desty = 0, srcx = pos[0], srcy = pos[1]; + ImBuf *clonebuf = IMB_allocImBuf(w, h, ibufb->planes, ibufb->flags); + + IMB_rectclip(clonebuf, ibuf, &destx, &desty, &srcx, &srcy, &w, &h); + IMB_rectblend(clonebuf, ibuf, destx, desty, srcx, srcy, w, h, + IMB_BLEND_COPY_RGB); + IMB_rectblend(clonebuf, ibufb, destx, desty, destx, desty, w, h, + IMB_BLEND_COPY_ALPHA); + + return clonebuf; } +static void paint_2d_convert_brushco(ImBuf *ibufb, const float pos[2], int ipos[2]) +{ + ipos[0] = (int)floorf((pos[0] - ibufb->x / 2) + 1.0f); + ipos[1] = (int)floorf((pos[1] - ibufb->y / 2) + 1.0f); +} -/* TODO: should probably be unified with BrushPainter stuff? */ -unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) +static int paint_2d_op(void *state, ImBuf *ibufb, const float lastpos[2], const float pos[2]) { - unsigned int *texcache = NULL; - MTex *mtex = &br->mtex; - TexResult texres = {0}; - int hasrgb, ix, iy; - int side = half_side * 2; - - if (mtex->tex) { - float x, y, step = 2.0 / side, co[3]; - - texcache = MEM_callocN(sizeof(int) * side * side, "Brush texture cache"); - - /*do normalized cannonical view coords for texture*/ - for (y = -1.0, iy = 0; iy < side; iy++, y += step) { - for (x = -1.0, ix = 0; ix < side; ix++, x += step) { - co[0] = x; - co[1] = y; - co[2] = 0.0f; - - /* This is copied from displace modifier code */ - hasrgb = multitex_ext(mtex->tex, co, NULL, NULL, 0, &texres, NULL); - - /* if the texture gave an RGB value, we assume it didn't give a valid - * intensity, so calculate one (formula from do_material_tex). - * if the texture didn't give an RGB value, copy the intensity across - */ - if (hasrgb & TEX_RGB) - texres.tin = rgb_to_grayscale(&texres.tr); - - ((char *)texcache)[(iy * side + ix) * 4] = - ((char *)texcache)[(iy * side + ix) * 4 + 1] = - ((char *)texcache)[(iy * side + ix) * 4 + 2] = - ((char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(texres.tin * 255.0f); - } + ImagePaintState *s = ((ImagePaintState *)state); + ImBuf *clonebuf = NULL, *frombuf; + ImagePaintRegion region[4]; + short torus = s->brush->flag & BRUSH_TORUS; + short blend = s->blend; + float *offset = s->brush->clone.offset; + float liftpos[2]; + int bpos[2], blastpos[2], bliftpos[2]; + int a, tot; + + paint_2d_convert_brushco(ibufb, pos, bpos); + + /* lift from canvas */ + if (s->tool == PAINT_TOOL_SOFTEN) { + paint_2d_lift_soften(s->canvas, ibufb, bpos, torus); + } + else if (s->tool == PAINT_TOOL_SMEAR) { + if (lastpos[0] == pos[0] && lastpos[1] == pos[1]) + return 0; + + paint_2d_convert_brushco(ibufb, lastpos, blastpos); + paint_2d_lift_smear(s->canvas, ibufb, blastpos); + } + else if (s->tool == PAINT_TOOL_CLONE && s->clonecanvas) { + liftpos[0] = pos[0] - offset[0] * s->canvas->x; + liftpos[1] = pos[1] - offset[1] * s->canvas->y; + + paint_2d_convert_brushco(ibufb, liftpos, bliftpos); + clonebuf = paint_2d_lift_clone(s->clonecanvas, ibufb, bliftpos); + } + + frombuf = (clonebuf) ? clonebuf : ibufb; + + if (torus) { + paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y); + tot = paint_2d_torus_split_region(region, s->canvas, frombuf); + } + else { + paint_2d_set_region(region, bpos[0], bpos[1], 0, 0, frombuf->x, frombuf->y); + tot = 1; + } + + /* blend into canvas */ + for (a = 0; a < tot; a++) { + imapaint_dirty_region(s->image, s->canvas, + region[a].destx, region[a].desty, + region[a].width, region[a].height); + + IMB_rectblend(s->canvas, frombuf, + region[a].destx, region[a].desty, + region[a].srcx, region[a].srcy, + region[a].width, region[a].height, blend); + } + + if (clonebuf) IMB_freeImBuf(clonebuf); + + return 1; +} + + +static int paint_2d_canvas_set(ImagePaintState *s, Image *ima) +{ + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); + + /* verify that we can paint and set canvas */ + if (ima == NULL) { + return 0; + } + else if (ima->packedfile && ima->rr) { + s->warnpackedfile = ima->id.name + 2; + return 0; + } + else if (ibuf && ibuf->channels != 4) { + s->warnmultifile = ima->id.name + 2; + return 0; + } + else if (!ibuf || !(ibuf->rect || ibuf->rect_float)) + return 0; + + s->image = ima; + s->canvas = ibuf; + + /* set clone canvas */ + if (s->tool == PAINT_TOOL_CLONE) { + ima = s->brush->clone.image; + ibuf = BKE_image_acquire_ibuf(ima, s->sima ? &s->sima->iuser : NULL, NULL); + + if (!ima || !ibuf || !(ibuf->rect || ibuf->rect_float)) { + BKE_image_release_ibuf(ima, ibuf, NULL); + BKE_image_release_ibuf(s->image, s->canvas, NULL); + return 0; + } + + s->clonecanvas = ibuf; + + /* temporarily add float rect for cloning */ + if (s->canvas->rect_float && !s->clonecanvas->rect_float) { + IMB_float_from_rect(s->clonecanvas); } + else if (!s->canvas->rect_float && !s->clonecanvas->rect) + IMB_rect_from_float(s->clonecanvas); } - return texcache; + return 1; } +static void paint_2d_canvas_free(ImagePaintState *s) +{ + BKE_image_release_ibuf(s->image, s->canvas, NULL); + BKE_image_release_ibuf(s->brush->clone.image, s->clonecanvas, NULL); +} + +int paint_2d_stroke(void *ps, const int prev_mval[2], const int mval[2], int eraser) +{ + float newuv[2], olduv[2]; + int redraw = 0; + ImagePaintState *s = ps; + BrushPainter *painter = s->painter; + ImBuf *ibuf = BKE_image_acquire_ibuf(s->image, s->sima ? &s->sima->iuser : NULL, NULL); + const bool is_data = (ibuf && ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA); + + if (!ibuf) + return 0; + + s->blend = s->brush->blend; + if (eraser) + s->blend = IMB_BLEND_ERASE_ALPHA; + + UI_view2d_region_to_view(s->v2d, mval[0], mval[1], &newuv[0], &newuv[1]); + UI_view2d_region_to_view(s->v2d, prev_mval[0], prev_mval[1], &olduv[0], &olduv[1]); + + newuv[0] *= ibuf->x; + newuv[1] *= ibuf->y; + + olduv[0] *= ibuf->x; + olduv[1] *= ibuf->y; + + if (painter->firsttouch) { + /* paint exactly once on first touch */ + painter->startpaintpos[0] = newuv[0]; + painter->startpaintpos[1] = newuv[1]; + + painter->firsttouch = 0; + copy_v2_v2(painter->lastpaintpos, newuv); + } + else { + copy_v2_v2(painter->lastpaintpos, olduv); + } + /* OCIO_TODO: float buffers are now always linear, so always use color correction + * this should probably be changed when texture painting color space is supported + */ + brush_painter_2d_require_imbuf(painter, ((ibuf->rect_float) ? 1 : 0), 0, 0); + + if (painter->cache.enabled) + brush_painter_2d_refresh_cache(painter, newuv, is_data == false); + + if (paint_2d_op(s, painter->cache.ibuf, olduv, newuv)) { + imapaint_image_update(s->sima, s->image, ibuf, false); + BKE_image_release_ibuf(s->image, ibuf, NULL); + redraw |= 1; + } + else { + BKE_image_release_ibuf(s->image, ibuf, NULL); + } + + if (redraw) + imapaint_clear_partial_redraw(); + + return redraw; +} + +void *paint_2d_new_stroke(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + Brush *brush = paint_brush(&settings->imapaint.paint); + + ImagePaintState *s = MEM_callocN(sizeof(ImagePaintState), "ImagePaintState"); + + s->sima = CTX_wm_space_image(C); + s->v2d = &CTX_wm_region(C)->v2d; + s->scene = scene; + s->screen = CTX_wm_screen(C); + + s->brush = brush; + s->tool = brush->imagepaint_tool; + s->blend = brush->blend; + + s->image = s->sima->image; + + if (!paint_2d_canvas_set(s, s->image)) { + if (s->warnmultifile) + BKE_report(op->reports, RPT_WARNING, "Image requires 4 color channels to paint"); + if (s->warnpackedfile) + BKE_report(op->reports, RPT_WARNING, "Packed MultiLayer files cannot be painted"); + + MEM_freeN(s); + return NULL; + } + + paint_brush_init_tex(s->brush); + + /* create painter */ + s->painter = brush_painter_2d_new(scene, s->brush); + + return s; +} + +void paint_2d_redraw (const bContext *C, void *ps, int final) +{ + ImagePaintState *s = ps; + + if (final) { + if (s->image && !(s->sima && s->sima->lock)) + GPU_free_image(s->image); + + /* compositor listener deals with updating */ + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image); + } + else { + if (!s->sima || !s->sima->lock) + ED_region_tag_redraw(CTX_wm_region(C)); + else + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, s->image); + } +} + +void paint_2d_stroke_done(void *ps) +{ + ImagePaintState *s = ps; + + paint_2d_canvas_free(s); + brush_painter_2d_free(s->painter); + paint_brush_exit_tex(s->brush); + + MEM_freeN(s); +} diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c new file mode 100644 index 00000000000..96916236279 --- /dev/null +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -0,0 +1,4465 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: some of this file. + * + * Contributor(s): Jens Ole Wund (bjornmose), Campbell Barton (ideasman42) + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/sculpt_paint/paint_image_proj.c + * \ingroup edsculpt + * \brief Functions to paint images in 2D and 3D. + */ + +#include <float.h> +#include <string.h> +#include <stdio.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#ifdef WIN32 +# include "BLI_winstuff.h" +#endif + +#include "BLI_math.h" +#include "BLI_blenlib.h" +#include "BLI_linklist.h" +#include "BLI_memarena.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "PIL_time.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "DNA_brush_types.h" +#include "DNA_mesh_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" + +#include "BKE_camera.h" +#include "BKE_context.h" +#include "BKE_depsgraph.h" +#include "BKE_DerivedMesh.h" +#include "BKE_idprop.h" +#include "BKE_brush.h" +#include "BKE_image.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_mesh.h" +#include "BKE_node.h" +#include "BKE_object.h" +#include "BKE_paint.h" +#include "BKE_report.h" +#include "BKE_scene.h" +#include "BKE_colortools.h" + +#include "BKE_tessmesh.h" + +#include "BIF_gl.h" +#include "BIF_glutil.h" + +#include "UI_view2d.h" + +#include "ED_image.h" +#include "ED_screen.h" +#include "ED_sculpt.h" +#include "ED_uvedit.h" +#include "ED_view3d.h" +#include "ED_mesh.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "GPU_draw.h" + +#include "IMB_colormanagement.h" + +#include "paint_intern.h" + +/* Defines and Structs */ +/* FTOCHAR as inline function */ +BLI_INLINE unsigned char f_to_char(const float val) +{ + return FTOCHAR(val); +} + +#define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ + (c)[3] = f_to_char((f)[3]); \ +} (void)0 + +#define IMAPAINT_CHAR_RGBA_TO_FLOAT(f, c) { \ + (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ + (f)[1] = IMAPAINT_CHAR_TO_FLOAT((c)[1]); \ + (f)[2] = IMAPAINT_CHAR_TO_FLOAT((c)[2]); \ + (f)[3] = IMAPAINT_CHAR_TO_FLOAT((c)[3]); \ +} (void)0 + +#define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ +} (void)0 + +/* ProjectionPaint defines */ + +/* approx the number of buckets to have under the brush, + * used with the brush size to set the ps->buckets_x and ps->buckets_y value. + * + * When 3 - a brush should have ~9 buckets under it at once + * ...this helps for threading while painting as well as + * avoiding initializing pixels that wont touch the brush */ +#define PROJ_BUCKET_BRUSH_DIV 4 + +#define PROJ_BUCKET_RECT_MIN 4 +#define PROJ_BUCKET_RECT_MAX 256 + +#define PROJ_BOUNDBOX_DIV 8 +#define PROJ_BOUNDBOX_SQUARED (PROJ_BOUNDBOX_DIV * PROJ_BOUNDBOX_DIV) + +//#define PROJ_DEBUG_PAINT 1 +//#define PROJ_DEBUG_NOSEAMBLEED 1 +//#define PROJ_DEBUG_PRINT_CLIP 1 +#define PROJ_DEBUG_WINCLIP 1 + +/* projectFaceSeamFlags options */ +//#define PROJ_FACE_IGNORE (1<<0) /* When the face is hidden, backfacing or occluded */ +//#define PROJ_FACE_INIT (1<<1) /* When we have initialized the faces data */ +#define PROJ_FACE_SEAM1 (1 << 0) /* If this face has a seam on any of its edges */ +#define PROJ_FACE_SEAM2 (1 << 1) +#define PROJ_FACE_SEAM3 (1 << 2) +#define PROJ_FACE_SEAM4 (1 << 3) + +#define PROJ_FACE_NOSEAM1 (1 << 4) +#define PROJ_FACE_NOSEAM2 (1 << 5) +#define PROJ_FACE_NOSEAM3 (1 << 6) +#define PROJ_FACE_NOSEAM4 (1 << 7) + +#define PROJ_SRC_VIEW 1 +#define PROJ_SRC_IMAGE_CAM 2 +#define PROJ_SRC_IMAGE_VIEW 3 + +#define PROJ_VIEW_DATA_ID "view_data" +#define PROJ_VIEW_DATA_SIZE (4 * 4 + 4 * 4 + 3) /* viewmat + winmat + clipsta + clipend + is_ortho */ + + +/* a slightly scaled down face is used to get fake 3D location for edge pixels in the seams + * as this number approaches 1.0f the likelihood increases of float precision errors where + * it is occluded by an adjacent face */ +#define PROJ_FACE_SCALE_SEAM 0.99f + +#define PROJ_BUCKET_NULL 0 +#define PROJ_BUCKET_INIT (1 << 0) +// #define PROJ_BUCKET_CLONE_INIT (1<<1) + +/* used for testing doubles, if a point is on a line etc */ +#define PROJ_GEOM_TOLERANCE 0.00075f + +/* vert flags */ +#define PROJ_VERT_CULL 1 + +/* This is mainly a convenience struct used so we can keep an array of images we use + * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread + * because 'partRedrawRect' and 'touch' values would not be thread safe */ +typedef struct ProjPaintImage { + Image *ima; + ImBuf *ibuf; + ImagePaintPartialRedraw *partRedrawRect; + void **undoRect; /* only used to build undo tiles after painting */ + int touch; +} ProjPaintImage; + +/* Main projection painting struct passed to all projection painting functions */ +typedef struct ProjPaintState { + View3D *v3d; + RegionView3D *rv3d; + ARegion *ar; + Scene *scene; + int source; /* PROJ_SRC_**** */ + + Brush *brush; + short tool, blend, mode; + int orig_brush_size; + Object *ob; + /* end similarities with ImagePaintState */ + + DerivedMesh *dm; + int dm_totface; + int dm_totvert; + int dm_release; + + MVert *dm_mvert; + MFace *dm_mface; + MTFace *dm_mtface; + MTFace *dm_mtface_clone; /* other UV map, use for cloning between layers */ + MTFace *dm_mtface_stencil; + + /* projection painting only */ + MemArena *arena_mt[BLENDER_MAX_THREADS]; /* for multithreading, the first item is sometimes used for non threaded cases too */ + LinkNode **bucketRect; /* screen sized 2D array, each pixel has a linked list of ProjPixel's */ + LinkNode **bucketFaces; /* bucketRect aligned array linkList of faces overlapping each bucket */ + unsigned char *bucketFlags; /* store if the bucks have been initialized */ +#ifndef PROJ_DEBUG_NOSEAMBLEED + char *faceSeamFlags; /* store info about faces, if they are initialized etc*/ + float (*faceSeamUVs)[4][2]; /* expanded UVs for faces to use as seams */ + LinkNode **vertFaces; /* Only needed for when seam_bleed_px is enabled, use to find UV seams */ +#endif + char *vertFlags; /* store options per vert, now only store if the vert is pointing away from the view */ + int buckets_x; /* The size of the bucket grid, the grid span's screenMin/screenMax so you can paint outsize the screen or with 2 brushes at once */ + int buckets_y; + + ProjPaintImage *projImages; + + int pixel_sizeof; /* result of project_paint_pixel_sizeof(), constant per stroke */ + + int image_tot; /* size of projectImages array */ + + float (*screenCoords)[4]; /* verts projected into floating point screen space */ + + float screenMin[2]; /* 2D bounds for mesh verts on the screen's plane (screenspace) */ + float screenMax[2]; + float screen_width; /* Calculated from screenMin & screenMax */ + float screen_height; + int winx, winy; /* from the carea or from the projection render */ + + /* options for projection painting */ + int do_layer_clone; + int do_layer_stencil; + int do_layer_stencil_inv; + + short do_occlude; /* Use raytraced occlusion? - ortherwise will paint right through to the back*/ + short do_backfacecull; /* ignore faces with normals pointing away, skips a lot of raycasts if your normals are correctly flipped */ + short do_mask_normal; /* mask out pixels based on their normals */ + short do_new_shading_nodes; /* cache BKE_scene_use_new_shading_nodes value */ + float normal_angle; /* what angle to mask at*/ + float normal_angle_inner; + float normal_angle_range; /* difference between normal_angle and normal_angle_inner, for easy access */ + + short is_ortho; + bool do_masking; /* use masking during painting. Some operations such as airbrush may disable */ + short is_texbrush; /* only to avoid running */ +#ifndef PROJ_DEBUG_NOSEAMBLEED + float seam_bleed_px; +#endif + /* clone vars */ + float cloneOffset[2]; + + float projectMat[4][4]; /* Projection matrix, use for getting screen coords */ + float viewDir[3]; /* View vector, use for do_backfacecull and for ray casting with an ortho viewport */ + float viewPos[3]; /* View location in object relative 3D space, so can compare to verts */ + float clipsta, clipend; + + /* reproject vars */ + Image *reproject_image; + ImBuf *reproject_ibuf; + + + /* threads */ + int thread_tot; + int bucketMin[2]; + int bucketMax[2]; + int context_bucket_x, context_bucket_y; /* must lock threads while accessing these */ +} ProjPaintState; + +typedef union pixelPointer { + float *f_pt; /* float buffer */ + unsigned int *uint_pt; /* 2 ways to access a char buffer */ + unsigned char *ch_pt; +} PixelPointer; + +typedef union pixelStore { + unsigned char ch[4]; + unsigned int uint; + float f[4]; +} PixelStore; + +typedef struct ProjPixel { + float projCoSS[2]; /* the floating point screen projection of this pixel */ + float worldCoSS[3]; + /* Only used when the airbrush is disabled. + * Store the max mask value to avoid painting over an area with a lower opacity + * with an advantage that we can avoid touching the pixel at all, if the + * new mask value is lower then mask_max */ + unsigned short mask_max; + + /* for various reasons we may want to mask out painting onto this pixel */ + unsigned short mask; + + short x_px, y_px; + + PixelStore origColor; + PixelStore newColor; + PixelPointer pixel; + + short image_index; /* if anyone wants to paint onto more then 32768 images they can bite me */ + unsigned char bb_cell_index; +} ProjPixel; + +typedef struct ProjPixelClone { + struct ProjPixel __pp; + PixelStore clonepx; +} ProjPixelClone; + +/* blur, store surrounding colors */ +#define PROJ_PIXEL_SOFTEN_TOT 4 +/* blur picking offset (in screenspace) */ +#define PROJ_PIXEL_SOFTEN_OFS_PX 1.0f + +static const float proj_pixel_soften_v2[PROJ_PIXEL_SOFTEN_TOT][2] = { + {-PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, + { 0.0f, -PROJ_PIXEL_SOFTEN_OFS_PX}, + { 0.0f, PROJ_PIXEL_SOFTEN_OFS_PX}, + { PROJ_PIXEL_SOFTEN_OFS_PX, 0.0f}, +}; + +/* Finish projection painting structs */ + +static Image *project_paint_face_image(const ProjPaintState *ps, MTFace *dm_mtface, int face_index) +{ + Image *ima; + + if (ps->do_new_shading_nodes) { /* cached BKE_scene_use_new_shading_nodes result */ + MFace *mf = ps->dm_mface + face_index; + ED_object_get_active_image(ps->ob, mf->mat_nr + 1, &ima, NULL, NULL); + } + else { + ima = dm_mtface[face_index].tpage; + } + + return ima; +} + +/* fast projection bucket array lookup, use the safe version for bound checking */ +static int project_bucket_offset(const ProjPaintState *ps, const float projCoSS[2]) +{ + /* If we were not dealing with screenspace 2D coords we could simple do... + * ps->bucketRect[x + (y*ps->buckets_y)] */ + + /* please explain? + * projCoSS[0] - ps->screenMin[0] : zero origin + * ... / ps->screen_width : range from 0.0 to 1.0 + * ... * ps->buckets_x : use as a bucket index + * + * Second multiplication does similar but for vertical offset + */ + return ( (int)(((projCoSS[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x)) + + (((int)(((projCoSS[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y)) * ps->buckets_x); +} + +static int project_bucket_offset_safe(const ProjPaintState *ps, const float projCoSS[2]) +{ + int bucket_index = project_bucket_offset(ps, projCoSS); + + if (bucket_index < 0 || bucket_index >= ps->buckets_x * ps->buckets_y) { + return -1; + } + else { + return bucket_index; + } +} + +/* still use 2D X,Y space but this works for verts transformed by a perspective matrix, using their 4th component as a weight */ +static void barycentric_weights_v2_persp(const float v1[4], const float v2[4], const float v3[4], const float co[2], float w[3]) +{ + float wtot_inv, wtot; + + w[0] = area_tri_signed_v2(v2, v3, co) / v1[3]; + w[1] = area_tri_signed_v2(v3, v1, co) / v2[3]; + w[2] = area_tri_signed_v2(v1, v2, co) / v3[3]; + wtot = w[0] + w[1] + w[2]; + + if (wtot != 0.0f) { + wtot_inv = 1.0f / wtot; + + w[0] = w[0] * wtot_inv; + w[1] = w[1] * wtot_inv; + w[2] = w[2] * wtot_inv; + } + else /* dummy values for zero area face */ + w[0] = w[1] = w[2] = 1.0f / 3.0f; +} + +static float VecZDepthOrtho(const float pt[2], + const float v1[3], const float v2[3], const float v3[3], + float w[3]) +{ + barycentric_weights_v2(v1, v2, v3, pt, w); + return (v1[2] * w[0]) + (v2[2] * w[1]) + (v3[2] * w[2]); +} + +static float VecZDepthPersp(const float pt[2], + const float v1[4], const float v2[4], const float v3[4], + float w[3]) +{ + float wtot_inv, wtot; + float w_tmp[3]; + + barycentric_weights_v2_persp(v1, v2, v3, pt, w); + /* for the depth we need the weights to match what + * barycentric_weights_v2 would return, in this case its easiest just to + * undo the 4th axis division and make it unit-sum + * + * don't call barycentric_weights_v2() because our callers expect 'w' + * to be weighted from the perspective */ + w_tmp[0] = w[0] * v1[3]; + w_tmp[1] = w[1] * v2[3]; + w_tmp[2] = w[2] * v3[3]; + + wtot = w_tmp[0] + w_tmp[1] + w_tmp[2]; + + if (wtot != 0.0f) { + wtot_inv = 1.0f / wtot; + + w_tmp[0] = w_tmp[0] * wtot_inv; + w_tmp[1] = w_tmp[1] * wtot_inv; + w_tmp[2] = w_tmp[2] * wtot_inv; + } + else /* dummy values for zero area face */ + w_tmp[0] = w_tmp[1] = w_tmp[2] = 1.0f / 3.0f; + /* done mimicing barycentric_weights_v2() */ + + return (v1[2] * w_tmp[0]) + (v2[2] * w_tmp[1]) + (v3[2] * w_tmp[2]); +} + + +/* Return the top-most face index that the screen space coord 'pt' touches (or -1) */ +static int project_paint_PickFace(const ProjPaintState *ps, const float pt[2], float w[3], int *side) +{ + LinkNode *node; + float w_tmp[3]; + float *v1, *v2, *v3, *v4; + int bucket_index; + int face_index; + int best_side = -1; + int best_face_index = -1; + float z_depth_best = FLT_MAX, z_depth; + MFace *mf; + + bucket_index = project_bucket_offset_safe(ps, pt); + if (bucket_index == -1) + return -1; + + + + /* we could return 0 for 1 face buckets, as long as this function assumes + * that the point its testing is only every originated from an existing face */ + + for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { + face_index = GET_INT_FROM_POINTER(node->link); + mf = ps->dm_mface + face_index; + + v1 = ps->screenCoords[mf->v1]; + v2 = ps->screenCoords[mf->v2]; + v3 = ps->screenCoords[mf->v3]; + + if (isect_point_tri_v2(pt, v1, v2, v3)) { + if (ps->is_ortho) z_depth = VecZDepthOrtho(pt, v1, v2, v3, w_tmp); + else z_depth = VecZDepthPersp(pt, v1, v2, v3, w_tmp); + + if (z_depth < z_depth_best) { + best_face_index = face_index; + best_side = 0; + z_depth_best = z_depth; + copy_v3_v3(w, w_tmp); + } + } + else if (mf->v4) { + v4 = ps->screenCoords[mf->v4]; + + if (isect_point_tri_v2(pt, v1, v3, v4)) { + if (ps->is_ortho) z_depth = VecZDepthOrtho(pt, v1, v3, v4, w_tmp); + else z_depth = VecZDepthPersp(pt, v1, v3, v4, w_tmp); + + if (z_depth < z_depth_best) { + best_face_index = face_index; + best_side = 1; + z_depth_best = z_depth; + copy_v3_v3(w, w_tmp); + } + } + } + } + + *side = best_side; + return best_face_index; /* will be -1 or a valid face */ +} + +/* Converts a uv coord into a pixel location wrapping if the uv is outside 0-1 range */ +static void uvco_to_wrapped_pxco(float uv[2], int ibuf_x, int ibuf_y, float *x, float *y) +{ + /* use */ + *x = (float)fmodf(uv[0], 1.0f); + *y = (float)fmodf(uv[1], 1.0f); + + if (*x < 0.0f) *x += 1.0f; + if (*y < 0.0f) *y += 1.0f; + + *x = *x * ibuf_x - 0.5f; + *y = *y * ibuf_y - 0.5f; +} + +/* Set the top-most face color that the screen space coord 'pt' touches (or return 0 if none touch) */ +static int project_paint_PickColor(const ProjPaintState *ps, const float pt[2], + float *rgba_fp, unsigned char *rgba, const int interp) +{ + float w[3], uv[2]; + int side; + int face_index; + MTFace *tf; + Image *ima; + ImBuf *ibuf; + int xi, yi; + + + face_index = project_paint_PickFace(ps, pt, w, &side); + + if (face_index == -1) + return 0; + + tf = ps->dm_mtface + face_index; + + if (side == 0) { + interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[1], tf->uv[2], w); + } + else { /* QUAD */ + interp_v2_v2v2v2(uv, tf->uv[0], tf->uv[2], tf->uv[3], w); + } + + ima = project_paint_face_image(ps, ps->dm_mtface, face_index); + ibuf = ima->ibufs.first; /* we must have got the imbuf before getting here */ + if (!ibuf) return 0; + + if (interp) { + float x, y; + uvco_to_wrapped_pxco(uv, ibuf->x, ibuf->y, &x, &y); + + if (ibuf->rect_float) { + if (rgba_fp) { + bilinear_interpolation_color_wrap(ibuf, NULL, rgba_fp, x, y); + } + else { + float rgba_tmp_f[4]; + bilinear_interpolation_color_wrap(ibuf, NULL, rgba_tmp_f, x, y); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_f); + } + } + else { + if (rgba) { + bilinear_interpolation_color_wrap(ibuf, rgba, NULL, x, y); + } + else { + unsigned char rgba_tmp[4]; + bilinear_interpolation_color_wrap(ibuf, rgba_tmp, NULL, x, y); + IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, rgba_tmp); + } + } + } + else { + //xi = (int)((uv[0]*ibuf->x) + 0.5f); + //yi = (int)((uv[1]*ibuf->y) + 0.5f); + //if (xi < 0 || xi >= ibuf->x || yi < 0 || yi >= ibuf->y) return 0; + + /* wrap */ + xi = ((int)(uv[0] * ibuf->x)) % ibuf->x; + if (xi < 0) xi += ibuf->x; + yi = ((int)(uv[1] * ibuf->y)) % ibuf->y; + if (yi < 0) yi += ibuf->y; + + + if (rgba) { + if (ibuf->rect_float) { + float *rgba_tmp_fp = ibuf->rect_float + (xi + yi * ibuf->x * 4); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba, rgba_tmp_fp); + } + else { + *((unsigned int *)rgba) = *(unsigned int *)(((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4)); + } + } + + if (rgba_fp) { + if (ibuf->rect_float) { + copy_v4_v4(rgba_fp, (ibuf->rect_float + ((xi + yi * ibuf->x) * 4))); + } + else { + char *tmp_ch = ((char *)ibuf->rect) + ((xi + yi * ibuf->x) * 4); + IMAPAINT_CHAR_RGBA_TO_FLOAT(rgba_fp, tmp_ch); + } + } + } + return 1; +} + +/* Check if 'pt' is infront of the 3 verts on the Z axis (used for screenspace occlusuion test) + * return... + * 0 : no occlusion + * -1 : no occlusion but 2D intersection is true (avoid testing the other half of a quad) + * 1 : occluded + * 2 : occluded with w[3] weights set (need to know in some cases) */ + +static int project_paint_occlude_ptv(float pt[3], float v1[4], float v2[4], float v3[4], float w[3], int is_ortho) +{ + /* if all are behind us, return false */ + if (v1[2] > pt[2] && v2[2] > pt[2] && v3[2] > pt[2]) + return 0; + + /* do a 2D point in try intersection */ + if (!isect_point_tri_v2(pt, v1, v2, v3)) + return 0; /* we know there is */ + + + /* From here on we know there IS an intersection */ + /* if ALL of the verts are infront of us then we know it intersects ? */ + if (v1[2] < pt[2] && v2[2] < pt[2] && v3[2] < pt[2]) { + return 1; + } + else { + /* we intersect? - find the exact depth at the point of intersection */ + /* Is this point is occluded by another face? */ + if (is_ortho) { + if (VecZDepthOrtho(pt, v1, v2, v3, w) < pt[2]) return 2; + } + else { + if (VecZDepthPersp(pt, v1, v2, v3, w) < pt[2]) return 2; + } + } + return -1; +} + + +static int project_paint_occlude_ptv_clip(const ProjPaintState *ps, const MFace *mf, + float pt[3], float v1[4], float v2[4], float v3[4], + const int side) +{ + float w[3], wco[3]; + int ret = project_paint_occlude_ptv(pt, v1, v2, v3, w, ps->is_ortho); + + if (ret <= 0) + return ret; + + if (ret == 1) { /* weights not calculated */ + if (ps->is_ortho) barycentric_weights_v2(v1, v2, v3, pt, w); + else barycentric_weights_v2_persp(v1, v2, v3, pt, w); + } + + /* Test if we're in the clipped area, */ + if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); + else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + + if (!ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + return 1; + } + + return -1; +} + + +/* Check if a screenspace location is occluded by any other faces + * check, pixelScreenCo must be in screenspace, its Z-Depth only needs to be used for comparison + * and doesn't need to be correct in relation to X and Y coords (this is the case in perspective view) */ +static int project_bucket_point_occluded(const ProjPaintState *ps, LinkNode *bucketFace, const int orig_face, float pixelScreenCo[4]) +{ + MFace *mf; + int face_index; + int isect_ret; + float w[3]; /* not needed when clipping */ + const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; + + /* we could return 0 for 1 face buckets, as long as this function assumes + * that the point its testing is only every originated from an existing face */ + + for (; bucketFace; bucketFace = bucketFace->next) { + face_index = GET_INT_FROM_POINTER(bucketFace->link); + + if (orig_face != face_index) { + mf = ps->dm_mface + face_index; + if (do_clip) + isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], 0); + else + isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v2], ps->screenCoords[mf->v3], w, ps->is_ortho); + + /* Note, if (isect_ret == -1) then we don't want to test the other side of the quad */ + if (isect_ret == 0 && mf->v4) { + if (do_clip) + isect_ret = project_paint_occlude_ptv_clip(ps, mf, pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], 1); + else + isect_ret = project_paint_occlude_ptv(pixelScreenCo, ps->screenCoords[mf->v1], ps->screenCoords[mf->v3], ps->screenCoords[mf->v4], w, ps->is_ortho); + } + if (isect_ret >= 1) { + /* TODO - we may want to cache the first hit, + * it is not possible to swap the face order in the list anymore */ + return 1; + } + } + } + return 0; +} + +/* basic line intersection, could move to math_geom.c, 2 points with a horiz line + * 1 for an intersection, 2 if the first point is aligned, 3 if the second point is aligned */ +#define ISECT_TRUE 1 +#define ISECT_TRUE_P1 2 +#define ISECT_TRUE_P2 3 +static int line_isect_y(const float p1[2], const float p2[2], const float y_level, float *x_isect) +{ + float y_diff; + + if (y_level == p1[1]) { /* are we touching the first point? - no interpolation needed */ + *x_isect = p1[0]; + return ISECT_TRUE_P1; + } + if (y_level == p2[1]) { /* are we touching the second point? - no interpolation needed */ + *x_isect = p2[0]; + return ISECT_TRUE_P2; + } + + y_diff = fabsf(p1[1] - p2[1]); /* yuck, horizontal line, we cant do much here */ + + if (y_diff < 0.000001f) { + *x_isect = (p1[0] + p2[0]) * 0.5f; + return ISECT_TRUE; + } + + if (p1[1] > y_level && p2[1] < y_level) { + *x_isect = (p2[0] * (p1[1] - y_level) + p1[0] * (y_level - p2[1])) / y_diff; /*(p1[1]-p2[1]);*/ + return ISECT_TRUE; + } + else if (p1[1] < y_level && p2[1] > y_level) { + *x_isect = (p2[0] * (y_level - p1[1]) + p1[0] * (p2[1] - y_level)) / y_diff; /*(p2[1]-p1[1]);*/ + return ISECT_TRUE; + } + else { + return 0; + } +} + +static int line_isect_x(const float p1[2], const float p2[2], const float x_level, float *y_isect) +{ + float x_diff; + + if (x_level == p1[0]) { /* are we touching the first point? - no interpolation needed */ + *y_isect = p1[1]; + return ISECT_TRUE_P1; + } + if (x_level == p2[0]) { /* are we touching the second point? - no interpolation needed */ + *y_isect = p2[1]; + return ISECT_TRUE_P2; + } + + x_diff = fabsf(p1[0] - p2[0]); /* yuck, horizontal line, we cant do much here */ + + if (x_diff < 0.000001f) { /* yuck, vertical line, we cant do much here */ + *y_isect = (p1[0] + p2[0]) * 0.5f; + return ISECT_TRUE; + } + + if (p1[0] > x_level && p2[0] < x_level) { + *y_isect = (p2[1] * (p1[0] - x_level) + p1[1] * (x_level - p2[0])) / x_diff; /*(p1[0]-p2[0]);*/ + return ISECT_TRUE; + } + else if (p1[0] < x_level && p2[0] > x_level) { + *y_isect = (p2[1] * (x_level - p1[0]) + p1[1] * (p2[0] - x_level)) / x_diff; /*(p2[0]-p1[0]);*/ + return ISECT_TRUE; + } + else { + return 0; + } +} + +/* simple func use for comparing UV locations to check if there are seams. + * Its possible this gives incorrect results, when the UVs for 1 face go into the next + * tile, but do not do this for the adjacent face, it could return a false positive. + * This is so unlikely that Id not worry about it. */ +#ifndef PROJ_DEBUG_NOSEAMBLEED +static int cmp_uv(const float vec2a[2], const float vec2b[2]) +{ + /* if the UV's are not between 0.0 and 1.0 */ + float xa = (float)fmodf(vec2a[0], 1.0f); + float ya = (float)fmodf(vec2a[1], 1.0f); + + float xb = (float)fmodf(vec2b[0], 1.0f); + float yb = (float)fmodf(vec2b[1], 1.0f); + + if (xa < 0.0f) xa += 1.0f; + if (ya < 0.0f) ya += 1.0f; + + if (xb < 0.0f) xb += 1.0f; + if (yb < 0.0f) yb += 1.0f; + + return ((fabsf(xa - xb) < PROJ_GEOM_TOLERANCE) && (fabsf(ya - yb) < PROJ_GEOM_TOLERANCE)) ? 1 : 0; +} +#endif + +/* set min_px and max_px to the image space bounds of the UV coords + * return zero if there is no area in the returned rectangle */ +#ifndef PROJ_DEBUG_NOSEAMBLEED +static int pixel_bounds_uv( + const float uv1[2], const float uv2[2], const float uv3[2], const float uv4[2], + rcti *bounds_px, + const int ibuf_x, const int ibuf_y, + int is_quad + ) +{ + float min_uv[2], max_uv[2]; /* UV bounds */ + + INIT_MINMAX2(min_uv, max_uv); + + minmax_v2v2_v2(min_uv, max_uv, uv1); + minmax_v2v2_v2(min_uv, max_uv, uv2); + minmax_v2v2_v2(min_uv, max_uv, uv3); + if (is_quad) + minmax_v2v2_v2(min_uv, max_uv, uv4); + + bounds_px->xmin = (int)(ibuf_x * min_uv[0]); + bounds_px->ymin = (int)(ibuf_y * min_uv[1]); + + bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1; + bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1; + + /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ + + /* face uses no UV area when quantized to pixels? */ + return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1; +} +#endif + +static int pixel_bounds_array(float (*uv)[2], rcti *bounds_px, const int ibuf_x, const int ibuf_y, int tot) +{ + float min_uv[2], max_uv[2]; /* UV bounds */ + + if (tot == 0) { + return 0; + } + + INIT_MINMAX2(min_uv, max_uv); + + while (tot--) { + minmax_v2v2_v2(min_uv, max_uv, (*uv)); + uv++; + } + + bounds_px->xmin = (int)(ibuf_x * min_uv[0]); + bounds_px->ymin = (int)(ibuf_y * min_uv[1]); + + bounds_px->xmax = (int)(ibuf_x * max_uv[0]) + 1; + bounds_px->ymax = (int)(ibuf_y * max_uv[1]) + 1; + + /*printf("%d %d %d %d\n", min_px[0], min_px[1], max_px[0], max_px[1]);*/ + + /* face uses no UV area when quantized to pixels? */ + return (bounds_px->xmin == bounds_px->xmax || bounds_px->ymin == bounds_px->ymax) ? 0 : 1; +} + +#ifndef PROJ_DEBUG_NOSEAMBLEED + +/* This function returns 1 if this face has a seam along the 2 face-vert indices + * 'orig_i1_fidx' and 'orig_i2_fidx' */ +static int check_seam(const ProjPaintState *ps, const int orig_face, const int orig_i1_fidx, const int orig_i2_fidx, int *other_face, int *orig_fidx) +{ + LinkNode *node; + int face_index; + unsigned int i1, i2; + int i1_fidx = -1, i2_fidx = -1; /* index in face */ + MFace *mf; + MTFace *tf; + const MFace *orig_mf = ps->dm_mface + orig_face; + const MTFace *orig_tf = ps->dm_mtface + orig_face; + + /* vert indices from face vert order indices */ + i1 = (*(&orig_mf->v1 + orig_i1_fidx)); + i2 = (*(&orig_mf->v1 + orig_i2_fidx)); + + for (node = ps->vertFaces[i1]; node; node = node->next) { + face_index = GET_INT_FROM_POINTER(node->link); + + if (face_index != orig_face) { + mf = ps->dm_mface + face_index; + /* could check if the 2 faces images match here, + * but then there wouldn't be a way to return the opposite face's info */ + + + /* We need to know the order of the verts in the adjacent face + * set the i1_fidx and i2_fidx to (0,1,2,3) */ + if (mf->v1 == i1) i1_fidx = 0; + else if (mf->v2 == i1) i1_fidx = 1; + else if (mf->v3 == i1) i1_fidx = 2; + else if (mf->v4 && mf->v4 == i1) i1_fidx = 3; + + if (mf->v1 == i2) i2_fidx = 0; + else if (mf->v2 == i2) i2_fidx = 1; + else if (mf->v3 == i2) i2_fidx = 2; + else if (mf->v4 && mf->v4 == i2) i2_fidx = 3; + + /* Only need to check if 'i2_fidx' is valid because we know i1_fidx is the same vert on both faces */ + if (i2_fidx != -1) { + Image *tpage = project_paint_face_image(ps, ps->dm_mtface, face_index); + Image *orig_tpage = project_paint_face_image(ps, ps->dm_mtface, orig_face); + + /* This IS an adjacent face!, now lets check if the UVs are ok */ + tf = ps->dm_mtface + face_index; + + /* set up the other face */ + *other_face = face_index; + *orig_fidx = (i1_fidx < i2_fidx) ? i1_fidx : i2_fidx; + + /* first test if they have the same image */ + if ((orig_tpage == tpage) && + cmp_uv(orig_tf->uv[orig_i1_fidx], tf->uv[i1_fidx]) && + cmp_uv(orig_tf->uv[orig_i2_fidx], tf->uv[i2_fidx]) ) + { + // printf("SEAM (NONE)\n"); + return 0; + + } + else { + // printf("SEAM (UV GAP)\n"); + return 1; + } + } + } + } + // printf("SEAM (NO FACE)\n"); + *other_face = -1; + return 1; +} + +/* Calculate outset UV's, this is not the same as simply scaling the UVs, + * since the outset coords are a margin that keep an even distance from the original UV's, + * note that the image aspect is taken into account */ +static void uv_image_outset(float (*orig_uv)[2], float (*outset_uv)[2], const float scaler, + const int ibuf_x, const int ibuf_y, const int is_quad) +{ + float a1, a2, a3, a4 = 0.0f; + float puv[4][2]; /* pixelspace uv's */ + float no1[2], no2[2], no3[2], no4[2]; /* normals */ + float dir1[2], dir2[2], dir3[2], dir4[2]; + float ibuf_inv[2]; + + ibuf_inv[0] = 1.0f / (float)ibuf_x; + ibuf_inv[1] = 1.0f / (float)ibuf_y; + + /* make UV's in pixel space so we can */ + puv[0][0] = orig_uv[0][0] * ibuf_x; + puv[0][1] = orig_uv[0][1] * ibuf_y; + + puv[1][0] = orig_uv[1][0] * ibuf_x; + puv[1][1] = orig_uv[1][1] * ibuf_y; + + puv[2][0] = orig_uv[2][0] * ibuf_x; + puv[2][1] = orig_uv[2][1] * ibuf_y; + + if (is_quad) { + puv[3][0] = orig_uv[3][0] * ibuf_x; + puv[3][1] = orig_uv[3][1] * ibuf_y; + } + + /* face edge directions */ + sub_v2_v2v2(dir1, puv[1], puv[0]); + sub_v2_v2v2(dir2, puv[2], puv[1]); + normalize_v2(dir1); + normalize_v2(dir2); + + if (is_quad) { + sub_v2_v2v2(dir3, puv[3], puv[2]); + sub_v2_v2v2(dir4, puv[0], puv[3]); + normalize_v2(dir3); + normalize_v2(dir4); + } + else { + sub_v2_v2v2(dir3, puv[0], puv[2]); + normalize_v2(dir3); + } + + /* TODO - angle_normalized_v2v2(...) * (M_PI/180.0f) + * This is incorrect. Its already given radians but without it wont work. + * need to look into a fix - campbell */ + if (is_quad) { + a1 = shell_angle_to_dist(angle_normalized_v2v2(dir4, dir1) * ((float)M_PI / 180.0f)); + a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f)); + a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f)); + a4 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir4) * ((float)M_PI / 180.0f)); + } + else { + a1 = shell_angle_to_dist(angle_normalized_v2v2(dir3, dir1) * ((float)M_PI / 180.0f)); + a2 = shell_angle_to_dist(angle_normalized_v2v2(dir1, dir2) * ((float)M_PI / 180.0f)); + a3 = shell_angle_to_dist(angle_normalized_v2v2(dir2, dir3) * ((float)M_PI / 180.0f)); + } + + if (is_quad) { + sub_v2_v2v2(no1, dir4, dir1); + sub_v2_v2v2(no2, dir1, dir2); + sub_v2_v2v2(no3, dir2, dir3); + sub_v2_v2v2(no4, dir3, dir4); + normalize_v2(no1); + normalize_v2(no2); + normalize_v2(no3); + normalize_v2(no4); + mul_v2_fl(no1, a1 * scaler); + mul_v2_fl(no2, a2 * scaler); + mul_v2_fl(no3, a3 * scaler); + mul_v2_fl(no4, a4 * scaler); + add_v2_v2v2(outset_uv[0], puv[0], no1); + add_v2_v2v2(outset_uv[1], puv[1], no2); + add_v2_v2v2(outset_uv[2], puv[2], no3); + add_v2_v2v2(outset_uv[3], puv[3], no4); + mul_v2_v2(outset_uv[0], ibuf_inv); + mul_v2_v2(outset_uv[1], ibuf_inv); + mul_v2_v2(outset_uv[2], ibuf_inv); + mul_v2_v2(outset_uv[3], ibuf_inv); + } + else { + sub_v2_v2v2(no1, dir3, dir1); + sub_v2_v2v2(no2, dir1, dir2); + sub_v2_v2v2(no3, dir2, dir3); + normalize_v2(no1); + normalize_v2(no2); + normalize_v2(no3); + mul_v2_fl(no1, a1 * scaler); + mul_v2_fl(no2, a2 * scaler); + mul_v2_fl(no3, a3 * scaler); + add_v2_v2v2(outset_uv[0], puv[0], no1); + add_v2_v2v2(outset_uv[1], puv[1], no2); + add_v2_v2v2(outset_uv[2], puv[2], no3); + + mul_v2_v2(outset_uv[0], ibuf_inv); + mul_v2_v2(outset_uv[1], ibuf_inv); + mul_v2_v2(outset_uv[2], ibuf_inv); + } +} + +/* + * Be tricky with flags, first 4 bits are PROJ_FACE_SEAM1 to 4, last 4 bits are PROJ_FACE_NOSEAM1 to 4 + * 1<<i - where i is (0-3) + * + * If we're multithreadng, make sure threads are locked when this is called + */ +static void project_face_seams_init(const ProjPaintState *ps, const int face_index, const int is_quad) +{ + int other_face, other_fidx; /* vars for the other face, we also set its flag */ + int fidx1 = is_quad ? 3 : 2; + int fidx2 = 0; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) or (0,1,2) -> (1,2,0) for a tri */ + + do { + if ((ps->faceSeamFlags[face_index] & (1 << fidx1 | 16 << fidx1)) == 0) { + if (check_seam(ps, face_index, fidx1, fidx2, &other_face, &other_fidx)) { + ps->faceSeamFlags[face_index] |= 1 << fidx1; + if (other_face != -1) + ps->faceSeamFlags[other_face] |= 1 << other_fidx; + } + else { + ps->faceSeamFlags[face_index] |= 16 << fidx1; + if (other_face != -1) + ps->faceSeamFlags[other_face] |= 16 << other_fidx; /* second 4 bits for disabled */ + } + } + + fidx2 = fidx1; + } while (fidx1--); +} +#endif // PROJ_DEBUG_NOSEAMBLEED + + +/* Converts a UV location to a 3D screenspace location + * Takes a 'uv' and 3 UV coords, and sets the values of pixelScreenCo + * + * This is used for finding a pixels location in screenspace for painting */ +static void screen_px_from_ortho( + float uv[2], + float v1co[3], float v2co[3], float v3co[3], /* Screenspace coords */ + float uv1co[2], float uv2co[2], float uv3co[2], + float pixelScreenCo[4], + float w[3]) +{ + barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w); + interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w); +} + +/* same as screen_px_from_ortho except we need to take into account + * the perspective W coord for each vert */ +static void screen_px_from_persp( + float uv[2], + float v1co[4], float v2co[4], float v3co[4], /* screenspace coords */ + float uv1co[2], float uv2co[2], float uv3co[2], + float pixelScreenCo[4], + float w[3]) +{ + + float wtot_inv, wtot; + barycentric_weights_v2(uv1co, uv2co, uv3co, uv, w); + + /* re-weight from the 4th coord of each screen vert */ + w[0] *= v1co[3]; + w[1] *= v2co[3]; + w[2] *= v3co[3]; + + wtot = w[0] + w[1] + w[2]; + + if (wtot > 0.0f) { + wtot_inv = 1.0f / wtot; + w[0] *= wtot_inv; + w[1] *= wtot_inv; + w[2] *= wtot_inv; + } + else { + w[0] = w[1] = w[2] = 1.0f / 3.0f; /* dummy values for zero area face */ + } + /* done re-weighting */ + + interp_v3_v3v3v3(pixelScreenCo, v1co, v2co, v3co, w); +} + +static void project_face_pixel(const MTFace *tf_other, ImBuf *ibuf_other, const float w[3], + int side, unsigned char rgba_ub[4], float rgba_f[4]) +{ + float *uvCo1, *uvCo2, *uvCo3; + float uv_other[2], x, y; + + uvCo1 = (float *)tf_other->uv[0]; + if (side == 1) { + uvCo2 = (float *)tf_other->uv[2]; + uvCo3 = (float *)tf_other->uv[3]; + } + else { + uvCo2 = (float *)tf_other->uv[1]; + uvCo3 = (float *)tf_other->uv[2]; + } + + interp_v2_v2v2v2(uv_other, uvCo1, uvCo2, uvCo3, (float *)w); + + /* use */ + uvco_to_wrapped_pxco(uv_other, ibuf_other->x, ibuf_other->y, &x, &y); + + + if (ibuf_other->rect_float) { /* from float to float */ + bilinear_interpolation_color_wrap(ibuf_other, NULL, rgba_f, x, y); + } + else { /* from char to float */ + bilinear_interpolation_color_wrap(ibuf_other, rgba_ub, NULL, x, y); + } + +} + +/* run this outside project_paint_uvpixel_init since pixels with mask 0 don't need init */ +static float project_paint_uvpixel_mask( + const ProjPaintState *ps, + const int face_index, + const int side, + const float w[3]) +{ + float mask; + + /* Image Mask */ + if (ps->do_layer_stencil) { + /* another UV maps image is masking this one's */ + ImBuf *ibuf_other; + Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_stencil, face_index); + const MTFace *tf_other = ps->dm_mtface_stencil + face_index; + + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ + unsigned char rgba_ub[4]; + float rgba_f[4]; + + project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, rgba_f); + + if (ibuf_other->rect_float) { /* from float to float */ + mask = ((rgba_f[0] + rgba_f[1] + rgba_f[2]) / 3.0f) * rgba_f[3]; + } + else { /* from char to float */ + mask = ((rgba_ub[0] + rgba_ub[1] + rgba_ub[2]) / (256 * 3.0f)) * (rgba_ub[3] / 256.0f); + } + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); + + if (!ps->do_layer_stencil_inv) /* matching the gimps layer mask black/white rules, white==full opacity */ + mask = (1.0f - mask); + + if (mask == 0.0f) { + return 0.0f; + } + } + else { + return 0.0f; + } + } + else { + mask = 1.0f; + } + + /* calculate mask */ + if (ps->do_mask_normal) { + MFace *mf = &ps->dm_mface[face_index]; + float no[3], angle; + if (mf->flag & ME_SMOOTH) { + short *no1, *no2, *no3; + no1 = ps->dm_mvert[mf->v1].no; + if (side == 1) { + no2 = ps->dm_mvert[mf->v3].no; + no3 = ps->dm_mvert[mf->v4].no; + } + else { + no2 = ps->dm_mvert[mf->v2].no; + no3 = ps->dm_mvert[mf->v3].no; + } + + no[0] = w[0] * no1[0] + w[1] * no2[0] + w[2] * no3[0]; + no[1] = w[0] * no1[1] + w[1] * no2[1] + w[2] * no3[1]; + no[2] = w[0] * no1[2] + w[1] * no2[2] + w[2] * no3[2]; + normalize_v3(no); + } + else { + /* incase the */ +#if 1 + /* normalizing per pixel isn't optimal, we could cache or check ps->*/ + if (mf->v4) + normal_quad_v3(no, + ps->dm_mvert[mf->v1].co, + ps->dm_mvert[mf->v2].co, + ps->dm_mvert[mf->v3].co, + ps->dm_mvert[mf->v4].co); + else + normal_tri_v3(no, + ps->dm_mvert[mf->v1].co, + ps->dm_mvert[mf->v2].co, + ps->dm_mvert[mf->v3].co); +#else + /* don't use because some modifiers dont have normal data (subsurf for eg) */ + copy_v3_v3(no, (float *)ps->dm->getTessFaceData(ps->dm, face_index, CD_NORMAL)); +#endif + } + + /* now we can use the normal as a mask */ + if (ps->is_ortho) { + angle = angle_normalized_v3v3((float *)ps->viewDir, no); + } + else { + /* Annoying but for the perspective view we need to get the pixels location in 3D space :/ */ + float viewDirPersp[3]; + float *co1, *co2, *co3; + co1 = ps->dm_mvert[mf->v1].co; + if (side == 1) { + co2 = ps->dm_mvert[mf->v3].co; + co3 = ps->dm_mvert[mf->v4].co; + } + else { + co2 = ps->dm_mvert[mf->v2].co; + co3 = ps->dm_mvert[mf->v3].co; + } + + /* Get the direction from the viewPoint to the pixel and normalize */ + viewDirPersp[0] = (ps->viewPos[0] - (w[0] * co1[0] + w[1] * co2[0] + w[2] * co3[0])); + viewDirPersp[1] = (ps->viewPos[1] - (w[0] * co1[1] + w[1] * co2[1] + w[2] * co3[1])); + viewDirPersp[2] = (ps->viewPos[2] - (w[0] * co1[2] + w[1] * co2[2] + w[2] * co3[2])); + normalize_v3(viewDirPersp); + + angle = angle_normalized_v3v3(viewDirPersp, no); + } + + if (angle >= ps->normal_angle) { + return 0.0f; /* outsize the normal limit*/ + } + else if (angle > ps->normal_angle_inner) { + mask *= (ps->normal_angle - angle) / ps->normal_angle_range; + } /* otherwise no mask normal is needed, were within the limit */ + } + + /* This only works when the opacity dosnt change while painting, stylus pressure messes with this + * so don't use it. */ + // if (ps->is_airbrush == 0) mask *= BKE_brush_alpha_get(ps->brush); + + return mask; +} + +static int project_paint_pixel_sizeof(const short tool) +{ + if ((tool == PAINT_TOOL_CLONE) || (tool == PAINT_TOOL_SMEAR)) { + return sizeof(ProjPixelClone); + } + else { + return sizeof(ProjPixel); + } +} + + +/* run this function when we know a bucket's, face's pixel can be initialized, + * return the ProjPixel which is added to 'ps->bucketRect[bucket_index]' */ +static ProjPixel *project_paint_uvpixel_init( + const ProjPaintState *ps, + MemArena *arena, + const ImBuf *ibuf, + short x_px, short y_px, + const float mask, + const int face_index, + const int image_index, + const float pixelScreenCo[4], + const float world_spaceCo[3], + const int side, + const float w[3]) +{ + ProjPixel *projPixel; + + /* wrap pixel location */ + x_px = x_px % ibuf->x; + if (x_px < 0) x_px += ibuf->x; + y_px = y_px % ibuf->y; + if (y_px < 0) y_px += ibuf->y; + + BLI_assert(ps->pixel_sizeof == project_paint_pixel_sizeof(ps->tool)); + projPixel = (ProjPixel *)BLI_memarena_alloc(arena, ps->pixel_sizeof); + //memset(projPixel, 0, size); + + if (ibuf->rect_float) { + projPixel->pixel.f_pt = ibuf->rect_float + ((x_px + y_px * ibuf->x) * 4); + projPixel->origColor.f[0] = projPixel->newColor.f[0] = projPixel->pixel.f_pt[0]; + projPixel->origColor.f[1] = projPixel->newColor.f[1] = projPixel->pixel.f_pt[1]; + projPixel->origColor.f[2] = projPixel->newColor.f[2] = projPixel->pixel.f_pt[2]; + projPixel->origColor.f[3] = projPixel->newColor.f[3] = projPixel->pixel.f_pt[3]; + } + else { + projPixel->pixel.ch_pt = ((unsigned char *)ibuf->rect + ((x_px + y_px * ibuf->x) * 4)); + projPixel->origColor.uint = projPixel->newColor.uint = *projPixel->pixel.uint_pt; + } + + /* screenspace unclamped, we could keep its z and w values but don't need them at the moment */ + if (ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { + copy_v3_v3(projPixel->worldCoSS, world_spaceCo); + } + + copy_v2_v2(projPixel->projCoSS, pixelScreenCo); + + projPixel->x_px = x_px; + projPixel->y_px = y_px; + + projPixel->mask = (unsigned short)(mask * 65535); + projPixel->mask_max = 0; + + /* which bounding box cell are we in?, needed for undo */ + projPixel->bb_cell_index = ((int)(((float)x_px / (float)ibuf->x) * PROJ_BOUNDBOX_DIV)) + + ((int)(((float)y_px / (float)ibuf->y) * PROJ_BOUNDBOX_DIV)) * PROJ_BOUNDBOX_DIV; + + /* done with view3d_project_float inline */ + if (ps->tool == PAINT_TOOL_CLONE) { + if (ps->dm_mtface_clone) { + ImBuf *ibuf_other; + Image *other_tpage = project_paint_face_image(ps, ps->dm_mtface_clone, face_index); + const MTFace *tf_other = ps->dm_mtface_clone + face_index; + + if (other_tpage && (ibuf_other = BKE_image_acquire_ibuf(other_tpage, NULL, NULL))) { + /* BKE_image_acquire_ibuf - TODO - this may be slow */ + + if (ibuf->rect_float) { + if (ibuf_other->rect_float) { /* from float to float */ + project_face_pixel(tf_other, ibuf_other, w, side, NULL, ((ProjPixelClone *)projPixel)->clonepx.f); + } + else { /* from char to float */ + unsigned char rgba_ub[4]; + float rgba[4]; + project_face_pixel(tf_other, ibuf_other, w, side, rgba_ub, NULL); + srgb_to_linearrgb_uchar4(rgba, rgba_ub); + straight_to_premul_v4_v4(((ProjPixelClone *)projPixel)->clonepx.f, rgba); + } + } + else { + if (ibuf_other->rect_float) { /* float to char */ + float rgba[4]; + project_face_pixel(tf_other, ibuf_other, w, side, NULL, rgba); + premul_to_straight_v4(rgba); + linearrgb_to_srgb_uchar3(((ProjPixelClone *)projPixel)->clonepx.ch, rgba); + } + else { /* char to char */ + project_face_pixel(tf_other, ibuf_other, w, side, ((ProjPixelClone *)projPixel)->clonepx.ch, NULL); + } + } + + BKE_image_release_ibuf(other_tpage, ibuf_other, NULL); + } + else { + if (ibuf->rect_float) { + ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; + } + else { + ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; + } + } + + } + else { + float co[2]; + sub_v2_v2v2(co, projPixel->projCoSS, (float *)ps->cloneOffset); + + /* no need to initialize the bucket, we're only checking buckets faces and for this + * the faces are already initialized in project_paint_delayed_face_init(...) */ + if (ibuf->rect_float) { + if (!project_paint_PickColor(ps, co, ((ProjPixelClone *)projPixel)->clonepx.f, NULL, 1)) { + ((ProjPixelClone *)projPixel)->clonepx.f[3] = 0; /* zero alpha - ignore */ + } + } + else { + if (!project_paint_PickColor(ps, co, NULL, ((ProjPixelClone *)projPixel)->clonepx.ch, 1)) { + ((ProjPixelClone *)projPixel)->clonepx.ch[3] = 0; /* zero alpha - ignore */ + } + } + } + } + +#ifdef PROJ_DEBUG_PAINT + if (ibuf->rect_float) projPixel->pixel.f_pt[0] = 0; + else projPixel->pixel.ch_pt[0] = 0; +#endif + projPixel->image_index = image_index; + + return projPixel; +} + +static int line_clip_rect2f( + rctf *rect, + const float l1[2], const float l2[2], + float l1_clip[2], float l2_clip[2]) +{ + /* first account for horizontal, then vertical lines */ + /* horiz */ + if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_TOLERANCE) { + /* is the line out of range on its Y axis? */ + if (l1[1] < rect->ymin || l1[1] > rect->ymax) { + return 0; + } + /* line is out of range on its X axis */ + if ((l1[0] < rect->xmin && l2[0] < rect->xmin) || (l1[0] > rect->xmax && l2[0] > rect->xmax)) { + return 0; + } + + + if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/ + if (BLI_rctf_isect_pt_v(rect, l1)) { + copy_v2_v2(l1_clip, l1); + copy_v2_v2(l2_clip, l2); + return 1; + } + else { + return 0; + } + } + + copy_v2_v2(l1_clip, l1); + copy_v2_v2(l2_clip, l2); + CLAMP(l1_clip[0], rect->xmin, rect->xmax); + CLAMP(l2_clip[0], rect->xmin, rect->xmax); + return 1; + } + else if (fabsf(l1[0] - l2[0]) < PROJ_GEOM_TOLERANCE) { + /* is the line out of range on its X axis? */ + if (l1[0] < rect->xmin || l1[0] > rect->xmax) { + return 0; + } + + /* line is out of range on its Y axis */ + if ((l1[1] < rect->ymin && l2[1] < rect->ymin) || (l1[1] > rect->ymax && l2[1] > rect->ymax)) { + return 0; + } + + if (fabsf(l1[1] - l2[1]) < PROJ_GEOM_TOLERANCE) { /* this is a single point (or close to)*/ + if (BLI_rctf_isect_pt_v(rect, l1)) { + copy_v2_v2(l1_clip, l1); + copy_v2_v2(l2_clip, l2); + return 1; + } + else { + return 0; + } + } + + copy_v2_v2(l1_clip, l1); + copy_v2_v2(l2_clip, l2); + CLAMP(l1_clip[1], rect->ymin, rect->ymax); + CLAMP(l2_clip[1], rect->ymin, rect->ymax); + return 1; + } + else { + float isect; + short ok1 = 0; + short ok2 = 0; + + /* Done with vertical lines */ + + /* are either of the points inside the rectangle ? */ + if (BLI_rctf_isect_pt_v(rect, l1)) { + copy_v2_v2(l1_clip, l1); + ok1 = 1; + } + + if (BLI_rctf_isect_pt_v(rect, l2)) { + copy_v2_v2(l2_clip, l2); + ok2 = 1; + } + + /* line inside rect */ + if (ok1 && ok2) return 1; + + /* top/bottom */ + if (line_isect_y(l1, l2, rect->ymin, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) { + if (l1[1] < l2[1]) { /* line 1 is outside */ + l1_clip[0] = isect; + l1_clip[1] = rect->ymin; + ok1 = 1; + } + else { + l2_clip[0] = isect; + l2_clip[1] = rect->ymin; + ok2 = 2; + } + } + + if (ok1 && ok2) return 1; + + if (line_isect_y(l1, l2, rect->ymax, &isect) && (isect >= rect->xmin) && (isect <= rect->xmax)) { + if (l1[1] > l2[1]) { /* line 1 is outside */ + l1_clip[0] = isect; + l1_clip[1] = rect->ymax; + ok1 = 1; + } + else { + l2_clip[0] = isect; + l2_clip[1] = rect->ymax; + ok2 = 2; + } + } + + if (ok1 && ok2) return 1; + + /* left/right */ + if (line_isect_x(l1, l2, rect->xmin, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) { + if (l1[0] < l2[0]) { /* line 1 is outside */ + l1_clip[0] = rect->xmin; + l1_clip[1] = isect; + ok1 = 1; + } + else { + l2_clip[0] = rect->xmin; + l2_clip[1] = isect; + ok2 = 2; + } + } + + if (ok1 && ok2) return 1; + + if (line_isect_x(l1, l2, rect->xmax, &isect) && (isect >= rect->ymin) && (isect <= rect->ymax)) { + if (l1[0] > l2[0]) { /* line 1 is outside */ + l1_clip[0] = rect->xmax; + l1_clip[1] = isect; + ok1 = 1; + } + else { + l2_clip[0] = rect->xmax; + l2_clip[1] = isect; + ok2 = 2; + } + } + + if (ok1 && ok2) { + return 1; + } + else { + return 0; + } + } +} + + + +/* scale the quad & tri about its center + * scaling by PROJ_FACE_SCALE_SEAM (0.99x) is used for getting fake UV pixel coords that are on the + * edge of the face but slightly inside it occlusion tests don't return hits on adjacent faces */ +#ifndef PROJ_DEBUG_NOSEAMBLEED +static void scale_quad(float insetCos[4][3], float *origCos[4], const float inset) +{ + float cent[3]; + cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0] + origCos[3][0]) / 4.0f; + cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1] + origCos[3][1]) / 4.0f; + cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2] + origCos[3][2]) / 4.0f; + + sub_v3_v3v3(insetCos[0], origCos[0], cent); + sub_v3_v3v3(insetCos[1], origCos[1], cent); + sub_v3_v3v3(insetCos[2], origCos[2], cent); + sub_v3_v3v3(insetCos[3], origCos[3], cent); + + mul_v3_fl(insetCos[0], inset); + mul_v3_fl(insetCos[1], inset); + mul_v3_fl(insetCos[2], inset); + mul_v3_fl(insetCos[3], inset); + + add_v3_v3(insetCos[0], cent); + add_v3_v3(insetCos[1], cent); + add_v3_v3(insetCos[2], cent); + add_v3_v3(insetCos[3], cent); +} + + +static void scale_tri(float insetCos[4][3], float *origCos[4], const float inset) +{ + float cent[3]; + cent[0] = (origCos[0][0] + origCos[1][0] + origCos[2][0]) / 3.0f; + cent[1] = (origCos[0][1] + origCos[1][1] + origCos[2][1]) / 3.0f; + cent[2] = (origCos[0][2] + origCos[1][2] + origCos[2][2]) / 3.0f; + + sub_v3_v3v3(insetCos[0], origCos[0], cent); + sub_v3_v3v3(insetCos[1], origCos[1], cent); + sub_v3_v3v3(insetCos[2], origCos[2], cent); + + mul_v3_fl(insetCos[0], inset); + mul_v3_fl(insetCos[1], inset); + mul_v3_fl(insetCos[2], inset); + + add_v3_v3(insetCos[0], cent); + add_v3_v3(insetCos[1], cent); + add_v3_v3(insetCos[2], cent); +} +#endif //PROJ_DEBUG_NOSEAMBLEED + +static float len_squared_v2v2_alt(const float *v1, const float v2_1, const float v2_2) +{ + float x, y; + + x = v1[0] - v2_1; + y = v1[1] - v2_2; + return x * x + y * y; +} + +/* note, use a squared value so we can use len_squared_v2v2 + * be sure that you have done a bounds check first or this may fail */ +/* only give bucket_bounds as an arg because we need it elsewhere */ +static int project_bucket_isect_circle(const float cent[2], const float radius_squared, rctf *bucket_bounds) +{ + + /* Would normally to a simple intersection test, however we know the bounds of these 2 already intersect + * so we only need to test if the center is inside the vertical or horizontal bounds on either axis, + * this is even less work then an intersection test + */ +#if 0 + if (BLI_rctf_isect_pt_v(bucket_bounds, cent)) + return 1; +#endif + + if ((bucket_bounds->xmin <= cent[0] && bucket_bounds->xmax >= cent[0]) || + (bucket_bounds->ymin <= cent[1] && bucket_bounds->ymax >= cent[1])) + { + return 1; + } + + /* out of bounds left */ + if (cent[0] < bucket_bounds->xmin) { + /* lower left out of radius test */ + if (cent[1] < bucket_bounds->ymin) { + return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymin) < radius_squared) ? 1 : 0; + } + /* top left test */ + else if (cent[1] > bucket_bounds->ymax) { + return (len_squared_v2v2_alt(cent, bucket_bounds->xmin, bucket_bounds->ymax) < radius_squared) ? 1 : 0; + } + } + else if (cent[0] > bucket_bounds->xmax) { + /* lower right out of radius test */ + if (cent[1] < bucket_bounds->ymin) { + return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymin) < radius_squared) ? 1 : 0; + } + /* top right test */ + else if (cent[1] > bucket_bounds->ymax) { + return (len_squared_v2v2_alt(cent, bucket_bounds->xmax, bucket_bounds->ymax) < radius_squared) ? 1 : 0; + } + } + + return 0; +} + + + +/* Note for rect_to_uvspace_ortho() and rect_to_uvspace_persp() + * in ortho view this function gives good results when bucket_bounds are outside the triangle + * however in some cases, perspective view will mess up with faces that have minimal screenspace area + * (viewed from the side) + * + * for this reason its not reliable in this case so we'll use the Simple Barycentric' + * funcs that only account for points inside the triangle. + * however switching back to this for ortho is always an option */ + +static void rect_to_uvspace_ortho( + rctf *bucket_bounds, + float *v1coSS, float *v2coSS, float *v3coSS, + float *uv1co, float *uv2co, float *uv3co, + float bucket_bounds_uv[4][2], + const int flip) +{ + float uv[2]; + float w[3]; + + /* get the UV space bounding box */ + uv[0] = bucket_bounds->xmax; + uv[1] = bucket_bounds->ymin; + barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmax; // set above + uv[1] = bucket_bounds->ymax; + barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w); + + uv[0] = bucket_bounds->xmin; + //uv[1] = bucket_bounds->ymax; // set above + barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmin; // set above + uv[1] = bucket_bounds->ymin; + barycentric_weights_v2(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w); +} + +/* same as above but use barycentric_weights_v2_persp */ +static void rect_to_uvspace_persp( + rctf *bucket_bounds, + float *v1coSS, float *v2coSS, float *v3coSS, + float *uv1co, float *uv2co, float *uv3co, + float bucket_bounds_uv[4][2], + const int flip + ) +{ + float uv[2]; + float w[3]; + + /* get the UV space bounding box */ + uv[0] = bucket_bounds->xmax; + uv[1] = bucket_bounds->ymin; + barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 3 : 0], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmax; // set above + uv[1] = bucket_bounds->ymax; + barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 2 : 1], uv1co, uv2co, uv3co, w); + + uv[0] = bucket_bounds->xmin; + //uv[1] = bucket_bounds->ymax; // set above + barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 1 : 2], uv1co, uv2co, uv3co, w); + + //uv[0] = bucket_bounds->xmin; // set above + uv[1] = bucket_bounds->ymin; + barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, uv, w); + interp_v2_v2v2v2(bucket_bounds_uv[flip ? 0 : 3], uv1co, uv2co, uv3co, w); +} + +/* This works as we need it to but we can save a few steps and not use it */ + +#if 0 +static float angle_2d_clockwise(const float p1[2], const float p2[2], const float p3[2]) +{ + float v1[2], v2[2]; + + v1[0] = p1[0] - p2[0]; v1[1] = p1[1] - p2[1]; + v2[0] = p3[0] - p2[0]; v2[1] = p3[1] - p2[1]; + + return -atan2(v1[0] * v2[1] - v1[1] * v2[0], v1[0] * v2[0] + v1[1] * v2[1]); +} +#endif + +#define ISECT_1 (1) +#define ISECT_2 (1 << 1) +#define ISECT_3 (1 << 2) +#define ISECT_4 (1 << 3) +#define ISECT_ALL3 ((1 << 3) - 1) +#define ISECT_ALL4 ((1 << 4) - 1) + +/* limit must be a fraction over 1.0f */ +static int IsectPT2Df_limit(float pt[2], float v1[2], float v2[2], float v3[2], float limit) +{ + return ((area_tri_v2(pt, v1, v2) + area_tri_v2(pt, v2, v3) + area_tri_v2(pt, v3, v1)) / (area_tri_v2(v1, v2, v3))) < limit; +} + +/* Clip the face by a bucket and set the uv-space bucket_bounds_uv + * so we have the clipped UV's to do pixel intersection tests with + * */ +static int float_z_sort_flip(const void *p1, const void *p2) +{ + return (((float *)p1)[2] < ((float *)p2)[2] ? 1 : -1); +} + +static int float_z_sort(const void *p1, const void *p2) +{ + return (((float *)p1)[2] < ((float *)p2)[2] ? -1 : 1); +} + +static void project_bucket_clip_face( + const int is_ortho, + rctf *bucket_bounds, + float *v1coSS, float *v2coSS, float *v3coSS, + float *uv1co, float *uv2co, float *uv3co, + float bucket_bounds_uv[8][2], + int *tot) +{ + int inside_bucket_flag = 0; + int inside_face_flag = 0; + const int flip = ((line_point_side_v2(v1coSS, v2coSS, v3coSS) > 0.0f) != (line_point_side_v2(uv1co, uv2co, uv3co) > 0.0f)); + + float bucket_bounds_ss[4][2]; + + /* get the UV space bounding box */ + inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v1coSS); + inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v2coSS) << 1; + inside_bucket_flag |= BLI_rctf_isect_pt_v(bucket_bounds, v3coSS) << 2; + + if (inside_bucket_flag == ISECT_ALL3) { + /* all screenspace points are inside the bucket bounding box, this means we don't need to clip and can simply return the UVs */ + if (flip) { /* facing the back? */ + copy_v2_v2(bucket_bounds_uv[0], uv3co); + copy_v2_v2(bucket_bounds_uv[1], uv2co); + copy_v2_v2(bucket_bounds_uv[2], uv1co); + } + else { + copy_v2_v2(bucket_bounds_uv[0], uv1co); + copy_v2_v2(bucket_bounds_uv[1], uv2co); + copy_v2_v2(bucket_bounds_uv[2], uv3co); + } + + *tot = 3; + return; + } + + /* get the UV space bounding box */ + /* use IsectPT2Df_limit here so we catch points are are touching the tri edge (or a small fraction over) */ + bucket_bounds_ss[0][0] = bucket_bounds->xmax; + bucket_bounds_ss[0][1] = bucket_bounds->ymin; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[0], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_1 : 0); + + bucket_bounds_ss[1][0] = bucket_bounds->xmax; + bucket_bounds_ss[1][1] = bucket_bounds->ymax; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[1], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_2 : 0); + + bucket_bounds_ss[2][0] = bucket_bounds->xmin; + bucket_bounds_ss[2][1] = bucket_bounds->ymax; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[2], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_3 : 0); + + bucket_bounds_ss[3][0] = bucket_bounds->xmin; + bucket_bounds_ss[3][1] = bucket_bounds->ymin; + inside_face_flag |= (IsectPT2Df_limit(bucket_bounds_ss[3], v1coSS, v2coSS, v3coSS, 1 + PROJ_GEOM_TOLERANCE) ? ISECT_4 : 0); + + if (inside_face_flag == ISECT_ALL4) { + /* bucket is totally inside the screenspace face, we can safely use weights */ + + if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip); + else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, bucket_bounds_uv, flip); + + *tot = 4; + return; + } + else { + /* The Complicated Case! + * + * The 2 cases above are where the face is inside the bucket or the bucket is inside the face. + * + * we need to make a convex polyline from the intersection between the screenspace face + * and the bucket bounds. + * + * There are a number of ways this could be done, currently it just collects all intersecting verts, + * and line intersections, then sorts them clockwise, this is a lot easier then evaluating the geometry to + * do a correct clipping on both shapes. */ + + + /* add a bunch of points, we know must make up the convex hull which is the clipped rect and triangle */ + + + + /* Maximum possible 6 intersections when using a rectangle and triangle */ + float isectVCosSS[8][3]; /* The 3rd float is used to store angle for qsort(), NOT as a Z location */ + float v1_clipSS[2], v2_clipSS[2]; + float w[3]; + + /* calc center */ + float cent[2] = {0.0f, 0.0f}; + /*float up[2] = {0.0f, 1.0f};*/ + int i; + short doubles; + + (*tot) = 0; + + if (inside_face_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[0]); (*tot)++; } + if (inside_face_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[1]); (*tot)++; } + if (inside_face_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[2]); (*tot)++; } + if (inside_face_flag & ISECT_4) { copy_v2_v2(isectVCosSS[*tot], bucket_bounds_ss[3]); (*tot)++; } + + if (inside_bucket_flag & ISECT_1) { copy_v2_v2(isectVCosSS[*tot], v1coSS); (*tot)++; } + if (inside_bucket_flag & ISECT_2) { copy_v2_v2(isectVCosSS[*tot], v2coSS); (*tot)++; } + if (inside_bucket_flag & ISECT_3) { copy_v2_v2(isectVCosSS[*tot], v3coSS); (*tot)++; } + + if ((inside_bucket_flag & (ISECT_1 | ISECT_2)) != (ISECT_1 | ISECT_2)) { + if (line_clip_rect2f(bucket_bounds, v1coSS, v2coSS, v1_clipSS, v2_clipSS)) { + if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } + if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } + } + } + + if ((inside_bucket_flag & (ISECT_2 | ISECT_3)) != (ISECT_2 | ISECT_3)) { + if (line_clip_rect2f(bucket_bounds, v2coSS, v3coSS, v1_clipSS, v2_clipSS)) { + if ((inside_bucket_flag & ISECT_2) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } + if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } + } + } + + if ((inside_bucket_flag & (ISECT_3 | ISECT_1)) != (ISECT_3 | ISECT_1)) { + if (line_clip_rect2f(bucket_bounds, v3coSS, v1coSS, v1_clipSS, v2_clipSS)) { + if ((inside_bucket_flag & ISECT_3) == 0) { copy_v2_v2(isectVCosSS[*tot], v1_clipSS); (*tot)++; } + if ((inside_bucket_flag & ISECT_1) == 0) { copy_v2_v2(isectVCosSS[*tot], v2_clipSS); (*tot)++; } + } + } + + + if ((*tot) < 3) { /* no intersections to speak of */ + *tot = 0; + return; + } + + /* now we have all points we need, collect their angles and sort them clockwise */ + + for (i = 0; i < (*tot); i++) { + cent[0] += isectVCosSS[i][0]; + cent[1] += isectVCosSS[i][1]; + } + cent[0] = cent[0] / (float)(*tot); + cent[1] = cent[1] / (float)(*tot); + + + + /* Collect angles for every point around the center point */ + + +#if 0 /* uses a few more cycles then the above loop */ + for (i = 0; i < (*tot); i++) { + isectVCosSS[i][2] = angle_2d_clockwise(up, cent, isectVCosSS[i]); + } +#endif + + v1_clipSS[0] = cent[0]; /* Abuse this var for the loop below */ + v1_clipSS[1] = cent[1] + 1.0f; + + for (i = 0; i < (*tot); i++) { + v2_clipSS[0] = isectVCosSS[i][0] - cent[0]; + v2_clipSS[1] = isectVCosSS[i][1] - cent[1]; + isectVCosSS[i][2] = atan2f(v1_clipSS[0] * v2_clipSS[1] - v1_clipSS[1] * v2_clipSS[0], v1_clipSS[0] * v2_clipSS[0] + v1_clipSS[1] * v2_clipSS[1]); + } + + if (flip) qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort_flip); + else qsort(isectVCosSS, *tot, sizeof(float) * 3, float_z_sort); + + /* remove doubles */ + /* first/last check */ + if (fabsf(isectVCosSS[0][0] - isectVCosSS[(*tot) - 1][0]) < PROJ_GEOM_TOLERANCE && + fabsf(isectVCosSS[0][1] - isectVCosSS[(*tot) - 1][1]) < PROJ_GEOM_TOLERANCE) + { + (*tot)--; + } + + /* its possible there is only a few left after remove doubles */ + if ((*tot) < 3) { + // printf("removed too many doubles A\n"); + *tot = 0; + return; + } + + doubles = TRUE; + while (doubles == TRUE) { + doubles = FALSE; + for (i = 1; i < (*tot); i++) { + if (fabsf(isectVCosSS[i - 1][0] - isectVCosSS[i][0]) < PROJ_GEOM_TOLERANCE && + fabsf(isectVCosSS[i - 1][1] - isectVCosSS[i][1]) < PROJ_GEOM_TOLERANCE) + { + int j; + for (j = i + 1; j < (*tot); j++) { + isectVCosSS[j - 1][0] = isectVCosSS[j][0]; + isectVCosSS[j - 1][1] = isectVCosSS[j][1]; + } + doubles = TRUE; /* keep looking for more doubles */ + (*tot)--; + } + } + } + + /* its possible there is only a few left after remove doubles */ + if ((*tot) < 3) { + // printf("removed too many doubles B\n"); + *tot = 0; + return; + } + + + if (is_ortho) { + for (i = 0; i < (*tot); i++) { + barycentric_weights_v2(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w); + interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); + } + } + else { + for (i = 0; i < (*tot); i++) { + barycentric_weights_v2_persp(v1coSS, v2coSS, v3coSS, isectVCosSS[i], w); + interp_v2_v2v2v2(bucket_bounds_uv[i], uv1co, uv2co, uv3co, w); + } + } + } + +#ifdef PROJ_DEBUG_PRINT_CLIP + /* include this at the bottom of the above function to debug the output */ + + { + /* If there are ever any problems, */ + float test_uv[4][2]; + int i; + if (is_ortho) rect_to_uvspace_ortho(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip); + else rect_to_uvspace_persp(bucket_bounds, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, test_uv, flip); + printf("( [(%f,%f), (%f,%f), (%f,%f), (%f,%f)], ", test_uv[0][0], test_uv[0][1], test_uv[1][0], test_uv[1][1], test_uv[2][0], test_uv[2][1], test_uv[3][0], test_uv[3][1]); + + printf(" [(%f,%f), (%f,%f), (%f,%f)], ", uv1co[0], uv1co[1], uv2co[0], uv2co[1], uv3co[0], uv3co[1]); + + printf("["); + for (i = 0; i < (*tot); i++) { + printf("(%f, %f),", bucket_bounds_uv[i][0], bucket_bounds_uv[i][1]); + } + printf("]),\\\n"); + } +#endif +} + +/* + * # This script creates faces in a blender scene from printed data above. + * + * project_ls = [ + * ...(output from above block)... + * ] + * + * from Blender import Scene, Mesh, Window, sys, Mathutils + * + * import bpy + * + * V = Mathutils.Vector + * + * def main(): + * sce = bpy.data.scenes.active + * + * for item in project_ls: + * bb = item[0] + * uv = item[1] + * poly = item[2] + * + * me = bpy.data.meshes.new() + * ob = sce.objects.new(me) + * + * me.verts.extend([V(bb[0]).xyz, V(bb[1]).xyz, V(bb[2]).xyz, V(bb[3]).xyz]) + * me.faces.extend([(0,1,2,3),]) + * me.verts.extend([V(uv[0]).xyz, V(uv[1]).xyz, V(uv[2]).xyz]) + * me.faces.extend([(4,5,6),]) + * + * vs = [V(p).xyz for p in poly] + * print len(vs) + * l = len(me.verts) + * me.verts.extend(vs) + * + * i = l + * while i < len(me.verts): + * ii = i + 1 + * if ii == len(me.verts): + * ii = l + * me.edges.extend([i, ii]) + * i += 1 + * + * if __name__ == '__main__': + * main() + */ + + +#undef ISECT_1 +#undef ISECT_2 +#undef ISECT_3 +#undef ISECT_4 +#undef ISECT_ALL3 +#undef ISECT_ALL4 + + +/* checks if pt is inside a convex 2D polyline, the polyline must be ordered rotating clockwise + * otherwise it would have to test for mixed (line_point_side_v2 > 0.0f) cases */ +static int IsectPoly2Df(const float pt[2], float uv[][2], const int tot) +{ + int i; + if (line_point_side_v2(uv[tot - 1], uv[0], pt) < 0.0f) + return 0; + + for (i = 1; i < tot; i++) { + if (line_point_side_v2(uv[i - 1], uv[i], pt) < 0.0f) + return 0; + + } + + return 1; +} +static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) +{ + int i; + int side = (line_point_side_v2(uv[tot - 1], uv[0], pt) > 0.0f); + + for (i = 1; i < tot; i++) { + if ((line_point_side_v2(uv[i - 1], uv[i], pt) > 0.0f) != side) + return 0; + + } + + return 1; +} + +/* One of the most important function for projection painting, since it selects the pixels to be added into each bucket. + * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */ +static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v) +{ + /* Projection vars, to get the 3D locations into screen space */ + MemArena *arena = ps->arena_mt[thread_index]; + LinkNode **bucketPixelNodes = ps->bucketRect + bucket_index; + LinkNode *bucketFaceNodes = ps->bucketFaces[bucket_index]; + + const MFace *mf = ps->dm_mface + face_index; + const MTFace *tf = ps->dm_mtface + face_index; + + /* UV/pixel seeking data */ + int x; /* Image X-Pixel */ + int y; /* Image Y-Pixel */ + float mask; + float uv[2]; /* Image floating point UV - same as x, y but from 0.0-1.0 */ + + int side; + float *v1coSS, *v2coSS, *v3coSS; /* vert co screen-space, these will be assigned to mf->v1,2,3 or mf->v1,3,4 */ + + float *vCo[4]; /* vertex screenspace coords */ + + float w[3], wco[3]; + + float *uv1co, *uv2co, *uv3co; /* for convenience only, these will be assigned to tf->uv[0],1,2 or tf->uv[0],2,3 */ + float pixelScreenCo[4]; + bool do_3d_mapping = ps->brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D; + + rcti bounds_px; /* ispace bounds */ + /* vars for getting uvspace bounds */ + + float tf_uv_pxoffset[4][2]; /* bucket bounds in UV space so we can init pixels only for this face, */ + float xhalfpx, yhalfpx; + const float ibuf_xf = (float)ibuf->x, ibuf_yf = (float)ibuf->y; + + int has_x_isect = 0, has_isect = 0; /* for early loop exit */ + + int i1, i2, i3; + + float uv_clip[8][2]; + int uv_clip_tot; + const short is_ortho = ps->is_ortho; + const short do_backfacecull = ps->do_backfacecull; + const short do_clip = ps->rv3d ? ps->rv3d->rflag & RV3D_CLIPPING : 0; + + vCo[0] = ps->dm_mvert[mf->v1].co; + vCo[1] = ps->dm_mvert[mf->v2].co; + vCo[2] = ps->dm_mvert[mf->v3].co; + + + /* Use tf_uv_pxoffset instead of tf->uv so we can offset the UV half a pixel + * this is done so we can avoid offsetting all the pixels by 0.5 which causes + * problems when wrapping negative coords */ + xhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 3.0f)) / ibuf_xf; + yhalfpx = (0.5f + (PROJ_GEOM_TOLERANCE / 4.0f)) / ibuf_yf; + + /* Note about (PROJ_GEOM_TOLERANCE/x) above... + * Needed to add this offset since UV coords are often quads aligned to pixels. + * In this case pixels can be exactly between 2 triangles causing nasty + * artifacts. + * + * This workaround can be removed and painting will still work on most cases + * but since the first thing most people try is painting onto a quad- better make it work. + */ + + + + tf_uv_pxoffset[0][0] = tf->uv[0][0] - xhalfpx; + tf_uv_pxoffset[0][1] = tf->uv[0][1] - yhalfpx; + + tf_uv_pxoffset[1][0] = tf->uv[1][0] - xhalfpx; + tf_uv_pxoffset[1][1] = tf->uv[1][1] - yhalfpx; + + tf_uv_pxoffset[2][0] = tf->uv[2][0] - xhalfpx; + tf_uv_pxoffset[2][1] = tf->uv[2][1] - yhalfpx; + + if (mf->v4) { + vCo[3] = ps->dm_mvert[mf->v4].co; + + tf_uv_pxoffset[3][0] = tf->uv[3][0] - xhalfpx; + tf_uv_pxoffset[3][1] = tf->uv[3][1] - yhalfpx; + side = 1; + } + else { + side = 0; + } + + do { + if (side == 1) { + i1 = 0; i2 = 2; i3 = 3; + } + else { + i1 = 0; i2 = 1; i3 = 2; + } + + uv1co = tf_uv_pxoffset[i1]; // was tf->uv[i1]; + uv2co = tf_uv_pxoffset[i2]; // was tf->uv[i2]; + uv3co = tf_uv_pxoffset[i3]; // was tf->uv[i3]; + + v1coSS = ps->screenCoords[(*(&mf->v1 + i1))]; + v2coSS = ps->screenCoords[(*(&mf->v1 + i2))]; + v3coSS = ps->screenCoords[(*(&mf->v1 + i3))]; + + /* This funtion gives is a concave polyline in UV space from the clipped quad and tri*/ + project_bucket_clip_face( + is_ortho, bucket_bounds, + v1coSS, v2coSS, v3coSS, + uv1co, uv2co, uv3co, + uv_clip, &uv_clip_tot + ); + + /* sometimes this happens, better just allow for 8 intersectiosn even though there should be max 6 */ +#if 0 + if (uv_clip_tot > 6) { + printf("this should never happen! %d\n", uv_clip_tot); + } +#endif + + if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) { + + if (clamp_u) { + CLAMP(bounds_px.xmin, 0, ibuf->x); + CLAMP(bounds_px.xmax, 0, ibuf->x); + } + + if (clamp_v) { + CLAMP(bounds_px.ymin, 0, ibuf->y); + CLAMP(bounds_px.ymax, 0, ibuf->y); + } + + /* clip face and */ + + has_isect = 0; + for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { + //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; + uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */ + + has_x_isect = 0; + for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { + //uv[0] = (((float)x) + 0.5f) / ibuf->x; + uv[0] = (float)x / ibuf_xf; /* use pixel offset UV coords instead */ + + /* Note about IsectPoly2Df_twoside, checking the face or uv flipping doesnt work, + * could check the poly direction but better to do this */ + if ((do_backfacecull == TRUE && IsectPoly2Df(uv, uv_clip, uv_clip_tot)) || + (do_backfacecull == FALSE && IsectPoly2Df_twoside(uv, uv_clip, uv_clip_tot))) + { + + has_x_isect = has_isect = 1; + + if (is_ortho) screen_px_from_ortho(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); + else screen_px_from_persp(uv, v1coSS, v2coSS, v3coSS, uv1co, uv2co, uv3co, pixelScreenCo, w); + + /* a pity we need to get the worldspace pixel location here */ + if (do_clip || do_3d_mapping) { + interp_v3_v3v3v3(wco, ps->dm_mvert[(*(&mf->v1 + i1))].co, ps->dm_mvert[(*(&mf->v1 + i2))].co, ps->dm_mvert[(*(&mf->v1 + i3))].co, w); + if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + continue; /* Watch out that no code below this needs to run */ + } + } + + /* Is this UV visible from the view? - raytrace */ + /* project_paint_PickFace is less complex, use for testing */ + //if (project_paint_PickFace(ps, pixelScreenCo, w, &side) == face_index) { + if ((ps->do_occlude == FALSE) || + !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) + { + mask = project_paint_uvpixel_mask(ps, face_index, side, w); + + if (mask > 0.0f) { + BLI_linklist_prepend_arena( + bucketPixelNodes, + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, + image_index, pixelScreenCo, wco, side, w), + arena + ); + } + } + + } +//#if 0 + else if (has_x_isect) { + /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + break; + } +//#endif + } + + +#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */ + /* no intersection for this entire row, after some intersection above means we can quit now */ + if (has_x_isect == 0 && has_isect) { + break; + } +#endif + } + } + } while (side--); + + + +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + int face_seam_flag; + + if (ps->thread_tot > 1) + BLI_lock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ + + face_seam_flag = ps->faceSeamFlags[face_index]; + + /* are any of our edges un-initialized? */ + if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_NOSEAM1)) == 0 || + (face_seam_flag & (PROJ_FACE_SEAM2 | PROJ_FACE_NOSEAM2)) == 0 || + (face_seam_flag & (PROJ_FACE_SEAM3 | PROJ_FACE_NOSEAM3)) == 0 || + (face_seam_flag & (PROJ_FACE_SEAM4 | PROJ_FACE_NOSEAM4)) == 0) + { + project_face_seams_init(ps, face_index, mf->v4); + face_seam_flag = ps->faceSeamFlags[face_index]; + //printf("seams - %d %d %d %d\n", flag&PROJ_FACE_SEAM1, flag&PROJ_FACE_SEAM2, flag&PROJ_FACE_SEAM3, flag&PROJ_FACE_SEAM4); + } + + if ((face_seam_flag & (PROJ_FACE_SEAM1 | PROJ_FACE_SEAM2 | PROJ_FACE_SEAM3 | PROJ_FACE_SEAM4)) == 0) { + + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ + + } + else { + /* we have a seam - deal with it! */ + + /* Now create new UV's for the seam face */ + float (*outset_uv)[2] = ps->faceSeamUVs[face_index]; + float insetCos[4][3]; /* inset face coords. NOTE!!! ScreenSace for ortho, Worldspace in prespective view */ + + float *vCoSS[4]; /* vertex screenspace coords */ + + float bucket_clip_edges[2][2]; /* store the screenspace coords of the face, clipped by the bucket's screen aligned rectangle */ + float edge_verts_inset_clip[2][3]; + int fidx1, fidx2; /* face edge pairs - loop throuh these ((0,1), (1,2), (2,3), (3,0)) or ((0,1), (1,2), (2,0)) for a tri */ + + float seam_subsection[4][2]; + float fac1, fac2, ftot; + + + if (outset_uv[0][0] == FLT_MAX) /* first time initialize */ + uv_image_outset(tf_uv_pxoffset, outset_uv, ps->seam_bleed_px, ibuf->x, ibuf->y, mf->v4); + + /* ps->faceSeamUVs cant be modified when threading, now this is done we can unlock */ + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); /* Other threads could be modifying these vars */ + + vCoSS[0] = ps->screenCoords[mf->v1]; + vCoSS[1] = ps->screenCoords[mf->v2]; + vCoSS[2] = ps->screenCoords[mf->v3]; + if (mf->v4) + vCoSS[3] = ps->screenCoords[mf->v4]; + + /* PROJ_FACE_SCALE_SEAM must be slightly less then 1.0f */ + if (is_ortho) { + if (mf->v4) scale_quad(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM); + else scale_tri(insetCos, vCoSS, PROJ_FACE_SCALE_SEAM); + } + else { + if (mf->v4) scale_quad(insetCos, vCo, PROJ_FACE_SCALE_SEAM); + else scale_tri(insetCos, vCo, PROJ_FACE_SCALE_SEAM); + } + + side = 0; /* for triangles this wont need to change */ + + for (fidx1 = 0; fidx1 < (mf->v4 ? 4 : 3); fidx1++) { + if (mf->v4) fidx2 = (fidx1 == 3) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2,3) -> (1,2,3,0) */ + else fidx2 = (fidx1 == 2) ? 0 : fidx1 + 1; /* next fidx in the face (0,1,2) -> (1,2,0) */ + + if ((face_seam_flag & (1 << fidx1)) && /* 1<<fidx1 -> PROJ_FACE_SEAM# */ + line_clip_rect2f(bucket_bounds, vCoSS[fidx1], vCoSS[fidx2], bucket_clip_edges[0], bucket_clip_edges[1])) + { + + ftot = len_v2v2(vCoSS[fidx1], vCoSS[fidx2]); /* screenspace edge length */ + + if (ftot > 0.0f) { /* avoid div by zero */ + if (mf->v4) { + if (fidx1 == 2 || fidx2 == 2) side = 1; + else side = 0; + } + + fac1 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[0]) / ftot; + fac2 = len_v2v2(vCoSS[fidx1], bucket_clip_edges[1]) / ftot; + + interp_v2_v2v2(seam_subsection[0], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac1); + interp_v2_v2v2(seam_subsection[1], tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2], fac2); + + interp_v2_v2v2(seam_subsection[2], outset_uv[fidx1], outset_uv[fidx2], fac2); + interp_v2_v2v2(seam_subsection[3], outset_uv[fidx1], outset_uv[fidx2], fac1); + + /* if the bucket_clip_edges values Z values was kept we could avoid this + * Inset needs to be added so occlusion tests wont hit adjacent faces */ + interp_v3_v3v3(edge_verts_inset_clip[0], insetCos[fidx1], insetCos[fidx2], fac1); + interp_v3_v3v3(edge_verts_inset_clip[1], insetCos[fidx1], insetCos[fidx2], fac2); + + + if (pixel_bounds_uv(seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3], &bounds_px, ibuf->x, ibuf->y, 1)) { + /* bounds between the seam rect and the uvspace bucket pixels */ + + has_isect = 0; + for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { + // uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; + uv[1] = (float)y / ibuf_yf; /* use offset uvs instead */ + + has_x_isect = 0; + for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { + //uv[0] = (((float)x) + 0.5f) / (float)ibuf->x; + uv[0] = (float)x / ibuf_xf; /* use offset uvs instead */ + + /* test we're inside uvspace bucket and triangle bounds */ + if (isect_point_quad_v2(uv, seam_subsection[0], seam_subsection[1], seam_subsection[2], seam_subsection[3])) { + float fac; + + /* We need to find the closest point along the face edge, + * getting the screen_px_from_*** wont work because our actual location + * is not relevant, since we are outside the face, Use VecLerpf to find + * our location on the side of the face's UV */ +#if 0 + if (is_ortho) screen_px_from_ortho(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo); + else screen_px_from_persp(ps, uv, v1co, v2co, v3co, uv1co, uv2co, uv3co, pixelScreenCo); +#endif + + /* Since this is a seam we need to work out where on the line this pixel is */ + //fac = line_point_factor_v2(uv, uv_seam_quad[0], uv_seam_quad[1]); + + fac = line_point_factor_v2(uv, seam_subsection[0], seam_subsection[1]); + if (fac < 0.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[0]); } + else if (fac > 1.0f) { copy_v3_v3(pixelScreenCo, edge_verts_inset_clip[1]); } + else { interp_v3_v3v3(pixelScreenCo, edge_verts_inset_clip[0], edge_verts_inset_clip[1], fac); } + + if (!is_ortho) { + pixelScreenCo[3] = 1.0f; + mul_m4_v4((float(*)[4])ps->projectMat, pixelScreenCo); /* cast because of const */ + pixelScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * pixelScreenCo[0] / pixelScreenCo[3]; + pixelScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * pixelScreenCo[1] / pixelScreenCo[3]; + pixelScreenCo[2] = pixelScreenCo[2] / pixelScreenCo[3]; /* Use the depth for bucket point occlusion */ + } + + if ((ps->do_occlude == FALSE) || + !project_bucket_point_occluded(ps, bucketFaceNodes, face_index, pixelScreenCo)) + { + /* Only bother calculating the weights if we intersect */ + if (ps->do_mask_normal || ps->dm_mtface_clone) { +#if 1 + /* get the UV on the line since we want to copy the pixels from there for bleeding */ + float uv_close[2]; + float uv_fac = closest_to_line_v2(uv_close, uv, tf_uv_pxoffset[fidx1], tf_uv_pxoffset[fidx2]); + if (uv_fac < 0.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx1]); + else if (uv_fac > 1.0f) copy_v2_v2(uv_close, tf_uv_pxoffset[fidx2]); + + if (side) { + barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[2], tf_uv_pxoffset[3], uv_close, w); + } + else { + barycentric_weights_v2(tf_uv_pxoffset[0], tf_uv_pxoffset[1], tf_uv_pxoffset[2], uv_close, w); + } +#else /* this is buggy with quads, don't use for now */ + + /* Cheat, we know where we are along the edge so work out the weights from that */ + uv_fac = fac1 + (uv_fac * (fac2 - fac1)); + + w[0] = w[1] = w[2] = 0.0; + if (side) { + w[fidx1 ? fidx1 - 1 : 0] = 1.0f - uv_fac; + w[fidx2 ? fidx2 - 1 : 0] = uv_fac; + } + else { + w[fidx1] = 1.0f - uv_fac; + w[fidx2] = uv_fac; + } +#endif + } + + /* a pity we need to get the worldspace pixel location here */ + if (do_clip || do_3d_mapping) { + if (side) interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v3].co, ps->dm_mvert[mf->v4].co, w); + else interp_v3_v3v3v3(wco, ps->dm_mvert[mf->v1].co, ps->dm_mvert[mf->v2].co, ps->dm_mvert[mf->v3].co, w); + + if (do_clip && ED_view3d_clipping_test(ps->rv3d, wco, TRUE)) { + continue; /* Watch out that no code below this needs to run */ + } + } + + mask = project_paint_uvpixel_mask(ps, face_index, side, w); + + if (mask > 0.0f) { + BLI_linklist_prepend_arena( + bucketPixelNodes, + project_paint_uvpixel_init(ps, arena, ibuf, x, y, mask, face_index, image_index, pixelScreenCo, wco, side, w), + arena + ); + } + + } + } + else if (has_x_isect) { + /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + break; + } + } + +#if 0 /* TODO - investigate why this dosnt work sometimes! it should! */ + /* no intersection for this entire row, after some intersection above means we can quit now */ + if (has_x_isect == 0 && has_isect) { + break; + } +#endif + } + } + } + } + } + } + } +#endif // PROJ_DEBUG_NOSEAMBLEED +} + + +/* takes floating point screenspace min/max and returns int min/max to be used as indices for ps->bucketRect, ps->bucketFlags */ +static void project_paint_bucket_bounds(const ProjPaintState *ps, const float min[2], const float max[2], int bucketMin[2], int bucketMax[2]) +{ + /* divide by bucketWidth & bucketHeight so the bounds are offset in bucket grid units */ + /* XXX: the offset of 0.5 is always truncated to zero and the offset of 1.5f is always truncated to 1, is this really correct?? - jwilkins */ + bucketMin[0] = (int)((int)(((float)(min[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 0.5f); /* these offsets of 0.5 and 1.5 seem odd but they are correct */ + bucketMin[1] = (int)((int)(((float)(min[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 0.5f); + + bucketMax[0] = (int)((int)(((float)(max[0] - ps->screenMin[0]) / ps->screen_width) * ps->buckets_x) + 1.5f); + bucketMax[1] = (int)((int)(((float)(max[1] - ps->screenMin[1]) / ps->screen_height) * ps->buckets_y) + 1.5f); + + /* in case the rect is outside the mesh 2d bounds */ + CLAMP(bucketMin[0], 0, ps->buckets_x); + CLAMP(bucketMin[1], 0, ps->buckets_y); + + CLAMP(bucketMax[0], 0, ps->buckets_x); + CLAMP(bucketMax[1], 0, ps->buckets_y); +} + +/* set bucket_bounds to a screen space-aligned floating point bound-box */ +static void project_bucket_bounds(const ProjPaintState *ps, const int bucket_x, const int bucket_y, rctf *bucket_bounds) +{ + bucket_bounds->xmin = ps->screenMin[0] + ((bucket_x) * (ps->screen_width / ps->buckets_x)); /* left */ + bucket_bounds->xmax = ps->screenMin[0] + ((bucket_x + 1) * (ps->screen_width / ps->buckets_x)); /* right */ + + bucket_bounds->ymin = ps->screenMin[1] + ((bucket_y) * (ps->screen_height / ps->buckets_y)); /* bottom */ + bucket_bounds->ymax = ps->screenMin[1] + ((bucket_y + 1) * (ps->screen_height / ps->buckets_y)); /* top */ +} + +/* Fill this bucket with pixels from the faces that intersect it. + * + * have bucket_bounds as an argument so we don't need to give bucket_x/y the rect function needs */ +static void project_bucket_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, rctf *bucket_bounds) +{ + LinkNode *node; + int face_index, image_index = 0; + ImBuf *ibuf = NULL; + Image *tpage_last = NULL, *tpage; + Image *ima = NULL; + + if (ps->image_tot == 1) { + /* Simple loop, no context switching */ + ibuf = ps->projImages[0].ibuf; + ima = ps->projImages[0].ima; + + for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { + project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); + } + } + else { + + /* More complicated loop, switch between images */ + for (node = ps->bucketFaces[bucket_index]; node; node = node->next) { + face_index = GET_INT_FROM_POINTER(node->link); + + /* Image context switching */ + tpage = project_paint_face_image(ps, ps->dm_mtface, face_index); + if (tpage_last != tpage) { + tpage_last = tpage; + + for (image_index = 0; image_index < ps->image_tot; image_index++) { + if (ps->projImages[image_index].ima == tpage_last) { + ibuf = ps->projImages[image_index].ibuf; + ima = ps->projImages[image_index].ima; + break; + } + } + } + /* context switching done */ + + project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); + } + } + + ps->bucketFlags[bucket_index] |= PROJ_BUCKET_INIT; +} + + +/* We want to know if a bucket and a face overlap in screen-space + * + * Note, if this ever returns false positives its not that bad, since a face in the bounding area will have its pixels + * calculated when it might not be needed later, (at the moment at least) + * obviously it shouldn't have bugs though */ + +static int project_bucket_face_isect(ProjPaintState *ps, int bucket_x, int bucket_y, const MFace *mf) +{ + /* TODO - replace this with a tricker method that uses sideofline for all screenCoords's edges against the closest bucket corner */ + rctf bucket_bounds; + float p1[2], p2[2], p3[2], p4[2]; + float *v, *v1, *v2, *v3, *v4 = NULL; + int fidx; + + project_bucket_bounds(ps, bucket_x, bucket_y, &bucket_bounds); + + /* Is one of the faces verts in the bucket bounds? */ + + fidx = mf->v4 ? 3 : 2; + do { + v = ps->screenCoords[(*(&mf->v1 + fidx))]; + if (BLI_rctf_isect_pt_v(&bucket_bounds, v)) { + return 1; + } + } while (fidx--); + + v1 = ps->screenCoords[mf->v1]; + v2 = ps->screenCoords[mf->v2]; + v3 = ps->screenCoords[mf->v3]; + if (mf->v4) { + v4 = ps->screenCoords[mf->v4]; + } + + p1[0] = bucket_bounds.xmin; p1[1] = bucket_bounds.ymin; + p2[0] = bucket_bounds.xmin; p2[1] = bucket_bounds.ymax; + p3[0] = bucket_bounds.xmax; p3[1] = bucket_bounds.ymax; + p4[0] = bucket_bounds.xmax; p4[1] = bucket_bounds.ymin; + + if (mf->v4) { + if (isect_point_quad_v2(p1, v1, v2, v3, v4) || + isect_point_quad_v2(p2, v1, v2, v3, v4) || + isect_point_quad_v2(p3, v1, v2, v3, v4) || + isect_point_quad_v2(p4, v1, v2, v3, v4) || + + /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */ + (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3) || isect_line_line_v2(p1, p2, v3, v4)) || + (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3) || isect_line_line_v2(p2, p3, v3, v4)) || + (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3) || isect_line_line_v2(p3, p4, v3, v4)) || + (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3) || isect_line_line_v2(p4, p1, v3, v4))) + { + return 1; + } + } + else { + if (isect_point_tri_v2(p1, v1, v2, v3) || + isect_point_tri_v2(p2, v1, v2, v3) || + isect_point_tri_v2(p3, v1, v2, v3) || + isect_point_tri_v2(p4, v1, v2, v3) || + /* we can avoid testing v3,v1 because another intersection MUST exist if this intersects */ + (isect_line_line_v2(p1, p2, v1, v2) || isect_line_line_v2(p1, p2, v2, v3)) || + (isect_line_line_v2(p2, p3, v1, v2) || isect_line_line_v2(p2, p3, v2, v3)) || + (isect_line_line_v2(p3, p4, v1, v2) || isect_line_line_v2(p3, p4, v2, v3)) || + (isect_line_line_v2(p4, p1, v1, v2) || isect_line_line_v2(p4, p1, v2, v3))) + { + return 1; + } + } + + return 0; +} + +/* Add faces to the bucket but don't initialize its pixels + * TODO - when painting occluded, sort the faces on their min-Z and only add faces that faces that are not occluded */ +static void project_paint_delayed_face_init(ProjPaintState *ps, const MFace *mf, const int face_index) +{ + float min[2], max[2], *vCoSS; + int bucketMin[2], bucketMax[2]; /* for ps->bucketRect indexing */ + int fidx, bucket_x, bucket_y; + int has_x_isect = -1, has_isect = 0; /* for early loop exit */ + MemArena *arena = ps->arena_mt[0]; /* just use the first thread arena since threading has not started yet */ + + INIT_MINMAX2(min, max); + + fidx = mf->v4 ? 3 : 2; + do { + vCoSS = ps->screenCoords[*(&mf->v1 + fidx)]; + minmax_v2v2_v2(min, max, vCoSS); + } while (fidx--); + + project_paint_bucket_bounds(ps, min, max, bucketMin, bucketMax); + + for (bucket_y = bucketMin[1]; bucket_y < bucketMax[1]; bucket_y++) { + has_x_isect = 0; + for (bucket_x = bucketMin[0]; bucket_x < bucketMax[0]; bucket_x++) { + if (project_bucket_face_isect(ps, bucket_x, bucket_y, mf)) { + int bucket_index = bucket_x + (bucket_y * ps->buckets_x); + BLI_linklist_prepend_arena( + &ps->bucketFaces[bucket_index], + SET_INT_IN_POINTER(face_index), /* cast to a pointer to shut up the compiler */ + arena + ); + + has_x_isect = has_isect = 1; + } + else if (has_x_isect) { + /* assuming the face is not a bow-tie - we know we cant intersect again on the X */ + break; + } + } + + /* no intersection for this entire row, after some intersection above means we can quit now */ + if (has_x_isect == 0 && has_isect) { + break; + } + } + +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + if (!mf->v4) { + ps->faceSeamFlags[face_index] |= PROJ_FACE_NOSEAM4; /* so this wont show up as an untagged edge */ + } + **ps->faceSeamUVs[face_index] = FLT_MAX; /* set as uninitialized */ + } +#endif +} + +/* run once per stroke before projection painting */ +static void project_paint_begin(ProjPaintState *ps) +{ + /* Viewport vars */ + float mat[3][3]; + + float no[3]; + + float *projScreenCo; /* Note, we could have 4D vectors are only needed for */ + float projMargin; + + /* Image Vars - keep track of images we have used */ + LinkNode *image_LinkList = NULL; + LinkNode *node; + + ProjPaintImage *projIma; + Image *tpage_last = NULL, *tpage; + + /* Face vars */ + MFace *mf; + MTFace *tf; + + int a, i; /* generic looping vars */ + int image_index = -1, face_index; + MVert *mv; + + MemArena *arena; /* at the moment this is just ps->arena_mt[0], but use this to show were not multithreading */ + + const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush); + + /* ---- end defines ---- */ + + if (ps->source == PROJ_SRC_VIEW) + ED_view3d_clipping_local(ps->rv3d, ps->ob->obmat); /* faster clipping lookups */ + + /* paint onto the derived mesh */ + + /* Workaround for subsurf selection, try the display mesh first */ + if (ps->source == PROJ_SRC_IMAGE_CAM) { + /* using render mesh, assume only camera was rendered from */ + ps->dm = mesh_create_derived_render(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); + ps->dm_release = TRUE; + } + else if (ps->ob->derivedFinal && CustomData_has_layer(&ps->ob->derivedFinal->faceData, CD_MTFACE)) { + ps->dm = ps->ob->derivedFinal; + ps->dm_release = FALSE; + } + else { + ps->dm = mesh_get_derived_final(ps->scene, ps->ob, ps->scene->customdata_mask | CD_MASK_MTFACE); + ps->dm_release = TRUE; + } + + if (!CustomData_has_layer(&ps->dm->faceData, CD_MTFACE) ) { + + if (ps->dm_release) + ps->dm->release(ps->dm); + + ps->dm = NULL; + return; + } + + ps->dm_mvert = ps->dm->getVertArray(ps->dm); + ps->dm_mface = ps->dm->getTessFaceArray(ps->dm); + ps->dm_mtface = ps->dm->getTessFaceDataArray(ps->dm, CD_MTFACE); + + ps->dm_totvert = ps->dm->getNumVerts(ps->dm); + ps->dm_totface = ps->dm->getNumTessFaces(ps->dm); + + /* use clone mtface? */ + + + /* Note, use the original mesh for getting the clone and mask layer index + * this avoids re-generating the derived mesh just to get the new index */ + if (ps->do_layer_clone) { + //int layer_num = CustomData_get_clone_layer(&ps->dm->faceData, CD_MTFACE); + int layer_num = CustomData_get_clone_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); + if (layer_num != -1) + ps->dm_mtface_clone = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); + + if (ps->dm_mtface_clone == NULL || ps->dm_mtface_clone == ps->dm_mtface) { + ps->do_layer_clone = FALSE; + ps->dm_mtface_clone = NULL; + printf("ACK!\n"); + } + } + + if (ps->do_layer_stencil) { + //int layer_num = CustomData_get_stencil_layer(&ps->dm->faceData, CD_MTFACE); + int layer_num = CustomData_get_stencil_layer(&((Mesh *)ps->ob->data)->fdata, CD_MTFACE); + if (layer_num != -1) + ps->dm_mtface_stencil = CustomData_get_layer_n(&ps->dm->faceData, CD_MTFACE, layer_num); + + if (ps->dm_mtface_stencil == NULL || ps->dm_mtface_stencil == ps->dm_mtface) { + ps->do_layer_stencil = FALSE; + ps->dm_mtface_stencil = NULL; + } + } + + /* when using subsurf or multires, mface arrays are thrown away, we need to keep a copy */ + if (ps->dm->type != DM_TYPE_CDDM) { + ps->dm_mvert = MEM_dupallocN(ps->dm_mvert); + ps->dm_mface = MEM_dupallocN(ps->dm_mface); + /* looks like these are ok for now.*/ +#if 0 + ps->dm_mtface = MEM_dupallocN(ps->dm_mtface); + ps->dm_mtface_clone = MEM_dupallocN(ps->dm_mtface_clone); + ps->dm_mtface_stencil = MEM_dupallocN(ps->dm_mtface_stencil); +#endif + } + + ps->viewDir[0] = 0.0f; + ps->viewDir[1] = 0.0f; + ps->viewDir[2] = 1.0f; + + { + float viewmat[4][4]; + float viewinv[4][4]; + + invert_m4_m4(ps->ob->imat, ps->ob->obmat); + + if (ps->source == PROJ_SRC_VIEW) { + /* normal drawing */ + ps->winx = ps->ar->winx; + ps->winy = ps->ar->winy; + + copy_m4_m4(viewmat, ps->rv3d->viewmat); + copy_m4_m4(viewinv, ps->rv3d->viewinv); + + ED_view3d_ob_project_mat_get(ps->rv3d, ps->ob, ps->projectMat); + + ps->is_ortho = ED_view3d_clip_range_get(ps->v3d, ps->rv3d, &ps->clipsta, &ps->clipend, true); + } + else { + /* re-projection */ + float winmat[4][4]; + float vmat[4][4]; + + ps->winx = ps->reproject_ibuf->x; + ps->winy = ps->reproject_ibuf->y; + + if (ps->source == PROJ_SRC_IMAGE_VIEW) { + /* image stores camera data, tricky */ + IDProperty *idgroup = IDP_GetProperties(&ps->reproject_image->id, 0); + IDProperty *view_data = IDP_GetPropertyFromGroup(idgroup, PROJ_VIEW_DATA_ID); + + float *array = (float *)IDP_Array(view_data); + + /* use image array, written when creating image */ + memcpy(winmat, array, sizeof(winmat)); array += sizeof(winmat) / sizeof(float); + memcpy(viewmat, array, sizeof(viewmat)); array += sizeof(viewmat) / sizeof(float); + ps->clipsta = array[0]; + ps->clipend = array[1]; + ps->is_ortho = array[2] ? 1 : 0; + + invert_m4_m4(viewinv, viewmat); + } + else if (ps->source == PROJ_SRC_IMAGE_CAM) { + Object *cam_ob = ps->scene->camera; + CameraParams params; + + /* viewmat & viewinv */ + copy_m4_m4(viewinv, cam_ob->obmat); + normalize_m4(viewinv); + invert_m4_m4(viewmat, viewinv); + + /* window matrix, clipping and ortho */ + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, cam_ob); + BKE_camera_params_compute_viewplane(¶ms, ps->winx, ps->winy, 1.0f, 1.0f); + BKE_camera_params_compute_matrix(¶ms); + + copy_m4_m4(winmat, params.winmat); + ps->clipsta = params.clipsta; + ps->clipend = params.clipend; + ps->is_ortho = params.is_ortho; + } + + /* same as #ED_view3d_ob_project_mat_get */ + mult_m4_m4m4(vmat, viewmat, ps->ob->obmat); + mult_m4_m4m4(ps->projectMat, winmat, vmat); + } + + + /* viewDir - object relative */ + invert_m4_m4(ps->ob->imat, ps->ob->obmat); + copy_m3_m4(mat, viewinv); + mul_m3_v3(mat, ps->viewDir); + copy_m3_m4(mat, ps->ob->imat); + mul_m3_v3(mat, ps->viewDir); + normalize_v3(ps->viewDir); + + /* viewPos - object relative */ + copy_v3_v3(ps->viewPos, viewinv[3]); + copy_m3_m4(mat, ps->ob->imat); + mul_m3_v3(mat, ps->viewPos); + add_v3_v3(ps->viewPos, ps->ob->imat[3]); + } + + /* calculate vert screen coords + * run this early so we can calculate the x/y resolution of our bucket rect */ + INIT_MINMAX2(ps->screenMin, ps->screenMax); + + ps->screenCoords = MEM_mallocN(sizeof(float) * ps->dm_totvert * 4, "ProjectPaint ScreenVerts"); + projScreenCo = *ps->screenCoords; + + if (ps->is_ortho) { + for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) { + mul_v3_m4v3(projScreenCo, ps->projectMat, mv->co); + + /* screen space, not clamped */ + projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0]; + projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1]; + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); + } + } + else { + for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++, projScreenCo += 4) { + copy_v3_v3(projScreenCo, mv->co); + projScreenCo[3] = 1.0f; + + mul_m4_v4(ps->projectMat, projScreenCo); + + if (projScreenCo[3] > ps->clipsta) { + /* screen space, not clamped */ + projScreenCo[0] = (float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projScreenCo[0] / projScreenCo[3]; + projScreenCo[1] = (float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projScreenCo[1] / projScreenCo[3]; + projScreenCo[2] = projScreenCo[2] / projScreenCo[3]; /* Use the depth for bucket point occlusion */ + minmax_v2v2_v2(ps->screenMin, ps->screenMax, projScreenCo); + } + else { + /* TODO - deal with cases where 1 side of a face goes behind the view ? + * + * After some research this is actually very tricky, only option is to + * clip the derived mesh before painting, which is a Pain */ + projScreenCo[0] = FLT_MAX; + } + } + } + + /* If this border is not added we get artifacts for faces that + * have a parallel edge and at the bounds of the the 2D projected verts eg + * - a single screen aligned quad */ + projMargin = (ps->screenMax[0] - ps->screenMin[0]) * 0.000001f; + ps->screenMax[0] += projMargin; + ps->screenMin[0] -= projMargin; + projMargin = (ps->screenMax[1] - ps->screenMin[1]) * 0.000001f; + ps->screenMax[1] += projMargin; + ps->screenMin[1] -= projMargin; + + if (ps->source == PROJ_SRC_VIEW) { +#ifdef PROJ_DEBUG_WINCLIP + CLAMP(ps->screenMin[0], (float)(-diameter), (float)(ps->winx + diameter)); + CLAMP(ps->screenMax[0], (float)(-diameter), (float)(ps->winx + diameter)); + + CLAMP(ps->screenMin[1], (float)(-diameter), (float)(ps->winy + diameter)); + CLAMP(ps->screenMax[1], (float)(-diameter), (float)(ps->winy + diameter)); +#endif + } + else { /* re-projection, use bounds */ + ps->screenMin[0] = 0; + ps->screenMax[0] = (float)(ps->winx); + + ps->screenMin[1] = 0; + ps->screenMax[1] = (float)(ps->winy); + } + + /* only for convenience */ + ps->screen_width = ps->screenMax[0] - ps->screenMin[0]; + ps->screen_height = ps->screenMax[1] - ps->screenMin[1]; + + ps->buckets_x = (int)(ps->screen_width / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV)); + ps->buckets_y = (int)(ps->screen_height / (((float)diameter) / PROJ_BUCKET_BRUSH_DIV)); + + /* printf("\tscreenspace bucket division x:%d y:%d\n", ps->buckets_x, ps->buckets_y); */ + + /* really high values could cause problems since it has to allocate a few + * (ps->buckets_x*ps->buckets_y) sized arrays */ + CLAMP(ps->buckets_x, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); + CLAMP(ps->buckets_y, PROJ_BUCKET_RECT_MIN, PROJ_BUCKET_RECT_MAX); + + ps->bucketRect = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketRect"); + ps->bucketFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); + + ps->bucketFlags = (unsigned char *)MEM_callocN(sizeof(char) * ps->buckets_x * ps->buckets_y, "paint-bucketFaces"); +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + ps->vertFaces = (LinkNode **)MEM_callocN(sizeof(LinkNode *) * ps->dm_totvert, "paint-vertFaces"); + ps->faceSeamFlags = (char *)MEM_callocN(sizeof(char) * ps->dm_totface, "paint-faceSeamFlags"); + ps->faceSeamUVs = MEM_mallocN(sizeof(float) * ps->dm_totface * 8, "paint-faceSeamUVs"); + } +#endif + + /* Thread stuff + * + * very small brushes run a lot slower multithreaded since the advantage with + * threads is being able to fill in multiple buckets at once. + * Only use threads for bigger brushes. */ + + if (ps->scene->r.mode & R_FIXED_THREADS) { + ps->thread_tot = ps->scene->r.threads; + } + else { + ps->thread_tot = BLI_system_thread_count(); + } + for (a = 0; a < ps->thread_tot; a++) { + ps->arena_mt[a] = BLI_memarena_new(1 << 16, "project paint arena"); + } + + arena = ps->arena_mt[0]; + + if (ps->do_backfacecull && ps->do_mask_normal) { + float viewDirPersp[3]; + + ps->vertFlags = MEM_callocN(sizeof(char) * ps->dm_totvert, "paint-vertFlags"); + + for (a = 0, mv = ps->dm_mvert; a < ps->dm_totvert; a++, mv++) { + normal_short_to_float_v3(no, mv->no); + + if (ps->is_ortho) { + if (angle_normalized_v3v3(ps->viewDir, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + ps->vertFlags[a] |= PROJ_VERT_CULL; + } + } + else { + sub_v3_v3v3(viewDirPersp, ps->viewPos, mv->co); + normalize_v3(viewDirPersp); + if (angle_normalized_v3v3(viewDirPersp, no) >= ps->normal_angle) { /* 1 vert of this face is towards us */ + ps->vertFlags[a] |= PROJ_VERT_CULL; + } + } + } + } + + + for (face_index = 0, tf = ps->dm_mtface, mf = ps->dm_mface; face_index < ps->dm_totface; mf++, tf++, face_index++) { + +#ifndef PROJ_DEBUG_NOSEAMBLEED + /* add face user if we have bleed enabled, set the UV seam flags later */ + /* annoying but we need to add all faces even ones we never use elsewhere */ + if (ps->seam_bleed_px > 0.0f) { + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v1], SET_INT_IN_POINTER(face_index), arena); + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v2], SET_INT_IN_POINTER(face_index), arena); + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v3], SET_INT_IN_POINTER(face_index), arena); + if (mf->v4) { + BLI_linklist_prepend_arena(&ps->vertFaces[mf->v4], SET_INT_IN_POINTER(face_index), arena); + } + } +#endif + + tpage = project_paint_face_image(ps, ps->dm_mtface, face_index); + + if (tpage && ((((Mesh *)ps->ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) == 0 || mf->flag & ME_FACE_SEL)) { + + float *v1coSS, *v2coSS, *v3coSS, *v4coSS = NULL; + + v1coSS = ps->screenCoords[mf->v1]; + v2coSS = ps->screenCoords[mf->v2]; + v3coSS = ps->screenCoords[mf->v3]; + if (mf->v4) { + v4coSS = ps->screenCoords[mf->v4]; + } + + + if (!ps->is_ortho) { + if (v1coSS[0] == FLT_MAX || + v2coSS[0] == FLT_MAX || + v3coSS[0] == FLT_MAX || + (mf->v4 && v4coSS[0] == FLT_MAX)) + { + continue; + } + } + +#ifdef PROJ_DEBUG_WINCLIP + /* ignore faces outside the view */ + if ( + (v1coSS[0] < ps->screenMin[0] && + v2coSS[0] < ps->screenMin[0] && + v3coSS[0] < ps->screenMin[0] && + (mf->v4 && v4coSS[0] < ps->screenMin[0])) || + + (v1coSS[0] > ps->screenMax[0] && + v2coSS[0] > ps->screenMax[0] && + v3coSS[0] > ps->screenMax[0] && + (mf->v4 && v4coSS[0] > ps->screenMax[0])) || + + (v1coSS[1] < ps->screenMin[1] && + v2coSS[1] < ps->screenMin[1] && + v3coSS[1] < ps->screenMin[1] && + (mf->v4 && v4coSS[1] < ps->screenMin[1])) || + + (v1coSS[1] > ps->screenMax[1] && + v2coSS[1] > ps->screenMax[1] && + v3coSS[1] > ps->screenMax[1] && + (mf->v4 && v4coSS[1] > ps->screenMax[1])) + ) + { + continue; + } + +#endif //PROJ_DEBUG_WINCLIP + + + if (ps->do_backfacecull) { + if (ps->do_mask_normal) { + /* Since we are interpolating the normals of faces, we want to make + * sure all the verts are pointing away from the view, + * not just the face */ + if ((ps->vertFlags[mf->v1] & PROJ_VERT_CULL) && + (ps->vertFlags[mf->v2] & PROJ_VERT_CULL) && + (ps->vertFlags[mf->v3] & PROJ_VERT_CULL) && + (mf->v4 == 0 || ps->vertFlags[mf->v4] & PROJ_VERT_CULL) + ) + { + continue; + } + } + else { + if (line_point_side_v2(v1coSS, v2coSS, v3coSS) < 0.0f) { + continue; + } + + } + } + + if (tpage_last != tpage) { + + image_index = BLI_linklist_index(image_LinkList, tpage); + + if (image_index == -1 && BKE_image_has_ibuf(tpage, NULL)) { /* MemArena dosnt have an append func */ + BLI_linklist_append(&image_LinkList, tpage); + image_index = ps->image_tot; + ps->image_tot++; + } + + tpage_last = tpage; + } + + if (image_index != -1) { + /* Initialize the faces screen pixels */ + /* Add this to a list to initialize later */ + project_paint_delayed_face_init(ps, mf, face_index); + } + } + } + + /* build an array of images we use*/ + projIma = ps->projImages = (ProjPaintImage *)BLI_memarena_alloc(arena, sizeof(ProjPaintImage) * ps->image_tot); + + for (node = image_LinkList, i = 0; node; node = node->next, i++, projIma++) { + projIma->ima = node->link; + projIma->touch = 0; + projIma->ibuf = BKE_image_acquire_ibuf(projIma->ima, NULL, NULL); + projIma->partRedrawRect = BLI_memarena_alloc(arena, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + memset(projIma->partRedrawRect, 0, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + } + + /* we have built the array, discard the linked list */ + BLI_linklist_free(image_LinkList, NULL); +} + +static void paint_proj_begin_clone(ProjPaintState *ps, const int mouse[2]) +{ + /* setup clone offset */ + if (ps->tool == PAINT_TOOL_CLONE) { + float projCo[4]; + copy_v3_v3(projCo, give_cursor(ps->scene, ps->v3d)); + mul_m4_v3(ps->ob->imat, projCo); + + projCo[3] = 1.0f; + mul_m4_v4(ps->projectMat, projCo); + ps->cloneOffset[0] = mouse[0] - ((float)(ps->winx / 2.0f) + (ps->winx / 2.0f) * projCo[0] / projCo[3]); + ps->cloneOffset[1] = mouse[1] - ((float)(ps->winy / 2.0f) + (ps->winy / 2.0f) * projCo[1] / projCo[3]); + } +} + +static void project_paint_end(ProjPaintState *ps) +{ + int a; + ProjPaintImage *projIma; + + /* build undo data from original pixel colors */ + if (U.uiflag & USER_GLOBALUNDO) { + ProjPixel *projPixel; + ImBuf *tmpibuf = NULL, *tmpibuf_float = NULL; + LinkNode *pixel_node; + void *tilerect; + MemArena *arena = ps->arena_mt[0]; /* threaded arena re-used for non threaded case */ + + int bucket_tot = (ps->buckets_x * ps->buckets_y); /* we could get an X/Y but easier to loop through all possible buckets */ + int bucket_index; + int tile_index; + int x_round, y_round; + int x_tile, y_tile; + int is_float = -1; + + /* context */ + ProjPaintImage *last_projIma; + int last_image_index = -1; + int last_tile_width = 0; + + for (a = 0, last_projIma = ps->projImages; a < ps->image_tot; a++, last_projIma++) { + int size = sizeof(void **) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x) * IMAPAINT_TILE_NUMBER(last_projIma->ibuf->y); + last_projIma->undoRect = (void **) BLI_memarena_alloc(arena, size); + memset(last_projIma->undoRect, 0, size); + last_projIma->ibuf->userflags |= IB_BITMAPDIRTY; + } + + for (bucket_index = 0; bucket_index < bucket_tot; bucket_index++) { + /* loop through all pixels */ + for (pixel_node = ps->bucketRect[bucket_index]; pixel_node; pixel_node = pixel_node->next) { + + /* ok we have a pixel, was it modified? */ + projPixel = (ProjPixel *)pixel_node->link; + + if (last_image_index != projPixel->image_index) { + /* set the context */ + last_image_index = projPixel->image_index; + last_projIma = ps->projImages + last_image_index; + last_tile_width = IMAPAINT_TILE_NUMBER(last_projIma->ibuf->x); + is_float = last_projIma->ibuf->rect_float ? 1 : 0; + } + + + if ((is_float == 0 && projPixel->origColor.uint != *projPixel->pixel.uint_pt) || + (is_float == 1 && + (projPixel->origColor.f[0] != projPixel->pixel.f_pt[0] || + projPixel->origColor.f[1] != projPixel->pixel.f_pt[1] || + projPixel->origColor.f[2] != projPixel->pixel.f_pt[2] || + projPixel->origColor.f[3] != projPixel->pixel.f_pt[3])) + ) + { + + x_tile = projPixel->x_px >> IMAPAINT_TILE_BITS; + y_tile = projPixel->y_px >> IMAPAINT_TILE_BITS; + + x_round = x_tile * IMAPAINT_TILE_SIZE; + y_round = y_tile * IMAPAINT_TILE_SIZE; + + tile_index = x_tile + y_tile * last_tile_width; + + if (last_projIma->undoRect[tile_index] == NULL) { + /* add the undo tile from the modified image, then write the original colors back into it */ + tilerect = last_projIma->undoRect[tile_index] = image_undo_push_tile(last_projIma->ima, last_projIma->ibuf, is_float ? (&tmpibuf_float) : (&tmpibuf), x_tile, y_tile); + } + else { + tilerect = last_projIma->undoRect[tile_index]; + } + + /* This is a BIT ODD, but overwrite the undo tiles image info with this pixels original color + * because allocating the tiles along the way slows down painting */ + + if (is_float) { + float *rgba_fp = (float *)tilerect + (((projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE)) * 4; + copy_v4_v4(rgba_fp, projPixel->origColor.f); + } + else { + ((unsigned int *)tilerect)[(projPixel->x_px - x_round) + (projPixel->y_px - y_round) * IMAPAINT_TILE_SIZE] = projPixel->origColor.uint; + } + } + } + } + + if (tmpibuf) IMB_freeImBuf(tmpibuf); + if (tmpibuf_float) IMB_freeImBuf(tmpibuf_float); + } + /* done calculating undo data */ + + /* dereference used image buffers */ + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + BKE_image_release_ibuf(projIma->ima, projIma->ibuf, NULL); + } + + BKE_image_release_ibuf(ps->reproject_image, ps->reproject_ibuf, NULL); + + MEM_freeN(ps->screenCoords); + MEM_freeN(ps->bucketRect); + MEM_freeN(ps->bucketFaces); + MEM_freeN(ps->bucketFlags); + +#ifndef PROJ_DEBUG_NOSEAMBLEED + if (ps->seam_bleed_px > 0.0f) { + MEM_freeN(ps->vertFaces); + MEM_freeN(ps->faceSeamFlags); + MEM_freeN(ps->faceSeamUVs); + } +#endif + + if (ps->vertFlags) MEM_freeN(ps->vertFlags); + + for (a = 0; a < ps->thread_tot; a++) { + BLI_memarena_free(ps->arena_mt[a]); + } + + /* copy for subsurf/multires, so throw away */ + if (ps->dm->type != DM_TYPE_CDDM) { + if (ps->dm_mvert) MEM_freeN(ps->dm_mvert); + if (ps->dm_mface) MEM_freeN(ps->dm_mface); + /* looks like these don't need copying */ +#if 0 + if (ps->dm_mtface) MEM_freeN(ps->dm_mtface); + if (ps->dm_mtface_clone) MEM_freeN(ps->dm_mtface_clone); + if (ps->dm_mtface_stencil) MEM_freeN(ps->dm_mtface_stencil); +#endif + } + + if (ps->dm_release) + ps->dm->release(ps->dm); +} + +/* 1 = an undo, -1 is a redo. */ +static void partial_redraw_array_init(ImagePaintPartialRedraw *pr) +{ + int tot = PROJ_BOUNDBOX_SQUARED; + while (tot--) { + pr->x1 = 10000000; + pr->y1 = 10000000; + + pr->x2 = -1; + pr->y2 = -1; + + pr->enabled = 1; + + pr++; + } +} + + +static int partial_redraw_array_merge(ImagePaintPartialRedraw *pr, ImagePaintPartialRedraw *pr_other, int tot) +{ + int touch = 0; + while (tot--) { + pr->x1 = min_ii(pr->x1, pr_other->x1); + pr->y1 = min_ii(pr->y1, pr_other->y1); + + pr->x2 = max_ii(pr->x2, pr_other->x2); + pr->y2 = max_ii(pr->y2, pr_other->y2); + + if (pr->x2 != -1) + touch = 1; + + pr++; pr_other++; + } + + return touch; +} + +/* Loop over all images on this mesh and update any we have touched */ +static int project_image_refresh_tagged(ProjPaintState *ps) +{ + ImagePaintPartialRedraw *pr; + ProjPaintImage *projIma; + int a, i; + int redraw = 0; + + + for (a = 0, projIma = ps->projImages; a < ps->image_tot; a++, projIma++) { + if (projIma->touch) { + /* look over each bound cell */ + for (i = 0; i < PROJ_BOUNDBOX_SQUARED; i++) { + pr = &(projIma->partRedrawRect[i]); + if (pr->x2 != -1) { /* TODO - use 'enabled' ? */ + set_imapaintpartial(pr); + imapaint_image_update(NULL, projIma->ima, projIma->ibuf, true); + redraw = 1; + } + } + + projIma->touch = 0; /* clear for reuse */ + } + } + + return redraw; +} + +/* run this per painting onto each mouse location */ +static int project_bucket_iter_init(ProjPaintState *ps, const float mval_f[2]) +{ + if (ps->source == PROJ_SRC_VIEW) { + float min_brush[2], max_brush[2]; + const float radius = (float)BKE_brush_size_get(ps->scene, ps->brush); + + /* so we don't have a bucket bounds that is way too small to paint into */ + // if (radius < 1.0f) radius = 1.0f; // this doesn't work yet :/ + + min_brush[0] = mval_f[0] - radius; + min_brush[1] = mval_f[1] - radius; + + max_brush[0] = mval_f[0] + radius; + max_brush[1] = mval_f[1] + radius; + + /* offset to make this a valid bucket index */ + project_paint_bucket_bounds(ps, min_brush, max_brush, ps->bucketMin, ps->bucketMax); + + /* mouse outside the model areas? */ + if (ps->bucketMin[0] == ps->bucketMax[0] || ps->bucketMin[1] == ps->bucketMax[1]) { + return 0; + } + + ps->context_bucket_x = ps->bucketMin[0]; + ps->context_bucket_y = ps->bucketMin[1]; + } + else { /* reproject: PROJ_SRC_* */ + ps->bucketMin[0] = 0; + ps->bucketMin[1] = 0; + + ps->bucketMax[0] = ps->buckets_x; + ps->bucketMax[1] = ps->buckets_y; + + ps->context_bucket_x = 0; + ps->context_bucket_y = 0; + } + return 1; +} + + +static int project_bucket_iter_next(ProjPaintState *ps, int *bucket_index, rctf *bucket_bounds, const float mval[2]) +{ + const int diameter = 2 * BKE_brush_size_get(ps->scene, ps->brush); + + if (ps->thread_tot > 1) + BLI_lock_thread(LOCK_CUSTOM1); + + //printf("%d %d\n", ps->context_bucket_x, ps->context_bucket_y); + + for (; ps->context_bucket_y < ps->bucketMax[1]; ps->context_bucket_y++) { + for (; ps->context_bucket_x < ps->bucketMax[0]; ps->context_bucket_x++) { + + /* use bucket_bounds for project_bucket_isect_circle and project_bucket_init*/ + project_bucket_bounds(ps, ps->context_bucket_x, ps->context_bucket_y, bucket_bounds); + + if ((ps->source != PROJ_SRC_VIEW) || + project_bucket_isect_circle(mval, (float)(diameter * diameter), bucket_bounds)) + { + *bucket_index = ps->context_bucket_x + (ps->context_bucket_y * ps->buckets_x); + ps->context_bucket_x++; + + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); + + return 1; + } + } + ps->context_bucket_x = ps->bucketMin[0]; + } + + if (ps->thread_tot > 1) + BLI_unlock_thread(LOCK_CUSTOM1); + return 0; +} + +/* Each thread gets one of these, also used as an argument to pass to project_paint_op */ +typedef struct ProjectHandle { + /* args */ + ProjPaintState *ps; + float prevmval[2]; + float mval[2]; + + /* annoying but we need to have image bounds per thread, then merge into ps->projectPartialRedraws */ + ProjPaintImage *projImages; /* array of partial redraws */ + + /* thread settings */ + int thread_index; + + struct ImagePool *pool; +} ProjectHandle; + +static void blend_color_mix(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) +{ + /* this and other blending modes previously used >>8 instead of /255. both + * are not equivalent (>>8 is /256), and the former results in rounding + * errors that can turn colors black fast after repeated blending */ + const int mfac = 255 - fac; + + cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255; + cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255; + cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255; + cp[3] = (mfac * cp1[3] + fac * cp2[3]) / 255; +} + +static void blend_color_mix_float(float cp[4], const float cp1[4], const float cp2[4], const float fac) +{ + const float mfac = 1.0f - fac; + cp[0] = mfac * cp1[0] + fac * cp2[0]; + cp[1] = mfac * cp1[1] + fac * cp2[1]; + cp[2] = mfac * cp1[2] + fac * cp2[2]; + cp[3] = mfac * cp1[3] + fac * cp2[3]; +} + +static void blend_color_mix_accum(unsigned char cp[4], const unsigned char cp1[4], const unsigned char cp2[4], const int fac) +{ + /* this and other blending modes previously used >>8 instead of /255. both + * are not equivalent (>>8 is /256), and the former results in rounding + * errors that can turn colors black fast after repeated blending */ + const int mfac = 255 - fac; + const int alpha = cp1[3] + ((fac * cp2[3]) / 255); + + cp[0] = (mfac * cp1[0] + fac * cp2[0]) / 255; + cp[1] = (mfac * cp1[1] + fac * cp2[1]) / 255; + cp[2] = (mfac * cp1[2] + fac * cp2[2]) / 255; + cp[3] = alpha > 255 ? 255 : alpha; +} +static void blend_color_mix_accum_float(float cp[4], const float cp1[4], const unsigned char cp2[4], const float fac) +{ + const float mfac = 1.0f - fac; + const float alpha = cp1[3] + (fac * (cp2[3] / 255.0f)); + + cp[0] = (mfac * cp1[0] + (fac * (cp2[0] / 255.0f))); + cp[1] = (mfac * cp1[1] + (fac * (cp2[1] / 255.0f))); + cp[2] = (mfac * cp1[2] + (fac * (cp2[2] / 255.0f))); + cp[3] = alpha > 1.0f ? 1.0f : alpha; +} + + +static void do_projectpaint_clone(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) +{ + if (ps->do_masking && mask < 1.0f) { + projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * 255), ps->blend); + blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); + } + else { + *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, ((ProjPixelClone *)projPixel)->clonepx.uint, (int)(alpha * mask * 255), ps->blend); + } +} + +static void do_projectpaint_clone_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask) +{ + if (ps->do_masking && mask < 1.0f) { + IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, ((ProjPixelClone *)projPixel)->clonepx.f, alpha, ps->blend); + blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); + } + else { + IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f, alpha * mask, ps->blend); + } +} + +/* do_projectpaint_smear* + * + * note, mask is used to modify the alpha here, this is not correct since it allows + * accumulation of color greater then 'projPixel->mask' however in the case of smear its not + * really that important to be correct as it is with clone and painting + */ +static void do_projectpaint_smear(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, + MemArena *smearArena, LinkNode **smearPixels, const float co[2]) +{ + unsigned char rgba_ub[4]; + + if (project_paint_PickColor(ps, co, NULL, rgba_ub, 1) == 0) + return; + /* ((ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */ + blend_color_mix(((ProjPixelClone *)projPixel)->clonepx.ch, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * mask * 255)); + BLI_linklist_prepend_arena(smearPixels, (void *)projPixel, smearArena); +} + +static void do_projectpaint_smear_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, + MemArena *smearArena, LinkNode **smearPixels_f, const float co[2]) +{ + float rgba[4]; + + if (project_paint_PickColor(ps, co, rgba, NULL, 1) == 0) + return; + + /* (ProjPixelClone *)projPixel)->clonepx.uint = IMB_blend_color(*((unsigned int *)rgba_smear), *((unsigned int *)rgba_ub), (int)(alpha*mask*255), ps->blend); */ + blend_color_mix_float(((ProjPixelClone *)projPixel)->clonepx.f, projPixel->pixel.f_pt, rgba, alpha * mask); + BLI_linklist_prepend_arena(smearPixels_f, (void *)projPixel, smearArena); +} + +/* do_projectpaint_soften for float & byte + */ +static float inv_pow2(float f) +{ + f = 1.0f - f; + f = f * f; + return 1.0f - f; +} + +static void do_projectpaint_soften_f(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, + MemArena *softenArena, LinkNode **softenPixels) +{ + unsigned int accum_tot = 0; + unsigned int i; + + float *rgba = projPixel->newColor.f; + + /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ + mask = inv_pow2(mask); + alpha = inv_pow2(alpha); + + /* rather then painting, accumulate surrounding colors */ + zero_v4(rgba); + + for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { + float co_ofs[2]; + float rgba_tmp[4]; + sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); + if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { + add_v4_v4(rgba, rgba_tmp); + accum_tot++; + } + } + + if (LIKELY(accum_tot != 0)) { + mul_v4_fl(rgba, 1.0f / (float)accum_tot); + blend_color_mix_float(rgba, projPixel->pixel.f_pt, rgba, alpha); + if (mask < 1.0f) blend_color_mix_float(rgba, projPixel->origColor.f, rgba, mask); + BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); + } +} + +static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, float alpha, float mask, + MemArena *softenArena, LinkNode **softenPixels) +{ + unsigned int accum_tot = 0; + unsigned int i; + + float rgba[4]; /* convert to byte after */ + + /* sigh, alpha values tend to need to be a _lot_ stronger with blur */ + mask = inv_pow2(mask); + alpha = inv_pow2(alpha); + + /* rather then painting, accumulate surrounding colors */ + zero_v4(rgba); + + for (i = 0; i < PROJ_PIXEL_SOFTEN_TOT; i++) { + float co_ofs[2]; + float rgba_tmp[4]; + sub_v2_v2v2(co_ofs, projPixel->projCoSS, proj_pixel_soften_v2[i]); + if (project_paint_PickColor(ps, co_ofs, rgba_tmp, NULL, TRUE)) { + add_v4_v4(rgba, rgba_tmp); + accum_tot++; + } + } + + if (LIKELY(accum_tot != 0)) { + unsigned char *rgba_ub = projPixel->newColor.ch; + + mul_v4_fl(rgba, 1.0f / (float)accum_tot); + IMAPAINT_FLOAT_RGBA_TO_CHAR(rgba_ub, rgba); + + blend_color_mix(rgba_ub, projPixel->pixel.ch_pt, rgba_ub, (int)(alpha * 255)); + if (mask != 1.0f) blend_color_mix(rgba_ub, projPixel->origColor.ch, rgba_ub, (int)(mask * 255)); + BLI_linklist_prepend_arena(softenPixels, (void *)projPixel, softenArena); + } +} + +BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3]) +{ + rgba_ub[0] = f_to_char(rgba[0] * rgb[0]); + rgba_ub[1] = f_to_char(rgba[1] * rgb[1]); + rgba_ub[2] = f_to_char(rgba[2] * rgb[2]); + rgba_ub[3] = f_to_char(rgba[3]); +} + +static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask) +{ + unsigned char rgba_ub[4]; + + if (ps->is_texbrush) { + rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb); + } + else { + IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb); + rgba_ub[3] = 255; + } + + if (ps->do_masking && mask < 1.0f) { + projPixel->newColor.uint = IMB_blend_color(projPixel->newColor.uint, *((unsigned int *)rgba_ub), (int)(alpha * 255), ps->blend); + blend_color_mix(projPixel->pixel.ch_pt, projPixel->origColor.ch, projPixel->newColor.ch, (int)(mask * 255)); + } + else { + *projPixel->pixel.uint_pt = IMB_blend_color(*projPixel->pixel.uint_pt, *((unsigned int *)rgba_ub), (int)(alpha * mask * 255), ps->blend); + } +} + +static void do_projectpaint_draw_f(ProjPaintState *ps, ProjPixel *projPixel, float rgba[4], float alpha, float mask) +{ + if (ps->is_texbrush) { + /* rgba already holds a texture result here from higher level function */ + float rgba_br[3]; + srgb_to_linearrgb_v3_v3(rgba_br, ps->brush->rgb); + mul_v3_v3(rgba, rgba_br); + } + else { + srgb_to_linearrgb_v3_v3(rgba, ps->brush->rgb); + rgba[3] = 1.0; + } + + if (ps->do_masking && mask < 1.0f) { + IMB_blend_color_float(projPixel->newColor.f, projPixel->newColor.f, rgba, alpha, ps->blend); + blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, projPixel->newColor.f, mask); + } + else { + IMB_blend_color_float(projPixel->pixel.f_pt, projPixel->pixel.f_pt, rgba, alpha * mask, ps->blend); + } +} + + + +/* run this for single and multithreaded painting */ +static void *do_projectpaint_thread(void *ph_v) +{ + /* First unpack args from the struct */ + ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps; + ProjPaintImage *projImages = ((ProjectHandle *)ph_v)->projImages; + const float *lastpos = ((ProjectHandle *)ph_v)->prevmval; + const float *pos = ((ProjectHandle *)ph_v)->mval; + const int thread_index = ((ProjectHandle *)ph_v)->thread_index; + struct ImagePool *pool = ((ProjectHandle *)ph_v)->pool; + /* Done with args from ProjectHandle */ + + LinkNode *node; + ProjPixel *projPixel; + Brush *brush = ps->brush; + + int last_index = -1; + ProjPaintImage *last_projIma = NULL; + ImagePaintPartialRedraw *last_partial_redraw_cell; + + float rgba[4], alpha, dist_nosqrt, dist; + + float falloff; + int bucket_index; + int is_floatbuf = 0; + const short tool = ps->tool; + rctf bucket_bounds; + + /* for smear only */ + float pos_ofs[2] = {0}; + float co[2]; + float mask = 1.0f; /* airbrush wont use mask */ + unsigned short mask_short; + const float radius = (float)BKE_brush_size_get(ps->scene, brush); + const float radius_squared = radius * radius; /* avoid a square root with every dist comparison */ + + short lock_alpha = ELEM(brush->blend, IMB_BLEND_ERASE_ALPHA, IMB_BLEND_ADD_ALPHA) ? 0 : brush->flag & BRUSH_LOCK_ALPHA; + + LinkNode *smearPixels = NULL; + LinkNode *smearPixels_f = NULL; + MemArena *smearArena = NULL; /* mem arena for this brush projection only */ + + LinkNode *softenPixels = NULL; + LinkNode *softenPixels_f = NULL; + MemArena *softenArena = NULL; /* mem arena for this brush projection only */ + + if (tool == PAINT_TOOL_SMEAR) { + pos_ofs[0] = pos[0] - lastpos[0]; + pos_ofs[1] = pos[1] - lastpos[1]; + + smearArena = BLI_memarena_new(1 << 16, "paint smear arena"); + } + else if (tool == PAINT_TOOL_SOFTEN) { + softenArena = BLI_memarena_new(1 << 16, "paint soften arena"); + } + + /* printf("brush bounds %d %d %d %d\n", bucketMin[0], bucketMin[1], bucketMax[0], bucketMax[1]); */ + + while (project_bucket_iter_next(ps, &bucket_index, &bucket_bounds, pos)) { + + /* Check this bucket and its faces are initialized */ + if (ps->bucketFlags[bucket_index] == PROJ_BUCKET_NULL) { + /* No pixels initialized */ + project_bucket_init(ps, thread_index, bucket_index, &bucket_bounds); + } + + if (ps->source != PROJ_SRC_VIEW) { + + /* Re-Projection, simple, no brushes! */ + + for (node = ps->bucketRect[bucket_index]; node; node = node->next) { + projPixel = (ProjPixel *)node->link; + + /* copy of code below */ + if (last_index != projPixel->image_index) { + last_index = projPixel->image_index; + last_projIma = projImages + last_index; + + last_projIma->touch = 1; + is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; + } + /* end copy */ + + if (is_floatbuf) { + /* re-project buffer is assumed byte - TODO, allow float */ + bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, + projPixel->projCoSS[0], projPixel->projCoSS[1]); + if (projPixel->newColor.ch[3]) { + mask = ((float)projPixel->mask) / 65535.0f; + blend_color_mix_accum_float(projPixel->pixel.f_pt, projPixel->origColor.f, + projPixel->newColor.ch, (mask * (projPixel->newColor.ch[3] / 255.0f))); + } + } + else { + /* re-project buffer is assumed byte - TODO, allow float */ + bicubic_interpolation_color(ps->reproject_ibuf, projPixel->newColor.ch, NULL, + projPixel->projCoSS[0], projPixel->projCoSS[1]); + if (projPixel->newColor.ch[3]) { + mask = ((float)projPixel->mask) / 65535.0f; + blend_color_mix_accum(projPixel->pixel.ch_pt, projPixel->origColor.ch, + projPixel->newColor.ch, (int)(mask * projPixel->newColor.ch[3])); + } + } + } + } + else { + /* Normal brush painting */ + + for (node = ps->bucketRect[bucket_index]; node; node = node->next) { + + projPixel = (ProjPixel *)node->link; + + dist_nosqrt = len_squared_v2v2(projPixel->projCoSS, pos); + + /*if (dist < radius) {*/ /* correct but uses a sqrtf */ + if (dist_nosqrt <= radius_squared) { + float samplecos[3]; + dist = sqrtf(dist_nosqrt); + + falloff = BKE_brush_curve_strength_clamp(ps->brush, dist, radius); + + if (ps->is_texbrush) { + MTex *mtex = &brush->mtex; + /* taking 3d copy to account for 3D mapping too. It gets concatenated during sampling */ + if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { + copy_v3_v3(samplecos, projPixel->worldCoSS); + } + else { + copy_v2_v2(samplecos, projPixel->projCoSS); + samplecos[2] = 0.0f; + } + } + + if (falloff > 0.0f) { + if (ps->is_texbrush) { + /* note, for clone and smear, we only use the alpha, could be a special function */ + BKE_brush_sample_tex_3D(ps->scene, brush, samplecos, rgba, thread_index, pool); + alpha = rgba[3]; + } + else { + alpha = 1.0f; + } + + if (!ps->do_masking) { + /* for an aurbrush there is no real mask, so just multiply the alpha by it */ + alpha *= falloff * BKE_brush_alpha_get(ps->scene, brush); + mask = ((float)projPixel->mask) / 65535.0f; + } + else { + /* This brush dosnt accumulate so add some curve to the brushes falloff */ + falloff = 1.0f - falloff; + falloff = 1.0f - (falloff * falloff); + + mask_short = (unsigned short)(projPixel->mask * (BKE_brush_alpha_get(ps->scene, brush) * falloff)); + if (mask_short > projPixel->mask_max) { + mask = ((float)mask_short) / 65535.0f; + projPixel->mask_max = mask_short; + } + else { + /*mask = ((float)projPixel->mask_max)/65535.0f;*/ + + /* Go onto the next pixel */ + continue; + } + } + + if (alpha > 0.0f) { + + /* copy of code above */ + if (last_index != projPixel->image_index) { + last_index = projPixel->image_index; + last_projIma = projImages + last_index; + + last_projIma->touch = 1; + is_floatbuf = last_projIma->ibuf->rect_float ? 1 : 0; + } + /* end copy */ + + last_partial_redraw_cell = last_projIma->partRedrawRect + projPixel->bb_cell_index; + last_partial_redraw_cell->x1 = min_ii(last_partial_redraw_cell->x1, (int)projPixel->x_px); + last_partial_redraw_cell->y1 = min_ii(last_partial_redraw_cell->y1, (int)projPixel->y_px); + + last_partial_redraw_cell->x2 = max_ii(last_partial_redraw_cell->x2, (int)projPixel->x_px + 1); + last_partial_redraw_cell->y2 = max_ii(last_partial_redraw_cell->y2, (int)projPixel->y_px + 1); + + + switch (tool) { + case PAINT_TOOL_CLONE: + if (is_floatbuf) { + if (((ProjPixelClone *)projPixel)->clonepx.f[3]) { + do_projectpaint_clone_f(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */ + } + } + else { + if (((ProjPixelClone *)projPixel)->clonepx.ch[3]) { + do_projectpaint_clone(ps, projPixel, alpha, mask); /* rgba isn't used for cloning, only alpha */ + } + } + break; + case PAINT_TOOL_SMEAR: + sub_v2_v2v2(co, projPixel->projCoSS, pos_ofs); + + if (is_floatbuf) do_projectpaint_smear_f(ps, projPixel, alpha, mask, smearArena, &smearPixels_f, co); + else do_projectpaint_smear(ps, projPixel, alpha, mask, smearArena, &smearPixels, co); + break; + case PAINT_TOOL_SOFTEN: + if (is_floatbuf) do_projectpaint_soften_f(ps, projPixel, alpha, mask, softenArena, &softenPixels_f); + else do_projectpaint_soften(ps, projPixel, alpha, mask, softenArena, &softenPixels); + break; + default: + if (is_floatbuf) do_projectpaint_draw_f(ps, projPixel, rgba, alpha, mask); + else do_projectpaint_draw(ps, projPixel, rgba, alpha, mask); + break; + } + } + + if (lock_alpha) { + if (is_floatbuf) projPixel->pixel.f_pt[3] = projPixel->origColor.f[3]; + else projPixel->pixel.ch_pt[3] = projPixel->origColor.ch[3]; + } + + /* done painting */ + } + } + } + } + } + + + if (tool == PAINT_TOOL_SMEAR) { + + for (node = smearPixels; node; node = node->next) { /* this wont run for a float image */ + projPixel = node->link; + *projPixel->pixel.uint_pt = ((ProjPixelClone *)projPixel)->clonepx.uint; + } + + for (node = smearPixels_f; node; node = node->next) { + projPixel = node->link; + copy_v4_v4(projPixel->pixel.f_pt, ((ProjPixelClone *)projPixel)->clonepx.f); + } + + BLI_memarena_free(smearArena); + } + else if (tool == PAINT_TOOL_SOFTEN) { + + for (node = softenPixels; node; node = node->next) { /* this wont run for a float image */ + projPixel = node->link; + *projPixel->pixel.uint_pt = projPixel->newColor.uint; + } + + for (node = softenPixels_f; node; node = node->next) { + projPixel = node->link; + copy_v4_v4(projPixel->pixel.f_pt, projPixel->newColor.f); + } + + BLI_memarena_free(softenArena); + } + + return NULL; +} + +static int project_paint_op(void *state, const float lastpos[2], const float pos[2]) +{ + /* First unpack args from the struct */ + ProjPaintState *ps = (ProjPaintState *)state; + int touch_any = 0; + + ProjectHandle handles[BLENDER_MAX_THREADS]; + ListBase threads; + int a, i; + + struct ImagePool *pool; + + if (!project_bucket_iter_init(ps, pos)) { + return 0; + } + + if (ps->thread_tot > 1) + BLI_init_threads(&threads, do_projectpaint_thread, ps->thread_tot); + + pool = BKE_image_pool_new(); + + /* get the threads running */ + for (a = 0; a < ps->thread_tot; a++) { + + /* set defaults in handles */ + //memset(&handles[a], 0, sizeof(BakeShade)); + + handles[a].ps = ps; + copy_v2_v2(handles[a].mval, pos); + copy_v2_v2(handles[a].prevmval, lastpos); + + /* thread specific */ + handles[a].thread_index = a; + + handles[a].projImages = (ProjPaintImage *)BLI_memarena_alloc(ps->arena_mt[a], ps->image_tot * sizeof(ProjPaintImage)); + + memcpy(handles[a].projImages, ps->projImages, ps->image_tot * sizeof(ProjPaintImage)); + + /* image bounds */ + for (i = 0; i < ps->image_tot; i++) { + handles[a].projImages[i].partRedrawRect = (ImagePaintPartialRedraw *)BLI_memarena_alloc(ps->arena_mt[a], sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + memcpy(handles[a].projImages[i].partRedrawRect, ps->projImages[i].partRedrawRect, sizeof(ImagePaintPartialRedraw) * PROJ_BOUNDBOX_SQUARED); + } + + handles[a].pool = pool; + + if (ps->thread_tot > 1) + BLI_insert_thread(&threads, &handles[a]); + } + + if (ps->thread_tot > 1) /* wait for everything to be done */ + BLI_end_threads(&threads); + else + do_projectpaint_thread(&handles[0]); + + + BKE_image_pool_free(pool); + + /* move threaded bounds back into ps->projectPartialRedraws */ + for (i = 0; i < ps->image_tot; i++) { + int touch = 0; + for (a = 0; a < ps->thread_tot; a++) { + touch |= partial_redraw_array_merge(ps->projImages[i].partRedrawRect, handles[a].projImages[i].partRedrawRect, PROJ_BOUNDBOX_SQUARED); + } + + if (touch) { + ps->projImages[i].touch = 1; + touch_any = 1; + } + } + + return touch_any; +} + + +int paint_proj_stroke(bContext *C, void *pps, const int prevmval_i[2], const int mval_i[2]) +{ + ProjPaintState *ps = pps; + int a, redraw; + float pos[2], prev_pos[2]; + + pos[0] = (float)(mval_i[0]); + pos[1] = (float)(mval_i[1]); + + prev_pos[0] = (float)(prevmval_i[0]); + prev_pos[1] = (float)(prevmval_i[1]); + + /* clone gets special treatment here to avoid going through image initialization */ + if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) { + Scene *scene = ps->scene; + View3D *v3d = ps->v3d; + float *cursor = give_cursor(scene, v3d); + + view3d_operator_needs_opengl(C); + + if (!ED_view3d_autodist(scene, ps->ar, v3d, mval_i, cursor)) + return 0; + + ED_region_tag_redraw(ps->ar); + + return 0; + } + + for (a = 0; a < ps->image_tot; a++) + partial_redraw_array_init(ps->projImages[a].partRedrawRect); + + redraw = project_paint_op(ps, prev_pos, pos) ? 1 : 0; + + if (project_image_refresh_tagged(ps)) + return redraw; + + return 0; +} + + +/* initialize project paint settings from context */ +static void project_state_init(bContext *C, Object *ob, ProjPaintState *ps, int mode) +{ + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + + /* brush */ + ps->mode = mode; + ps->brush = paint_brush(&settings->imapaint.paint); + if (ps->brush) { + Brush *brush = ps->brush; + ps->tool = brush->imagepaint_tool; + ps->blend = brush->blend; + + /* disable for 3d mapping also because painting on mirrored mesh can create "stripes" */ + ps->do_masking = (brush->flag & BRUSH_AIRBRUSH || brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW || + brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) ? false : true; + ps->is_texbrush = (brush->mtex.tex && brush->imagepaint_tool == PAINT_TOOL_DRAW) ? 1 : 0; + } + else { + /* brush may be NULL*/ + ps->do_masking = false; + ps->is_texbrush = false; + } + + /* sizeof(ProjPixel), since we alloc this a _lot_ */ + ps->pixel_sizeof = project_paint_pixel_sizeof(ps->tool); + BLI_assert(ps->pixel_sizeof >= sizeof(ProjPixel)); + + /* these can be NULL */ + ps->v3d = CTX_wm_view3d(C); + ps->rv3d = CTX_wm_region_view3d(C); + ps->ar = CTX_wm_region(C); + + ps->scene = scene; + ps->ob = ob; /* allow override of active object */ + + /* setup projection painting data */ + ps->do_backfacecull = (settings->imapaint.flag & IMAGEPAINT_PROJECT_BACKFACE) ? 0 : 1; + ps->do_occlude = (settings->imapaint.flag & IMAGEPAINT_PROJECT_XRAY) ? 0 : 1; + ps->do_mask_normal = (settings->imapaint.flag & IMAGEPAINT_PROJECT_FLAT) ? 0 : 1; + ps->do_new_shading_nodes = BKE_scene_use_new_shading_nodes(scene); /* only cache the value */ + + if (ps->tool == PAINT_TOOL_CLONE) + ps->do_layer_clone = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_CLONE); + + ps->do_layer_stencil = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL) ? 1 : 0; + ps->do_layer_stencil_inv = (settings->imapaint.flag & IMAGEPAINT_PROJECT_LAYER_STENCIL_INV) ? 1 : 0; + + +#ifndef PROJ_DEBUG_NOSEAMBLEED + ps->seam_bleed_px = settings->imapaint.seam_bleed; /* pixel num to bleed */ +#endif + + if (ps->do_mask_normal) { + ps->normal_angle_inner = settings->imapaint.normal_angle; + ps->normal_angle = (ps->normal_angle_inner + 90.0f) * 0.5f; + } + else { + ps->normal_angle_inner = ps->normal_angle = settings->imapaint.normal_angle; + } + + ps->normal_angle_inner *= (float)(M_PI_2 / 90); + ps->normal_angle *= (float)(M_PI_2 / 90); + ps->normal_angle_range = ps->normal_angle - ps->normal_angle_inner; + + if (ps->normal_angle_range <= 0.0f) + ps->do_mask_normal = FALSE; /* no need to do blending */ + + return; +} + +void *paint_proj_new_stroke(bContext *C, Object *ob, const int mouse[2], int mode) +{ + ProjPaintState *ps = MEM_callocN(sizeof(ProjPaintState), "ProjectionPaintState"); + project_state_init(C, ob, ps, mode); + + if (ps->tool == PAINT_TOOL_CLONE && mode == BRUSH_STROKE_INVERT) { + view3d_operator_needs_opengl(C); + return ps; + } + + /* needed so multiple threads don't try to initialize the brush at once (can leak memory) */ + curvemapping_initialize(ps->brush->curve); + + paint_brush_init_tex(ps->brush); + + ps->source = PROJ_SRC_VIEW; + + if (ps->ob == NULL || !(ps->ob->lay & ps->v3d->lay)) { + MEM_freeN(ps); + return NULL; + } + + ps->orig_brush_size = BKE_brush_size_get(ps->scene, ps->brush); + + /* Don't allow brush size below 2 */ + if (BKE_brush_size_get(ps->scene, ps->brush) < 2) + BKE_brush_size_set(ps->scene, ps->brush, 2); + + /* allocate and initialize spatial data structures */ + project_paint_begin(ps); + + if (ps->dm == NULL) { + MEM_freeN(ps); + return NULL; + } + + paint_proj_begin_clone(ps, mouse); + + return ps; +} + +void paint_proj_stroke_done(void *pps) +{ + ProjPaintState *ps = pps; + if (ps->tool == PAINT_TOOL_CLONE && ps->mode == BRUSH_STROKE_INVERT) { + MEM_freeN(ps); + return; + } + BKE_brush_size_set(ps->scene, ps->brush, ps->orig_brush_size); + + paint_brush_exit_tex(ps->brush); + + project_paint_end(ps); + MEM_freeN(ps); +} +/* use project paint to re-apply an image */ +static int texture_paint_camera_project_exec(bContext *C, wmOperator *op) +{ + Image *image = BLI_findlink(&CTX_data_main(C)->image, RNA_enum_get(op->ptr, "image")); + Scene *scene = CTX_data_scene(C); + ProjPaintState ps = {NULL}; + int orig_brush_size; + IDProperty *idgroup; + IDProperty *view_data = NULL; + + project_state_init(C, OBACT, &ps, BRUSH_STROKE_NORMAL); + + if (ps.ob == NULL || ps.ob->type != OB_MESH) { + BKE_report(op->reports, RPT_ERROR, "No active mesh object"); + return OPERATOR_CANCELLED; + } + + if (image == NULL) { + BKE_report(op->reports, RPT_ERROR, "Image could not be found"); + return OPERATOR_CANCELLED; + } + + ps.reproject_image = image; + ps.reproject_ibuf = BKE_image_acquire_ibuf(image, NULL, NULL); + + if (ps.reproject_ibuf == NULL || ps.reproject_ibuf->rect == NULL) { + BKE_report(op->reports, RPT_ERROR, "Image data could not be found"); + return OPERATOR_CANCELLED; + } + + idgroup = IDP_GetProperties(&image->id, 0); + + if (idgroup) { + view_data = IDP_GetPropertyTypeFromGroup(idgroup, PROJ_VIEW_DATA_ID, IDP_ARRAY); + + /* type check to make sure its ok */ + if (view_data->len != PROJ_VIEW_DATA_SIZE || view_data->subtype != IDP_FLOAT) { + BKE_report(op->reports, RPT_ERROR, "Image project data invalid"); + return OPERATOR_CANCELLED; + } + } + + if (view_data) { + /* image has stored view projection info */ + ps.source = PROJ_SRC_IMAGE_VIEW; + } + else { + ps.source = PROJ_SRC_IMAGE_CAM; + + if (scene->camera == NULL) { + BKE_report(op->reports, RPT_ERROR, "No active camera set"); + return OPERATOR_CANCELLED; + } + } + + /* override */ + ps.is_texbrush = 0; + ps.do_masking = false; + orig_brush_size = BKE_brush_size_get(scene, ps.brush); + BKE_brush_size_set(scene, ps.brush, 32); /* cover the whole image */ + + ps.tool = PAINT_TOOL_DRAW; /* so pixels are initialized with minimal info */ + + scene->toolsettings->imapaint.flag |= IMAGEPAINT_DRAWING; + + undo_paint_push_begin(UNDO_PAINT_IMAGE, op->type->name, + image_undo_restore, image_undo_free); + + /* allocate and initialize spatial data structures */ + project_paint_begin(&ps); + + if (ps.dm == NULL) { + BKE_brush_size_set(scene, ps.brush, orig_brush_size); + return OPERATOR_CANCELLED; + } + else { + float pos[2] = {0.0, 0.0}; + float lastpos[2] = {0.0, 0.0}; + int a; + + for (a = 0; a < ps.image_tot; a++) + partial_redraw_array_init(ps.projImages[a].partRedrawRect); + + project_paint_op(&ps, lastpos, pos); + + project_image_refresh_tagged(&ps); + + for (a = 0; a < ps.image_tot; a++) { + GPU_free_image(ps.projImages[a].ima); + WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ps.projImages[a].ima); + } + } + + project_paint_end(&ps); + + scene->toolsettings->imapaint.flag &= ~IMAGEPAINT_DRAWING; + BKE_brush_size_set(scene, ps.brush, orig_brush_size); + + return OPERATOR_FINISHED; +} + +void PAINT_OT_project_image(wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Project Image"; + ot->idname = "PAINT_OT_project_image"; + ot->description = "Project an edited render from the active camera back onto the object"; + + /* api callbacks */ + ot->invoke = WM_enum_search_invoke; + ot->exec = texture_paint_camera_project_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + prop = RNA_def_enum(ot->srna, "image", DummyRNA_NULL_items, 0, "Image", ""); + RNA_def_enum_funcs(prop, RNA_image_itemf); + ot->prop = prop; +} + +static int texture_paint_image_from_view_exec(bContext *C, wmOperator *op) +{ + Image *image; + ImBuf *ibuf; + char filename[FILE_MAX]; + + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + int w = settings->imapaint.screen_grab_size[0]; + int h = settings->imapaint.screen_grab_size[1]; + int maxsize; + char err_out[256] = "unknown"; + + RNA_string_get(op->ptr, "filepath", filename); + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxsize); + + if (w > maxsize) w = maxsize; + if (h > maxsize) h = maxsize; + + ibuf = ED_view3d_draw_offscreen_imbuf(CTX_data_scene(C), CTX_wm_view3d(C), CTX_wm_region(C), w, h, IB_rect, FALSE, R_ALPHAPREMUL, err_out); + if (!ibuf) { + /* Mostly happens when OpenGL offscreen buffer was failed to create, */ + /* but could be other reasons. Should be handled in the future. nazgul */ + BKE_reportf(op->reports, RPT_ERROR, "Failed to create OpenGL off-screen buffer: %s", err_out); + return OPERATOR_CANCELLED; + } + + image = BKE_image_add_from_imbuf(ibuf); + + if (image) { + /* now for the trickyness. store the view projection here! + * re-projection will reuse this */ + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = CTX_wm_region_view3d(C); + + IDPropertyTemplate val; + IDProperty *idgroup = IDP_GetProperties(&image->id, 1); + IDProperty *view_data; + bool is_ortho; + float *array; + + val.array.len = PROJ_VIEW_DATA_SIZE; + val.array.type = IDP_FLOAT; + view_data = IDP_New(IDP_ARRAY, &val, PROJ_VIEW_DATA_ID); + + array = (float *)IDP_Array(view_data); + memcpy(array, rv3d->winmat, sizeof(rv3d->winmat)); array += sizeof(rv3d->winmat) / sizeof(float); + memcpy(array, rv3d->viewmat, sizeof(rv3d->viewmat)); array += sizeof(rv3d->viewmat) / sizeof(float); + is_ortho = ED_view3d_clip_range_get(v3d, rv3d, &array[0], &array[1], true); + array[2] = is_ortho ? 1.0f : 0.0f; /* using float for a bool is dodgy but since its an extra member in the array... easier then adding a single bool prop */ + + IDP_AddToGroup(idgroup, view_data); + + rename_id(&image->id, "image_view"); + } + + return OPERATOR_FINISHED; +} + +void PAINT_OT_image_from_view(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Image from View"; + ot->idname = "PAINT_OT_image_from_view"; + ot->description = "Make an image from the current 3D view for re-projection"; + + /* api callbacks */ + ot->exec = texture_paint_image_from_view_exec; + ot->poll = ED_operator_region_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER; + + RNA_def_string_file_name(ot->srna, "filepath", "", FILE_MAX, "File Path", "Name of the file"); +} diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h index e7c3ddd071b..a15795dc2da 100644 --- a/source/blender/editors/sculpt_paint/paint_intern.h +++ b/source/blender/editors/sculpt_paint/paint_intern.h @@ -50,6 +50,8 @@ struct ViewContext; struct wmEvent; struct wmOperator; struct wmOperatorType; +struct ImagePaintState; +enum PaintMode; /* paint_stroke.c */ typedef int (*StrokeGetLocation)(struct bContext *C, float location[3], const float mouse[2]); @@ -62,11 +64,14 @@ struct PaintStroke *paint_stroke_new(struct bContext *C, StrokeUpdateStep update_step, StrokeDone done, int event_type); void paint_stroke_data_free(struct wmOperator *op); -bool paint_space_stroke_enabled(struct Brush *br); -bool paint_supports_dynamic_size(struct Brush *br); +bool paint_space_stroke_enabled(struct Brush *br, enum PaintMode mode); +bool paint_supports_dynamic_size(struct Brush *br, enum PaintMode mode); +bool paint_supports_dynamic_tex_coords(struct Brush *br, enum PaintMode mode); +bool paint_supports_smooth_stroke(struct Brush *br, enum PaintMode mode); +bool paint_supports_jitter(enum PaintMode mode); struct wmKeyMap *paint_stroke_modal_keymap(struct wmKeyConfig *keyconf); -int paint_stroke_modal(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int paint_stroke_modal(struct bContext *C, struct wmOperator *op, const 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); @@ -103,16 +108,46 @@ void PAINT_OT_vertex_paint(struct wmOperatorType *ot); unsigned int vpaint_get_current_col(struct VPaint *vp); /* paint_image.c */ +typedef struct ImagePaintPartialRedraw { + int x1, y1, x2, y2; /* XXX, could use 'rcti' */ + int enabled; +} ImagePaintPartialRedraw; + +#define IMAPAINT_TILE_BITS 6 +#define IMAPAINT_TILE_SIZE (1 << IMAPAINT_TILE_BITS) +#define IMAPAINT_TILE_NUMBER(size) (((size) + IMAPAINT_TILE_SIZE - 1) >> IMAPAINT_TILE_BITS) + +#define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f) + int image_texture_paint_poll(struct bContext *C); +void *image_undo_push_tile(struct Image *ima, struct ImBuf *ibuf, struct ImBuf **tmpibuf, int x_tile, int y_tile); +void image_undo_restore(struct bContext *C, struct ListBase *lb); +void image_undo_free(struct ListBase *lb); +void imapaint_image_update(struct SpaceImage *sima, struct Image *image, struct ImBuf *ibuf, short texpaint); +struct ImagePaintPartialRedraw *get_imapaintpartial(void); +void set_imapaintpartial(struct ImagePaintPartialRedraw * ippr); +void imapaint_clear_partial_redraw(void); +void imapaint_dirty_region(struct Image *ima, struct ImBuf *ibuf, int x, int y, int w, int h); +int get_imapaint_zoom(struct bContext *C, float *zoomx, float *zoomy); +void *paint_2d_new_stroke(struct bContext *, struct wmOperator *); +void paint_2d_redraw(const bContext *C, void *ps, int final); +void paint_2d_stroke_done(void *ps); +int paint_2d_stroke(void *ps, const int prev_mval[2], const int mval[2], int eraser); +void *paint_proj_new_stroke(struct bContext *C, struct Object *ob, const int mouse[2], int mode); +int paint_proj_stroke(struct bContext *C, void *ps, const int prevmval_i[2], const int mval_i[2]); +void paint_proj_stroke_done(void *ps); +void paint_brush_init_tex(struct Brush *brush); +void paint_brush_exit_tex(struct Brush *brush); -void PAINT_OT_image_paint(struct wmOperatorType *ot); void PAINT_OT_grab_clone(struct wmOperatorType *ot); void PAINT_OT_sample_color(struct wmOperatorType *ot); -void PAINT_OT_clone_cursor_set(struct wmOperatorType *ot); void PAINT_OT_texture_paint_toggle(struct wmOperatorType *ot); void PAINT_OT_project_image(struct wmOperatorType *ot); void PAINT_OT_image_from_view(struct wmOperatorType *ot); +/* new texture painting */ +void PAINT_OT_image_paint(struct wmOperatorType *ot); + /* uv sculpting */ int uv_sculpt_poll(struct bContext *C); @@ -144,6 +179,7 @@ float paint_calc_object_space_radius(struct ViewContext *vc, const float center[ float paint_get_tex_pixel(struct Brush *br, float u, float v, struct ImagePool *pool); int imapaint_pick_face(struct ViewContext *vc, const int mval[2], unsigned int *index, unsigned int totface); void imapaint_pick_uv(struct Scene *scene, struct Object *ob, unsigned int faceindex, const int xy[2], float uv[2]); +void brush_drawcursor_texpaint_uvsculpt(struct bContext *C, int x, int y, void *customdata); void paint_sample_color(const struct bContext *C, struct ARegion *ar, int x, int y); void BRUSH_OT_curve_preset(struct wmOperatorType *ot); @@ -155,6 +191,7 @@ void PAINT_OT_face_select_hide(struct wmOperatorType *ot); void PAINT_OT_face_select_reveal(struct wmOperatorType *ot); void PAINT_OT_vert_select_all(struct wmOperatorType *ot); +void PAINT_OT_vert_select_ungrouped(struct wmOperatorType *ot); int vert_paint_poll(struct bContext *C); int mask_paint_poll(struct bContext *C); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index dffb8c39bf2..e0b3905b30f 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -38,6 +38,7 @@ #include "DNA_meshdata_types.h" #include "DNA_object_types.h" +#include "BLI_utildefines.h" #include "BKE_pbvh.h" #include "BKE_ccg.h" #include "BKE_context.h" diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index 7385c2f0cf1..120d0a3b10a 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -467,7 +467,6 @@ void ED_operatortypes_paint(void) WM_operatortype_append(PAINT_OT_image_paint); WM_operatortype_append(PAINT_OT_sample_color); WM_operatortype_append(PAINT_OT_grab_clone); - WM_operatortype_append(PAINT_OT_clone_cursor_set); WM_operatortype_append(PAINT_OT_project_image); WM_operatortype_append(PAINT_OT_image_from_view); @@ -485,6 +484,7 @@ void ED_operatortypes_paint(void) /* vertex selection */ WM_operatortype_append(PAINT_OT_vert_select_all); + WM_operatortype_append(PAINT_OT_vert_select_ungrouped); /* vertex */ WM_operatortype_append(PAINT_OT_vertex_paint_toggle); @@ -533,7 +533,7 @@ static void ed_keymap_paint_brush_size(wmKeyMap *keymap, const char *UNUSED(path typedef enum { RC_COLOR = 1, RC_ROTATION = 2, - RC_ZOOM = 4, + RC_ZOOM = 4 } RCFlags; static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path, @@ -707,11 +707,17 @@ void ED_keymap_paint(wmKeyConfig *keyconf) ed_keymap_paint_brush_switch(keymap, "vertex_paint"); ed_keymap_paint_brush_size(keymap, "tool_settings.vertex_paint.brush.size"); - ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR); + ed_keymap_paint_brush_radial_control(keymap, "vertex_paint", RC_COLOR | RC_ROTATION); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */ RNA_string_set(kmi->ptr, "data_path", "vertex_paint_object.data.use_paint_mask"); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.use_smooth_stroke"); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.vertex_paint.brush.texture_angle_source_random"); + /* Weight Paint mode */ keymap = WM_keymap_find(keyconf, "Weight Paint", 0, 0); keymap->poll = weight_paint_mode_poll; @@ -741,7 +747,9 @@ void ED_keymap_paint(wmKeyConfig *keyconf) WM_keymap_verify_item(keymap, "PAINT_OT_weight_from_bones", WKEY, KM_PRESS, 0, 0); - + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.weight_paint.brush.use_smooth_stroke"); + /*Weight paint's Vertex Selection Mode */ keymap = WM_keymap_find(keyconf, "Weight Paint Vertex Selection", 0, 0); keymap->poll = vert_paint_poll; @@ -759,18 +767,24 @@ void ED_keymap_paint(wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Image Paint", 0, 0); keymap->poll = image_texture_paint_poll; - WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0); + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, 0, 0)->ptr, "mode", BRUSH_STROKE_NORMAL); + RNA_enum_set(WM_keymap_add_item(keymap, "PAINT_OT_image_paint", LEFTMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "mode", BRUSH_STROKE_INVERT); WM_keymap_add_item(keymap, "PAINT_OT_grab_clone", RIGHTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "PAINT_OT_sample_color", RIGHTMOUSE, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "PAINT_OT_clone_cursor_set", LEFTMOUSE, KM_PRESS, KM_CTRL, 0); ed_keymap_paint_brush_switch(keymap, "image_paint"); ed_keymap_paint_brush_size(keymap, "tool_settings.image_paint.brush.size"); - ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM); + ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION); kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", MKEY, KM_PRESS, 0, 0); /* mask toggle */ RNA_string_set(kmi->ptr, "data_path", "image_paint_object.data.use_paint_mask"); + kmi = WM_keymap_add_item(keymap, "WM_OT_context_toggle", SKEY, KM_PRESS, KM_SHIFT, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.use_smooth_stroke"); + + kmi = WM_keymap_add_item(keymap, "WM_OT_context_menu_enum", RKEY, KM_PRESS, 0, 0); + RNA_string_set(kmi->ptr, "data_path", "tool_settings.image_paint.brush.texture_angle_source_random"); + /* face-mask mode */ keymap = WM_keymap_find(keyconf, "Face Mask", 0, 0); keymap->poll = facemask_paint_poll; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 5d9313485d2..8c5552f48bc 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -35,6 +35,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_rand.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -91,6 +92,12 @@ typedef struct PaintStroke { /* event that started stroke, for modal() return */ int event_type; + bool brush_init; + float initial_mouse[2]; + float cached_pressure; + + float zoom_2d; + StrokeGetLocation get_location; StrokeTestStart test_start; StrokeUpdateStep update_step; @@ -104,23 +111,21 @@ static void paint_draw_smooth_stroke(bContext *C, int x, int y, void *customdata Brush *brush = paint_brush(paint); PaintStroke *stroke = customdata; - glColor4ubv(paint->paint_cursor_col); - glEnable(GL_LINE_SMOOTH); - glEnable(GL_BLEND); - if (stroke && brush && (brush->flag & BRUSH_SMOOTH_STROKE)) { - ARegion *ar = CTX_wm_region(C); - sdrawline(x, y, (int)stroke->last_mouse_position[0] - ar->winrct.xmin, - (int)stroke->last_mouse_position[1] - ar->winrct.ymin); + glColor4ubv(paint->paint_cursor_col); + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + sdrawline(x, y, (int)stroke->last_mouse_position[0], + (int)stroke->last_mouse_position[1]); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); } - - glDisable(GL_BLEND); - glDisable(GL_LINE_SMOOTH); } /* if this is a tablet event, return tablet pressure and set *pen_flip * to 1 if the eraser tool is being used, 0 otherwise */ -static float event_tablet_data(wmEvent *event, int *pen_flip) +static float event_tablet_data(const wmEvent *event, int *pen_flip) { int erasor = 0; float pressure = 1; @@ -138,11 +143,105 @@ static float event_tablet_data(wmEvent *event, int *pen_flip) return pressure; } + +/* Initialize the stroke cache variants from operator properties */ +static void paint_brush_update(bContext *C, Brush *brush, PaintMode mode, + struct PaintStroke *stroke, + const float mouse[2], float pressure) +{ + Scene *scene = CTX_data_scene(C); + UnifiedPaintSettings *ups = &scene->toolsettings->unified_paint_settings; + + /* XXX: Use pressure value from first brush step for brushes which don't + * support strokes (grab, thumb). They depends on initial state and + * brush coord/pressure/etc. + * It's more an events design issue, which doesn't split coordinate/pressure/angle + * changing events. We should avoid this after events system re-design */ + if (paint_supports_dynamic_size(brush, mode) || !stroke->brush_init) { + copy_v2_v2(stroke->initial_mouse, mouse); + copy_v2_v2(ups->tex_mouse, mouse); + stroke->cached_pressure = pressure; + } + + /* Truly temporary data that isn't stored in properties */ + + ups->draw_pressure = TRUE; + ups->pressure_value = stroke->cached_pressure; + + ups->pixel_radius = BKE_brush_size_get(scene, brush); + + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, mode)) { + ups->pixel_radius *= stroke->cached_pressure; + } + + if (!(brush->flag & BRUSH_ANCHORED || + ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, + SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE))) + { + copy_v2_v2(ups->tex_mouse, mouse); + + if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) && + (brush->flag & BRUSH_RANDOM_ROTATION) && + !(brush->flag & BRUSH_RAKE)) + { + ups->brush_rotation = 2.0f * (float)M_PI * BLI_frand(); + } + } + + if (brush->flag & BRUSH_ANCHORED) { + bool hit = false; + float halfway[2]; + + const float dx = mouse[0] - stroke->initial_mouse[0]; + const float dy = mouse[1] - stroke->initial_mouse[1]; + + ups->anchored_size = ups->pixel_radius = sqrt(dx * dx + dy * dy); + + ups->brush_rotation = atan2(dx, dy) + M_PI; + + if (brush->flag & BRUSH_EDGE_TO_EDGE) { + float out[3]; + + halfway[0] = dx * 0.5f + stroke->initial_mouse[0]; + halfway[1] = dy * 0.5f + stroke->initial_mouse[1]; + + if (stroke->get_location) { + if (stroke->get_location(C, out, halfway)) { + hit = true; + } + } + else { + hit = true; + } + } + if (hit) { + copy_v2_v2(ups->anchored_initial_mouse, halfway); + copy_v2_v2(ups->tex_mouse, halfway); + ups->anchored_size /= 2.0f; + ups->pixel_radius /= 2.0f; + } + else + copy_v2_v2(ups->anchored_initial_mouse, stroke->initial_mouse); + + ups->draw_anchored = 1; + } + else if (brush->flag & BRUSH_RAKE) { + if (!stroke->brush_init) + copy_v2_v2(ups->last_rake, mouse); + else + paint_calculate_rake_rotation(ups, mouse); + } + + stroke->brush_init = TRUE; +} + + /* Put the location of the next stroke dot into the stroke RNA and apply it to the mesh */ -static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *event, const float mouse_in[2]) +static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const wmEvent *event, const float mouse_in[2]) { Scene *scene = CTX_data_scene(C); Paint *paint = paint_get_active_from_context(C); + PaintMode mode = paintmode_get_active_from_context(C); Brush *brush = paint_brush(paint); PaintStroke *stroke = op->customdata; float mouse_out[2]; @@ -154,19 +253,45 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev /* see if tablet affects event */ pressure = event_tablet_data(event, &pen_flip); +/* the following code is adapted from texture paint. It may not be needed but leaving here + * just in case for reference (code in texpaint removed as part of refactoring). + * It's strange that only texpaint had these guards. */ +#if 0 + /* special exception here for too high pressure values on first touch in + * windows for some tablets, then we just skip first touch .. */ + if (tablet && (pressure >= 0.99f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush))) + return; + + /* This can be removed once fixed properly in + * BKE_brush_painter_paint(BrushPainter *painter, BrushFunc func, float *pos, double time, float pressure, void *user) + * at zero pressure we should do nothing 1/2^12 is 0.0002 which is the sensitivity of the most sensitive pen tablet available */ + if (tablet && (pressure < 0.0002f) && ((pop->s.brush->flag & BRUSH_SPACING_PRESSURE) || BKE_brush_use_alpha_pressure(scene, pop->s.brush) || BKE_brush_use_size_pressure(scene, pop->s.brush))) + return; +#endif + + /* copy last position -before- jittering, or space fill code + * will create too many dabs */ + copy_v2_v2(stroke->last_mouse_position, mouse_in); + + paint_brush_update(C, brush, mode, stroke, mouse_in, pressure); + /* TODO: as sculpt and other paint modes are unified, this * separation will go away */ - if (stroke->vc.obact->sculpt) { + if (paint_supports_jitter(mode)) { float delta[2]; + float factor = stroke->zoom_2d; + + if (brush->flag & BRUSH_JITTER_PRESSURE) + factor *= pressure; BKE_brush_jitter_pos(scene, brush, mouse_in, mouse_out); /* XXX: meh, this is round about because * BKE_brush_jitter_pos isn't written in the best way to * be reused here */ - if (brush->flag & BRUSH_JITTER_PRESSURE) { + if (factor != 1.0f) { sub_v2_v2v2(delta, mouse_out, mouse_in); - mul_v2_fl(delta, pressure); + mul_v2_fl(delta, factor); add_v2_v2v2(mouse_out, mouse_in, delta); } } @@ -188,34 +313,25 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev RNA_boolean_set(&itemptr, "pen_flip", pen_flip); RNA_float_set(&itemptr, "pressure", pressure); - copy_v2_v2(stroke->last_mouse_position, mouse_out); - stroke->update_step(C, stroke, &itemptr); } /* Returns zero if no sculpt changes should be made, non-zero otherwise */ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], - const PaintSample *sample) + const PaintSample *sample, PaintMode mode) { output[0] = sample->mouse[0]; output[1] = sample->mouse[1]; - if ((stroke->brush->flag & BRUSH_SMOOTH_STROKE) && - !ELEM4(stroke->brush->sculpt_tool, - SCULPT_TOOL_GRAB, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_SNAKE_HOOK) && - !(stroke->brush->flag & BRUSH_ANCHORED) && - !(stroke->brush->flag & BRUSH_RESTORE_MESH)) - { + if (paint_supports_smooth_stroke(stroke->brush, mode)) { + float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d; float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u; float dx = stroke->last_mouse_position[0] - sample->mouse[0]; float dy = stroke->last_mouse_position[1] - sample->mouse[1]; /* If the mouse is moving within the radius of the last move, * don't update the mouse position. This allows sharp turns. */ - if (dx * dx + dy * dy < stroke->brush->smooth_stroke_radius * stroke->brush->smooth_stroke_radius) + if (dx * dx + dy * dy < radius * radius) return 0; output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u; @@ -227,12 +343,14 @@ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], /* For brushes with stroke spacing enabled, moves mouse in steps * towards the final mouse location. */ -static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const float final_mouse[2]) +static int paint_space_stroke(bContext *C, wmOperator *op, const wmEvent *event, const float final_mouse[2]) { PaintStroke *stroke = op->customdata; + PaintMode mode = paintmode_get_active_from_context(C); + int cnt = 0; - if (paint_space_stroke_enabled(stroke->brush)) { + if (paint_space_stroke_enabled(stroke->brush, mode)) { float mouse[2]; float vec[2]; float length, scale; @@ -246,17 +364,28 @@ static int paint_space_stroke(bContext *C, wmOperator *op, wmEvent *event, const const Scene *scene = CTX_data_scene(C); int steps; int i; - float pressure = 1.0f; + float size_pressure = 1.0f; + float pressure = event_tablet_data(event, NULL); /* XXX mysterious :) what has 'use size' do with this here... if you don't check for it, pressure fails */ if (BKE_brush_use_size_pressure(scene, stroke->brush)) - pressure = event_tablet_data(event, NULL); + size_pressure = pressure; - if (pressure > FLT_EPSILON) { + if (size_pressure > FLT_EPSILON) { /* brushes can have a minimum size of 1.0 but with pressure it can be smaller then a pixel * causing very high step sizes, hanging blender [#32381] */ - const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * pressure); - scale = (size_clamp * stroke->brush->spacing / 50.0f) / length; + const float size_clamp = max_ff(1.0f, BKE_brush_size_get(scene, stroke->brush) * size_pressure); + float spacing = stroke->brush->spacing; + + /* stroke system is used for 2d paint too, so we need to account for + * the fact that brush can be scaled there. */ + + if (stroke->brush->flag & BRUSH_SPACING_PRESSURE) + spacing = max_ff(1.0f, spacing * (1.5f - pressure)); + + spacing *= stroke->zoom_2d; + + scale = (size_clamp * spacing / 50.0f) / length; if (scale > FLT_EPSILON) { mul_v2_fl(vec, scale); @@ -286,7 +415,8 @@ PaintStroke *paint_stroke_new(bContext *C, stroke->brush = paint_brush(paint_get_active_from_context(C)); view3d_set_viewcontext(C, &stroke->vc); - view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats); + if (stroke->vc.v3d) + view3d_get_transformation(stroke->vc.ar, stroke->vc.rv3d, stroke->vc.obact, &stroke->mats); stroke->get_location = get_location; stroke->test_start = test_start; @@ -324,16 +454,77 @@ static void stroke_done(struct bContext *C, struct wmOperator *op) } /* Returns zero if the stroke dots should not be spaced, non-zero otherwise */ -bool paint_space_stroke_enabled(Brush *br) +bool paint_space_stroke_enabled(Brush *br, PaintMode mode) +{ + return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br, mode); +} + +/* return true if the brush size can change during paint (normally used for pressure) */ +bool paint_supports_dynamic_size(Brush *br, PaintMode mode) { - return (br->flag & BRUSH_SPACE) && paint_supports_dynamic_size(br); + if (br->flag & BRUSH_ANCHORED) + return false; + + switch (mode) { + case PAINT_SCULPT: + if (ELEM4(br->sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_SNAKE_HOOK)) + { + return false; + } + default: + ; + } + return true; +} + +bool paint_supports_smooth_stroke(Brush *br, PaintMode mode) +{ + if (!(br->flag & BRUSH_SMOOTH_STROKE) || + (br->flag & BRUSH_ANCHORED) || + (br->flag & BRUSH_RESTORE_MESH)) + { + return false; + } + + switch (mode) { + case PAINT_SCULPT: + if (ELEM4(br->sculpt_tool, + SCULPT_TOOL_GRAB, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_SNAKE_HOOK)) + { + return false; + } + default: + ; + } + return true; } /* return true if the brush size can change during paint (normally used for pressure) */ -bool paint_supports_dynamic_size(Brush *br) +bool paint_supports_dynamic_tex_coords(Brush *br, PaintMode mode) { - return !(br->flag & BRUSH_ANCHORED) && - !ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK); + if (br->flag & BRUSH_ANCHORED) + return false; + + switch (mode) { + case PAINT_SCULPT: + if (ELEM4(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE, SCULPT_TOOL_SNAKE_HOOK)) + return false; + default: + ; + } + return true; +} + +bool paint_supports_jitter(PaintMode mode) +{ + return ELEM3(mode, PAINT_SCULPT, PAINT_TEXTURE_PROJECTIVE, PAINT_TEXTURE_2D); } #define PAINT_STROKE_MODAL_CANCEL 1 @@ -400,17 +591,22 @@ static void paint_stroke_sample_average(const PaintStroke *stroke, /*printf("avg=(%f, %f), num=%d\n", average->mouse[0], average->mouse[1], stroke->num_samples);*/ } -int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) +int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) { Paint *p = paint_get_active_from_context(C); + PaintMode mode = paintmode_get_active_from_context(C); PaintStroke *stroke = op->customdata; PaintSample sample_average; float mouse[2]; int first = 0; + float zoomx, zoomy; - paint_stroke_add_sample(p, stroke, event->x, event->y); + paint_stroke_add_sample(p, stroke, event->mval[0], event->mval[1]); paint_stroke_sample_average(stroke, &sample_average); + get_imapaint_zoom(C, &zoomx, &zoomy); + stroke->zoom_2d = max_ff(zoomx, zoomy); + /* let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! * this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it * since the 2D deltas are zero -- code in this file needs to be updated to use the @@ -452,8 +648,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) (event->type == TIMER && (event->customdata == stroke->timer)) ) { if (stroke->stroke_started) { - if (paint_smooth_stroke(stroke, mouse, &sample_average)) { - if (paint_space_stroke_enabled(stroke->brush)) { + if (paint_smooth_stroke(stroke, mouse, &sample_average, mode)) { + if (paint_space_stroke_enabled(stroke->brush, mode)) { if (!paint_space_stroke(C, op, event, mouse)) { //ED_region_tag_redraw(ar); } @@ -472,7 +668,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) * instead of waiting till we have moved the space distance */ if (first && stroke->stroke_started && - paint_space_stroke_enabled(stroke->brush) && + paint_space_stroke_enabled(stroke->brush, mode) && !(stroke->brush->flag & BRUSH_ANCHORED) && !(stroke->brush->flag & BRUSH_SMOOTH_STROKE)) { diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index dc3f310b405..5e88c7b5730 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -47,6 +47,7 @@ #include "BKE_context.h" #include "BKE_DerivedMesh.h" #include "BKE_paint.h" +#include "BKE_report.h" #include "RNA_access.h" #include "RNA_define.h" @@ -160,12 +161,12 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], Object *ob = vc->obact; float delta[3], scale, loc[3]; const float mval_f[2] = {pixel_radius, 0.0f}; + float zfac; mul_v3_m4v3(loc, ob->obmat, center); - initgrabz(vc->rv3d, loc[0], loc[1], loc[2]); - - ED_view3d_win_to_delta(vc->ar, mval_f, delta); + zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL); + ED_view3d_win_to_delta(vc->ar, mval_f, delta, zfac); scale = fabsf(mat4_to_scale(ob->obmat)); scale = (scale == 0.0f) ? 1.0f : scale; @@ -414,7 +415,7 @@ void PAINT_OT_face_select_linked(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int paint_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int mode = RNA_boolean_get(op->ptr, "extend") ? 1 : 0; paintface_select_linked(C, CTX_data_active_object(C), event->mval, mode); @@ -484,6 +485,39 @@ void PAINT_OT_vert_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } + +static int vert_select_ungrouped_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + Mesh *me = ob->data; + + if ((ob->defbase.first == NULL) || (me->dvert == NULL)) { + BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object"); + return OPERATOR_CANCELLED; + } + + paintvert_select_ungrouped(ob, RNA_boolean_get(op->ptr, "extend"), TRUE); + ED_region_tag_redraw(CTX_wm_region(C)); + return OPERATOR_FINISHED; +} + +void PAINT_OT_vert_select_ungrouped(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Ungrouped"; + ot->idname = "PAINT_OT_vert_select_ungrouped"; + ot->description = "Select vertices without a group"; + + /* api callbacks */ + ot->exec = vert_select_ungrouped_exec; + ot->poll = vert_paint_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection"); +} + static int face_select_hide_exec(bContext *C, wmOperator *op) { const int unselected = RNA_boolean_get(op->ptr, "unselected"); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 0277e1e11dc..2bdcda1430d 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -43,6 +43,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_math_color.h" #include "BLI_memarena.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -854,36 +855,46 @@ static int sample_backbuf_area(ViewContext *vc, int *indexar, int totface, int x } /* whats _dl mean? */ -static float calc_vp_strength_dl(VPaint *vp, ViewContext *vc, const float co[3], - const float mval[2], const float brush_size_pressure) +static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co[3], + const float mval[2], const float brush_size_pressure, float rgba[4]) { - float vertco[2]; + float co_ss[2]; /* screenspace */ if (ED_view3d_project_float_object(vc->ar, - co, vertco, + co, co_ss, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { float delta[2]; float dist_squared; - sub_v2_v2v2(delta, mval, vertco); + sub_v2_v2v2(delta, mval, co_ss); dist_squared = dot_v2v2(delta, delta); /* len squared */ if (dist_squared <= brush_size_pressure * brush_size_pressure) { Brush *brush = paint_brush(&vp->paint); const float dist = sqrtf(dist_squared); + if (brush->mtex.tex && rgba) { + if (brush->mtex.brush_map_mode == MTEX_MAP_MODE_3D) { + BKE_brush_sample_tex_3D(vc->scene, brush, co, rgba, 0, NULL); + } + else { + const float co_ss_3d[3] = {co_ss[0], co_ss[1], 0.0f}; /* we need a 3rd empty value */ + BKE_brush_sample_tex_3D(vc->scene, brush, co_ss_3d, rgba, 0, NULL); + } + } return BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure); } } - + if (rgba) + zero_v4(rgba); return 0.0f; } -static float calc_vp_alpha_dl(VPaint *vp, ViewContext *vc, +static float calc_vp_alpha_col_dl(VPaint *vp, ViewContext *vc, float vpimat[3][3], const DMCoNo *v_co_no, const float mval[2], - const float brush_size_pressure, const float brush_alpha_pressure) + const float brush_size_pressure, const float brush_alpha_pressure, float rgba[4]) { - float strength = calc_vp_strength_dl(vp, vc, v_co_no->co, mval, brush_size_pressure); + float strength = calc_vp_strength_col_dl(vp, vc, v_co_no->co, mval, brush_size_pressure, rgba); if (strength > 0.0f) { float alpha = brush_alpha_pressure * strength; @@ -1015,7 +1026,7 @@ static float wpaint_blend(VPaint *wp, float weight, float weight_prev, /* sets wp->weight to the closest weight value to vertex */ /* note: we cant sample frontbuf, weight colors are interpolated too unpredictable */ -static int weight_sample_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int weight_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewContext vc; Mesh *me; @@ -1467,7 +1478,7 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, MDeformWeight *ndw; MDeformWeight *odw; - float changed_sum = 0.0f; + // float changed_sum = 0.0f; // UNUSED char *change_status; @@ -1496,7 +1507,7 @@ static void enforce_locks(MDeformVert *odv, MDeformVert *ndv, } else if (ndw->weight != odw->weight) { /* changed groups are handled here */ totchange += ndw->weight - odw->weight; - changed_sum += ndw->weight; + // changed_sum += ndw->weight; // UNUSED change_status[i] = 2; /* was altered already */ total_changed++; } /* unchanged, unlocked bone groups are handled here */ @@ -2239,11 +2250,6 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P mult_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat); RNA_float_get_array(itemptr, "mouse", mval); - mval[0] -= vc->ar->winrct.xmin; - mval[1] -= vc->ar->winrct.ymin; - - - /* *** setup WeightPaintInfo - pass onto do_weight_paint_vertex *** */ wpi.defbase_tot = wpd->defbase_tot; @@ -2312,7 +2318,7 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P #define WP_BLUR_ACCUM(v_idx_var) \ { \ const unsigned int vidx = v_idx_var; \ - const float fac = calc_vp_strength_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure); \ + const float fac = calc_vp_strength_col_dl(wp, vc, wpd->vertexcosnos[vidx].co, mval, brush_size_pressure, NULL); \ if (fac > 0.0f) { \ MDeformWeight *dw = dw_func(&me->dvert[vidx], wpi.vgroup_active); \ paintweight += dw ? (dw->weight * fac) : 0.0f; \ @@ -2382,8 +2388,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P { \ unsigned int vidx = v_idx_var; \ if (me->dvert[vidx].flag) { \ - alpha = calc_vp_alpha_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx], \ - mval, brush_size_pressure, brush_alpha_pressure); \ + alpha = calc_vp_alpha_col_dl(wp, vc, wpd->wpimat, &wpd->vertexcosnos[vidx], \ + mval, brush_size_pressure, brush_alpha_pressure, NULL); \ if (alpha) { \ do_weight_paint_vertex(wp, ob, &wpi, vidx, alpha, paintweight); \ } \ @@ -2480,7 +2486,7 @@ static void wpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) } -static int wpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int wpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int retval; @@ -2667,6 +2673,8 @@ typedef struct VPaintData { /* mpoly -> mface mapping */ MemArena *polyfacemap_arena; ListBase *polyfacemap; + + bool is_texbrush; } VPaintData; static void vpaint_build_poly_facemap(struct VPaintData *vd, Mesh *me) @@ -2703,6 +2711,7 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl ToolSettings *ts = CTX_data_tool_settings(C); struct PaintStroke *stroke = op->customdata; VPaint *vp = ts->vpaint; + Brush *brush = paint_brush(&vp->paint); struct VPaintData *vpd; Object *ob = CTX_data_active_object(C); Mesh *me; @@ -2732,6 +2741,8 @@ static int vpaint_stroke_test_start(bContext *C, struct wmOperator *op, const fl vpd->indexar = get_indexarray(me); vpd->paintcol = vpaint_get_current_col(vp); + vpd->is_texbrush = !(brush->vertexpaint_tool == PAINT_BLEND_BLUR) && + brush->mtex.tex; /* are we painting onto a modified mesh?, * if not we can skip face map trickyness */ @@ -2808,12 +2819,24 @@ static void vpaint_paint_poly(VPaint *vp, VPaintData *vpd, Mesh *me, ml = me->mloop + mpoly->loopstart; for (i = 0; i < mpoly->totloop; i++, ml++) { - alpha = calc_vp_alpha_dl(vp, vc, vpd->vpimat, + float rgba[4]; + unsigned int paintcol; + alpha = calc_vp_alpha_col_dl(vp, vc, vpd->vpimat, &vpd->vertexcosnos[ml->v], mval, - brush_size_pressure, brush_alpha_pressure); + brush_size_pressure, brush_alpha_pressure, rgba); + + if (vpd->is_texbrush) { + float rgba_br[3]; + rgb_uchar_to_float(rgba_br, (const unsigned char *)&vpd->paintcol); + mul_v3_v3(rgba_br, rgba); + rgb_float_to_uchar((unsigned char *)&paintcol, rgba_br); + } + else + paintcol = vpd->paintcol; + if (alpha > 0.0f) { const int alpha_i = (int)(alpha * 255.0f); - lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], vpd->paintcol, alpha_i, brush_alpha_pressure_i); + lcol[i] = vpaint_blend(vp, lcol[i], lcolorig[i], paintcol, alpha_i, brush_alpha_pressure_i); } } @@ -2872,10 +2895,6 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P /* load projection matrix */ mult_m4_m4m4(mat, vc->rv3d->persmat, ob->obmat); - mval[0] -= vc->ar->winrct.xmin; - mval[1] -= vc->ar->winrct.ymin; - - /* which faces are involved */ if (vp->flag & VP_AREA) { totindex = sample_backbuf_area(vc, indexar, me->totpoly, mval[0], mval[1], brush_size_pressure); @@ -2959,7 +2978,7 @@ static void vpaint_stroke_done(const bContext *C, struct PaintStroke *stroke) MEM_freeN(vpd); } -static int vpaint_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int vpaint_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int retval; @@ -3165,7 +3184,7 @@ static void gradientVert__mapFunc(void *userData, int index, const float co[3], } } -static int paint_weight_gradient_modal(bContext *C, wmOperator *op, wmEvent *event) +static int paint_weight_gradient_modal(bContext *C, wmOperator *op, const wmEvent *event) { int ret = WM_gesture_straightline_modal(C, op, event); @@ -3273,7 +3292,7 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int paint_weight_gradient_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int ret; diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 90e7645032b..376622e95a6 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -43,6 +43,8 @@ #include "BLI_threads.h" #include "BLI_rand.h" +#include "BLF_translation.h" + #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_node_types.h" @@ -243,7 +245,6 @@ typedef struct StrokeCache { float pressure; float mouse[2]; float bstrength; - float tex_mouse[2]; /* The rest is temporary storage that isn't saved as a property */ @@ -257,8 +258,8 @@ typedef struct StrokeCache { Brush *brush; float (*face_norms)[3]; /* Copy of the mesh faces' normals */ - float special_rotation; /* Texture rotation (radians) for anchored and rake modes */ - int pixel_radius, previous_pixel_radius; + + float special_rotation; float grab_delta[3], grab_delta_symmetry[3]; float old_grab_location[3], orig_grab_location[3]; @@ -282,8 +283,8 @@ typedef struct StrokeCache { int radial_symmetry_pass; float symm_rot_mat[4][4]; float symm_rot_mat_inv[4][4]; - float last_rake[2]; /* Last location of updating rake rotation */ int original; + float anchored_location[3]; float vertex_rotation; @@ -316,8 +317,8 @@ typedef struct { /* Initialize a SculptOrigVertData for accessing original vertex data; * handles BMesh, mesh, and multires */ static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data, - Object *ob, - SculptUndoNode *unode) + Object *ob, + SculptUndoNode *unode) { SculptSession *ss = ob->sculpt; BMesh *bm = ss->bm; @@ -338,19 +339,18 @@ static void sculpt_orig_vert_data_unode_init(SculptOrigVertData *data, /* Initialize a SculptOrigVertData for accessing original vertex data; * handles BMesh, mesh, and multires */ static void sculpt_orig_vert_data_init(SculptOrigVertData *data, - Object *ob, - PBVHNode *node) + Object *ob, + PBVHNode *node) { SculptUndoNode *unode; unode = sculpt_undo_push_node(ob, node, SCULPT_UNDO_COORDS); sculpt_orig_vert_data_unode_init(data, ob, unode); - } /* Update a SculptOrigVertData for a particular vertex from the PBVH * iterator */ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, - PBVHVertexIter *iter) + PBVHVertexIter *iter) { if (orig_data->unode->type == SCULPT_UNDO_COORDS) { if (orig_data->coords) { @@ -387,30 +387,30 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, Others, like smooth, are better without. Same goes for alt- key smoothing. */ static int sculpt_stroke_dynamic_topology(const SculptSession *ss, - const Brush *brush) + const Brush *brush) { return ((BKE_pbvh_type(ss->pbvh) == PBVH_BMESH) && - (!ss->cache || (!ss->cache->alt_smooth)) && - - /* Requires mesh restore, which doesn't work with - * dynamic-topology */ - !(brush->flag & BRUSH_ANCHORED) && - !(brush->flag & BRUSH_RESTORE_MESH) && + (!ss->cache || (!ss->cache->alt_smooth)) && - (!ELEM6(brush->sculpt_tool, - /* These brushes, as currently coded, cannot - * support dynamic topology */ - SCULPT_TOOL_GRAB, - SCULPT_TOOL_ROTATE, - SCULPT_TOOL_THUMB, - SCULPT_TOOL_LAYER, + /* Requires mesh restore, which doesn't work with + * dynamic-topology */ + !(brush->flag & BRUSH_ANCHORED) && + !(brush->flag & BRUSH_RESTORE_MESH) && + + (!ELEM6(brush->sculpt_tool, + /* These brushes, as currently coded, cannot + * support dynamic topology */ + SCULPT_TOOL_GRAB, + SCULPT_TOOL_ROTATE, + SCULPT_TOOL_THUMB, + SCULPT_TOOL_LAYER, - /* These brushes could handle dynamic topology, - * but user feedback indicates it's better not - * to */ - SCULPT_TOOL_SMOOTH, - SCULPT_TOOL_MASK))); + /* These brushes could handle dynamic topology, + * but user feedback indicates it's better not + * to */ + SCULPT_TOOL_SMOOTH, + SCULPT_TOOL_MASK))); } /*** paint mesh ***/ @@ -439,7 +439,7 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) for (n = 0; n < totnode; n++) { SculptUndoNode *unode; SculptUndoType type = (brush->sculpt_tool == SCULPT_TOOL_MASK ? - SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); + SCULPT_UNDO_MASK : SCULPT_UNDO_COORDS); if (ss->bm) { unode = sculpt_undo_push_node(ob, nodes[n], type); @@ -545,13 +545,32 @@ typedef struct SculptBrushTest { float radius_squared; float location[3]; float dist; + + /* View3d clipping - only set rv3d for clipping */ + RegionView3D *clip_rv3d; } SculptBrushTest; static void sculpt_brush_test_init(SculptSession *ss, SculptBrushTest *test) { + RegionView3D *rv3d = ss->cache->vc->rv3d; + test->radius_squared = ss->cache->radius_squared; copy_v3_v3(test->location, ss->cache->location); test->dist = 0.0f; /* just for initialize */ + + + if (rv3d->rflag & RV3D_CLIPPING) { + test->clip_rv3d = rv3d; + } + else { + test->clip_rv3d = NULL; + } +} + +BLI_INLINE bool sculpt_brush_test_clipping(SculptBrushTest *test, const float co[3]) +{ + RegionView3D *rv3d = test->clip_rv3d; + return (rv3d && (ED_view3d_clipping_test(rv3d, co, true))); } static int sculpt_brush_test(SculptBrushTest *test, const float co[3]) @@ -559,6 +578,9 @@ static int sculpt_brush_test(SculptBrushTest *test, const float co[3]) float distsq = len_squared_v3v3(co, test->location); if (distsq <= test->radius_squared) { + if (sculpt_brush_test_clipping(test, co)) { + return 0; + } test->dist = sqrt(distsq); return 1; } @@ -572,6 +594,9 @@ static int sculpt_brush_test_sq(SculptBrushTest *test, const float co[3]) float distsq = len_squared_v3v3(co, test->location); if (distsq <= test->radius_squared) { + if (sculpt_brush_test_clipping(test, co)) { + return 0; + } test->dist = distsq; return 1; } @@ -582,6 +607,9 @@ static int sculpt_brush_test_sq(SculptBrushTest *test, const float co[3]) static int sculpt_brush_test_fast(SculptBrushTest *test, float co[3]) { + if (sculpt_brush_test_clipping(test, co)) { + return 0; + } return len_squared_v3v3(co, test->location) <= test->radius_squared; } @@ -590,6 +618,10 @@ static int sculpt_brush_test_cube(SculptBrushTest *test, float co[3], float loca float side = M_SQRT1_2; float local_co[3]; + if (sculpt_brush_test_clipping(test, co)) { + return 0; + } + mul_v3_m4v3(local_co, local, co); local_co[0] = fabs(local_co[0]); @@ -890,25 +922,22 @@ static float tex_strength(SculptSession *ss, Brush *br, const float fno[3], const float mask) { + const Scene *scene = ss->cache->vc->scene; MTex *mtex = &br->mtex; float avg = 1; + float rgba[4]; if (!mtex->tex) { avg = 1; } else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { - float jnk; - /* Get strength by feeding the vertex * location directly into a texture */ - externtex(mtex, point, &avg, - &jnk, &jnk, &jnk, &jnk, 0, ss->tex_pool); + avg = BKE_brush_sample_tex_3D(scene, br, point, rgba, 0, ss->tex_pool); } else if (ss->texcache) { - float rotation = -mtex->rot; float symm_point[3], point_2d[2]; float x = 0.0f, y = 0.0f; /* Quite warnings */ - float radius = 1.0f; /* Quite warnings */ /* if the active area is being applied for symmetry, flip it * across the symmetry axis and rotate it back to the original @@ -922,77 +951,33 @@ static float tex_strength(SculptSession *ss, Brush *br, ED_view3d_project_float_v2_m4(ss->cache->vc->ar, symm_point, point_2d, ss->cache->projection_mat); - if (mtex->brush_map_mode == MTEX_MAP_MODE_VIEW) { - /* keep coordinates relative to mouse */ - - rotation += ss->cache->special_rotation; - - point_2d[0] -= ss->cache->tex_mouse[0]; - point_2d[1] -= ss->cache->tex_mouse[1]; - - /* use pressure adjusted size for fixed mode */ - radius = ss->cache->pixel_radius; - - x = point_2d[0] + ss->cache->vc->ar->winrct.xmin; - y = point_2d[1] + ss->cache->vc->ar->winrct.ymin; - } - else if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { - /* leave the coordinates relative to the screen */ - - /* use unadjusted size for tiled mode */ - radius = BKE_brush_size_get(ss->cache->vc->scene, br); - - x = point_2d[0]; - y = point_2d[1]; - } - else if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) { + /* still no symmetry supported for other paint modes. + * Sculpt does it DIY */ + if (mtex->brush_map_mode == MTEX_MAP_MODE_AREA) { /* Similar to fixed mode, but projects from brush angle * rather than view direction */ - /* Rotation is handled by the brush_local_mat */ - rotation = 0; - mul_m4_v3(ss->cache->brush_local_mat, symm_point); x = symm_point[0]; y = symm_point[1]; - } - if (mtex->brush_map_mode != MTEX_MAP_MODE_AREA) { - x /= ss->cache->vc->ar->winx; - y /= ss->cache->vc->ar->winy; + x *= br->mtex.size[0]; + y *= br->mtex.size[1]; - if (mtex->brush_map_mode == MTEX_MAP_MODE_TILED) { - x -= 0.5f; - y -= 0.5f; - } - - x *= ss->cache->vc->ar->winx / radius; - y *= ss->cache->vc->ar->winy / radius; - } + x += br->mtex.ofs[0]; + y += br->mtex.ofs[1]; - /* it is probably worth optimizing for those cases where - * the texture is not rotated by skipping the calls to - * atan2, sqrtf, sin, and cos. */ - if (rotation > 0.001f || rotation < -0.001f) { - const float angle = atan2f(y, x) + rotation; - const float flen = sqrtf(x * x + y * y); + avg = paint_get_tex_pixel(br, x, y, ss->tex_pool); - x = flen * cosf(angle); - y = flen * sinf(angle); + avg += br->texture_sample_bias; + } + else { + const float point_3d[3] = {point_2d[0], point_2d[1], 0.0f}; + avg = BKE_brush_sample_tex_3D(scene, br, point_3d, rgba, 0, ss->tex_pool); } - - x *= br->mtex.size[0]; - y *= br->mtex.size[1]; - - x += br->mtex.ofs[0]; - y += br->mtex.ofs[1]; - - avg = paint_get_tex_pixel(br, x, y, ss->tex_pool); } - avg += br->texture_sample_bias; - /* Falloff curve */ avg *= BKE_brush_curve_strength(br, len, ss->cache->radius); @@ -1203,11 +1188,12 @@ static void calc_local_y(ViewContext *vc, const float center[3], float y[3]) { Object *ob = vc->obact; float loc[3], mval_f[2] = {0.0f, 1.0f}; + float zfac; mul_v3_m4v3(loc, ob->imat, center); - initgrabz(vc->rv3d, loc[0], loc[1], loc[2]); + zfac = ED_view3d_calc_zfac(vc->rv3d, loc, NULL); - ED_view3d_win_to_delta(vc->ar, mval_f, y); + ED_view3d_win_to_delta(vc->ar, mval_f, y, zfac); normalize_v3(y); add_v3_v3(y, ob->loc); @@ -3173,8 +3159,8 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) if (use_orco) { if (ss->bm) { copy_v3_v3(val, - BM_log_original_vert_co(ss->bm_log, - vd.bm_vert)); + BM_log_original_vert_co(ss->bm_log, + vd.bm_vert)); } else copy_v3_v3(val, orco[vd.i]); @@ -3342,7 +3328,7 @@ static void sculpt_fix_noise_tear(Sculpt *sd, Object *ob) } static void do_symmetrical_brush_actions(Sculpt *sd, Object *ob, - BrushActionFunc action) + BrushActionFunc action) { Brush *brush = paint_brush(&sd->paint); SculptSession *ss = ob->sculpt; @@ -3480,7 +3466,9 @@ void sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, } } } - else free_sculptsession_deformMats(ss); + else { + free_sculptsession_deformMats(ss); + } /* if pbvh is deformed, key block is already applied to it */ if (ss->kb && !BKE_pbvh_isDeformed(ss->pbvh)) { @@ -3673,27 +3661,28 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio Brush *brush = paint_brush(&sd->paint); ViewContext *vc = paint_stroke_view_context(op->customdata); Object *ob = CTX_data_active_object(C); + float rot[3][3], scale[3], loc[3]; int i; int mode; ss->cache = cache; /* Set scaling adjustment */ - ss->cache->scale[0] = 1.0f / ob->size[0]; - ss->cache->scale[1] = 1.0f / ob->size[1]; - ss->cache->scale[2] = 1.0f / ob->size[2]; + cache->scale[0] = 1.0f / ob->size[0]; + cache->scale[1] = 1.0f / ob->size[1]; + cache->scale[2] = 1.0f / ob->size[2]; - ss->cache->plane_trim_squared = brush->plane_trim * brush->plane_trim; + cache->plane_trim_squared = brush->plane_trim * brush->plane_trim; - ss->cache->flag = 0; + cache->flag = 0; sculpt_init_mirror_clipping(ob, ss); /* Initial mouse location */ if (mouse) - copy_v2_v2(ss->cache->initial_mouse, mouse); + copy_v2_v2(cache->initial_mouse, mouse); else - zero_v2(ss->cache->initial_mouse); + zero_v2(cache->initial_mouse); mode = RNA_enum_get(op->ptr, "mode"); cache->invert = mode == BRUSH_STROKE_INVERT; @@ -3705,7 +3694,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio else brush->flag &= ~BRUSH_INVERTED; /* Alt-Smooth */ - if (ss->cache->alt_smooth) { + if (cache->alt_smooth) { if (brush->sculpt_tool == SCULPT_TOOL_MASK) { cache->saved_mask_brush_tool = brush->mask_tool; brush->mask_tool = BRUSH_MASK_SMOOTH; @@ -3726,7 +3715,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } copy_v2_v2(cache->mouse, cache->initial_mouse); - copy_v2_v2(cache->tex_mouse, cache->initial_mouse); + copy_v2_v2(ups->tex_mouse, cache->initial_mouse); /* Truly temporary data that isn't stored in properties */ @@ -3737,7 +3726,12 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio /* cache projection matrix */ ED_view3d_ob_project_mat_get(cache->vc->rv3d, ob, cache->projection_mat); + mat4_to_loc_rot_size(loc, rot, scale, ob->obmat); + /* transposing an orthonormal matrix inverts */ + transpose_m3(rot); ED_view3d_global_to_vector(cache->vc->rv3d, cache->vc->rv3d->twmat[3], cache->true_view_normal); + /* This takes care of rotated mesh. Instead of rotating every normal, we inverse rotate view normal. */ + mul_m3_v3(rot, cache->true_view_normal); /* Initialize layer brush displacements and persistent coords */ if (brush->sculpt_tool == SCULPT_TOOL_LAYER) { /* not supported yet for multires or dynamic topology */ @@ -3748,7 +3742,9 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio ss->layer_co = MEM_mallocN(sizeof(float) * 3 * ss->totvert, "sculpt mesh vertices copy"); - if (ss->deform_cos) memcpy(ss->layer_co, ss->deform_cos, ss->totvert); + if (ss->deform_cos) { + memcpy(ss->layer_co, ss->deform_cos, ss->totvert); + } else { for (i = 0; i < ss->totvert; ++i) { copy_v3_v3(ss->layer_co[i], ss->mvert[i].co); @@ -3779,8 +3775,6 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio } } - cache->special_rotation = (brush->flag & BRUSH_RAKE) ? ups->last_angle : 0; - cache->first_time = 1; cache->vertex_rotation = 0; @@ -3793,8 +3787,8 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru SculptSession *ss = ob->sculpt; StrokeCache *cache = ss->cache; float mouse[2] = { - cache->mouse[0] - cache->vc->ar->winrct.xmin, - cache->mouse[1] - cache->vc->ar->winrct.ymin + cache->mouse[0], + cache->mouse[1] }; int tool = brush->sculpt_tool; @@ -3814,8 +3808,6 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru /* compute 3d coordinate at same z from original location + mouse */ mul_v3_m4v3(loc, ob->obmat, cache->orig_grab_location); - initgrabz(cache->vc->rv3d, loc[0], loc[1], loc[2]); - ED_view3d_win_to_3d(cache->vc->ar, loc, mouse, grab_location); /* compute delta to move verts by */ @@ -3853,9 +3845,9 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru copy_v3_v3(cache->old_grab_location, grab_location); if (tool == SCULPT_TOOL_GRAB) - copy_v3_v3(ups->anchored_location, cache->true_location); + copy_v3_v3(cache->anchored_location, cache->true_location); else if (tool == SCULPT_TOOL_THUMB) - copy_v3_v3(ups->anchored_location, cache->orig_grab_location); + copy_v3_v3(cache->anchored_location, cache->orig_grab_location); if (ELEM(tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_THUMB)) { /* location stays the same for finding vertices in brush radius */ @@ -3863,7 +3855,7 @@ static void sculpt_update_brush_delta(UnifiedPaintSettings *ups, Object *ob, Bru ups->draw_anchored = 1; copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - ups->anchored_size = cache->pixel_radius; + ups->anchored_size = ups->pixel_radius; } } } @@ -3898,18 +3890,11 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, * brush coord/pressure/etc. * It's more an events design issue, which doesn't split coordinate/pressure/angle * changing events. We should avoid this after events system re-design */ - if (paint_supports_dynamic_size(brush) || cache->first_time) { + if (paint_supports_dynamic_size(brush, PAINT_SCULPT) || cache->first_time) { cache->pressure = RNA_float_get(ptr, "pressure"); } /* Truly temporary data that isn't stored in properties */ - - ups->draw_pressure = 1; - ups->pressure_value = cache->pressure; - - cache->previous_pixel_radius = cache->pixel_radius; - cache->pixel_radius = BKE_brush_size_get(scene, brush); - if (cache->first_time) { if (!BKE_brush_use_locked_size(scene, brush)) { cache->initial_radius = paint_calc_object_space_radius(cache->vc, @@ -3922,8 +3907,7 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, } } - if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush)) { - cache->pixel_radius *= cache->pressure; + if (BKE_brush_use_size_pressure(scene, brush) && paint_supports_dynamic_size(brush, PAINT_SCULPT)) { cache->radius = cache->initial_radius * cache->pressure; } else { @@ -3932,77 +3916,25 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, cache->radius_squared = cache->radius * cache->radius; - if (!(brush->flag & BRUSH_ANCHORED || - ELEM4(brush->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK, - SCULPT_TOOL_THUMB, SCULPT_TOOL_ROTATE))) - { - copy_v2_v2(cache->tex_mouse, cache->mouse); - - if ((brush->mtex.brush_map_mode == MTEX_MAP_MODE_VIEW) && - (brush->flag & BRUSH_RANDOM_ROTATION) && - !(brush->flag & BRUSH_RAKE)) - { - cache->special_rotation = 2.0f * (float)M_PI * BLI_frand(); - } - } - if (brush->flag & BRUSH_ANCHORED) { - int hit = 0; - - const float dx = cache->mouse[0] - cache->initial_mouse[0]; - const float dy = cache->mouse[1] - cache->initial_mouse[1]; - - ups->anchored_size = cache->pixel_radius = sqrt(dx * dx + dy * dy); - - cache->special_rotation = atan2(dx, dy) + M_PI; - if (brush->flag & BRUSH_EDGE_TO_EDGE) { float halfway[2]; float out[3]; - - halfway[0] = dx * 0.5f + cache->initial_mouse[0]; - halfway[1] = dy * 0.5f + cache->initial_mouse[1]; + halfway[0] = 0.5f * (cache->mouse[0] + cache->initial_mouse[0]); + halfway[1] = 0.5f * (cache->mouse[1] + cache->initial_mouse[1]); if (sculpt_stroke_get_location(C, out, halfway)) { - copy_v3_v3(ups->anchored_location, out); - copy_v2_v2(ups->anchored_initial_mouse, halfway); - copy_v2_v2(cache->tex_mouse, halfway); - copy_v3_v3(cache->true_location, ups->anchored_location); - ups->anchored_size /= 2.0f; - cache->pixel_radius /= 2.0f; - hit = 1; + copy_v3_v3(cache->anchored_location, out); + copy_v3_v3(cache->true_location, cache->anchored_location); } } - if (!hit) - copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - cache->radius = paint_calc_object_space_radius(paint_stroke_view_context(stroke), cache->true_location, - cache->pixel_radius); + ups->pixel_radius); cache->radius_squared = cache->radius * cache->radius; - copy_v3_v3(ups->anchored_location, cache->true_location); - - ups->draw_anchored = 1; - } - else if (brush->flag & BRUSH_RAKE) { - const float u = 0.5f; - const float v = 1 - u; - const float r = 20; - - const float dx = cache->last_rake[0] - cache->mouse[0]; - const float dy = cache->last_rake[1] - cache->mouse[1]; - - if (cache->first_time) { - copy_v2_v2(cache->last_rake, cache->mouse); - } - else if (dx * dx + dy * dy >= r * r) { - cache->special_rotation = atan2(dx, dy); - - cache->last_rake[0] = u * cache->last_rake[0] + v * cache->mouse[0]; - cache->last_rake[1] = u * cache->last_rake[1] + v * cache->mouse[1]; - } + copy_v3_v3(cache->anchored_location, cache->true_location); } sculpt_update_brush_delta(ups, ob, brush); @@ -4015,14 +3947,14 @@ static void sculpt_update_cache_variants(bContext *C, Sculpt *sd, Object *ob, ups->draw_anchored = 1; copy_v2_v2(ups->anchored_initial_mouse, cache->initial_mouse); - copy_v3_v3(ups->anchored_location, cache->true_location); - ups->anchored_size = cache->pixel_radius; + copy_v3_v3(cache->anchored_location, cache->true_location); + ups->anchored_size = ups->pixel_radius; } - ups->special_rotation = cache->special_rotation; + cache->special_rotation = ups->brush_rotation; } -/* Returns true iff any of the smoothing modes are active (currently +/* Returns true if any of the smoothing modes are active (currently * one of smooth brush, autosmooth, mask smooth, or shift-key * smooth) */ static int sculpt_any_smooth_mode(const Brush *brush, @@ -4098,7 +4030,6 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) StrokeCache *cache; float ray_start[3], ray_end[3], ray_normal[3], dist; float obimat[4][4]; - float mval[2]; SculptRaycastData srd; view3d_set_viewcontext(C, &vc); @@ -4109,11 +4040,8 @@ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]) sculpt_stroke_modifiers_check(C, ob); - mval[0] = mouse[0] - vc.ar->winrct.xmin; - mval[1] = mouse[1] - vc.ar->winrct.ymin; - /* TODO: what if the segment is totally clipped? (return == 0) */ - ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mval, ray_start, ray_end); + ED_view3d_win_to_segment_clip(vc.ar, vc.v3d, mouse, ray_start, ray_end); invert_m4_m4(obimat, ob->obmat); mul_m4_v3(obimat, ray_start); @@ -4279,6 +4207,7 @@ static int sculpt_stroke_test_start(bContext *C, struct wmOperator *op, static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, PointerRNA *itemptr) { + UnifiedPaintSettings *ups = &CTX_data_tool_settings(C)->unified_paint_settings; Sculpt *sd = CTX_data_tool_settings(C)->sculpt; Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -4289,9 +4218,9 @@ static void sculpt_stroke_update_step(bContext *C, struct PaintStroke *stroke, P sculpt_restore_mesh(sd, ob); BKE_pbvh_bmesh_detail_size_set(ss->pbvh, - (ss->cache->radius / - (float)ss->cache->pixel_radius) * - (float)sd->detail_size); + (ss->cache->radius / + (float)ups->pixel_radius) * + (float)sd->detail_size); if (sculpt_stroke_dynamic_topology(ss, brush)) { do_symmetrical_brush_actions(sd, ob, sculpt_topology_update); @@ -4335,7 +4264,6 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str /* reset values used to draw brush after completing the stroke */ ups->draw_anchored = 0; ups->draw_pressure = 0; - ups->special_rotation = 0; /* Finished */ if (ss->cache) { @@ -4390,7 +4318,7 @@ static void sculpt_stroke_done(const bContext *C, struct PaintStroke *UNUSED(str sculpt_brush_exit_tex(sd); } -static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event) { struct PaintStroke *stroke; int ignore_background_click; @@ -4407,8 +4335,7 @@ static int sculpt_brush_stroke_invoke(bContext *C, wmOperator *op, wmEvent *even op->customdata = stroke; /* For tablet rotation */ - ignore_background_click = RNA_boolean_get(op->ptr, - "ignore_background_click"); + ignore_background_click = RNA_boolean_get(op->ptr, "ignore_background_click"); if (ignore_background_click && !over_mesh(C, op, event->x, event->y)) { paint_stroke_data_free(op); @@ -4487,8 +4414,7 @@ static void SCULPT_OT_brush_stroke(wmOperatorType *ot) /* properties */ - RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, - "Stroke", ""); + RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_enum(ot->srna, "mode", stroke_mode_items, BRUSH_STROKE_NORMAL, "Sculpt Stroke Mode", @@ -4570,7 +4496,7 @@ void sculpt_dynamic_topology_enable(bContext *C) sculpt_pbvh_clear(ob); ss->bm_smooth_shading = (scene->toolsettings->sculpt->flags & - SCULPT_DYNTOPO_SMOOTH_SHADING); + SCULPT_DYNTOPO_SMOOTH_SHADING); /* Create triangles-only BMesh */ ss->bm = BM_mesh_create(&bm_mesh_allocsize_default); @@ -4596,7 +4522,7 @@ void sculpt_dynamic_topology_enable(bContext *C) * If 'unode' is given, the BMesh's data is copied out to the unode * before the BMesh is deleted so that it can be restored from */ void sculpt_dynamic_topology_disable(bContext *C, - SculptUndoNode *unode) + SculptUndoNode *unode) { Object *ob = CTX_data_active_object(C); SculptSession *ss = ob->sculpt; @@ -4619,13 +4545,13 @@ void sculpt_dynamic_topology_disable(bContext *C, me->totedge = unode->bm_enter_totedge; me->totface = 0; CustomData_copy(&unode->bm_enter_vdata, &me->vdata, CD_MASK_MESH, - CD_DUPLICATE, unode->bm_enter_totvert); + CD_DUPLICATE, unode->bm_enter_totvert); CustomData_copy(&unode->bm_enter_edata, &me->edata, CD_MASK_MESH, - CD_DUPLICATE, unode->bm_enter_totedge); + CD_DUPLICATE, unode->bm_enter_totedge); CustomData_copy(&unode->bm_enter_ldata, &me->ldata, CD_MASK_MESH, - CD_DUPLICATE, unode->bm_enter_totloop); + CD_DUPLICATE, unode->bm_enter_totloop); CustomData_copy(&unode->bm_enter_pdata, &me->pdata, CD_MASK_MESH, - CD_DUPLICATE, unode->bm_enter_totpoly); + CD_DUPLICATE, unode->bm_enter_totpoly); mesh_update_customdata_pointers(me, FALSE); } @@ -4665,28 +4591,23 @@ static int sculpt_dynamic_topology_toggle_exec(bContext *C, wmOperator *UNUSED(o return OPERATOR_FINISHED; } -static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, - wmEvent *UNUSED(event)) +static int sculpt_dynamic_topology_toggle_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *ob = CTX_data_active_object(C); Mesh *me = ob->data; SculptSession *ss = ob->sculpt; - const char *msg = "Dynamic-topology sculpting will not preserve" - "vertex colors, UVs, or other customdata"; + const char *msg = TIP_("Dynamic-topology sculpting will not preserve vertex colors, UVs, or other customdata"); if (!ss->bm) { int i; for (i = 0; i < CD_NUMTYPES; i++) { - if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE, - CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, - CD_ORIGINDEX) && + if (!ELEM7(i, CD_MVERT, CD_MEDGE, CD_MFACE, CD_MLOOP, CD_MPOLY, CD_PAINT_MASK, CD_ORIGINDEX) && (CustomData_has_layer(&me->vdata, i) || CustomData_has_layer(&me->edata, i) || CustomData_has_layer(&me->fdata, i))) { - /* The mesh has customdata that will be lost, let the - * user confirm this is OK */ + /* The mesh has customdata that will be lost, let the user confirm this is OK */ return WM_operator_confirm_message(C, op, msg); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index fa1bdd6ca82..82a07c9e3be 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -62,9 +62,6 @@ int sculpt_poll(struct bContext *C); void sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob, int need_pmap, int need_mask); -/* Deformed mesh sculpt */ -void free_sculptsession_deformMats(struct SculptSession *ss); - /* Stroke */ int sculpt_stroke_get_location(bContext *C, float out[3], const float mouse[2]); diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 406756f4197..2cc09ea2aa9 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -131,7 +131,9 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo vertCos = BKE_key_convert_to_vertcos(ob, ss->kb); for (i = 0; i < unode->totvert; i++) { - if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); + if (ss->modifiers_active) { + sculpt_undo_restore_deformed(ss, unode, i, index[i], vertCos[index[i]]); + } else { if (unode->orig_co) swap_v3_v3(vertCos[index[i]], unode->orig_co[i]); else swap_v3_v3(vertCos[index[i]], unode->co[i]); @@ -149,7 +151,9 @@ static int sculpt_undo_restore_coords(bContext *C, DerivedMesh *dm, SculptUndoNo } else { for (i = 0; i < unode->totvert; i++) { - if (ss->modifiers_active) sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co); + if (ss->modifiers_active) { + sculpt_undo_restore_deformed(ss, unode, i, index[i], mvert[index[i]].co); + } else { if (unode->orig_co) swap_v3_v3(mvert[index[i]].co, unode->orig_co[i]); else swap_v3_v3(mvert[index[i]].co, unode->co[i]); @@ -263,8 +267,8 @@ static int sculpt_undo_restore_mask(bContext *C, DerivedMesh *dm, SculptUndoNode } static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, - Object *ob, - SculptSession *ss) + Object *ob, + SculptSession *ss) { if (unode->applied) { BM_log_undo(ss->bm, ss->bm_log); @@ -282,7 +286,7 @@ static void sculpt_undo_bmesh_restore_generic(SculptUndoNode *unode, /* Create empty sculpt BMesh and enable logging */ static void sculpt_undo_bmesh_enable(Object *ob, - SculptUndoNode *unode) + SculptUndoNode *unode) { SculptSession *ss = ob->sculpt; Mesh *me = ob->data; @@ -296,13 +300,13 @@ static void sculpt_undo_bmesh_enable(Object *ob, /* Restore the BMLog using saved entries */ ss->bm_log = BM_log_from_existing_entries_create(ss->bm, - unode->bm_entry); + unode->bm_entry); } static void sculpt_undo_bmesh_restore_begin(bContext *C, - SculptUndoNode *unode, - Object *ob, - SculptSession *ss) + SculptUndoNode *unode, + Object *ob, + SculptSession *ss) { if (unode->applied) { sculpt_dynamic_topology_disable(C, unode); @@ -319,9 +323,9 @@ static void sculpt_undo_bmesh_restore_begin(bContext *C, } static void sculpt_undo_bmesh_restore_end(bContext *C, - SculptUndoNode *unode, - Object *ob, - SculptSession *ss) + SculptUndoNode *unode, + Object *ob, + SculptSession *ss) { if (unode->applied) { sculpt_undo_bmesh_enable(ob, unode); @@ -343,9 +347,9 @@ static void sculpt_undo_bmesh_restore_end(bContext *C, * Returns TRUE if this was a dynamic-topology undo step, otherwise * returns FALSE to indicate the non-dyntopo code should run. */ static int sculpt_undo_bmesh_restore(bContext *C, - SculptUndoNode *unode, - Object *ob, - SculptSession *ss) + SculptUndoNode *unode, + Object *ob, + SculptSession *ss) { switch (unode->type) { case SCULPT_UNDO_DYNTOPO_BEGIN: @@ -375,7 +379,6 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) DerivedMesh *dm; SculptSession *ss = ob->sculpt; SculptUndoNode *unode; - MultiresModifierData *mmd; int update = FALSE, rebuild = FALSE; int need_mask = FALSE; @@ -446,7 +449,7 @@ static void sculpt_undo_restore(bContext *C, ListBase *lb) BKE_pbvh_search_callback(ss->pbvh, NULL, NULL, update_cb, &rebuild); BKE_pbvh_update(ss->pbvh, PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw, NULL); - if ((mmd = sculpt_multires_active(scene, ob))) { + if (sculpt_multires_active(scene, ob)) { if (rebuild) multires_mark_as_modified(ob, MULTIRES_HIDDEN_MODIFIED); else @@ -563,7 +566,7 @@ static SculptUndoNode *sculpt_undo_alloc_node(Object *ob, PBVHNode *node, if (node) { BKE_pbvh_node_num_verts(ss->pbvh, node, &totvert, &allvert); BKE_pbvh_node_get_grids(ss->pbvh, node, &grids, &totgrid, - &maxgrid, &gridsize, NULL, NULL); + &maxgrid, &gridsize, NULL, NULL); unode->totvert = totvert; } @@ -673,8 +676,8 @@ static void sculpt_undo_store_mask(Object *ob, SculptUndoNode *unode) } static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, - PBVHNode *node, - SculptUndoType type) + PBVHNode *node, + SculptUndoType type) { ListBase *lb = undo_paint_push_get_list(UNDO_PAINT_MESH); SculptUndoNode *unode = lb->first; @@ -701,13 +704,13 @@ static SculptUndoNode *sculpt_undo_bmesh_push(Object *ob, * (converting polys to triangles) that the BMLog can't * fully restore from */ CustomData_copy(&me->vdata, &unode->bm_enter_vdata, CD_MASK_MESH, - CD_DUPLICATE, me->totvert); + CD_DUPLICATE, me->totvert); CustomData_copy(&me->edata, &unode->bm_enter_edata, CD_MASK_MESH, - CD_DUPLICATE, me->totedge); + CD_DUPLICATE, me->totedge); CustomData_copy(&me->ldata, &unode->bm_enter_ldata, CD_MASK_MESH, - CD_DUPLICATE, me->totloop); + CD_DUPLICATE, me->totloop); CustomData_copy(&me->pdata, &unode->bm_enter_pdata, CD_MASK_MESH, - CD_DUPLICATE, me->totpoly); + CD_DUPLICATE, me->totpoly); unode->bm_enter_totvert = me->totvert; unode->bm_enter_totedge = me->totedge; unode->bm_enter_totloop = me->totloop; @@ -756,9 +759,9 @@ SculptUndoNode *sculpt_undo_push_node(Object *ob, PBVHNode *node, BLI_lock_thread(LOCK_CUSTOM1); if (ss->bm || - ELEM(type, - SCULPT_UNDO_DYNTOPO_BEGIN, - SCULPT_UNDO_DYNTOPO_END)) + ELEM(type, + SCULPT_UNDO_DYNTOPO_BEGIN, + SCULPT_UNDO_DYNTOPO_END)) { /* Dynamic topology stores only one undo node per stroke, * regardless of the number of PBVH nodes modified */ diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 0bcccd9479c..7cdfb6d22b2 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -144,6 +144,69 @@ typedef struct UvSculptData { char invert; } UvSculptData; + +static Brush *uv_sculpt_brush(bContext *C) +{ + Scene *scene = CTX_data_scene(C); + ToolSettings *settings = scene->toolsettings; + + if (!settings->uvsculpt) + return NULL; + return paint_brush(&settings->uvsculpt->paint); +} + + +static int uv_sculpt_brush_poll(bContext *C) +{ + BMEditMesh *em; + int ret; + Object *obedit = CTX_data_edit_object(C); + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + ToolSettings *toolsettings = scene->toolsettings; + + if (!uv_sculpt_brush(C) || !obedit || obedit->type != OB_MESH) + return 0; + + em = BMEdit_FromObject(obedit); + ret = EDBM_mtexpoly_check(em); + + if (ret && sima) { + ARegion *ar = CTX_wm_region(C); + if ((toolsettings->use_uv_sculpt) && ar->regiontype == RGN_TYPE_WINDOW) + return 1; + } + + return 0; +} + + +void ED_space_image_uv_sculpt_update(wmWindowManager *wm, ToolSettings *settings) +{ + if (settings->use_uv_sculpt) { + if (!settings->uvsculpt) { + settings->uvsculpt = MEM_callocN(sizeof(*settings->uvsculpt), "UV Smooth paint"); + settings->uv_sculpt_tool = UV_SCULPT_TOOL_GRAB; + settings->uv_sculpt_settings = UV_SCULPT_LOCK_BORDERS | UV_SCULPT_ALL_ISLANDS; + settings->uv_relax_method = UV_SCULPT_TOOL_RELAX_LAPLACIAN; + } + + BKE_paint_init(&settings->uvsculpt->paint, PAINT_CURSOR_SCULPT); + + WM_paint_cursor_activate(wm, uv_sculpt_brush_poll, + brush_drawcursor_texpaint_uvsculpt, NULL); + } + else { + if (settings->uvsculpt) + settings->uvsculpt->paint.flags &= ~PAINT_SHOW_BRUSH; + } +} + +int uv_sculpt_poll(bContext *C) +{ + return uv_sculpt_brush_poll(C); +} + /*********** Improved Laplacian Relaxation Operator ************************/ /* original code by Raul Fernandez Hernandez "farsthary" * * adapted to uv smoothing by Antony Riakiatakis * @@ -294,7 +357,7 @@ static void laplacian_relaxation_iteration_uv(BMEditMesh *em, UvSculptData *scul } -static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, wmEvent *event, Object *obedit) +static void uv_sculpt_stroke_apply(bContext *C, wmOperator *op, const wmEvent *event, Object *obedit) { float co[2], radius, radius_root; Scene *scene = CTX_data_scene(C); @@ -464,7 +527,7 @@ static int uv_edge_compare(const void *a, const void *b) } -static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent *event) +static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); @@ -649,7 +712,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent return NULL; } /* fill the edges with data */ - for (i = 0; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) { + for (i = 0; BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) { data->uvedges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi)); } data->totalUvEdges = BLI_ghash_size(edgeHash); @@ -731,7 +794,7 @@ static UvSculptData *uv_sculpt_stroke_init(bContext *C, wmOperator *op, wmEvent return op->customdata; } -static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, const wmEvent *event) { UvSculptData *data; Object *obedit = CTX_data_edit_object(C); @@ -754,7 +817,7 @@ static int uv_sculpt_stroke_invoke(bContext *C, wmOperator *op, wmEvent *event) } -static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) +static int uv_sculpt_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) { UvSculptData *data = (UvSculptData *)op->customdata; Object *obedit = CTX_data_edit_object(C); diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index eb138bfeeef..d25fd00514c 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -160,7 +160,7 @@ static int sound_open_exec(bContext *UNUSED(C), wmOperator *op) #endif -static int sound_open_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sound_open_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (RNA_struct_property_is_set(op->ptr, "filepath")) return sound_open_exec(C, op); @@ -439,7 +439,7 @@ static int sound_mixdown_check(bContext *UNUSED(C), wmOperator *op) #endif // WITH_AUDASPACE -static int sound_mixdown_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sound_mixdown_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (RNA_struct_property_is_set(op->ptr, "filepath")) return sound_mixdown_exec(C, op); @@ -747,7 +747,7 @@ static int sound_unpack_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sound_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sound_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Editing *ed = CTX_data_scene(C)->ed; bSound *sound; diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 7e99e6c065d..803e7b71c77 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -742,7 +742,7 @@ static int actkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int actkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { actkeys_duplicate_exec(C, op); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 964a6a20c37..b6d2d31f0ad 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -872,7 +872,7 @@ static int actkeys_select_leftright_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int actkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; short leftright = RNA_enum_get(op->ptr, "mode"); @@ -1223,7 +1223,7 @@ static void mouse_action_keys(bAnimContext *ac, const int mval[2], short select_ } /* handle clicking */ -static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int actkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; /* ARegion *ar; */ /* UNUSED */ @@ -1264,16 +1264,17 @@ void ACTION_OT_clickselect(wmOperatorType *ot) ot->idname = "ACTION_OT_clickselect"; ot->description = "Select keyframes by clicking on them"; - /* api callbacks - absolutely no exec() this yet... */ + /* callbacks */ ot->invoke = actkeys_clickselect_invoke; ot->poll = ED_operator_action_active; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* properties */ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "column", 0, "Column Select", ""); // ALTKEY RNA_def_property_flag(prop, PROP_SKIP_SAVE); } diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c index 8b6682ff1c9..dcc61cfa544 100644 --- a/source/blender/editors/space_buttons/buttons_ops.c +++ b/source/blender/editors/space_buttons/buttons_ops.c @@ -35,10 +35,10 @@ #include "DNA_userdef_types.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_path_util.h" #include "BLI_string.h" -#include "BLI_utildefines.h" #include "BLF_translation.h" @@ -62,7 +62,7 @@ /********************** toolbox operator *********************/ -static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int toolbox_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { bScreen *sc = CTX_wm_screen(C); SpaceButs *sbuts = CTX_wm_space_buts(C); @@ -113,7 +113,6 @@ static int file_browse_exec(bContext *C, wmOperator *op) /* add slash for directories, important for some properties */ if (RNA_property_subtype(fbo->prop) == PROP_DIRPATH) { - char name[FILE_MAX]; int is_relative = RNA_boolean_get(op->ptr, "relative_path"); id = fbo->ptr.id.data; @@ -132,8 +131,10 @@ static int file_browse_exec(bContext *C, wmOperator *op) } BLI_add_slash(str); } - else - BLI_splitdirstring(str, name); + else { + char * const lslash = (char *)BLI_last_slash(str); + if (lslash) lslash[1] = '\0'; + } } RNA_property_string_set(&fbo->ptr, fbo->prop, str); @@ -164,7 +165,7 @@ static int file_browse_cancel(bContext *UNUSED(C), wmOperator *op) return OPERATOR_CANCELLED; } -static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event) { PointerRNA ptr; PropertyRNA *prop; @@ -189,7 +190,7 @@ static int file_browse_invoke(bContext *C, wmOperator *op, wmEvent *event) PointerRNA props_ptr; if (event->alt) { - char *lslash = BLI_last_slash(str); + char *lslash = (char *)BLI_last_slash(str); if (lslash) *lslash = '\0'; } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 16d194d0929..1643921e4dd 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -404,7 +404,7 @@ void uiTemplateTextureUser(uiLayout *layout, bContext *C) } /* create button */ - BLI_snprintf(name, UI_MAX_NAME_STR, "%s", user->name); + BLI_strncpy(name, user->name, UI_MAX_NAME_STR); if (user->icon) { but = uiDefIconTextMenuBut(block, template_texture_user_menu, NULL, diff --git a/source/blender/editors/space_clip/SConscript b/source/blender/editors/space_clip/SConscript index c65a076186f..840a3b49f2b 100644 --- a/source/blender/editors/space_clip/SConscript +++ b/source/blender/editors/space_clip/SConscript @@ -34,5 +34,8 @@ incs += ' ../../makesrna ../../windowmanager #/intern/guardedalloc #/extern/glew if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') + +if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): + incs += ' ' + env['BF_PTHREADS_INC'] env.BlenderLib ( 'bf_editors_space_clip', sources, Split(incs), defs, libtype=['core'], priority=[95] ) diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index 09f6271b6ef..e5cd7247c43 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -59,12 +59,11 @@ #include "clip_intern.h" // own include -#if 0 -static int ED_space_clip_dopesheet_poll(bContext *C) +static int space_clip_dopesheet_poll(bContext *C) { - SpaceClip *sc = CTX_wm_space_clip(C); + if (ED_space_clip_tracking_poll(C)) { + SpaceClip *sc = CTX_wm_space_clip(C); - if (sc && sc->clip) { if (sc->view == SC_VIEW_DOPESHEET) { ARegion *ar = CTX_wm_region(C); @@ -74,7 +73,6 @@ static int ED_space_clip_dopesheet_poll(bContext *C) return FALSE; } -#endif /********************** select channel operator *********************/ @@ -129,7 +127,7 @@ static int dopesheet_select_channel_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int dopesheet_select_channel_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float location[2]; @@ -161,3 +159,54 @@ void CLIP_OT_dopesheet_select_channel(wmOperatorType *ot) RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection rather than clearing the existing selection"); } + +/********************** View All operator *********************/ + +static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + ARegion *ar = CTX_wm_region(C); + View2D *v2d = &ar->v2d; + MovieClip *clip = ED_space_clip_get_clip(sc); + MovieTracking *tracking = &clip->tracking; + MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; + MovieTrackingDopesheetChannel *channel; + int frame_min = INT_MAX, frame_max = INT_MIN; + + for (channel = dopesheet->channels.first; channel; channel = channel->next) { + frame_min = min_ii(frame_min, channel->segments[0]); + frame_max = max_ii(frame_max, channel->segments[channel->tot_segment]); + } + + if (frame_min < frame_max) { + float extra; + + v2d->cur.xmin = frame_min; + v2d->cur.xmax = frame_max; + + /* we need an extra "buffer" factor on either side so that the endpoints are visible */ + extra = 0.01f * BLI_rctf_size_x(&v2d->cur); + v2d->cur.xmin -= extra; + v2d->cur.xmax += extra; + + ED_region_tag_redraw(ar); + } + + + return OPERATOR_FINISHED; +} + +void CLIP_OT_dopesheet_view_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View All"; + ot->description = "Reset viewable area to show full keyframe range"; + ot->idname = "CLIP_OT_dopesheet_view_all"; + + /* api callbacks */ + ot->exec = dopesheet_view_all_exec; + ot->poll = space_clip_dopesheet_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index 56f2998b047..58626c79363 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -944,7 +944,7 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra if (state[0]) BLI_snprintf(str, sizeof(str), "%s: %s", track->name, state); else - BLI_snprintf(str, sizeof(str), "%s", track->name); + BLI_strncpy(str, track->name, sizeof(str)); BLF_position(fontid, pos[0], pos[1], 0.0f); BLF_draw(fontid, str, sizeof(str)); diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index fa235bd2997..edc6ac1ecf7 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -276,7 +276,7 @@ static int select_exec(bContext *C, wmOperator *op) return mouse_select(C, co, extend); } -static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float co[2]; diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 432032e9dbf..cd7da4229d2 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -67,6 +67,7 @@ void clip_draw_dopesheet_channels(const struct bContext *C, struct ARegion *ar); /* clip_dopesheet_ops.c */ void CLIP_OT_dopesheet_select_channel(struct wmOperatorType *ot); +void CLIP_OT_dopesheet_view_all(struct wmOperatorType *ot); /* clip_draw.c */ void clip_draw_main(const struct bContext *C, struct SpaceClip *sc, struct ARegion *ar); @@ -133,7 +134,7 @@ void clip_draw_cfra(struct SpaceClip *sc, struct ARegion *ar, struct Scene *scen void clip_draw_sfra_efra(struct View2D *v2d, struct Scene *scene); /* tracking_ops.c */ -struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, struct wmEvent *event, +struct MovieTrackingTrack *tracking_marker_check_slide(struct bContext *C, const struct wmEvent *event, int *area_r, int *action_r, int *corner_r); void CLIP_OT_add_marker(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index dfb69be6f18..914eb9526a8 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -30,16 +30,26 @@ */ #include <errno.h> +#include <sys/types.h> +#include <fcntl.h> + +#ifndef WIN32 +# include <unistd.h> +#else +# include <io.h> +#endif #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" #include "DNA_scene_types.h" /* min/max frames */ -#include "BLI_path_util.h" #include "BLI_utildefines.h" +#include "BLI_fileops.h" +#include "BLI_path_util.h" #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_threads.h" #include "BLF_translation.h" @@ -113,7 +123,7 @@ static void sclip_zoom_set_factor(const bContext *C, float zoomfac, float locati sclip_zoom_set(C, sc->zoom * zoomfac, location); } -static void sclip_zoom_set_factor_exec(bContext *C, wmEvent *event, float factor) +static void sclip_zoom_set_factor_exec(bContext *C, const wmEvent *event, float factor) { ARegion *ar = CTX_wm_region(C); @@ -230,7 +240,7 @@ static int open_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceClip *sc = CTX_wm_space_clip(C); char path[FILE_MAX]; @@ -318,7 +328,7 @@ typedef struct ViewPanData { float *vec; } ViewPanData; -static void view_pan_init(bContext *C, wmOperator *op, wmEvent *event) +static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ViewPanData *vpd; @@ -377,7 +387,7 @@ static int view_pan_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type == MOUSEPAN) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -399,7 +409,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) } } -static int view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) +static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ViewPanData *vpd = op->customdata; @@ -471,7 +481,7 @@ typedef struct ViewZoomData { float location[2]; } ViewZoomData; -static void view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) +static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -514,7 +524,7 @@ static int view_zoom_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type == MOUSEZOOM || event->type == MOUSEPAN) { float delta, factor; @@ -538,7 +548,7 @@ static int view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) } } -static int view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewZoomData *vpd = op->customdata; float delta, factor; @@ -611,7 +621,7 @@ static int view_zoom_in_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -654,7 +664,7 @@ static int view_zoom_out_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -844,7 +854,7 @@ static int change_frame_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int frame_from_event(bContext *C, wmEvent *event) +static int frame_from_event(bContext *C, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -866,7 +876,7 @@ static int frame_from_event(bContext *C, wmEvent *event) return framenr; } -static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); @@ -885,7 +895,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int change_frame_modal(bContext *C, wmOperator *op, wmEvent *event) +static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case ESCKEY: @@ -971,46 +981,39 @@ static int proxy_bitflag_to_array(int size_flag, int build_sizes[4], int undisto return build_count; } -/* only this runs inside thread */ -static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress) +/* simple case for movies -- handle frame-by-frame, do threading within single frame */ +static void do_movie_proxy(void *pjv, int *UNUSED(build_sizes), int UNUSED(build_count), + int *build_undistort_sizes, int build_undistort_count, + short *stop, short *do_update, float *progress) { ProxyJob *pj = pjv; Scene *scene = pj->scene; MovieClip *clip = pj->clip; struct MovieDistortion *distortion = NULL; - short size_flag; int cfra, sfra = SFRA, efra = EFRA; - int build_sizes[4], build_count = 0; - int build_undistort_sizes[4], build_undistort_count = 0; - size_flag = clip->proxy.build_size_flag; - - build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0); - build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1); - - if (clip->source == MCLIP_SRC_MOVIE) { - if (pj->index_context) - IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress); + if (pj->index_context) + IMB_anim_index_rebuild(pj->index_context, stop, do_update, progress); - if (!build_undistort_count) { - if (*stop) - pj->stop = 1; + if (!build_undistort_count) { + if (*stop) + pj->stop = 1; - return; - } - else { - sfra = 1; - efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE); - } + return; } + else { + sfra = 1; + efra = IMB_anim_get_duration(clip->anim, IMB_TC_NONE); + } + + if (build_undistort_count) { + int threads = BLI_system_thread_count(); - if (build_undistort_count) distortion = BKE_tracking_distortion_new(); + BKE_tracking_distortion_set_threads(distortion, threads); + } for (cfra = sfra; cfra <= efra; cfra++) { - if (clip->source != MCLIP_SRC_MOVIE) - BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, NULL, cfra, build_sizes, build_count, 0); - BKE_movieclip_build_proxy_frame(clip, pj->clip_flag, distortion, cfra, build_undistort_sizes, build_undistort_count, 1); @@ -1028,6 +1031,193 @@ static void proxy_startjob(void *pjv, short *stop, short *do_update, float *prog pj->stop = 1; } +/* ***** + * special case for sequences -- handle different frames in different threads, + * loading from disk happens in critical section, decoding frame happens from + * thread for maximal speed + */ + +typedef struct ProxyQueue { + int cfra; + int sfra; + int efra; + SpinLock spin; + + short *stop; + short *do_update; + float *progress; +} ProxyQueue; + +typedef struct ProxyThread { + MovieClip *clip; + ProxyQueue *queue; + + struct MovieDistortion *distortion; + + int *build_sizes, build_count; + int *build_undistort_sizes, build_undistort_count; +} ProxyThread; + +static unsigned char *proxy_thread_next_frame(ProxyQueue *queue, MovieClip *clip, size_t *size_r, int *cfra_r) +{ + unsigned char *mem = NULL; + + BLI_spin_lock(&queue->spin); + if (!*queue->stop && queue->cfra <= queue->efra) { + char name[FILE_MAX]; + size_t size; + int file; + + BKE_movieclip_filename_for_frame(clip, queue->cfra, name); + + file = open(name, O_BINARY | O_RDONLY, 0); + if (file < 0) { + BLI_spin_unlock(&queue->spin); + return NULL; + } + + size = BLI_file_descriptor_size(file); + if (size < 1) { + close(file); + BLI_spin_unlock(&queue->spin); + return NULL; + } + + mem = MEM_mallocN(size, "movieclip proxy memory file"); + + if (read(file, mem, size) != size) { + close(file); + BLI_spin_unlock(&queue->spin); + MEM_freeN(mem); + return NULL; + } + + *size_r = size; + *cfra_r = queue->cfra; + + queue->cfra++; + close(file); + + *queue->do_update = 1; + *queue->progress = (float)(queue->cfra - queue->sfra) / (queue->efra - queue->sfra); + } + BLI_spin_unlock(&queue->spin); + + return mem; +} + +static void *do_proxy_thread(void *data_v) +{ + ProxyThread *data = (ProxyThread *) data_v; + unsigned char *mem; + size_t size; + int cfra; + + while ((mem = proxy_thread_next_frame(data->queue, data->clip, &size, &cfra))) { + ImBuf *ibuf; + + ibuf = IMB_ibImageFromMemory(mem, size, IB_rect | IB_multilayer | IB_alphamode_detect, NULL, "proxy frame"); + + BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, NULL, cfra, + data->build_sizes, data->build_count, FALSE); + + BKE_movieclip_build_proxy_frame_for_ibuf(data->clip, ibuf, data->distortion, cfra, + data->build_undistort_sizes, data->build_undistort_count, TRUE); + + IMB_freeImBuf(ibuf); + + MEM_freeN(mem); + } + + return NULL; +} + +static void do_sequence_proxy(void *pjv, int *build_sizes, int build_count, + int *build_undistort_sizes, int build_undistort_count, + short *stop, short *do_update, float *progress) +{ + ProxyJob *pj = pjv; + MovieClip *clip = pj->clip; + Scene *scene = pj->scene; + int sfra = SFRA, efra = EFRA; + ProxyThread *handles; + ListBase threads; + int i, tot_thread = BLI_system_thread_count(); + ProxyQueue queue; + + BLI_spin_init(&queue.spin); + + queue.cfra = sfra; + queue.sfra = sfra; + queue.efra = efra; + queue.stop = stop; + queue.do_update = do_update; + queue.progress = progress; + + handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles"); + + if (tot_thread > 1) + BLI_init_threads(&threads, do_proxy_thread, tot_thread); + + for (i = 0; i < tot_thread; i++) { + ProxyThread *handle = &handles[i]; + + handle->clip = clip; + handle->queue = &queue; + + handle->build_count = build_count; + handle->build_sizes = build_sizes; + + handle->build_undistort_count = build_undistort_count; + handle->build_undistort_sizes = build_undistort_sizes; + + if (build_undistort_count) + handle->distortion = BKE_tracking_distortion_new(); + + if (tot_thread > 1) + BLI_insert_thread(&threads, handle); + } + + if (tot_thread > 1) + BLI_end_threads(&threads); + else + do_proxy_thread(handles); + + MEM_freeN(handles); + + if (build_undistort_count) { + for (i = 0; i < tot_thread; i++) { + ProxyThread *handle = &handles[i]; + + BKE_tracking_distortion_free(handle->distortion); + } + } +} + +static void proxy_startjob(void *pjv, short *stop, short *do_update, float *progress) +{ + ProxyJob *pj = pjv; + MovieClip *clip = pj->clip; + + short size_flag; + int build_sizes[4], build_count = 0; + int build_undistort_sizes[4], build_undistort_count = 0; + + size_flag = clip->proxy.build_size_flag; + + build_count = proxy_bitflag_to_array(size_flag, build_sizes, 0); + build_undistort_count = proxy_bitflag_to_array(size_flag, build_undistort_sizes, 1); + + if (clip->source == MCLIP_SRC_MOVIE) { + do_movie_proxy(pjv, build_sizes, build_count, build_undistort_sizes, + build_undistort_count, stop, do_update, progress); + } + else { + do_sequence_proxy(pjv, build_sizes, build_count, build_undistort_sizes, + build_undistort_count, stop, do_update, progress); + } +} + static void proxy_endjob(void *pjv) { ProxyJob *pj = pjv; @@ -1134,7 +1324,7 @@ void CLIP_OT_mode_set(wmOperatorType *ot) * that explains the negative signs in the code below */ -static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int clip_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { if (event->type != NDOF_MOTION) return OPERATOR_CANCELLED; diff --git a/source/blender/editors/space_clip/clip_toolbar.c b/source/blender/editors/space_clip/clip_toolbar.c index 7543988b5aa..10175d07300 100644 --- a/source/blender/editors/space_clip/clip_toolbar.c +++ b/source/blender/editors/space_clip/clip_toolbar.c @@ -33,8 +33,6 @@ #include "DNA_windowmanager_types.h" -#include "RNA_access.h" - #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" @@ -45,12 +43,14 @@ #include "BKE_context.h" #include "BKE_screen.h" -#include "ED_screen.h" -#include "ED_util.h" +#include "RNA_access.h" #include "WM_types.h" #include "WM_api.h" +#include "ED_screen.h" +#include "ED_util.h" + #include "UI_interface.h" #include "UI_resources.h" diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index f0c0e7b72fd..4f9757a6640 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -534,6 +534,7 @@ static void clip_operatortypes(void) /* ** clip_dopesheet_ops.c ** */ WM_operatortype_append(CLIP_OT_dopesheet_select_channel); + WM_operatortype_append(CLIP_OT_dopesheet_view_all); } static void clip_keymap(struct wmKeyConfig *keyconf) @@ -768,6 +769,8 @@ static void clip_keymap(struct wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_select_channel", ACTIONMOUSE, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "extend", TRUE); /* toggle */ + + WM_keymap_add_item(keymap, "CLIP_OT_dopesheet_view_all", HOMEKEY, KM_PRESS, 0, 0); } const char *clip_context_dir[] = {"edit_movieclip", "edit_mask", NULL}; @@ -796,7 +799,7 @@ static int clip_context(const bContext *C, const char *member, bContextDataResul } /* dropboxes */ -static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int clip_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */ @@ -1191,6 +1194,9 @@ static void clip_preview_area_init(wmWindowManager *wm, ARegion *ar) keymap = WM_keymap_find(wm->defaultconf, "Clip Graph Editor", SPACE_CLIP, 0); WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); + + keymap = WM_keymap_find(wm->defaultconf, "Clip Dopesheet Editor", SPACE_CLIP, 0); + WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); } static void graph_area_draw(const bContext *C, ARegion *ar) diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index ac7ebd9ddac..a51315d9a16 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -124,7 +124,7 @@ static int add_marker_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int add_marker_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int add_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -282,7 +282,7 @@ static void slide_marker_tilt_slider(MovieTrackingMarker *marker, float slider[2 } static SlideMarkerData *create_slide_marker_data(SpaceClip *sc, MovieTrackingTrack *track, - MovieTrackingMarker *marker, wmEvent *event, + MovieTrackingMarker *marker, const wmEvent *event, int area, int corner, int action, int width, int height) { SlideMarkerData *data = MEM_callocN(sizeof(SlideMarkerData), "slide marker data"); @@ -524,7 +524,7 @@ static void show_cursor(bContext *C) WM_cursor_set(win, CURSOR_STD); } -MovieTrackingTrack *tracking_marker_check_slide(bContext *C, wmEvent *event, int *area_r, int *action_r, int *corner_r) +MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *event, int *area_r, int *action_r, int *corner_r) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -623,7 +623,7 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, wmEvent *event, int return NULL; } -static void *slide_marker_customdata(bContext *C, wmEvent *event) +static void *slide_marker_customdata(bContext *C, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -652,7 +652,7 @@ static void *slide_marker_customdata(bContext *C, wmEvent *event) return customdata; } -static int slide_marker_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int slide_marker_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SlideMarkerData *slidedata = slide_marker_customdata(C, event); @@ -703,7 +703,7 @@ static void free_slide_data(SlideMarkerData *data) MEM_freeN(data); } -static int slide_marker_modal(bContext *C, wmOperator *op, wmEvent *event) +static int slide_marker_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -1228,7 +1228,7 @@ static int track_markers_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int track_markers_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { TrackMarkersJob *tmj; ScrArea *sa = CTX_wm_area(C); @@ -1286,7 +1286,7 @@ static int track_markers_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(eve return OPERATOR_RUNNING_MODAL; } -static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int track_markers_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { /* no running tracking, remove handler and pass through */ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY)) @@ -1457,7 +1457,7 @@ static int solve_camera_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int solve_camera_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SolveCameraJob *scj; ScrArea *sa = CTX_wm_area(C); @@ -1507,7 +1507,7 @@ static int solve_camera_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(even return OPERATOR_RUNNING_MODAL; } -static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int solve_camera_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { /* no running solver, remove handler and pass through */ if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_ANY)) @@ -2334,7 +2334,7 @@ static int set_scale_exec(bContext *C, wmOperator *op) return do_set_scale(C, op, 0); } -static int set_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int set_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); @@ -2390,7 +2390,7 @@ static int set_solution_scale_exec(bContext *C, wmOperator *op) return do_set_scale(C, op, 1); } -static int set_solution_scale_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int set_solution_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); @@ -3258,7 +3258,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) next = track->next; if ((track->flag & TRACK_HIDDEN) == 0 && (track->flag & TRACK_LOCKED) == 0) { - int ok = 1; + bool ok; ok = (is_track_clean(track, frames, action == TRACKING_CLEAN_DELETE_SEGMENT)) && (error == 0.0f || (track->flag & TRACK_HAS_BUNDLE) == 0 || track->error < error); @@ -3295,7 +3295,7 @@ static int clean_tracks_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int clean_tracks_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int clean_tracks_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index bec50130230..b03209173d8 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -268,6 +268,17 @@ static int mouse_select(bContext *C, float co[2], int extend) return OPERATOR_FINISHED; } +static int select_poll(bContext *C) +{ + SpaceClip *sc = CTX_wm_space_clip(C); + + if (sc) { + return sc->clip && sc->view == SC_VIEW_CLIP; + } + + return FALSE; +} + static int select_exec(bContext *C, wmOperator *op) { float co[2]; @@ -279,7 +290,7 @@ static int select_exec(bContext *C, wmOperator *op) return mouse_select(C, co, extend); } -static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceClip *sc = CTX_wm_space_clip(C); ARegion *ar = CTX_wm_region(C); @@ -317,8 +328,7 @@ void CLIP_OT_select(wmOperatorType *ot) /* api callbacks */ ot->exec = select_exec; ot->invoke = select_invoke; - //ot->poll = ED_space_clip_tracking_poll; // so mask view can Ctrl+RMB markers - ot->poll = ED_space_clip_view_clip_poll; + ot->poll = select_poll; /* flags */ ot->flag = OPTYPE_UNDO; diff --git a/source/blender/editors/space_console/console_draw.c b/source/blender/editors/space_console/console_draw.c index 73747239255..cb191d0b15e 100644 --- a/source/blender/editors/space_console/console_draw.c +++ b/source/blender/editors/space_console/console_draw.c @@ -150,6 +150,26 @@ static int console_textview_line_get(struct TextViewContext *tvc, const char **l return 1; } +static void console_cursor_wrap_offset(const char *str, int width, int *row, int *column, const char *end) +{ + int col; + + for (; *str; str += BLI_str_utf8_size_safe(str)) { + col = BLI_str_utf8_char_width_safe(str); + + if (*column + col > width) { + (*row)++; + *column = 0; + } + + if (end && str >= end) + break; + + *column += col; + } + return; +} + static int console_textview_line_color(struct TextViewContext *tvc, unsigned char fg[3], unsigned char UNUSED(bg[3])) { ConsoleLine *cl_iter = (ConsoleLine *)tvc->iter; @@ -158,24 +178,18 @@ static int console_textview_line_color(struct TextViewContext *tvc, unsigned cha if (tvc->iter_index == 0) { const SpaceConsole *sc = (SpaceConsole *)tvc->arg1; const ConsoleLine *cl = (ConsoleLine *)sc->history.last; - const int prompt_len = BLI_strlen_utf8(sc->prompt); - const int cursor_loc = BLI_strnlen_utf8(cl->line, cl->cursor) + prompt_len; - const int line_len = BLI_strlen_utf8(cl->line) + prompt_len; + int offl = 0, offc = 0; int xy[2] = {CONSOLE_DRAW_MARGIN, CONSOLE_DRAW_MARGIN}; int pen[2]; xy[1] += tvc->lheight / 6; - /* account for wrapping */ - if (line_len < tvc->console_width) { - /* simple case, no wrapping */ - pen[0] = tvc->cwidth * cursor_loc; - pen[1] = -2; - } - else { - /* wrap */ - pen[0] = tvc->cwidth * (cursor_loc % tvc->console_width); - pen[1] = -2 + (((line_len / tvc->console_width) - (cursor_loc / tvc->console_width)) * tvc->lheight); - } + console_cursor_wrap_offset(sc->prompt, tvc->console_width, &offl, &offc, NULL); + console_cursor_wrap_offset(cl->line, tvc->console_width, &offl, &offc, cl->line + cl->cursor); + pen[0] = tvc->cwidth * offc; + pen[1] = -2 - tvc->lheight * offl; + + console_cursor_wrap_offset(cl->line + cl->cursor, tvc->console_width, &offl, &offc, NULL); + pen[1] += tvc->lheight * offl; /* cursor */ UI_GetThemeColor3ubv(TH_CONSOLE_CURSOR, fg); diff --git a/source/blender/editors/space_console/console_ops.c b/source/blender/editors/space_console/console_ops.c index 1242d123a41..b735dee5bdf 100644 --- a/source/blender/editors/space_console/console_ops.c +++ b/source/blender/editors/space_console/console_ops.c @@ -390,7 +390,7 @@ static int console_insert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int console_insert_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int console_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { // if (!RNA_struct_property_is_set(op->ptr, "text")) { /* always set from keymap XXX */ if (!RNA_string_length(op->ptr, "text")) { @@ -1042,7 +1042,7 @@ static void console_cursor_set_to_pos(SpaceConsole *sc, ARegion *ar, SetConsoleC } } -static void console_modal_select_apply(bContext *C, wmOperator *op, wmEvent *event) +static void console_modal_select_apply(bContext *C, wmOperator *op, const wmEvent *event) { SpaceConsole *sc = CTX_wm_space_console(C); ARegion *ar = CTX_wm_region(C); @@ -1080,7 +1080,7 @@ static void console_cursor_set_exit(bContext *UNUSED(C), wmOperator *op) MEM_freeN(scu); } -static int console_modal_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int console_modal_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceConsole *sc = CTX_wm_space_console(C); // ARegion *ar = CTX_wm_region(C); @@ -1101,7 +1101,7 @@ static int console_modal_select_invoke(bContext *C, wmOperator *op, wmEvent *eve return OPERATOR_RUNNING_MODAL; } -static int console_modal_select(bContext *C, wmOperator *op, wmEvent *event) +static int console_modal_select(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: diff --git a/source/blender/editors/space_console/space_console.c b/source/blender/editors/space_console/space_console.c index eed269ff70f..4243ae4e2df 100644 --- a/source/blender/editors/space_console/space_console.c +++ b/source/blender/editors/space_console/space_console.c @@ -160,7 +160,7 @@ static void console_main_area_init(wmWindowManager *wm, ARegion *ar) /* ************* dropboxes ************* */ -static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int id_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { // SpaceConsole *sc = CTX_wm_space_console(C); if (drag->type == WM_DRAG_ID) @@ -179,7 +179,7 @@ static void id_drop_copy(wmDrag *drag, wmDropBox *drop) MEM_freeN(text); } -static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int path_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { // SpaceConsole *sc = CTX_wm_space_console(C); if (drag->type == WM_DRAG_PATH) diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index afe32ec0b85..5b6b8656072 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -35,6 +35,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_dynstr.h" +#include "BLI_fileops_types.h" #ifdef WIN32 # include "BLI_winstuff.h" @@ -55,6 +56,7 @@ #include "MEM_guardedalloc.h" #include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" #include "RNA_access.h" @@ -374,7 +376,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int /* the image */ glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, imb->rect, scale, scale); + glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); /* border */ if (dropshadow) { @@ -396,6 +398,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) char newname[FILE_MAX + 12]; char orgname[FILE_MAX + 12]; char filename[FILE_MAX + 12]; + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = (SpaceFile *)CTX_wm_space_data(C); ARegion *ar = CTX_wm_region(C); @@ -407,7 +410,7 @@ static void renamebutton_cb(bContext *C, void *UNUSED(arg1), char *oldname) if (!BLI_exists(newname)) { BLI_rename(orgname, newname); /* to make sure we show what is on disk */ - ED_fileselect_clear(C, sfile); + ED_fileselect_clear(wm, sfile); } ED_region_tag_redraw(ar); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 79a578a86d1..f705831c715 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -30,6 +30,7 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_fileops_types.h" #include "BKE_context.h" #include "BKE_screen.h" @@ -227,7 +228,7 @@ static FileSelect file_select(bContext *C, const rcti *rect, FileSelType select, return retval; } -static int file_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) +static int file_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -310,7 +311,7 @@ void FILE_OT_select_border(wmOperatorType *ot) WM_operator_properties_gesture_border(ot, 1); } -static int file_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int file_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -584,7 +585,7 @@ int file_highlight_set(SpaceFile *sfile, ARegion *ar, int mx, int my) return (params->active_file != origfile); } -static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int file_highlight_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -611,12 +612,13 @@ void FILE_OT_highlight(struct wmOperatorType *ot) int file_cancel_exec(bContext *C, wmOperator *UNUSED(unused)) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); wmOperator *op = sfile->op; sfile->op = NULL; - WM_event_fileselect_event(C, op, EVT_FILESELECT_CANCEL); + WM_event_fileselect_event(wm, op, EVT_FILESELECT_CANCEL); return OPERATOR_FINISHED; } @@ -779,6 +781,7 @@ int file_draw_check_exists(SpaceFile *sfile) /* sends events now, so things get handled on windowqueue level */ int file_exec(bContext *C, wmOperator *exec_op) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); char filepath[FILE_MAX]; @@ -810,7 +813,7 @@ int file_exec(bContext *C, wmOperator *exec_op) BLI_make_file_string(G.main->name, filepath, BLI_get_folder_create(BLENDER_USER_CONFIG, NULL), BLENDER_BOOKMARK_FILE); fsmenu_write_file(fsmenu_get(), filepath); - WM_event_fileselect_event(C, op, EVT_FILESELECT_EXEC); + WM_event_fileselect_event(wm, op, EVT_FILESELECT_EXEC); } @@ -870,10 +873,11 @@ void FILE_OT_parent(struct wmOperatorType *ot) static int file_refresh_exec(bContext *C, wmOperator *UNUSED(unused)) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); struct FSMenu *fsmenu = fsmenu_get(); - ED_fileselect_clear(C, sfile); + ED_fileselect_clear(wm, sfile); /* refresh system directory menu */ fsmenu_refresh_system_category(fsmenu); @@ -949,7 +953,7 @@ int file_next_exec(bContext *C, wmOperator *UNUSED(unused)) /* only meant for timer usage */ -static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int file_smoothscroll_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ScrArea *sa = CTX_wm_area(C); SpaceFile *sfile = CTX_wm_space_file(C); @@ -1087,6 +1091,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op) char path[FILE_MAX]; int generate_name = 1; + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); if (!sfile->params) { @@ -1125,7 +1130,7 @@ int file_directory_new_exec(bContext *C, wmOperator *op) sfile->scroll_offset = 0; /* reload dir to make sure we're seeing what's in the directory */ - ED_fileselect_clear(C, sfile); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; @@ -1189,7 +1194,7 @@ static void file_expand_directory(bContext *C) } } -static int file_directory_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int file_directory_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceFile *sfile = CTX_wm_space_file(C); @@ -1227,7 +1232,6 @@ int file_directory_exec(bContext *C, wmOperator *UNUSED(unused)) } BLI_cleanup_dir(G.main->name, sfile->params->dir); - BLI_add_slash(sfile->params->dir); file_change_dir(C, 1); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); @@ -1291,11 +1295,12 @@ void FILE_OT_refresh(struct wmOperatorType *ot) static int file_hidedot_exec(bContext *C, wmOperator *UNUSED(unused)) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); if (sfile->params) { sfile->params->flag ^= FILE_HIDE_DOT; - ED_fileselect_clear(C, sfile); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); } @@ -1477,14 +1482,15 @@ static int file_delete_poll(bContext *C) int file_delete_exec(bContext *C, wmOperator *UNUSED(op)) { char str[FILE_MAX]; + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); struct direntry *file; file = filelist_file(sfile->files, sfile->params->active_file); BLI_make_file_string(G.main->name, str, sfile->params->dir, file->relname); - BLI_delete(str, 0, 0); - ED_fileselect_clear(C, sfile); + BLI_delete(str, false, false); + ED_fileselect_clear(wm, sfile); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); return OPERATOR_FINISHED; diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 142eb2214a1..f1e707f8802 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -48,6 +48,7 @@ #include "BLI_linklist.h" #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLI_fileops_types.h" #ifdef WIN32 # include "BLI_winstuff.h" @@ -545,8 +546,6 @@ FileList *filelist_new(short type) void filelist_free(struct FileList *filelist) { - int i; - if (!filelist) { printf("Attempting to delete empty filelist.\n"); return; @@ -557,23 +556,8 @@ void filelist_free(struct FileList *filelist) filelist->fidx = NULL; } - for (i = 0; i < filelist->numfiles; ++i) { - if (filelist->filelist[i].image) { - IMB_freeImBuf(filelist->filelist[i].image); - } - filelist->filelist[i].image = NULL; - if (filelist->filelist[i].relname) - MEM_freeN(filelist->filelist[i].relname); - if (filelist->filelist[i].path) - MEM_freeN(filelist->filelist[i].path); - filelist->filelist[i].relname = NULL; - if (filelist->filelist[i].string) - MEM_freeN(filelist->filelist[i].string); - filelist->filelist[i].string = NULL; - } - + BLI_free_filelist(filelist->filelist, filelist->numfiles); filelist->numfiles = 0; - free(filelist->filelist); filelist->filelist = NULL; filelist->filter = 0; filelist->filter_glob[0] = '\0'; @@ -874,18 +858,14 @@ static void filelist_setfiletypes(struct FileList *filelist) static void filelist_read_dir(struct FileList *filelist) { - char wdir[FILE_MAX] = ""; if (!filelist) return; filelist->fidx = NULL; filelist->filelist = NULL; - BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */ - BLI_cleanup_dir(G.main->name, filelist->dir); filelist->numfiles = BLI_dir_contents(filelist->dir, &(filelist->filelist)); - if (!chdir(wdir)) {} /* fix warning about not checking return value */ filelist_setfiletypes(filelist); filelist_filter(filelist); } @@ -1033,7 +1013,7 @@ static int groupname_to_code(const char *group) char *lslash; BLI_strncpy(buf, group, sizeof(buf)); - lslash = BLI_last_slash(buf); + lslash = (char *)BLI_last_slash(buf); if (lslash) lslash[0] = '\0'; @@ -1364,7 +1344,7 @@ static void thumbnails_free(void *tjv) } -void thumbnails_start(struct FileList *filelist, const struct bContext *C) +void thumbnails_start(FileList *filelist, const bContext *C) { wmJob *wm_job; ThumbnailJob *tj; @@ -1376,7 +1356,7 @@ void thumbnails_start(struct FileList *filelist, const struct bContext *C) for (idx = 0; idx < filelist->numfiles; idx++) { if (!filelist->filelist[idx].image) { if ( (filelist->filelist[idx].flags & (IMAGEFILE | MOVIEFILE | BLENDERFILE | BLENDERFILE_BACKUP)) ) { - FileImage *limg = MEM_callocN(sizeof(struct FileImage), "loadimage"); + FileImage *limg = MEM_callocN(sizeof(FileImage), "loadimage"); BLI_strncpy(limg->path, filelist->filelist[idx].path, FILE_MAX); limg->index = idx; limg->flags = filelist->filelist[idx].flags; @@ -1398,12 +1378,12 @@ void thumbnails_start(struct FileList *filelist, const struct bContext *C) WM_jobs_start(CTX_wm_manager(C), wm_job); } -void thumbnails_stop(struct FileList *filelist, const struct bContext *C) +void thumbnails_stop(wmWindowManager *wm, FileList *filelist) { - WM_jobs_kill(CTX_wm_manager(C), filelist, NULL); + WM_jobs_kill(wm, filelist, NULL); } -int thumbnails_running(struct FileList *filelist, const struct bContext *C) +int thumbnails_running(wmWindowManager *wm, FileList *filelist) { - return WM_jobs_test(CTX_wm_manager(C), filelist, WM_JOB_TYPE_FILESEL_THUMBNAIL); + return WM_jobs_test(wm, filelist, WM_JOB_TYPE_FILESEL_THUMBNAIL); } diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index 32a31c51229..d093d427eae 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -37,15 +37,16 @@ extern "C" { #endif +struct BlendHandle; struct FileList; +struct FileSelection; struct FolderList; -struct direntry; -struct BlendHandle; -struct Scene; struct Main; -struct rcti; struct ReportList; -struct FileSelection; +struct Scene; +struct direntry; +struct rcti; +struct wmWindowManager; typedef enum FileSelType { FILE_SEL_REMOVE = 0, @@ -99,9 +100,9 @@ void folderlist_popdir(struct ListBase *folderlist, char *dir); void folderlist_pushdir(struct ListBase *folderlist, const char *dir); int folderlist_clear_next(struct SpaceFile *sfile); -void thumbnails_stop(struct FileList *filelist, const struct bContext *C); void thumbnails_start(struct FileList *filelist, const struct bContext *C); -int thumbnails_running(struct FileList *filelist, const struct bContext *C); +void thumbnails_stop(struct wmWindowManager *wm, struct FileList *filelist); +int thumbnails_running(struct wmWindowManager *wm, struct FileList *filelist); #ifdef __cplusplus } diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 3c6f6358171..b8db7dc97b7 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -58,6 +58,7 @@ #include "BLI_linklist.h" #include "BLI_dynstr.h" #include "BLI_utildefines.h" +#include "BLI_fileops_types.h" #include "BKE_context.h" #include "BKE_global.h" @@ -577,13 +578,14 @@ FileLayout *ED_fileselect_get_layout(struct SpaceFile *sfile, ARegion *ar) void file_change_dir(bContext *C, int checkdir) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); if (sfile->params) { - ED_fileselect_clear(C, sfile); + ED_fileselect_clear(wm, sfile); - if (checkdir && BLI_is_dir(sfile->params->dir) == 0) { + if (checkdir && !BLI_is_dir(sfile->params->dir)) { BLI_strncpy(sfile->params->dir, filelist_dir(sfile->files), sizeof(sfile->params->dir)); /* could return but just refresh the current dir */ } @@ -690,24 +692,24 @@ void autocomplete_file(struct bContext *C, char *str, void *UNUSED(arg_v)) } } -void ED_fileselect_clear(struct bContext *C, struct SpaceFile *sfile) +void ED_fileselect_clear(struct wmWindowManager *wm, struct SpaceFile *sfile) { /* only NULL in rare cases - [#29734] */ if (sfile->files) { - thumbnails_stop(sfile->files, C); + thumbnails_stop(wm, sfile->files); filelist_freelib(sfile->files); filelist_free(sfile->files); } sfile->params->active_file = -1; - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_FILE_LIST, NULL); + WM_main_add_notifier(NC_SPACE | ND_SPACE_FILE_LIST, NULL); } -void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile) +void ED_fileselect_exit(struct wmWindowManager *wm, struct SpaceFile *sfile) { if (!sfile) return; if (sfile->op) { - WM_event_fileselect_event(C, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL); + WM_event_fileselect_event(wm, sfile->op, EVT_FILESELECT_EXTERNAL_CANCEL); sfile->op = NULL; } @@ -715,7 +717,7 @@ void ED_fileselect_exit(struct bContext *C, struct SpaceFile *sfile) folderlist_free(sfile->folders_next); if (sfile->files) { - ED_fileselect_clear(C, sfile); + ED_fileselect_clear(wm, sfile); MEM_freeN(sfile->files); sfile->files = NULL; } diff --git a/source/blender/editors/space_file/fsmenu.c b/source/blender/editors/space_file/fsmenu.c index 5f1f9a3ab22..04c68e5ea68 100644 --- a/source/blender/editors/space_file/fsmenu.c +++ b/source/blender/editors/space_file/fsmenu.c @@ -281,14 +281,14 @@ void fsmenu_write_file(struct FSMenu *fsmenu, const char *filename) void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename) { - char line[256]; + char line[FILE_MAXDIR]; FSMenuCategory category = FS_CATEGORY_BOOKMARKS; FILE *fp; fp = BLI_fopen(filename, "r"); if (!fp) return; - while (fgets(line, 256, fp) != NULL) { /* read a line */ + while (fgets(line, sizeof(line), fp) != NULL) { /* read a line */ if (strncmp(line, "[Bookmarks]", 11) == 0) { category = FS_CATEGORY_BOOKMARKS; } @@ -318,7 +318,7 @@ void fsmenu_read_bookmarks(struct FSMenu *fsmenu, const char *filename) void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) { - char line[256]; + char line[FILE_MAXDIR]; #ifdef WIN32 /* Add the drive names to the listing */ { @@ -376,25 +376,25 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) * TODO : replace hardcoded paths with proper BLI_get_folder calls */ home = getenv("HOME"); if (read_bookmarks && home) { - BLI_snprintf(line, 256, "%s/", home); + BLI_snprintf(line, sizeof(line), "%s/", home); fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); - BLI_snprintf(line, 256, "%s/Desktop/", home); + BLI_snprintf(line, sizeof(line), "%s/Desktop/", home); if (BLI_exists(line)) { fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } - BLI_snprintf(line, 256, "%s/Documents/", home); + BLI_snprintf(line, sizeof(line), "%s/Documents/", home); if (BLI_exists(line)) { fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } - BLI_snprintf(line, 256, "%s/Pictures/", home); + BLI_snprintf(line, sizeof(line), "%s/Pictures/", home); if (BLI_exists(line)) { fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } - BLI_snprintf(line, 256, "%s/Music/", home); + BLI_snprintf(line, sizeof(line), "%s/Music/", home); if (BLI_exists(line)) { fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } - BLI_snprintf(line, 256, "%s/Movies/", home); + BLI_snprintf(line, sizeof(line), "%s/Movies/", home); if (BLI_exists(line)) { fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } @@ -427,7 +427,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle); - if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII)) + if (!CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII)) continue; fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED); @@ -480,7 +480,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle); - if (!CFStringGetCString(pathString, line, 256, kCFStringEncodingASCII)) + if (!CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingASCII)) continue; fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); @@ -499,9 +499,9 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) const char *home = getenv("HOME"); if (read_bookmarks && home) { - BLI_snprintf(line, FILE_MAXDIR, "%s/", home); + BLI_snprintf(line, sizeof(line), "%s/", home); fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); - BLI_snprintf(line, FILE_MAXDIR, "%s/Desktop/", home); + BLI_snprintf(line, sizeof(line), "%s/Desktop/", home); if (BLI_exists(line)) { fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, FS_INSERT_SORTED); } @@ -527,7 +527,7 @@ void fsmenu_read_system(struct FSMenu *fsmenu, int read_bookmarks) len = strlen(mnt->mnt_dir); if (len && mnt->mnt_dir[len - 1] != '/') { - BLI_snprintf(line, FILE_MAXDIR, "%s/", mnt->mnt_dir); + BLI_snprintf(line, sizeof(line), "%s/", mnt->mnt_dir); fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, line, FS_INSERT_SORTED); } else { diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 0a4b922bb38..698c355fad3 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -28,13 +28,9 @@ * \ingroup spfile */ - #include <string.h> #include <stdio.h> - -#include "RNA_access.h" - #include "MEM_guardedalloc.h" #include "BIF_gl.h" @@ -45,11 +41,17 @@ #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLI_fileops_types.h" #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_global.h" +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + #include "ED_space_api.h" #include "ED_screen.h" #include "ED_fileselect.h" @@ -57,9 +59,6 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" -#include "WM_api.h" -#include "WM_types.h" - #include "UI_resources.h" #include "UI_view2d.h" @@ -147,7 +146,7 @@ static void file_free(SpaceLink *sl) /* spacetype; init callback, area size changes, screen set, etc */ -static void file_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) +static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa) { SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; //printf("file_init\n"); @@ -158,6 +157,12 @@ static void file_init(struct wmWindowManager *UNUSED(wm), ScrArea *sa) if (sfile->layout) sfile->layout->dirty = TRUE; } +static void file_exit(wmWindowManager *wm, ScrArea *sa) +{ + SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; + + ED_fileselect_exit(wm, sfile); +} static SpaceLink *file_duplicate(SpaceLink *sl) { @@ -187,6 +192,7 @@ static SpaceLink *file_duplicate(SpaceLink *sl) static void file_refresh(const bContext *C, ScrArea *UNUSED(sa)) { + wmWindowManager *wm = CTX_wm_manager(C); SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); @@ -202,7 +208,7 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa)) filelist_setfilter_types(sfile->files, params->filter_glob); if (filelist_empty(sfile->files)) { - thumbnails_stop(sfile->files, C); + thumbnails_stop(wm, sfile->files); filelist_readdir(sfile->files); if (params->sort != FILE_SORT_NONE) { filelist_sort(sfile->files, params->sort); @@ -214,7 +220,7 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa)) } else { if (params->sort != FILE_SORT_NONE) { - thumbnails_stop(sfile->files, C); + thumbnails_stop(wm, sfile->files); filelist_sort(sfile->files, params->sort); if (params->display == FILE_IMGDISPLAY) { thumbnails_start(sfile->files, C); @@ -222,14 +228,14 @@ static void file_refresh(const bContext *C, ScrArea *UNUSED(sa)) } else { if (params->display == FILE_IMGDISPLAY) { - if (!thumbnails_running(sfile->files, C)) { + if (!thumbnails_running(wm, sfile->files)) { thumbnails_start(sfile->files, C); } } else { /* stop any running thumbnail jobs if we're not * displaying them - speedup for NFS */ - thumbnails_stop(sfile->files, C); + thumbnails_stop(wm, sfile->files); } filelist_filter(sfile->files); } @@ -577,6 +583,7 @@ void ED_spacetype_file(void) st->new = file_new; st->free = file_free; st->init = file_init; + st->exit = file_exit; st->duplicate = file_duplicate; st->refresh = file_refresh; st->listener = file_listener; @@ -629,7 +636,7 @@ void ED_spacetype_file(void) void ED_file_init(void) { - char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); + const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); fsmenu_read_system(fsmenu_get(), TRUE); diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index b92430ce0e9..a51fef6c692 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -609,7 +609,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, wmEvent *evt) +static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; ARegion *ar; @@ -625,8 +625,8 @@ static int graphkeys_click_insert_invoke(bContext *C, wmOperator *op, wmEvent *e ar = ac.ar; v2d = &ar->v2d; - mval[0] = (evt->x - ar->winrct.xmin); - mval[1] = (evt->y - ar->winrct.ymin); + mval[0] = (event->x - ar->winrct.xmin); + mval[1] = (event->y - ar->winrct.ymin); UI_view2d_region_to_view(v2d, mval[0], mval[1], &x, &y); @@ -835,7 +835,7 @@ static int graphkeys_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int graphkeys_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { graphkeys_duplicate_exec(C, op); @@ -1190,7 +1190,7 @@ static int graphkeys_sound_bake_exec(bContext *UNUSED(C), wmOperator *op) #endif //WITH_AUDASPACE -static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int graphkeys_sound_bake_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; @@ -2132,7 +2132,7 @@ void GRAPH_OT_smooth(wmOperatorType *ot) /* ******************** Add F-Modifier Operator *********************** */ /* present a special customised popup menu for this, with some filtering */ -static int graph_fmodifier_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int graph_fmodifier_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { wmOperatorType *ot = WM_operatortype_find("GRAPH_OT_fmodifier_add", 1); uiPopupMenu *pup; @@ -2196,8 +2196,9 @@ static int graph_fmodifier_add_exec(bContext *C, wmOperator *op) /* add F-Modifier of specified type to active F-Curve, and make it the active one */ fcm = add_fmodifier(&fcu->modifiers, type); - if (fcm) + if (fcm) { set_active_fmodifier(&fcu->modifiers, fcm); + } else { BKE_report(op->reports, RPT_ERROR, "Modifier could not be added (see console for details)"); break; diff --git a/source/blender/editors/space_graph/graph_ops.c b/source/blender/editors/space_graph/graph_ops.c index 54b417e740a..acb9e42d91b 100644 --- a/source/blender/editors/space_graph/graph_ops.c +++ b/source/blender/editors/space_graph/graph_ops.c @@ -109,7 +109,7 @@ static int graphview_cursor_exec(bContext *C, wmOperator *op) /* ... */ /* set the operator properties from the initial event */ -static void graphview_cursor_setprops(bContext *C, wmOperator *op, wmEvent *event) +static void graphview_cursor_setprops(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float viewx, viewy; @@ -128,7 +128,7 @@ static void graphview_cursor_setprops(bContext *C, wmOperator *op, wmEvent *even } /* Modal Operator init */ -static int graphview_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int graphview_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) { /* Change to frame that mouse is over before adding modal handler, * as user could click on a single frame (jump to frame) as well as @@ -145,7 +145,7 @@ static int graphview_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* Modal event handling of cursor changing */ -static int graphview_cursor_modal(bContext *C, wmOperator *op, wmEvent *event) +static int graphview_cursor_modal(bContext *C, wmOperator *op, const wmEvent *event) { /* execute the events */ switch (event->type) { diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index 978b3224850..cbec3072c44 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -815,7 +815,7 @@ static int graphkeys_select_leftright_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int graphkeys_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; short leftright = RNA_enum_get(op->ptr, "mode"); @@ -1297,7 +1297,7 @@ static void graphkeys_mselect_column(bAnimContext *ac, const int mval[2], short /* ------------------- */ /* handle clicking */ -static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int graphkeys_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; short selectmode; @@ -1342,10 +1342,13 @@ void GRAPH_OT_clickselect(wmOperatorType *ot) ot->idname = "GRAPH_OT_clickselect"; ot->description = "Select keyframes by clicking on them"; - /* api callbacks */ + /* callbacks */ ot->invoke = graphkeys_clickselect_invoke; ot->poll = graphop_visible_keyframes_poll; + /* flags */ + ot->flag = OPTYPE_UNDO; + /* properties */ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY RNA_def_property_flag(prop, PROP_SKIP_SAVE); diff --git a/source/blender/editors/space_image/SConscript b/source/blender/editors/space_image/SConscript index 6e7c5982d6e..68f747270a3 100644 --- a/source/blender/editors/space_image/SConscript +++ b/source/blender/editors/space_image/SConscript @@ -44,7 +44,7 @@ if env['WITH_BF_OPENJPEG']: if env['WITH_BF_TIFF']: defs.append('WITH_TIFF') if env['WITH_BF_CINEON']: - defs.append('WITH_CINEON') + defs.append('WITH_CINEON') if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 6237958e723..70001b59528 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -73,51 +73,55 @@ /* proto */ -static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str) +static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, char *str, size_t len) { - int ofs = 0; + size_t ofs = 0; str[0] = 0; - - if (ima == NULL) return; + if (ima == NULL) + return; if (ibuf == NULL) { - ofs += sprintf(str, IFACE_("Can't Load Image")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Can't Load Image"), len - ofs); } else { if (ima->source == IMA_SRC_MOVIE) { - ofs += sprintf(str, IFACE_("Movie")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Movie"), len - ofs); if (ima->anim) - ofs += sprintf(str + ofs, IFACE_(" %d frs"), IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN)); + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(" %d frs"), + IMB_anim_get_duration(ima->anim, IMB_TC_RECORD_RUN)); + } + else { + ofs += BLI_strncpy_rlen(str, IFACE_("Image"), len - ofs); } - else - ofs += sprintf(str, IFACE_("Image")); - ofs += sprintf(str + ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y); + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(": size %d x %d,"), ibuf->x, ibuf->y); if (ibuf->rect_float) { if (ibuf->channels != 4) { - ofs += sprintf(str + ofs, IFACE_("%d float channel(s)"), ibuf->channels); + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_("%d float channel(s)"), ibuf->channels); } else if (ibuf->planes == R_IMF_PLANES_RGBA) - ofs += sprintf(str + ofs, IFACE_(" RGBA float")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA float"), len - ofs); else - ofs += sprintf(str + ofs, IFACE_(" RGB float")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB float"), len - ofs); } else { if (ibuf->planes == R_IMF_PLANES_RGBA) - ofs += sprintf(str + ofs, IFACE_(" RGBA byte")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGBA byte"), len - ofs); else - ofs += sprintf(str + ofs, IFACE_(" RGB byte")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" RGB byte"), len - ofs); } if (ibuf->zbuf || ibuf->zbuf_float) - ofs += sprintf(str + ofs, IFACE_(" + Z")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_(" + Z"), len - ofs); if (ima->source == IMA_SRC_SEQUENCE) { - char *file = BLI_last_slash(ibuf->name); - if (file == NULL) file = ibuf->name; - else file++; - ofs += sprintf(str + ofs, ", %s", file); + const char *file = BLI_last_slash(ibuf->name); + if (file == NULL) + file = ibuf->name; + else + file++; + ofs += BLI_snprintf(str + ofs, len - ofs, ", %s", file); } } @@ -125,10 +129,8 @@ static void image_info(Scene *scene, ImageUser *iuser, Image *ima, ImBuf *ibuf, if (ima->source == IMA_SRC_SEQUENCE) { /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */ const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0, NULL); - ofs += sprintf(str + ofs, IFACE_(", Frame: %d"), framenr); + ofs += BLI_snprintf(str + ofs, len - ofs, IFACE_(", Frame: %d"), framenr); } - - (void)ofs; } /* gets active viewer user */ @@ -539,16 +541,17 @@ static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *userptr, int compact) { +#define MAX_INFO_LEN 128 + PropertyRNA *prop; PointerRNA imaptr; RNAUpdateCb *cb; Image *ima; ImageUser *iuser; - ImBuf *ibuf; Scene *scene = CTX_data_scene(C); uiLayout *row, *split, *col; uiBlock *block; - char str[128]; + char str[MAX_INFO_LEN]; void *lock; @@ -591,8 +594,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); if (ima->source == IMA_SRC_VIEWER) { - ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - image_info(scene, iuser, ima, ibuf, str); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); + image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN); BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, ima->id.name + 2, ICON_NONE); @@ -661,8 +664,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char } else if (ima->source != IMA_SRC_GENERATED) { if (compact == 0) { - ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); - image_info(scene, iuser, ima, ibuf, str); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); + image_info(scene, iuser, ima, ibuf, str, MAX_INFO_LEN); BKE_image_release_ibuf(ima, ibuf, lock); uiItemL(layout, str, ICON_NONE); } @@ -750,6 +753,8 @@ void uiTemplateImage(uiLayout *layout, bContext *C, PointerRNA *ptr, const char } MEM_freeN(cb); + +#undef MAX_INFO_LEN } void uiTemplateImageSettings(uiLayout *layout, PointerRNA *imfptr, int color_management) diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index cae71885b87..e69ce56c9d9 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -491,6 +491,8 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, /* set zoom */ glPixelZoom(zoomx, zoomy); + glaDefine2DArea(&ar->winrct); + /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, fx, fy, &x, &y); @@ -523,11 +525,7 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (display_buffer) - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); -#if 0 - else - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float); -#endif + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); IMB_display_buffer_release(cache_handle); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index b913b3528ac..54230d35312 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -162,7 +162,7 @@ static int space_image_file_exists_poll(bContext *C) if (BLI_exists(name) == FALSE) { CTX_wm_operator_poll_msg_set(C, "image file not found"); } - else if (BLI_file_is_writable(name) == FALSE) { + else if (!BLI_file_is_writable(name)) { CTX_wm_operator_poll_msg_set(C, "image path can't be written to"); } else { @@ -238,7 +238,7 @@ typedef struct ViewPanData { int event_type; } ViewPanData; -static void image_view_pan_init(bContext *C, wmOperator *op, wmEvent *event) +static void image_view_pan_init(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); ViewPanData *vpd; @@ -293,7 +293,7 @@ static int image_view_pan_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int image_view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type == MOUSEPAN) { SpaceImage *sima = CTX_wm_space_image(C); @@ -312,7 +312,7 @@ static int image_view_pan_invoke(bContext *C, wmOperator *op, wmEvent *event) } } -static int image_view_pan_modal(bContext *C, wmOperator *op, wmEvent *event) +static int image_view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); ViewPanData *vpd = op->customdata; @@ -383,7 +383,7 @@ typedef struct ViewZoomData { ARegion *ar; } ViewZoomData; -static void image_view_zoom_init(bContext *C, wmOperator *op, wmEvent *event) +static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); ARegion *ar = CTX_wm_region(C); @@ -455,7 +455,7 @@ enum { VIEW_CONFIRM }; -static int image_view_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type == MOUSEZOOM || event->type == MOUSEPAN) { SpaceImage *sima = CTX_wm_space_image(C); @@ -525,7 +525,7 @@ static void image_zoom_apply(ViewZoomData *vpd, wmOperator *op, const int x, con ED_region_tag_redraw(vpd->ar); } -static int image_view_zoom_modal(bContext *C, wmOperator *op, wmEvent *event) +static int image_view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewZoomData *vpd = op->customdata; short event_code = VIEW_PASS; @@ -589,7 +589,7 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) * that explains the negative signs in the code below */ -static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { if (event->type != NDOF_MOTION) return OPERATOR_CANCELLED; @@ -773,7 +773,7 @@ static int image_view_zoom_in_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float location[2]; @@ -815,7 +815,7 @@ static int image_view_zoom_out_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float location[2]; @@ -978,7 +978,7 @@ static int image_open_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */ char *path = U.textudir; @@ -1128,7 +1128,7 @@ static int image_replace_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_replace_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_replace_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceImage *sima = CTX_wm_space_image(C); @@ -1442,7 +1442,7 @@ static int image_save_as_check(bContext *UNUSED(C), wmOperator *op) return WM_operator_filesel_ensure_ext_imtype(op, imf); } -static int image_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceImage *sima = CTX_wm_space_image(C); Image *ima = ED_space_image(sima); @@ -1603,7 +1603,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op) SpaceImage *sima = CTX_wm_space_image(C); ImBuf *ibuf; int tot = 0; - char di[FILE_MAX], fi[FILE_MAX]; + char di[FILE_MAX]; if (sima->image == NULL) return OPERATOR_CANCELLED; @@ -1632,10 +1632,8 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op) for (ibuf = sima->image->ibufs.first; ibuf; ibuf = ibuf->next) if (ibuf->userflags & IB_BITMAPDIRTY) break; - - BLI_strncpy(di, ibuf->name, FILE_MAX); - BLI_splitdirstring(di, fi); - + + BLI_split_dir_part(ibuf->name, di, sizeof(di)); BKE_reportf(op->reports, RPT_INFO, "%d image(s) will be saved in %s", tot, di); for (ibuf = sima->image->ibufs.first; ibuf; ibuf = ibuf->next) { @@ -1775,7 +1773,7 @@ static int image_new_exec(bContext *C, wmOperator *op) /* XXX, Ton is not a fan of OK buttons but using this function to avoid undo/redo bug while in mesh-editmode, - campbell */ /* XXX Note: the WM_operator_props_dialog_popup() doesn't work for uiIDContextProperty(), image is not being that way */ -static int image_new_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y); @@ -1945,7 +1943,7 @@ static int image_pack_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_pack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_pack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Image *ima = CTX_data_edit_image(C); ImBuf *ibuf; @@ -2029,7 +2027,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_unpack_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Image *ima = CTX_data_edit_image(C); @@ -2145,7 +2143,7 @@ int ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], floa return ret; } -static void image_sample_apply(bContext *C, wmOperator *op, wmEvent *event) +static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); ARegion *ar = CTX_wm_region(C); @@ -2271,7 +2269,7 @@ static void image_sample_exit(bContext *C, wmOperator *op) MEM_freeN(info); } -static int image_sample_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); ARegion *ar = CTX_wm_region(C); @@ -2292,7 +2290,7 @@ static int image_sample_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int image_sample_modal(bContext *C, wmOperator *op, wmEvent *event) +static int image_sample_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: @@ -2378,7 +2376,7 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_sample_line_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int image_sample_line_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); @@ -2533,7 +2531,7 @@ static int image_record_composite_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int image_record_composite_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int image_record_composite_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { RecordCompositeData *rcd; @@ -2550,7 +2548,7 @@ static int image_record_composite_invoke(bContext *C, wmOperator *op, wmEvent *U return OPERATOR_RUNNING_MODAL; } -static int image_record_composite_modal(bContext *C, wmOperator *op, wmEvent *event) +static int image_record_composite_modal(bContext *C, wmOperator *op, const wmEvent *event) { RecordCompositeData *rcd = op->customdata; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index d82a46e9578..761becdbf8e 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -337,7 +337,7 @@ static void image_keymap(struct wmKeyConfig *keyconf) } /* dropboxes */ -static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int image_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) if (ELEM3(drag->icon, 0, ICON_FILE_IMAGE, ICON_FILE_BLANK)) /* rule might not work? */ diff --git a/source/blender/editors/space_info/info_ops.c b/source/blender/editors/space_info/info_ops.c index 04f6a5152e6..c68473820e3 100644 --- a/source/blender/editors/space_info/info_ops.c +++ b/source/blender/editors/space_info/info_ops.c @@ -104,7 +104,7 @@ static int unpack_libraries_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int unpack_libraries_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int unpack_libraries_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return WM_operator_confirm_message(C, op, "Unpack Blender Libraries - creates directories, all new paths should work"); } @@ -137,7 +137,7 @@ static int pack_all_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int pack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int pack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Main *bmain = CTX_data_main(C); Image *ima; @@ -203,7 +203,7 @@ static int unpack_all_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int unpack_all_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int unpack_all_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Main *bmain = CTX_data_main(C); uiPopupMenu *pup; @@ -288,7 +288,7 @@ static int unpack_item_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int unpack_item_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int unpack_item_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; @@ -429,7 +429,7 @@ static int find_missing_files_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int find_missing_files_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int find_missing_files_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { /* XXX file open button text "Find Missing Files" */ WM_event_add_fileselect(C, op); @@ -469,7 +469,7 @@ void FILE_OT_find_missing_files(wmOperatorType *ot) #define ERROR_TIMEOUT 10.0f #define ERROR_COLOR_TIMEOUT 6.0f #define COLLAPSE_TIMEOUT 0.25f -static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int update_reports_display_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { wmWindowManager *wm = CTX_wm_manager(C); ReportList *reports = CTX_wm_reports(C); diff --git a/source/blender/editors/space_info/info_report.c b/source/blender/editors/space_info/info_report.c index 3050563e538..b096b8f3e2b 100644 --- a/source/blender/editors/space_info/info_report.c +++ b/source/blender/editors/space_info/info_report.c @@ -127,7 +127,7 @@ static int select_report_pick_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int select_report_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_report_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceInfo *sinfo = CTX_wm_space_info(C); ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 976769752f9..b2e9427c799 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -38,8 +38,9 @@ #include "DNA_meta_types.h" #include "DNA_scene_types.h" -#include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" #include "BLF_translation.h" @@ -58,6 +59,7 @@ #include "ED_armature.h" #include "ED_mesh.h" +#define MAX_INFO_LEN 512 typedef struct SceneStats { int totvert, totvertsel; @@ -68,7 +70,7 @@ typedef struct SceneStats { int totlamp, totlampsel; int tottri, totmesh; - char infostr[512]; + char infostr[MAX_INFO_LEN]; } SceneStats; static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) @@ -357,60 +359,70 @@ static void stats_update(Scene *scene) static void stats_string(Scene *scene) { +#define MAX_INFO_MEM_LEN 64 SceneStats *stats = scene->stats; Object *ob = (scene->basact) ? scene->basact->object : NULL; uintptr_t mem_in_use, mmap_in_use; - char memstr[64]; + char memstr[MAX_INFO_MEM_LEN]; char *s; + size_t ofs = 0; mem_in_use = MEM_get_memory_in_use(); mmap_in_use = MEM_get_mapped_memory_in_use(); /* get memory statistics */ - s = memstr + sprintf(memstr, IFACE_(" | Mem:%.2fM"), (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); + s = memstr; + ofs += BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" | Mem:%.2fM"), + (double)((mem_in_use - mmap_in_use) >> 10) / 1024.0); if (mmap_in_use) - sprintf(s, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); + BLI_snprintf(s + ofs, MAX_INFO_MEM_LEN - ofs, IFACE_(" (%.2fM)"), (double)((mmap_in_use) >> 10) / 1024.0); s = stats->infostr; - - s += sprintf(s, "%s | ", versionstr); + ofs = 0; + + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", versionstr); if (scene->obedit) { if (BKE_keyblock_from_object(scene->obedit)) - s += sprintf(s, IFACE_("(Key) ")); + ofs += BLI_strncpy_rlen(s + ofs, IFACE_("(Key) "), MAX_INFO_LEN - ofs); if (scene->obedit->type == OB_MESH) { - s += sprintf(s, IFACE_("Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d"), - stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge, stats->totfacesel, - stats->totface, stats->tottri); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, + IFACE_("Verts:%d/%d | Edges:%d/%d | Faces:%d/%d | Tris:%d"), + stats->totvertsel, stats->totvert, stats->totedgesel, stats->totedge, + stats->totfacesel, stats->totface, stats->tottri); } else if (scene->obedit->type == OB_ARMATURE) { - s += sprintf(s, IFACE_("Verts:%d/%d | Bones:%d/%d"), stats->totvertsel, stats->totvert, stats->totbonesel, - stats->totbone); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d/%d | Bones:%d/%d"), stats->totvertsel, + stats->totvert, stats->totbonesel, stats->totbone); } else { - s += sprintf(s, IFACE_("Verts:%d/%d"), stats->totvertsel, stats->totvert); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d/%d"), stats->totvertsel, stats->totvert); } - strcat(s, memstr); + ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); } else if (ob && (ob->mode & OB_MODE_POSE)) { - s += sprintf(s, IFACE_("Bones:%d/%d %s"), - stats->totbonesel, stats->totbone, memstr); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Bones:%d/%d %s"), + stats->totbonesel, stats->totbone, memstr); } else if (stats_is_object_dynamic_topology_sculpt(ob)) { - s += sprintf(s, IFACE_("Verts:%d | Tris:%d"), stats->totvert, stats->tottri); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, IFACE_("Verts:%d | Tris:%d"), stats->totvert, stats->tottri); } else { - s += sprintf(s, IFACE_("Verts:%d | Faces:%d | Tris:%d | Objects:%d/%d | Lamps:%d/%d%s"), - stats->totvert, stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel, - stats->totlamp, memstr); + ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, + IFACE_("Verts:%d | Faces:%d | Tris:%d | Objects:%d/%d | Lamps:%d/%d%s"), stats->totvert, + stats->totface, stats->tottri, stats->totobjsel, stats->totobj, stats->totlampsel, + stats->totlamp, memstr); } if (ob) - sprintf(s, " | %s", ob->id.name + 2); + BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", ob->id.name + 2); +#undef MAX_INFO_MEM_LEN } +#undef MAX_INFO_LEN + void ED_info_stats_clear(Scene *scene) { if (scene->stats) { diff --git a/source/blender/editors/space_info/textview.c b/source/blender/editors/space_info/textview.c index 66f4904c340..e53cbdd04af 100644 --- a/source/blender/editors/space_info/textview.c +++ b/source/blender/editors/space_info/textview.c @@ -31,14 +31,19 @@ #include <limits.h> #include <assert.h> +#include "MEM_guardedalloc.h" + #include "BLF_api.h" #include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_string_utf8.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "BKE_text.h" + #include "ED_datafiles.h" #include "textview.h" @@ -68,12 +73,12 @@ BLI_INLINE void console_step_sel(ConsoleDrawContext *cdc, const int step) cdc->sel[1] += step; } -static void console_draw_sel(const int sel[2], const int xy[2], const int str_len_draw, int cwidth, int lheight, - const unsigned char bg_sel[4]) +static void console_draw_sel(const char *str, const int sel[2], const int xy[2], const int str_len_draw, + int cwidth, int lheight, const unsigned char bg_sel[4]) { if (sel[0] <= str_len_draw && sel[1] >= 0) { - const int sta = max_ii(sel[0], 0); - const int end = min_ii(sel[1], str_len_draw); + const int sta = txt_utf8_offset_to_column(str, max_ii(sel[0], 0)); + const int end = txt_utf8_offset_to_column(str, min_ii(sel[1], str_len_draw)); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -85,38 +90,72 @@ static void console_draw_sel(const int sel[2], const int xy[2], const int str_le } } +/* warning: allocated memory for 'offsets' must be freed by caller */ +static int console_wrap_offsets(const char *str, int len, int width, int *lines, int **offsets) +{ + int i, end; /* column */ + int j; /* mem */ + + *lines = 1; + + *offsets = MEM_callocN(sizeof(**offsets) * (len * BLI_UTF8_WIDTH_MAX / MAX2(1, width - (BLI_UTF8_WIDTH_MAX - 1)) + 1), + "console_wrap_offsets"); + (*offsets)[0] = 0; + + for (i = 0, end = width, j = 0; j < len && str[j]; j += BLI_str_utf8_size_safe(str + j)) { + int columns = BLI_str_utf8_char_width_safe(str + j); + + if (i + columns > end) { + (*offsets)[*lines] = j; + (*lines)++; + + end = i + width; + } + i += columns; + } + return j; /* return actual length */ +} + /* return 0 if the last line is off the screen * should be able to use this for any string type */ -static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const int str_len, +static int console_draw_string(ConsoleDrawContext *cdc, const char *str, int str_len, const unsigned char fg[3], const unsigned char bg[3], const unsigned char bg_sel[4]) { int rct_ofs = cdc->lheight / 4; - int tot_lines = (str_len / cdc->console_width) + 1; /* total number of lines for wrapping */ - int y_next = (str_len > cdc->console_width) ? cdc->xy[1] + cdc->lheight * tot_lines : cdc->xy[1] + cdc->lheight; + int tot_lines; /* total number of lines for wrapping */ + int *offsets; /* offsets of line beginnings for wrapping */ + int y_next; const int mono = blf_mono_font; + str_len = console_wrap_offsets(str, str_len, cdc->console_width, &tot_lines, &offsets); + y_next = cdc->xy[1] + cdc->lheight * tot_lines; + /* just advance the height */ if (cdc->draw == 0) { - if (cdc->pos_pick && (cdc->mval[1] != INT_MAX)) { - if (cdc->xy[1] <= cdc->mval[1]) { - if ((y_next >= cdc->mval[1])) { - int ofs = (int)floor(((float)cdc->mval[0] / (float)cdc->cwidth)); - - /* wrap */ - if (str_len > cdc->console_width) - ofs += cdc->console_width * ((int)((((float)(y_next - cdc->mval[1]) / - (float)(y_next - cdc->xy[1])) * tot_lines))); - - CLAMP(ofs, 0, str_len); - *cdc->pos_pick += str_len - ofs; + if (cdc->pos_pick && cdc->mval[1] != INT_MAX && cdc->xy[1] <= cdc->mval[1]) { + if (y_next >= cdc->mval[1]) { + int ofs = 0; + + /* wrap */ + if (tot_lines > 1) { + int iofs = (int)((float)(y_next - cdc->mval[1]) / cdc->lheight); + ofs += offsets[MIN2(iofs, tot_lines - 1)]; } - else - *cdc->pos_pick += str_len + 1; + + /* last part */ + ofs += txt_utf8_column_to_offset(str + ofs, + (int)floor((float)cdc->mval[0] / cdc->cwidth)); + + CLAMP(ofs, 0, str_len); + *cdc->pos_pick += str_len - ofs; } + else + *cdc->pos_pick += str_len + 1; } cdc->xy[1] = y_next; + MEM_freeN(offsets); return 1; } else if (y_next - cdc->lheight < cdc->ymin) { @@ -128,12 +167,15 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i console_step_sel(cdc, -(str_len + 1)); } + MEM_freeN(offsets); return 1; } if (tot_lines > 1) { /* wrap? */ - const int initial_offset = ((tot_lines - 1) * cdc->console_width); - const char *line_stride = str + initial_offset; /* advance to the last line and draw it first */ + const int initial_offset = offsets[tot_lines - 1]; + size_t len = str_len - initial_offset; + const char *s = str + initial_offset; + int i; int sel_orig[2]; copy_v2_v2_int(sel_orig, cdc->sel); @@ -151,36 +193,38 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i /* last part needs no clipping */ BLF_position(mono, cdc->xy[0], cdc->xy[1], 0); - BLF_draw(mono, line_stride, str_len - initial_offset); + BLF_draw_mono(mono, s, len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { console_step_sel(cdc, -initial_offset); // glColor4ub(255, 0, 0, 96); // debug - console_draw_sel(cdc->sel, cdc->xy, str_len % cdc->console_width, cdc->cwidth, cdc->lheight, bg_sel); - console_step_sel(cdc, cdc->console_width); + console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; - line_stride -= cdc->console_width; - - for (; line_stride >= str; line_stride -= cdc->console_width) { + for (i = tot_lines - 1; i > 0; i--) { + len = offsets[i] - offsets[i - 1]; + s = str + offsets[i - 1]; + BLF_position(mono, cdc->xy[0], cdc->xy[1], 0); - BLF_draw(mono, line_stride, cdc->console_width); + BLF_draw_mono(mono, s, len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { + console_step_sel(cdc, len); // glColor4ub(0, 255, 0, 96); // debug - console_draw_sel(cdc->sel, cdc->xy, cdc->console_width, cdc->cwidth, cdc->lheight, bg_sel); - console_step_sel(cdc, cdc->console_width); + console_draw_sel(s, cdc->sel, cdc->xy, len, cdc->cwidth, cdc->lheight, bg_sel); glColor3ubv(fg); } cdc->xy[1] += cdc->lheight; /* check if were out of view bounds */ - if (cdc->xy[1] > cdc->ymax) + if (cdc->xy[1] > cdc->ymax) { + MEM_freeN(offsets); return 0; + } } copy_v2_v2_int(cdc->sel, sel_orig); @@ -196,7 +240,7 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i glColor3ubv(fg); BLF_position(mono, cdc->xy[0], cdc->xy[1], 0); - BLF_draw(mono, str, str_len); + BLF_draw_mono(mono, str, str_len, cdc->cwidth); if (cdc->sel[0] != cdc->sel[1]) { int isel[2]; @@ -205,16 +249,19 @@ static int console_draw_string(ConsoleDrawContext *cdc, const char *str, const i isel[1] = str_len - cdc->sel[0]; // glColor4ub(255, 255, 0, 96); // debug - console_draw_sel(isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel); + console_draw_sel(str, isel, cdc->xy, str_len, cdc->cwidth, cdc->lheight, bg_sel); console_step_sel(cdc, -(str_len + 1)); } cdc->xy[1] += cdc->lheight; - if (cdc->xy[1] > cdc->ymax) + if (cdc->xy[1] > cdc->ymax) { + MEM_freeN(offsets); return 0; + } } + MEM_freeN(offsets); return 1; } diff --git a/source/blender/editors/space_logic/logic_ops.c b/source/blender/editors/space_logic/logic_ops.c index 2313885dbaf..5f2ecbf1b2b 100644 --- a/source/blender/editors/space_logic/logic_ops.c +++ b/source/blender/editors/space_logic/logic_ops.c @@ -122,7 +122,7 @@ static Object *edit_object_property_get(bContext *C, wmOperator *op) /* if ob_name is valid try to find the object with this name * otherwise gets the active object */ - if (BLI_strnlen(ob_name, MAX_NAME) > 0) + if (*ob_name) ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2); else ob = ED_object_active_context(C); @@ -250,7 +250,7 @@ static int sensor_remove_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sensor_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sensor_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_sensor_invoke_properties(C, op)) return sensor_remove_exec(C, op); @@ -295,12 +295,13 @@ static int sensor_add_exec(bContext *C, wmOperator *op) prop = RNA_struct_find_property(&sens_ptr, "type"); RNA_string_get(op->ptr, "name", name); - if (BLI_strnlen(name, MAX_NAME) < 1) { + if (*name) { + BLI_strncpy(sens->name, name, sizeof(sens->name)); + } + else { RNA_property_enum_name(C, &sens_ptr, prop, RNA_property_enum_get(&sens_ptr, prop), &sens_name); BLI_strncpy(sens->name, sens_name, sizeof(sens->name)); } - else - BLI_strncpy(sens->name, name, sizeof(sens->name)); make_unique_prop_names(C, sens->name); ob->scaflag |= OB_SHOWSENS; @@ -355,7 +356,7 @@ static int controller_remove_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int controller_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int controller_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_controller_invoke_properties(C, op)) return controller_remove_exec(C, op); @@ -401,12 +402,13 @@ static int controller_add_exec(bContext *C, wmOperator *op) prop = RNA_struct_find_property(&cont_ptr, "type"); RNA_string_get(op->ptr, "name", name); - if (BLI_strnlen(name, MAX_NAME) < 1) { + if (*name) { + BLI_strncpy(cont->name, name, sizeof(cont->name)); + } + else { RNA_property_enum_name(C, &cont_ptr, prop, RNA_property_enum_get(&cont_ptr, prop), &cont_name); BLI_strncpy(cont->name, cont_name, sizeof(cont->name)); } - else - BLI_strncpy(cont->name, name, sizeof(cont->name)); make_unique_prop_names(C, cont->name); /* set the controller state mask from the current object state. @@ -473,7 +475,7 @@ static int actuator_remove_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int actuator_remove_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int actuator_remove_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_actuator_invoke_properties(C, op)) return actuator_remove_exec(C, op); @@ -518,12 +520,13 @@ static int actuator_add_exec(bContext *C, wmOperator *op) prop = RNA_struct_find_property(&act_ptr, "type"); RNA_string_get(op->ptr, "name", name); - if (BLI_strnlen(name, MAX_NAME) < 1) { + if (*name) { + BLI_strncpy(act->name, name, sizeof(act->name)); + } + else { RNA_property_enum_name(C, &act_ptr, prop, RNA_property_enum_get(&act_ptr, prop), &act_name); BLI_strncpy(act->name, act_name, sizeof(act->name)); } - else - BLI_strncpy(act->name, name, sizeof(act->name)); make_unique_prop_names(C, act->name); ob->scaflag |= OB_SHOWACT; @@ -583,7 +586,7 @@ static int sensor_move_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sensor_move_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sensor_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_sensor_invoke_properties(C, op)) { return sensor_move_exec(C, op); @@ -628,7 +631,7 @@ static int controller_move_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int controller_move_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int controller_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_controller_invoke_properties(C, op)) { return controller_move_exec(C, op); @@ -673,7 +676,7 @@ static int actuator_move_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int actuator_move_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int actuator_move_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (edit_actuator_invoke_properties(C, op)) { return actuator_move_exec(C, op); @@ -711,7 +714,7 @@ static int texface_convert_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int texface_convert_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int texface_convert_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return texface_convert_exec(C, op); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 31c773e613e..b2cae8e5496 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -131,7 +131,6 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA case ANIMTYPE_SCENE: /* Top-Level Widgets doubling up as datablocks */ case ANIMTYPE_OBJECT: - case ANIMTYPE_FILLACTD: /* Action Expander */ case ANIMTYPE_DSMAT: /* Datablock AnimData Expanders */ case ANIMTYPE_DSLAM: case ANIMTYPE_DSCAM: @@ -142,22 +141,34 @@ static int nla_panel_context(const bContext *C, PointerRNA *adt_ptr, PointerRNA case ANIMTYPE_DSPART: case ANIMTYPE_DSMBALL: case ANIMTYPE_DSARM: + case ANIMTYPE_DSMESH: + case ANIMTYPE_DSTEX: + case ANIMTYPE_DSLAT: #ifdef WITH_FREESTYLE case ANIMTYPE_DSLINESTYLE: #endif case ANIMTYPE_DSSPK: { /* for these channels, we only do AnimData */ - if (ale->id && ale->adt) { - if (adt_ptr) { - /* AnimData pointer */ - RNA_pointer_create(ale->id, &RNA_AnimData, ale->adt, adt_ptr); - - /* set found status to -1, since setting to 1 would break the loop - * and potentially skip an active NLA-Track in some cases... - */ - found = -1; + if (ale->adt && adt_ptr) { + ID *id; + + if ((ale->data == NULL) || (ale->type == ANIMTYPE_OBJECT)) { + /* ale->data is not an ID block! */ + id = ale->id; } + else { + /* ale->data is always the proper ID block we need, but ale->id may not be (i.e. for textures) */ + id = (ID *)ale->data; + } + + /* AnimData pointer */ + RNA_pointer_create(id, &RNA_AnimData, ale->adt, adt_ptr); + + /* set found status to -1, since setting to 1 would break the loop + * and potentially skip an active NLA-Track in some cases... + */ + found = -1; } } break; @@ -250,6 +261,28 @@ static void nla_panel_animdata(const bContext *C, Panel *pa) block = uiLayoutGetBlock(layout); uiBlockSetHandleFunc(block, do_nla_region_buttons, NULL); + /* AnimData Source Properties ----------------------------------- */ + + /* icon + id-block name of block where AnimData came from to prevent + * accidentally changing the properties of the wrong action + */ + if (adt_ptr.id.data) { + ID *id = adt_ptr.id.data; + PointerRNA id_ptr; + + RNA_id_pointer_create(id, &id_ptr); + + /* ID-block name > AnimData */ + row = uiLayoutRow(layout, TRUE); + uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_LEFT); + + uiItemL(row, id->name + 2, RNA_struct_ui_icon(id_ptr.type)); /* id-block (src) */ + uiItemL(row, "", VICO_SMALL_TRI_RIGHT_VEC); /* expander */ + uiItemL(row, IFACE_("Animation Data"), ICON_ANIM_DATA); /* animdata */ + + uiItemS(layout); + } + /* Active Action Properties ------------------------------------- */ /* action */ row = uiLayoutRow(layout, TRUE); diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 97581cefc2b..6d091e3c7c4 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -48,6 +48,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_screen.h" +#include "BKE_report.h" #include "ED_anim_api.h" #include "ED_keyframes_edit.h" @@ -140,7 +141,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor } else { Base *b; - + /* deselect all */ /* TODO: should this deselect all other types of channels too? */ for (b = sce->base.first; b; b = b->next) { @@ -268,6 +269,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor { AnimData *adt = BKE_animdata_from_id(ale->id); + /* button area... */ if (x >= (v2d->cur.xmax - NLACHANNEL_BUTTON_WIDTH)) { if (nlaedit_is_tweakmode_on(ac) == 0) { /* 'push-down' action - only usable when not in TweakMode */ @@ -283,6 +285,30 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor /* changes to NLA-Action occurred */ notifierFlags |= ND_NLA_ACTCHANGE; } + /* OR rest of name... */ + else { + /* NOTE: rest of NLA-Action name doubles for operating on the AnimData block + * - this is useful when there's no clear divider, and makes more sense in + * the case of users trying to use this to change actions + */ + + /* select/deselect */ + if (selectmode == SELECT_INVERT) { + /* inverse selection status of this AnimData block only */ + adt->flag ^= ADT_UI_SELECTED; + } + else { + /* select AnimData block by itself */ + ANIM_deselect_anim_channels(ac, ac->data, ac->datatype, 0, ACHANNEL_SETFLAG_CLEAR); + adt->flag |= ADT_UI_SELECTED; + } + + /* set active? */ + if (adt->flag & ADT_UI_SELECTED) + adt->flag |= ADT_UI_ACTIVE; + + notifierFlags |= (ND_ANIMCHAN | NA_SELECTED); + } } break; @@ -301,7 +327,7 @@ static int mouse_nla_channels(bAnimContext *ac, float x, int channel_index, shor /* ------------------- */ /* handle clicking */ -static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int nlachannels_mouseclick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; SpaceNla *snla; @@ -358,7 +384,7 @@ void NLA_OT_channels_click(wmOperatorType *ot) ot->poll = ED_operator_nla_active; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* props */ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY @@ -371,24 +397,18 @@ void NLA_OT_channels_click(wmOperatorType *ot) /* ******************** Add Tracks Operator ***************************** */ /* Add NLA Tracks to the same AnimData block as a selected track, or above the selected tracks */ -static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op) +/* helper - add NLA Tracks alongside existing ones */ +static bool nlaedit_add_tracks_existing(bAnimContext *ac, bool above_sel) { - bAnimContext ac; - ListBase anim_data = {NULL, NULL}; bAnimListElem *ale; int filter; - AnimData *lastAdt = NULL; - short above_sel = RNA_boolean_get(op->ptr, "above_selected"); + bool added = false; - /* get editor data */ - if (ANIM_animdata_get_context(C, &ac) == 0) - return OPERATOR_CANCELLED; - - /* get a list of the AnimData blocks being shown in the NLA */ - filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL); - ANIM_animdata_filter(&ac, &anim_data, filter, ac.data, ac.datatype); + /* get a list of the (selected) NLA Tracks being shown in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); /* add tracks... */ for (ale = anim_data.first; ale; ale = ale->next) { @@ -402,11 +422,13 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op) if (above_sel) { /* just add a new one above this one */ add_nlatrack(adt, nlt); + added = true; } else if ((lastAdt == NULL) || (adt != lastAdt)) { /* add one track to the top of the owning AnimData's stack, then don't add anymore to this stack */ add_nlatrack(adt, NULL); lastAdt = adt; + added = true; } } } @@ -414,17 +436,80 @@ static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op) /* free temp data */ BLI_freelistN(&anim_data); - /* set notifier that things have changed */ - WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + return added; +} + +/* helper - add NLA Tracks to empty (and selected) AnimData blocks */ +static bool nlaedit_add_tracks_empty(bAnimContext *ac) +{ + ListBase anim_data = {NULL, NULL}; + bAnimListElem *ale; + int filter; + bool added = false; - /* done */ - return OPERATOR_FINISHED; + /* get a list of the selected AnimData blocks in the NLA */ + filter = (ANIMFILTER_DATA_VISIBLE | ANIMFILTER_LIST_VISIBLE | ANIMFILTER_ANIMDATA | ANIMFILTER_SEL | ANIMFILTER_NODUPLIS); + ANIM_animdata_filter(ac, &anim_data, filter, ac->data, ac->datatype); + + /* check if selected AnimData blocks are empty, and add tracks if so... */ + for (ale = anim_data.first; ale; ale = ale->next) { + AnimData *adt = ale->adt; + + /* sanity check */ + BLI_assert(adt->flag & ADT_UI_SELECTED); + + /* ensure it is empty */ + if (adt->nla_tracks.first == NULL) { + /* add new track to this AnimData block then */ + add_nlatrack(adt, NULL); + added = true; + } + } + + /* cleanup */ + BLI_freelistN(&anim_data); + + return added; +} + +/* ----- */ + +static int nlaedit_add_tracks_exec(bContext *C, wmOperator *op) +{ + bAnimContext ac; + bool above_sel = RNA_boolean_get(op->ptr, "above_selected"); + bool op_done = false; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* perform adding in two passes - existing first so that we don't double up for empty */ + op_done |= nlaedit_add_tracks_existing(&ac, above_sel); + op_done |= nlaedit_add_tracks_empty(&ac); + + /* done? */ + if (op_done) { + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; + } + else { + /* failed to add any tracks */ + BKE_report(op->reports, RPT_WARNING, + "Select an existing NLA Track or an empty action line first"); + + /* not done */ + return OPERATOR_CANCELLED; + } } void NLA_OT_tracks_add(wmOperatorType *ot) { /* identifiers */ - ot->name = "Add Track(s)"; + ot->name = "Add Tracks"; ot->idname = "NLA_OT_tracks_add"; ot->description = "Add NLA-Tracks above/after the selected tracks"; @@ -485,11 +570,11 @@ static int nlaedit_delete_tracks_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -void NLA_OT_delete_tracks(wmOperatorType *ot) +void NLA_OT_tracks_delete(wmOperatorType *ot) { /* identifiers */ ot->name = "Delete Tracks"; - ot->idname = "NLA_OT_delete_tracks"; + ot->idname = "NLA_OT_tracks_delete"; ot->description = "Delete selected NLA-Tracks and the strips they contain"; /* api callbacks */ @@ -501,3 +586,59 @@ void NLA_OT_delete_tracks(wmOperatorType *ot) } /* *********************************************** */ +/* AnimData Related Operators */ + +/* ******************** Include Objects Operator ***************************** */ +/* Include selected objects in NLA Editor, by giving them AnimData blocks + * NOTE: This doesn't help for non-object AnimData, where we do not have any effective + * selection mechanism in place. Unfortunately, this means that non-object AnimData + * once again becomes a second-class citizen here. However, at least for the most + * common use case, we now have a nice shortcut again. + */ + +static int nlaedit_objects_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + bAnimContext ac; + SpaceNla *snla; + + /* get editor data */ + if (ANIM_animdata_get_context(C, &ac) == 0) + return OPERATOR_CANCELLED; + + /* ensure that filters are set so that the effect will be immediately visible */ + snla = (SpaceNla *)ac.sl; + if (snla && snla->ads) { + snla->ads->filterflag &= ~ADS_FILTER_NLA_NOACT; + } + + /* operate on selected objects... */ + CTX_DATA_BEGIN (C, Object *, ob, selected_objects) + { + /* ensure that object has AnimData... that's all */ + BKE_id_add_animdata(&ob->id); + } + CTX_DATA_END; + + /* set notifier that things have changed */ + WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); + + /* done */ + return OPERATOR_FINISHED; +} + +void NLA_OT_selected_objects_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Include Selected Objects"; + ot->idname = "NLA_OT_selected_objects_add"; + ot->description = "Make selected objects appear in NLA Editor by adding Animation Data"; + + /* api callbacks */ + ot->exec = nlaedit_objects_add_exec; + ot->poll = nlaop_poll_tweakmode_off; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* *********************************************** */ diff --git a/source/blender/editors/space_nla/nla_draw.c b/source/blender/editors/space_nla/nla_draw.c index acfb4a51b14..56f2ec9ebe1 100644 --- a/source/blender/editors/space_nla/nla_draw.c +++ b/source/blender/editors/space_nla/nla_draw.c @@ -695,11 +695,8 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View special = ICON_ACTION; - if (act) - BLI_snprintf(name, sizeof(name), "%s", act->id.name + 2); - else - BLI_strncpy(name, "<No Action>", sizeof(name)); - + BLI_strncpy(name, act ? act->id.name + 2 : "<No Action>", sizeof(name)); + /* draw manually still */ do_draw = TRUE; } @@ -759,7 +756,6 @@ static void draw_nla_channel_list_gl(bAnimContext *ac, ListBase *anim_data, View glEnable(GL_BLEND); /* draw backing strip behind channel name */ - // FIXME: hardcoded colors!!! if (group == 5) { float color[4]; diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 484eb47fa8e..17d403789cf 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -200,7 +200,7 @@ static int nlaedit_disable_tweakmode_exec(bContext *C, wmOperator *op) for (ale = anim_data.first; ale; ale = ale->next) { AnimData *adt = ale->data; - /* try entering tweakmode if valid */ + /* to be sure, just exit tweakmode... */ BKE_nla_tweakmode_exit(adt); } @@ -891,7 +891,7 @@ static int nlaedit_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_CANCELLED; } -static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int nlaedit_duplicate_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { nlaedit_duplicate_exec(C, op); @@ -1627,7 +1627,7 @@ void NLA_OT_action_sync_length(wmOperatorType *ot) /* api callbacks */ ot->exec = nlaedit_sync_actlen_exec; - ot->poll = ED_operator_nla_active; // XXX: is this satisfactory... probably requires a check for active strip... + ot->poll = nlaop_poll_tweakmode_off; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -1801,7 +1801,7 @@ void NLA_OT_clear_scale(wmOperatorType *ot) /* defines for snap keyframes tool */ static EnumPropertyItem prop_nlaedit_snap_types[] = { - {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current frame", ""}, + {NLAEDIT_SNAP_CFRA, "CFRA", 0, "Current Frame", ""}, {NLAEDIT_SNAP_NEAREST_FRAME, "NEAREST_FRAME", 0, "Nearest Frame", ""}, // XXX as single entry? {NLAEDIT_SNAP_NEAREST_SECOND, "NEAREST_SECOND", 0, "Nearest Second", ""}, // XXX as single entry? {NLAEDIT_SNAP_NEAREST_MARKER, "NEAREST_MARKER", 0, "Nearest Marker", ""}, @@ -1947,7 +1947,7 @@ void NLA_OT_snap(wmOperatorType *ot) /* ******************** Add F-Modifier Operator *********************** */ /* present a special customised popup menu for this, with some filtering */ -static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int nla_fmodifier_add_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; @@ -2021,8 +2021,9 @@ static int nla_fmodifier_add_exec(bContext *C, wmOperator *op) /* add F-Modifier of specified type to selected, and make it the active one */ fcm = add_fmodifier(&strip->modifiers, type); - if (fcm) + if (fcm) { set_active_fmodifier(&strip->modifiers, fcm); + } else { BKE_reportf(op->reports, RPT_ERROR, "Modifier could not be added to (%s : %s) (see console for details)", @@ -2101,8 +2102,10 @@ static int nla_fmodifier_copy_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_ERROR, "No F-Modifiers available to be copied"); return OPERATOR_CANCELLED; } - else + else { + /* no updates needed - copy is non-destructive operation */ return OPERATOR_FINISHED; + } } void NLA_OT_fmodifier_copy(wmOperatorType *ot) @@ -2156,8 +2159,6 @@ static int nla_fmodifier_paste_exec(bContext *C, wmOperator *op) /* successful or not? */ if (ok) { - /* set notifier that things have changed */ - /* set notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_NLA | NA_EDITED, NULL); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_nla/nla_intern.h b/source/blender/editors/space_nla/nla_intern.h index 398d2d5f1f4..450b85738ad 100644 --- a/source/blender/editors/space_nla/nla_intern.h +++ b/source/blender/editors/space_nla/nla_intern.h @@ -125,7 +125,9 @@ void NLA_OT_fmodifier_paste(wmOperatorType *ot); void NLA_OT_channels_click(wmOperatorType *ot); void NLA_OT_tracks_add(wmOperatorType *ot); -void NLA_OT_delete_tracks(wmOperatorType *ot); +void NLA_OT_tracks_delete(wmOperatorType *ot); + +void NLA_OT_selected_objects_add(wmOperatorType *ot); /* **************************************** */ /* nla_ops.c */ diff --git a/source/blender/editors/space_nla/nla_ops.c b/source/blender/editors/space_nla/nla_ops.c index 54ade829c0d..fb0f11ffd87 100644 --- a/source/blender/editors/space_nla/nla_ops.c +++ b/source/blender/editors/space_nla/nla_ops.c @@ -120,7 +120,9 @@ void nla_operatortypes(void) WM_operatortype_append(NLA_OT_channels_click); WM_operatortype_append(NLA_OT_tracks_add); - WM_operatortype_append(NLA_OT_delete_tracks); + WM_operatortype_append(NLA_OT_tracks_delete); + + WM_operatortype_append(NLA_OT_selected_objects_add); /* select */ WM_operatortype_append(NLA_OT_click_select); @@ -188,8 +190,8 @@ static void nla_keymap_channels(wmKeyMap *keymap) RNA_boolean_set(kmi->ptr, "above_selected", TRUE); /* delete tracks */ - WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", XKEY, KM_PRESS, 0, 0); - WM_keymap_add_item(keymap, "NLA_OT_delete_tracks", DELKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", XKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "NLA_OT_tracks_delete", DELKEY, KM_PRESS, 0, 0); } static void nla_keymap_main(wmKeyConfig *keyconf, wmKeyMap *keymap) diff --git a/source/blender/editors/space_nla/nla_select.c b/source/blender/editors/space_nla/nla_select.c index 97553b7aa56..3e414233add 100644 --- a/source/blender/editors/space_nla/nla_select.c +++ b/source/blender/editors/space_nla/nla_select.c @@ -451,7 +451,7 @@ static int nlaedit_select_leftright_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int nlaedit_select_leftright_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; short leftright = RNA_enum_get(op->ptr, "mode"); @@ -613,7 +613,7 @@ static void mouse_nla_strips(bContext *C, bAnimContext *ac, const int mval[2], s /* ------------------- */ /* handle clicking */ -static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int nlaedit_clickselect_invoke(bContext *C, wmOperator *op, const wmEvent *event) { bAnimContext ac; /* Scene *scene; */ /* UNUSED */ @@ -660,7 +660,7 @@ void NLA_OT_click_select(wmOperatorType *ot) ot->poll = ED_operator_nla_active; /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->flag = OPTYPE_UNDO; /* properties */ prop = RNA_def_boolean(ot->srna, "extend", 0, "Extend Select", ""); // SHIFTKEY diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 8a2e03f2660..4a14d6ba6fd 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -687,14 +687,14 @@ static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket * static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode, bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out) { - const float dpi_fac = 1.0f; + const float dpi_fac = UI_DPI_FAC; bNodeTree *ngroup = (bNodeTree *)gnode->id; bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type); uiBut *bt; float offset; int draw_value; const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; - const float socket_size = NODE_SOCKSIZE * dpi_fac; + const float socket_size = NODE_SOCKSIZE; const float arrowbutw = 0.8f * UI_UNIT_X; const short co_text_w = 72 * dpi_fac; const float co_margin = 6.0f * dpi_fac; @@ -799,12 +799,12 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN uiLayout *layout; PointerRNA ptr; rctf rect = gnode->totr; - const float dpi_fac = 1.0f; + const float dpi_fac = UI_DPI_FAC; const float node_group_frame = NODE_GROUP_FRAME * dpi_fac; const float group_header = 26 * dpi_fac; int index; - + /* backdrop header */ glEnable(GL_BLEND); uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); @@ -1296,11 +1296,11 @@ static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), Poin uiItemR(row, ptr, "scale", 0, "", ICON_NONE); row = uiLayoutRow(layout, TRUE); - uiItemR(row, ptr, "use_min", 0, "Min", ICON_NONE); + uiItemR(row, ptr, "use_min", 0, IFACE_("Min"), ICON_NONE); uiItemR(row, ptr, "min", 0, "", ICON_NONE); row = uiLayoutRow(layout, TRUE); - uiItemR(row, ptr, "use_max", 0, "Max", ICON_NONE); + uiItemR(row, ptr, "use_max", 0, IFACE_("Max"), ICON_NONE); uiItemR(row, ptr, "max", 0, "", ICON_NONE); } @@ -3301,7 +3301,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, display_buffer); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); @@ -3309,7 +3309,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) else { glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, display_buffer); glPixelZoom(1.0f, 1.0f); } @@ -3320,6 +3320,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) /** @note draw selected info on backdrop */ if (snode->edittree) { bNode *node = snode->edittree->nodes.first; + rctf *viewer_border = &snode->edittree->viewer_border; while (node) { if (node->flag & NODE_SELECT) { if (node->typeinfo->uibackdropfunc) { @@ -3328,6 +3329,23 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) } node = node->next; } + + if ((snode->edittree->flag & NTREE_VIEWER_BORDER) && + viewer_border->xmin < viewer_border->xmax && + viewer_border->ymin < viewer_border->ymax) + { + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + setlinestyle(3); + cpack(0x4040FF); + + glRectf(x + snode->zoom * viewer_border->xmin * ibuf->x, + y + snode->zoom * viewer_border->ymin * ibuf->y, + x + snode->zoom * viewer_border->xmax * ibuf->x, + y + snode->zoom * viewer_border->ymax * ibuf->y); + + setlinestyle(0); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } } glMatrixMode(GL_PROJECTION); @@ -3340,57 +3358,6 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) } } -#if 0 -/* note: needs to be userpref or opengl profile option */ -static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode) -{ - - draw_nodespace_grid(snode); - - if (snode->flag & SNODE_BACKDRAW) { - Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); - ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); - if (ibuf) { - int x, y; - float zoom = 1.0; - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - - glaDefine2DArea(&sa->winrct); - - if (ibuf->x > sa->winx || ibuf->y > sa->winy) { - float zoomx, zoomy; - zoomx = (float)sa->winx / ibuf->x; - zoomy = (float)sa->winy / ibuf->y; - zoom = min_ff(zoomx, zoomy); - } - - x = (sa->winx - zoom * ibuf->x) / 2 + snode->xof; - y = (sa->winy - zoom * ibuf->y) / 2 + snode->yof; - - glPixelZoom(zoom, zoom); - - glColor4f(1.0, 1.0, 1.0, 1.0); - if (ibuf->rect) - glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); - else if (ibuf->channels == 4) - glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float); - - glPixelZoom(1.0, 1.0); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - BKE_image_release_ibuf(ima, ibuf, NULL); - } - } -} -#endif /* if v2d not NULL, it clips and returns 0 if not visible */ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol) diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index 4943bb45113..235d91ecd92 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -400,7 +400,7 @@ static int node_add_file_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int node_add_file_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_add_file_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceNode *snode = CTX_wm_space_node(C); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 34f7799d47c..d6a3a6a6a3f 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -629,7 +629,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* premul graphics */ glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, preview->rect); + glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); glDisable(GL_BLEND); glPixelZoom(1.0f, 1.0f); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index fb4e4f62e52..941bd783c39 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -73,6 +73,8 @@ #include "GPU_material.h" +#include "IMB_imbuf_types.h" + #include "node_intern.h" /* own include */ #define USE_ESC_COMPO @@ -835,7 +837,7 @@ typedef struct NodeSizeWidget { int directions; } NodeSizeWidget; -static void node_resize_init(bContext *C, wmOperator *op, wmEvent *UNUSED(event), bNode *node, int dir) +static void node_resize_init(bContext *C, wmOperator *op, const wmEvent *UNUSED(event), bNode *node, int dir) { SpaceNode *snode = CTX_wm_space_node(C); @@ -868,7 +870,7 @@ static void node_resize_exit(bContext *C, wmOperator *op, int UNUSED(cancel)) op->customdata = NULL; } -static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event) +static int node_resize_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -971,7 +973,7 @@ static int node_resize_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int node_resize_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_resize_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -1055,7 +1057,7 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) } /* return 0, nothing done */ -static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode * snode) +static int UNUSED_FUNCTION(node_mouse_groupheader) (SpaceNode *snode) { bNode *gnode; float mx = 0, my = 0; @@ -2138,7 +2140,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_clipboard_paste_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceNode *snode = CTX_wm_space_node(C); @@ -2281,3 +2283,105 @@ void NODE_OT_shader_script_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* ********************** Viewer border ******************/ + +static void viewer_border_corner_to_backdrop(SpaceNode *snode, ARegion *ar, int x, int y, + int backdrop_width, int backdrop_height, + float *fx, float *fy) +{ + float bufx, bufy; + + bufx = backdrop_width * snode->zoom; + bufy = backdrop_height * snode->zoom; + + *fx = (bufx > 0.0f ? ((float) x - 0.5f * ar->winx - snode->xof) / bufx + 0.5f : 0.0f); + *fy = (bufy > 0.0f ? ((float) y - 0.5f * ar->winy - snode->yof) / bufy + 0.5f : 0.0f); +} + +static int viewer_border_exec(bContext *C, wmOperator *op) +{ + Image *ima; + void *lock; + ImBuf *ibuf; + + ED_preview_kill_jobs(C); + + ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + ARegion *ar = CTX_wm_region(C); + SpaceNode *snode = CTX_wm_space_node(C); + bNodeTree *btree = snode->edittree; + rcti rect; + rctf rectf; + + /* get border from operator */ + WM_operator_properties_border_to_rcti(op, &rect); + + /* convert border to unified space within backdrop image */ + viewer_border_corner_to_backdrop(snode, ar, rect.xmin, rect.ymin, ibuf->x, ibuf->y, + &rectf.xmin, &rectf.ymin); + + viewer_border_corner_to_backdrop(snode, ar, rect.xmax, rect.ymax, ibuf->x, ibuf->y, + &rectf.xmax, &rectf.ymax); + + /* clamp coordinates */ + rectf.xmin = max_ff(rectf.xmin, 0.0f); + rectf.ymin = max_ff(rectf.ymin, 0.0f); + rectf.xmax = min_ff(rectf.xmax, 1.0f); + rectf.ymax = min_ff(rectf.ymax, 1.0f); + + if (rectf.xmin < rectf.xmax && rectf.ymin < rectf.ymax) { + btree->viewer_border = rectf; + + if (rectf.xmin == 0.0f && rectf.ymin == 0.0f && + rectf.xmax == 1.0f && rectf.ymax == 1.0f) + { + btree->flag &= ~NTREE_VIEWER_BORDER; + } + else { + if (ibuf->rect) + memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y); + + if (ibuf->rect_float) + memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float)); + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + btree->flag |= NTREE_VIEWER_BORDER; + } + + snode_notify(C, snode); + WM_event_add_notifier(C, NC_NODE | ND_DISPLAY, NULL); + } + else { + btree->flag &= ~NTREE_VIEWER_BORDER; + } + } + + BKE_image_release_ibuf(ima, ibuf, lock); + + return OPERATOR_FINISHED; +} + +void NODE_OT_viewer_border(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Viewer Border"; + ot->description = "Set the boundaries for viewer operations"; + ot->idname = "NODE_OT_viewer_border"; + + /* api callbacks */ + ot->invoke = WM_border_select_invoke; + ot->exec = viewer_border_exec; + ot->modal = WM_border_select_modal; + ot->cancel = WM_border_select_cancel; + ot->poll = composite_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_border(ot, TRUE); +} diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 7b7b98f132c..6696284b169 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -133,7 +133,7 @@ static int node_group_edit_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int node_group_edit_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int node_group_edit_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceNode *snode = CTX_wm_space_node(C); bNode *gnode; @@ -789,7 +789,7 @@ static int node_group_separate_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int node_group_separate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Separate"), ICON_NONE); uiLayout *layout = uiPupMenuLayout(pup); @@ -1146,7 +1146,7 @@ static int node_group_make_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int node_group_make_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { SpaceNode *snode = CTX_wm_space_node(C); bNode *act = nodeGetActive(snode->edittree); diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index e8dd1cf1528..cbf7101a101 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -217,6 +217,8 @@ void NODE_OT_clipboard_paste(struct wmOperatorType *ot); void NODE_OT_shader_script_update(struct wmOperatorType *ot); +void NODE_OT_viewer_border(struct wmOperatorType *ot); + extern const char *node_context_dir[]; // XXXXXX diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 8adccd9e6c4..d16c6627d3f 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -120,6 +120,8 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_clipboard_paste); WM_operatortype_append(NODE_OT_shader_script_update); + + WM_operatortype_append(NODE_OT_viewer_border); } void ED_operatormacros_node(void) @@ -298,5 +300,7 @@ void node_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "NODE_OT_clipboard_copy", CKEY, KM_PRESS, KM_CTRL, 0); WM_keymap_add_item(keymap, "NODE_OT_clipboard_paste", VKEY, KM_PRESS, KM_CTRL, 0); + WM_keymap_add_item(keymap, "NODE_OT_viewer_border", BKEY, KM_PRESS, KM_CTRL, 0); + transform_keymap_for_space(keyconf, keymap, SPACE_NODE); } diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 8d7eef22822..097e4f418e0 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -448,7 +448,7 @@ static int outside_group_rect(SpaceNode *snode) /* loop that adds a nodelink, called by function below */ /* in_out = starting socket */ -static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event) +static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -702,7 +702,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) return nldrag; } -static int node_link_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_link_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -840,7 +840,9 @@ static int cut_links_exec(bContext *C, wmOperator *op) if (i > 1) { int found = FALSE; bNodeLink *link, *next; - + + ED_preview_kill_jobs(C); + for (link = snode->edittree->links.first; link; link = next) { next = link->next; @@ -1181,7 +1183,7 @@ static int node_attach_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int node_attach_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_attach_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceNode *snode = CTX_wm_space_node(C); diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 7d2b80d50ba..c917b8ee756 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -429,7 +429,7 @@ static int node_select_exec(bContext *C, wmOperator *op) } } -static int node_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RNA_int_set(op->ptr, "mouse_x", event->mval[0]); RNA_int_set(op->ptr, "mouse_y", event->mval[1]); @@ -494,7 +494,7 @@ static int node_borderselect_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int node_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int node_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int tweak = RNA_boolean_get(op->ptr, "tweak"); diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index a69e73c1489..a8e84e0a0e5 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -196,7 +196,7 @@ typedef struct NodeViewMove { int xmin, ymin, xmax, ymax; } NodeViewMove; -static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) +static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -231,7 +231,7 @@ static int snode_bg_viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int snode_bg_viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -413,7 +413,7 @@ int ED_space_node_color_sample(SpaceNode *snode, ARegion *ar, int mval[2], float return ret; } -static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) +static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -513,7 +513,7 @@ static void sample_exit(bContext *C, wmOperator *op) MEM_freeN(info); } -static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceNode *snode = CTX_wm_space_node(C); ARegion *ar = CTX_wm_region(C); @@ -534,7 +534,7 @@ static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int sample_modal(bContext *C, wmOperator *op, wmEvent *event) +static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 264bea5f871..75f28baf558 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -423,7 +423,7 @@ static void node_main_area_draw(const bContext *C, ARegion *ar) /* ************* dropboxes ************* */ -static int node_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int node_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_ID) { ID *id = (ID *)drag->poin; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index cacbc6d6268..26a0d0a2fa8 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -41,6 +41,8 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" +#include "BLF_translation.h" + #include "BKE_context.h" #include "BKE_deform.h" #include "BKE_depsgraph.h" @@ -50,6 +52,7 @@ #include "BKE_modifier.h" #include "BKE_report.h" #include "BKE_scene.h" +#include "BKE_object.h" #include "ED_armature.h" #include "ED_object.h" @@ -129,11 +132,66 @@ static void outliner_rna_width(SpaceOops *soops, ListBase *lb, int *w, int start /* ****************************************************** */ +static void restrictbutton_recursive_ebone(bContext *C, EditBone *ebone_parent, int flag, bool set_flag) +{ + Object *obedit = CTX_data_edit_object(C); + bArmature *arm = obedit->data; + EditBone *ebone; + + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) { + if (set_flag) { + ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + ebone->flag |= flag; + } + else { + ebone->flag &= ~flag; + } + } + } +} + +static void restrictbutton_recursive_bone(bContext *C, bArmature *arm, Bone *bone_parent, int flag, bool set_flag) +{ + Bone *bone; + for (bone = bone_parent->childbase.first; bone; bone = bone->next) { + if (set_flag) { + bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + bone->flag |= flag; + } + else { + bone->flag &= ~flag; + } + restrictbutton_recursive_bone(C, arm, bone, flag, set_flag); + } + +} + +static void restrictbutton_recursive_child(bContext *C, Scene *scene, Object *ob_parent, char flag, + bool state, bool deselect) +{ + Main *bmain = CTX_data_main(C); + Object *ob; + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (BKE_object_is_child_recursive(ob_parent, ob)) { + if (state) { + ob->restrictflag |= flag; + if (deselect) { + ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); + } + } + else { + ob->restrictflag &= ~flag; + } + } + } +} + static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2) { Scene *scene = (Scene *)poin; Object *ob = (Object *)poin2; - + if (!common_restrict_check(C, ob)) return; /* deselect objects that are invisible */ @@ -142,6 +200,12 @@ static void restrictbutton_view_cb(bContext *C, void *poin, void *poin2) * so have to do loop to find it. */ ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); } + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_VIEW, + (ob->restrictflag & OB_RESTRICT_VIEW) != 0, true); + } + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } @@ -159,12 +223,25 @@ static void restrictbutton_sel_cb(bContext *C, void *poin, void *poin2) * so have to do loop to find it. */ ED_base_object_select(BKE_scene_base_find(scene, ob), BA_DESELECT); } + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_child(C, scene, ob, OB_RESTRICT_SELECT, + (ob->restrictflag & OB_RESTRICT_SELECT) != 0, true); + } + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } -static void restrictbutton_rend_cb(bContext *C, void *poin, void *UNUSED(poin2)) +static void restrictbutton_rend_cb(bContext *C, void *poin, void *poin2) { + Object *ob = (Object *)poin2; + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_child(C, (Scene *)poin, ob, OB_RESTRICT_RENDER, + (ob->restrictflag & OB_RESTRICT_RENDER) != 0, false); + } + WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, poin); } @@ -182,19 +259,59 @@ static void restrictbutton_modifier_cb(bContext *C, void *UNUSED(poin), void *po WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); } -static void restrictbutton_bone_cb(bContext *C, void *UNUSED(poin), void *poin2) +static void restrictbutton_bone_visibility_cb(bContext *C, void *poin, void *poin2) { + bArmature *arm = (bArmature *)poin; Bone *bone = (Bone *)poin2; if (bone && (bone->flag & BONE_HIDDEN_P)) bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_bone(C, arm, bone, BONE_HIDDEN_P, (bone->flag & BONE_HIDDEN_P) != 0); + } + + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); +} + +static void restrictbutton_bone_select_cb(bContext *C, void *poin, void *poin2) +{ + bArmature *arm = (bArmature *)poin; + Bone *bone = (Bone *)poin2; + if (bone && (bone->flag & BONE_UNSELECTABLE)) + bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_bone(C, arm, bone, BONE_UNSELECTABLE, (bone->flag & BONE_UNSELECTABLE) != 0); + } + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); } -static void restrictbutton_ebone_cb(bContext *C, void *UNUSED(poin), void *poin2) +static void restrictbutton_ebone_select_cb(bContext *C, void *UNUSED(poin), void *poin2) { EditBone *ebone = (EditBone *)poin2; - if (ebone && (ebone->flag & BONE_HIDDEN_A)) + + if (ebone->flag & BONE_UNSELECTABLE) { ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_ebone(C, ebone, BONE_UNSELECTABLE, (ebone->flag & BONE_UNSELECTABLE) != 0); + } + + WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); +} + +static void restrictbutton_ebone_visibility_cb(bContext *C, void *UNUSED(poin), void *poin2) +{ + EditBone *ebone = (EditBone *)poin2; + if (ebone->flag & BONE_HIDDEN_A) { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + + if (CTX_wm_window(C)->eventstate->ctrl) { + restrictbutton_recursive_ebone(C, ebone, BONE_HIDDEN_A, (ebone->flag & BONE_HIDDEN_A) != 0); + } WM_event_add_notifier(C, NC_OBJECT | ND_POSE, NULL); } @@ -238,7 +355,7 @@ static int group_select_flag(Group *gr) } void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag) -{ +{ Scene *scene = (Scene *)poin; GroupObject *gob; Group *gr = (Group *)poin2; @@ -297,7 +414,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) TreeElement *te = outliner_find_tse(soops, tselem); if (tselem->type == 0) { - test_idbutton(tselem->id->name + 2); // library.c, unique name and alpha sort + test_idbutton(tselem->id->name); // library.c, unique name and alpha sort switch (GS(tselem->id->name)) { case ID_MA: @@ -332,7 +449,7 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) defgroup_unique_name(te->directdata, (Object *)tselem->id); // id = object break; case TSE_NLA_ACTION: - test_idbutton(tselem->id->name + 2); + test_idbutton(tselem->id->name); break; case TSE_EBONE: { @@ -389,7 +506,8 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname) Object *ob = (Object *)tselem->id; // id = object bActionGroup *grp = te->directdata; - BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), sizeof(grp->name)); + BLI_uniquename(&ob->pose->agroups, grp, "Group", '.', offsetof(bActionGroup, name), + sizeof(grp->name)); WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob); } break; @@ -422,17 +540,20 @@ 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, UI_UNIT_X, UI_UNIT_Y, - &ptr, "hide", -1, 0, 0, -1, -1, NULL); + &ptr, "hide", -1, 0, 0, -1, -1, + TIP_("Restrict viewport visibility (Ctrl - Recursive)")); 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, UI_UNIT_X, UI_UNIT_Y, - &ptr, "hide_select", -1, 0, 0, -1, -1, NULL); + &ptr, "hide_select", -1, 0, 0, -1, -1, + TIP_("Restrict viewport selection (Ctrl - Recursive)")); 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, UI_UNIT_X, UI_UNIT_Y, - &ptr, "hide_render", -1, 0, 0, -1, -1, NULL); + &ptr, "hide_render", -1, 0, 0, -1, -1, + TIP_("Restrict rendering (Ctrl - Recursive)")); uiButSetFunc(bt, restrictbutton_rend_cb, scene, ob); uiBlockSetEmboss(block, UI_EMBOSS); @@ -447,19 +568,19 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar restrict_bool = group_restrict_flag(gr, OB_RESTRICT_VIEW); bt = uiDefIconBut(block, ICONTOG, 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, UI_UNIT_Y, - NULL, 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); + NULL, 0, 0, 0, 0, TIP_("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, ICONTOG, 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, UI_UNIT_Y, - NULL, 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); + NULL, 0, 0, 0, 0, TIP_("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, ICONTOG, 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, UI_UNIT_Y, - NULL, 0, 0, 0, 0, "Restrict/Allow renderability"); + NULL, 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); uiButSetFunc(bt, restrictbutton_gr_restrict_render, scene, gr); uiBlockSetEmboss(block, UI_EMBOSS); @@ -469,8 +590,8 @@ 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, UI_UNIT_X, UI_UNIT_Y, - te->directdata, 0, 0, 0, 0, "Render this RenderLayer"); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, te->directdata, 0, 0, 0, 0, TIP_("Render this RenderLayer")); uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); uiBlockSetEmboss(block, UI_EMBOSS); @@ -483,8 +604,8 @@ 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, UI_UNIT_X, UI_UNIT_Y, - layflag, 0, 0, 0, 0, "Render this Pass"); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, layflag, 0, 0, 0, 0, TIP_("Render this Pass")); uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); layflag++; /* is lay_xor */ @@ -492,8 +613,8 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar 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, UI_UNIT_X, UI_UNIT_Y, - 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, + UI_UNIT_Y, layflag, 0, 0, 0, 0, TIP_("Exclude this Pass from Combined")); } uiButSetFunc(bt, restrictbutton_r_lay_cb, tselem->id, NULL); @@ -505,43 +626,49 @@ 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, UI_UNIT_X, UI_UNIT_Y, - &(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, + UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, + TIP_("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, UI_UNIT_X, UI_UNIT_Y, - &(md->mode), 0, 0, 0, 0, "Restrict/Allow renderability"); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, &(md->mode), 0, 0, 0, 0, TIP_("Restrict/Allow renderability")); uiButSetFunc(bt, restrictbutton_modifier_cb, scene, ob); } else if (tselem->type == TSE_POSE_CHANNEL) { bPoseChannel *pchan = (bPoseChannel *)te->directdata; Bone *bone = pchan->bone; + ob = (Object *)tselem->id; 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, UI_UNIT_X, UI_UNIT_Y, - &(bone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); - uiButSetFunc(bt, restrictbutton_bone_cb, NULL, bone); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow visibility in the 3D View")); + uiButSetFunc(bt, restrictbutton_bone_visibility_cb, ob->data, bone); bt = uiDefIconButBitI(block, ICONTOG, BONE_UNSELECTABLE, 0, ICON_RESTRICT_SELECT_OFF, - (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, UI_UNIT_Y, - &(bone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); - uiButSetFunc(bt, restrictbutton_bone_cb, NULL, NULL); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, &(bone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow selection in the 3D View")); + uiButSetFunc(bt, restrictbutton_bone_select_cb, ob->data, bone); } else if (tselem->type == TSE_EBONE) { EditBone *ebone = (EditBone *)te->directdata; 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, UI_UNIT_X, UI_UNIT_Y, - &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow visibility in the 3D View"); - uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, ebone); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow visibility in the 3D View")); + uiButSetFunc(bt, restrictbutton_ebone_visibility_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, UI_UNIT_X, UI_UNIT_Y, - &(ebone->flag), 0, 0, 0, 0, "Restrict/Allow selection in the 3D View"); - uiButSetFunc(bt, restrictbutton_ebone_cb, NULL, NULL); + (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_SELECTX), (int)te->ys, UI_UNIT_X, + UI_UNIT_Y, &(ebone->flag), 0, 0, 0, 0, + TIP_("Restrict/Allow selection in the 3D View")); + uiButSetFunc(bt, restrictbutton_ebone_select_cb, NULL, ebone); } } @@ -571,7 +698,7 @@ static void outliner_draw_rnacols(ARegion *ar, int sizex) } static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, int sizex, ListBase *lb) -{ +{ TreeElement *te; TreeStoreElem *tselem; PointerRNA *ptr; @@ -586,14 +713,17 @@ static void outliner_draw_rnabuts(uiBlock *block, Scene *scene, ARegion *ar, Spa ptr = &te->rnaptr; prop = te->directdata; - if (!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem, soops))) ) - uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, UI_UNIT_Y - 1); + if (!(RNA_property_type(prop) == PROP_POINTER && (TSELEM_OPEN(tselem, soops)))) { + 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, UI_UNIT_Y - 1); + uiDefAutoButR(block, ptr, prop, te->index, "", ICON_NONE, sizex, (int)te->ys, OL_RNA_COL_SIZEX, + UI_UNIT_Y - 1); } } @@ -615,7 +745,7 @@ static void operator_search_cb(const struct bContext *UNUSED(C), void *UNUSED(ar { GHashIterator *iter = WM_operatortype_iter(); - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(iter); if (BLI_strcasestr(ot->idname, str)) { @@ -806,7 +936,8 @@ static void outliner_draw_keymapbuts(uiBlock *block, ARegion *ar, SpaceOops *soo /* pass */ } else { - uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys + 1, butw1, UI_UNIT_Y - 1, "Assign new Operator"); + uiDefBlockBut(block, operator_search_menu, kmi, "", xstart, (int)te->ys + 1, butw1, UI_UNIT_Y - 1, + TIP_("Assign new Operator")); } xstart += butw1 + 10; @@ -814,43 +945,58 @@ 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, UI_UNIT_Y - 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, TIP_("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, UI_UNIT_Y - 1, &kmi->type, "Key code"); + uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, &kmi->type, + TIP_("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, UI_UNIT_Y - 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, TIP_("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, UI_UNIT_Y - 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, TIP_("Tweak gesture")); xstart += butw2 + 5; str = keymap_tweak_dir_menu(); - uiDefButS(block, MENU, 0, str, xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 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, TIP_("Tweak gesture direction")); xstart += butw2 + 5; break; } /* modifiers */ - 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, UI_UNIT_Y - 1, &kmi->keymodifier, "Key Modifier code"); + uiDefButS(block, OPTION, 0, IFACE_("Shift"), xstart, (int)te->ys + 1, butw3 + 5, UI_UNIT_Y - 1, + &kmi->shift, 0, 0, 0, 0, TIP_("Modifier")); + xstart += butw3 + 5; + uiDefButS(block, OPTION, 0, IFACE_("Ctrl"), xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->ctrl, + 0, 0, 0, 0, TIP_("Modifier")); + xstart += butw3; + uiDefButS(block, OPTION, 0, IFACE_("Alt"), xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->alt, + 0, 0, 0, 0, TIP_("Modifier")); + xstart += butw3; + uiDefButS(block, OPTION, 0, IFACE_("OS"), xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->oskey, + 0, 0, 0, 0, TIP_("Modifier")); + xstart += butw3 + 5; + uiDefKeyevtButS(block, 0, "", xstart, (int)te->ys + 1, butw3, UI_UNIT_Y - 1, &kmi->keymodifier, + TIP_("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, UI_UNIT_Y - 1, NULL, 0, 0, 0, 0, ""); xstart += butw2; + uiDefBut(block, LABEL, 0, IFACE_("(RNA property)"), xstart, (int)te->ys + 1, butw2, UI_UNIT_Y - 1, + NULL, 0, 0, 0, 0, ""); + xstart += butw2; } (void)xstart; @@ -878,7 +1024,8 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa /* If we add support to rename Sequence. * need change this. */ - if (tselem->type == TSE_POSE_BASE) continue; // prevent crash when trying to rename 'pose' entry of armature + // prevent crash when trying to rename 'pose' entry of armature + if (tselem->type == TSE_POSE_BASE) continue; if (tselem->type == TSE_EBONE) len = sizeof(((EditBone *) 0)->name); else if (tselem->type == TSE_MODIFIER) len = sizeof(((ModifierData *) 0)->name); @@ -891,7 +1038,8 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa 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, UI_UNIT_Y - 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 */ @@ -924,7 +1072,8 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon) glDisable(GL_BLEND); } else { - uiBut *but = uiDefIconBut(arg->block, LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, arg->alpha, (arg->id && arg->id->lib) ? arg->id->lib->name : ""); + uiBut *but = uiDefIconBut(arg->block, LABEL, 0, icon, arg->xb, arg->yb, UI_UNIT_X, UI_UNIT_Y, 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); @@ -932,7 +1081,8 @@ static void tselem_draw_icon_uibut(struct DrawIconArg *arg, int icon) } -static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, float alpha) +static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeStoreElem *tselem, TreeElement *te, + float alpha) { struct DrawIconArg arg; float aspect; @@ -1217,7 +1367,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto } } -static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, int xmax, int *offsx, int ys) +static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, SpaceOops *soops, ListBase *lb, int level, + int xmax, int *offsx, int ys) { TreeElement *te; TreeStoreElem *tselem; @@ -1236,12 +1387,20 @@ static void outliner_draw_iconrow(bContext *C, uiBlock *block, Scene *scene, Spa /* active blocks get white circle */ if (tselem->type == 0) { - if (te->idcode == ID_OB) active = (OBACT == (Object *)tselem->id); - else if (scene->obedit && scene->obedit->data == tselem->id) active = 1; // XXX use context? - else active = tree_element_active(C, scene, soops, te, 0); + if (te->idcode == ID_OB) { + active = (OBACT == (Object *)tselem->id); + } + else if (scene->obedit && scene->obedit->data == tselem->id) { + active = 1; // XXX use context? + } + else { + active = tree_element_active(C, scene, soops, te, 0); + } } - else active = tree_element_type_active(NULL, scene, soops, te, tselem, 0); - + else { + active = tree_element_type_active(NULL, scene, soops, te, tselem, 0, false); + } + if (active) { float ufac = UI_UNIT_X / 20.0f; @@ -1286,7 +1445,8 @@ static void outliner_set_coord_tree_element(SpaceOops *soops, TreeElement *te, i } -static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, TreeElement *te, int startx, int *starty) +static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene, ARegion *ar, SpaceOops *soops, + TreeElement *te, int startx, int *starty) { TreeElement *ten; TreeStoreElem *tselem; @@ -1377,7 +1537,7 @@ static void outliner_draw_tree_element(bContext *C, uiBlock *block, Scene *scene } } else { - if (tree_element_type_active(NULL, scene, soops, te, tselem, 0) ) active = 2; + if (tree_element_type_active(NULL, scene, soops, te, tselem, 0, false) ) active = 2; glColor4ub(220, 220, 255, alpha); } @@ -1685,15 +1845,17 @@ void draw_outliner(const bContext *C) sizex_rna = max_ii(OL_RNA_COLX, sizex_rna + OL_RNA_COL_SPACEX); /* get width of data (for setting 'tot' rect, this is column 1 + column 2 + a bit extra) */ - if (soops->outlinevis == SO_KEYMAP) - sizex = sizex_rna + OL_RNA_COL_SIZEX * 3 + 50; // XXX this is only really a quick hack to make this wide enough... + if (soops->outlinevis == SO_KEYMAP) + // XXX this is only really a quick hack to make this wide enough... + sizex = sizex_rna + OL_RNA_COL_SIZEX * 3 + 50; else sizex = sizex_rna + OL_RNA_COL_SIZEX + 50; } else { /* width must take into account restriction columns (if visible) so that entries will still be visible */ //outliner_width(soops, &soops->tree, &sizex); - outliner_rna_width(soops, &soops->tree, &sizex, 0); // XXX should use outliner_width instead when te->xend will be set correctly... + // XXX should use outliner_width instead when te->xend will be set correctly... + outliner_rna_width(soops, &soops->tree, &sizex, 0); /* constant offset for restriction columns */ // XXX this isn't that great yet... diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 9a1b3628196..1e67e099508 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -146,7 +146,7 @@ static int do_outliner_item_openclose(bContext *C, SpaceOops *soops, TreeElement } /* event can enterkey, then it opens/closes */ -static int outliner_item_openclose(bContext *C, wmOperator *op, wmEvent *event) +static int outliner_item_openclose(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); @@ -222,12 +222,12 @@ static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, T 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 + UI_UNIT_X && mval[0] < te->xend) { - + /* click on name */ + if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) { do_item_rename(ar, te, tselem, reports); + return 1; } - return 1; + return 0; } for (te = te->subtree.first; te; te = te->next) { @@ -236,20 +236,24 @@ static int do_outliner_item_rename(bContext *C, ARegion *ar, SpaceOops *soops, T return 0; } -static int outliner_item_rename(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int outliner_item_rename(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); TreeElement *te; float fmval[2]; + bool change = false; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1); for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_rename(C, ar, soops, te, fmval)) break; + if (do_outliner_item_rename(C, ar, soops, te, fmval)) { + change = true; + break; + } } - return OPERATOR_FINISHED; + return change ? OPERATOR_FINISHED : OPERATOR_PASS_THROUGH; } @@ -890,9 +894,13 @@ static void tree_element_show_hierarchy(Scene *scene, SpaceOops *soops, ListBase else tselem->flag |= TSE_CLOSED; } } - else tselem->flag |= TSE_CLOSED; - - if (TSELEM_OPEN(tselem, soops)) tree_element_show_hierarchy(scene, soops, &te->subtree); + else { + tselem->flag |= TSE_CLOSED; + } + + if (TSELEM_OPEN(tselem, soops)) { + tree_element_show_hierarchy(scene, soops, &te->subtree); + } } } @@ -1440,7 +1448,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op) } /* Used for drag and drop parenting */ -TreeElement *outliner_dropzone_parent(bContext *C, wmEvent *event, TreeElement *te, float *fmval) +TreeElement *outliner_dropzone_parent(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2]) { SpaceOops *soops = CTX_wm_space_outliner(C); TreeStoreElem *tselem = TREESTORE(te); @@ -1469,7 +1477,7 @@ TreeElement *outliner_dropzone_parent(bContext *C, wmEvent *event, TreeElement * return NULL; } -static int parent_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *par = NULL; Object *ob = NULL; @@ -1643,7 +1651,7 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", ""); } -int outliner_dropzone_parent_clear(bContext *C, wmEvent *event, TreeElement *te, float *fmval) +int outliner_dropzone_parent_clear(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2]) { SpaceOops *soops = CTX_wm_space_outliner(C); TreeStoreElem *tselem = TREESTORE(te); @@ -1681,7 +1689,7 @@ int outliner_dropzone_parent_clear(bContext *C, wmEvent *event, TreeElement *te, return 0; } -static int parent_clear_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Main *bmain = CTX_data_main(C); Scene *scene = NULL; @@ -1730,7 +1738,7 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", ""); } -TreeElement *outliner_dropzone_scene(bContext *C, wmEvent *UNUSED(event), TreeElement *te, float *fmval) +TreeElement *outliner_dropzone_scene(bContext *C, const wmEvent *UNUSED(event), TreeElement *te, const float fmval[2]) { SpaceOops *soops = CTX_wm_space_outliner(C); TreeStoreElem *tselem = TREESTORE(te); @@ -1746,7 +1754,7 @@ TreeElement *outliner_dropzone_scene(bContext *C, wmEvent *UNUSED(event), TreeEl return NULL; } -static int scene_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = NULL; Object *ob = NULL; @@ -1822,7 +1830,7 @@ void OUTLINER_OT_scene_drop(wmOperatorType *ot) RNA_def_string(ot->srna, "scene", "Scene", MAX_ID_NAME, "Scene", "Target Scene"); } -static int material_drop_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Material *ma = NULL; Object *ob = NULL; diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 63452de18d0..a918357ced2 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -165,8 +165,9 @@ void draw_outliner(const struct bContext *C); void restrictbutton_gr_restrict_flag(void *poin, void *poin2, int flag); /* outliner_select.c -------------------------------------------- */ -int tree_element_type_active(struct bContext *C, struct Scene *scene, struct SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set); +int tree_element_type_active(struct bContext *C, struct Scene *scene, struct SpaceOops *soops, TreeElement *te, TreeStoreElem *tselem, int set, bool recursive); int tree_element_active(struct bContext *C, struct Scene *scene, SpaceOops *soops, TreeElement *te, int set); +int outliner_item_do_activate(struct bContext *C, int x, int y, bool extend, bool recursive); /* outliner_edit.c ---------------------------------------------- */ @@ -189,9 +190,9 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem); -TreeElement *outliner_dropzone_parent(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval); -int outliner_dropzone_parent_clear(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval); -TreeElement *outliner_dropzone_scene(struct bContext *C, struct wmEvent *event, struct TreeElement *te, float *fmval); +TreeElement *outliner_dropzone_parent(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]); +int outliner_dropzone_parent_clear(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]); +TreeElement *outliner_dropzone_scene(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]); /* ...................................................... */ void OUTLINER_OT_item_activate(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 1dd043409a5..b9e3942a7ce 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -30,12 +30,12 @@ #include "DNA_space_types.h" -#include "WM_api.h" -#include "WM_types.h" +#include "BLI_utildefines.h" #include "RNA_access.h" -#include "BLI_utildefines.h" +#include "WM_api.h" +#include "WM_types.h" #include "outliner_intern.h" @@ -88,10 +88,22 @@ void outliner_keymap(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "OUTLINER_OT_item_rename", LEFTMOUSE, KM_DBL_CLICK, 0, 0); kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, 0, 0); + RNA_boolean_set(kmi->ptr, "recursive", FALSE); RNA_boolean_set(kmi->ptr, "extend", FALSE); + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "recursive", FALSE); + RNA_boolean_set(kmi->ptr, "extend", TRUE); + + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL, 0); + RNA_boolean_set(kmi->ptr, "recursive", TRUE); + RNA_boolean_set(kmi->ptr, "extend", FALSE); + + kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_activate", LEFTMOUSE, KM_CLICK, KM_CTRL | KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "recursive", TRUE); RNA_boolean_set(kmi->ptr, "extend", TRUE); + WM_keymap_add_item(keymap, "OUTLINER_OT_select_border", BKEY, KM_PRESS, 0, 0); kmi = WM_keymap_add_item(keymap, "OUTLINER_OT_item_openclose", RETKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c index fa337ba7af1..6fcfb457615 100644 --- a/source/blender/editors/space_outliner/outliner_select.c +++ b/source/blender/editors/space_outliner/outliner_select.c @@ -47,8 +47,11 @@ #include "BKE_context.h" #include "BKE_depsgraph.h" +#include "BKE_main.h" +#include "BKE_object.h" #include "BKE_scene.h" #include "BKE_sequencer.h" +#include "BKE_armature.h" #include "ED_armature.h" #include "ED_object.h" @@ -140,7 +143,50 @@ static int tree_element_active_renderlayer(bContext *C, TreeElement *te, TreeSto return 0; } -static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, TreeElement *te, int set) +/** + * Select object tree: + * CTRL+LMB: Select/Deselect object and all cildren + * CTRL+SHIFT+LMB: Add/Remove object and all children + */ +static void do_outliner_object_select_recursive(Scene *scene, Object *ob_parent, bool select) +{ + Base *base; + + for (base = FIRSTBASE; base; base = base->next) { + Object *ob = base->object; + if ((((ob->restrictflag & OB_RESTRICT_VIEW) == 0) && BKE_object_is_child_recursive(ob_parent, ob))) { + ED_base_object_select(base, select ? BA_SELECT : BA_DESELECT); + } + } +} + +static void do_outliner_bone_select_recursive(bArmature *arm, Bone *bone_parent, bool select) +{ + Bone *bone; + for (bone = bone_parent->childbase.first; bone; bone = bone->next) { + if (select && PBONE_SELECTABLE(arm, bone)) + bone->flag |= BONE_SELECTED; + else + bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + do_outliner_bone_select_recursive(arm, bone, select); + } +} + +static void do_outliner_ebone_select_recursive(bArmature *arm, EditBone *ebone_parent, bool select) +{ + EditBone *ebone; + for (ebone = ebone_parent->next; ebone; ebone = ebone->next) { + if (ED_armature_ebone_is_child_recursive(ebone_parent, ebone)) { + if (select && EBONE_SELECTABLE(arm, ebone)) + ebone->flag |= BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL; + else + ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + } + } +} + +static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops *soops, + TreeElement *te, int set, bool recursive) { TreeStoreElem *tselem = TREESTORE(te); Scene *sce; @@ -148,7 +194,9 @@ static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops Object *ob = NULL; /* if id is not object, we search back */ - if (te->idcode == ID_OB) ob = (Object *)tselem->id; + if (te->idcode == ID_OB) { + ob = (Object *)tselem->id; + } else { ob = (Object *)outliner_search_back(soops, te, ID_OB); if (ob == OBACT) return 0; @@ -176,6 +224,12 @@ static int tree_element_set_active_object(bContext *C, Scene *scene, SpaceOops BKE_scene_base_deselect_all(scene); ED_base_object_select(base, BA_SELECT); } + + if (recursive) { + /* Recursive select/deselect for Object hierarchies */ + do_outliner_object_select_recursive(scene, ob, (ob->flag & SELECT) != 0); + } + if (C) { ED_base_object_activate(C, base); /* adds notifier */ WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); @@ -312,7 +366,9 @@ static int tree_element_active_lamp(bContext *UNUSED(C), Scene *scene, SpaceOops if (set) { // XXX extern_set_butspace(F5KEY, 0); } - else return 1; + else { + return 1; + } return 0; } @@ -395,7 +451,7 @@ static int tree_element_active_posegroup(bContext *C, Scene *scene, TreeElement return 0; } -static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set, bool recursive) { Object *ob = (Object *)tselem->id; bArmature *arm = ob->data; @@ -404,9 +460,13 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen if (set) { if (!(pchan->bone->flag & BONE_HIDDEN_P)) { - if (set == 2) ED_pose_deselectall(ob, 2); // 2 = clear active tag - else ED_pose_deselectall(ob, 0); // 0 = deselect - + if (set != 2) { + bPoseChannel *pchannel; + /* single select forces all other bones to get unselected */ + for (pchannel = ob->pose->chanbase.first; pchannel; pchannel = pchannel->next) + pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + } + if (set == 2 && (pchan->bone->flag & BONE_SELECTED)) { pchan->bone->flag &= ~BONE_SELECTED; } @@ -414,7 +474,12 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen pchan->bone->flag |= BONE_SELECTED; arm->act_bone = pchan->bone; } - + + if (recursive) { + /* Recursive select/deselect */ + do_outliner_bone_select_recursive(arm, pchan->bone, (pchan->bone->flag & BONE_SELECTED) != 0); + } + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob); } @@ -427,7 +492,7 @@ static int tree_element_active_posechannel(bContext *C, Scene *scene, TreeElemen return 0; } -static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set) +static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *tselem, int set, bool recursive) { bArmature *arm = (bArmature *)tselem->id; Bone *bone = te->directdata; @@ -436,8 +501,12 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, if (!(bone->flag & BONE_HIDDEN_P)) { Object *ob = OBACT; if (ob) { - if (set == 2) ED_pose_deselectall(ob, 2); // 2 is clear active tag - else ED_pose_deselectall(ob, 0); + if (set != 2) { + bPoseChannel *pchannel; + /* single select forces all other bones to get unselected */ + for (pchannel = ob->pose->chanbase.first; pchannel; pchannel = pchannel->next) + pchannel->bone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL); + } } if (set == 2 && (bone->flag & BONE_SELECTED)) { @@ -447,6 +516,12 @@ static int tree_element_active_bone(bContext *C, Scene *scene, TreeElement *te, bone->flag |= BONE_SELECTED; arm->act_bone = bone; } + + if (recursive) { + /* Recursive select/deselect */ + do_outliner_bone_select_recursive(arm, bone, (bone->flag & BONE_SELECTED) != 0); + } + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, ob); } @@ -479,35 +554,42 @@ static void tree_element_active_ebone__sel(bContext *C, Scene *scene, bArmature WM_event_add_notifier(C, NC_OBJECT | ND_BONE_ACTIVE, scene->obedit); } -static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set) +static int tree_element_active_ebone(bContext *C, Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tselem), int set, bool recursive) { bArmature *arm = scene->obedit->data; EditBone *ebone = te->directdata; - - if (set == 1) { - if (!(ebone->flag & BONE_HIDDEN_A)) { - ED_armature_deselect_all(scene->obedit, 0); // deselect - tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); - return 1; - } - } - else if (set == 2) { - if (!(ebone->flag & BONE_HIDDEN_A)) { - if (!(ebone->flag & BONE_SELECTED)) { + int status = 0; + if (set) { + if (set == 1) { + if (!(ebone->flag & BONE_HIDDEN_A)) { + ED_armature_deselect_all(scene->obedit, 0); // deselect tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); - return 1; + status = 1; } - else { - /* entirely selected, so de-select */ - tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE); - return 0; + } + else if (set == 2) { + if (!(ebone->flag & BONE_HIDDEN_A)) { + if (!(ebone->flag & BONE_SELECTED)) { + tree_element_active_ebone__sel(C, scene, arm, ebone, TRUE); + status = 1; + } + else { + /* entirely selected, so de-select */ + tree_element_active_ebone__sel(C, scene, arm, ebone, FALSE); + status = 0; + } } } + + if (recursive) { + /* Recursive select/deselect */ + do_outliner_ebone_select_recursive(arm, ebone, (ebone->flag & BONE_SELECTED) != 0); + } } else if (ebone->flag & BONE_SELECTED) { - return 1; + status = 1; } - return 0; + return status; } static int tree_element_active_modifier(bContext *C, TreeElement *UNUSED(te), TreeStoreElem *tselem, int set) @@ -675,19 +757,19 @@ int tree_element_active(bContext *C, Scene *scene, SpaceOops *soops, TreeElement /* generic call for non-id data to make/check active in UI */ /* Context can be NULL when set==0 */ int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, - TreeElement *te, TreeStoreElem *tselem, int set) + TreeElement *te, TreeStoreElem *tselem, int set, bool recursive) { switch (tselem->type) { case TSE_DEFGROUP: return tree_element_active_defgroup(C, scene, te, tselem, set); case TSE_BONE: - return tree_element_active_bone(C, scene, te, tselem, set); + return tree_element_active_bone(C, scene, te, tselem, set, recursive); case TSE_EBONE: - return tree_element_active_ebone(C, scene, te, tselem, set); + return tree_element_active_ebone(C, scene, te, tselem, set, recursive); case TSE_MODIFIER: return tree_element_active_modifier(C, te, tselem, set); case TSE_LINKED_OB: - if (set) tree_element_set_active_object(C, scene, soops, te, set); + if (set) tree_element_set_active_object(C, scene, soops, te, set, FALSE); else if (tselem->id == (ID *)OBACT) return 1; break; case TSE_LINKED_PSYS: @@ -695,7 +777,7 @@ int tree_element_type_active(bContext *C, Scene *scene, SpaceOops *soops, case TSE_POSE_BASE: return tree_element_active_pose(C, scene, te, tselem, set); case TSE_POSE_CHANNEL: - return tree_element_active_posechannel(C, scene, te, tselem, set); + return tree_element_active_posechannel(C, scene, te, tselem, set, recursive); case TSE_CONSTRAINT: return tree_element_active_constraint(C, te, tselem, set); case TSE_R_LAYER: @@ -716,7 +798,7 @@ 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]) + TreeElement *te, bool extend, bool recursive, const float mval[2]) { if (mval[1] > te->ys && mval[1] < te->ys + UI_UNIT_Y) { @@ -748,7 +830,9 @@ static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Spa /* always makes active object */ if (tselem->type != TSE_SEQUENCE && tselem->type != TSE_SEQ_STRIP && tselem->type != TSE_SEQUENCE_DUP) - tree_element_set_active_object(C, scene, soops, te, 1 + (extend != 0 && tselem->type == 0)); + tree_element_set_active_object(C, scene, soops, te, + 1 + (extend != 0 && tselem->type == 0), + recursive && tselem->type == 0 ); if (tselem->type == 0) { // the lib blocks /* editmode? */ @@ -791,31 +875,31 @@ static int do_outliner_item_activate(bContext *C, Scene *scene, ARegion *ar, Spa else { // rest of types tree_element_active(C, scene, soops, te, 1); } - + + } + else { + tree_element_type_active(C, scene, soops, te, tselem, 1 + (extend != 0), recursive); } - else tree_element_type_active(C, scene, soops, te, tselem, 1 + (extend != 0)); return 1; } } for (te = te->subtree.first; te; te = te->next) { - if (do_outliner_item_activate(C, scene, ar, soops, te, extend, mval)) return 1; + if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, mval)) return 1; } return 0; } -/* event can enterkey, then it opens/closes */ -static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event) +int outliner_item_do_activate(bContext *C, int x, int y, bool extend, bool recursive) { Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); TreeElement *te; float fmval[2]; - int extend = RNA_boolean_get(op->ptr, "extend"); - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], fmval, fmval + 1); + UI_view2d_region_to_view(&ar->v2d, x, y, fmval, fmval + 1); if (!ELEM3(soops->outlinevis, SO_DATABLOCKS, SO_USERDEF, SO_KEYMAP) && !(soops->flag & SO_HIDE_RESTRICTCOLS) && @@ -825,7 +909,7 @@ static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event) } for (te = soops->tree.first; te; te = te->next) { - if (do_outliner_item_activate(C, scene, ar, soops, te, extend, fmval)) break; + if (do_outliner_item_activate(C, scene, ar, soops, te, extend, recursive, fmval)) break; } if (te) { @@ -855,6 +939,16 @@ static int outliner_item_activate(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_FINISHED; } +/* event can enterkey, then it opens/closes */ +static int outliner_item_activate(bContext *C, wmOperator *op, const wmEvent *event) +{ + bool extend = RNA_boolean_get(op->ptr, "extend"); + bool recursive = RNA_boolean_get(op->ptr, "recursive"); + int x = event->mval[0]; + int y = event->mval[1]; + return outliner_item_do_activate(C, x, y, extend, recursive); +} + void OUTLINER_OT_item_activate(wmOperatorType *ot) { ot->name = "Activate Item"; @@ -865,7 +959,8 @@ void OUTLINER_OT_item_activate(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; - RNA_def_boolean(ot->srna, "extend", 1, "Extend", "Extend selection for activation"); + RNA_def_boolean(ot->srna, "extend", true, "Extend", "Extend selection for activation"); + RNA_def_boolean(ot->srna, "recursive", false, "Recursive", "Select Objects and their children"); } /* ****************************************************** */ diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index cd04c8c6bd1..258f0338d1e 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -75,6 +75,7 @@ #include "outliner_intern.h" + /* ****************************************************** */ /* ************ SELECTION OPERATIONS ********* */ @@ -190,8 +191,10 @@ static void unlink_texture_cb(bContext *UNUSED(C), Scene *UNUSED(scene), TreeEle World *wrld = (World *)tsep->id; mtex = wrld->mtex; } - else return; - + else { + return; + } + for (a = 0; a < MAX_MTEX; a++) { if (a == te->index && mtex[a]) { if (mtex[a]->tex) { @@ -264,6 +267,17 @@ static void object_select_cb(bContext *UNUSED(C), Scene *scene, TreeElement *te, } } +static void object_select_hierarchy_cb(bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(te), + TreeStoreElem *UNUSED(tsep), TreeStoreElem *UNUSED(tselem)) +{ + /* From where do i get the x,y coordinate of the mouse event ? */ + wmWindow *win = CTX_wm_window(C); + int x = win->eventstate->mval[0]; + int y = win->eventstate->mval[1]; + outliner_item_do_activate(C, x, y, true, true); +} + + static void object_deselect_cb(bContext *UNUSED(C), Scene *scene, TreeElement *te, TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem) { @@ -300,7 +314,7 @@ static void id_local_cb(bContext *C, Scene *UNUSED(scene), TreeElement *UNUSED(t if (tselem->id->lib && (tselem->id->flag & LIB_EXTERN)) { /* if the ID type has no special local function, * just clear the lib */ - if (id_make_local(tselem->id, FALSE) == FALSE) { + if (id_make_local(tselem->id, false) == false) { Main *bmain = CTX_data_main(C); id_clear_lib_data(bmain, tselem->id); } @@ -526,9 +540,9 @@ static void sequence_cb(int event, TreeElement *te, TreeStoreElem *tselem, void Sequence *seq = (Sequence *)te->directdata; if (event == 1) { Scene *scene = (Scene *)scene_ptr; - Editing *ed = BKE_sequencer_editing_get(scene, FALSE); + Editing *ed = BKE_sequencer_editing_get(scene, false); if (BLI_findindex(ed->seqbasep, seq) != -1) { - ED_sequencer_select_sequence_single(scene, seq, TRUE); + ED_sequencer_select_sequence_single(scene, seq, true); } } @@ -569,15 +583,29 @@ static void outliner_do_data_operation(SpaceOops *soops, int type, int event, Li /* **************************************** */ +enum { + OL_OP_ENDMARKER = 0, + OL_OP_SELECT, + OL_OP_DESELECT, + OL_OP_SELECT_HIERARCHY, + OL_OP_DELETE, + OL_OP_LOCALIZED, /* disabled, see below */ + OL_OP_TOGVIS, + OL_OP_TOGSEL, + OL_OP_TOGREN, + OL_OP_RENAME +}; + static EnumPropertyItem prop_object_op_types[] = { - {1, "SELECT", 0, "Select", ""}, - {2, "DESELECT", 0, "Deselect", ""}, - {4, "DELETE", 0, "Delete", ""}, - {6, "TOGVIS", 0, "Toggle Visible", ""}, - {7, "TOGSEL", 0, "Toggle Selectable", ""}, - {8, "TOGREN", 0, "Toggle Renderable", ""}, - {9, "RENAME", 0, "Rename", ""}, - {0, NULL, 0, NULL, NULL} + {OL_OP_SELECT, "SELECT", 0, "Select", ""}, + {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""}, + {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""}, + {OL_OP_DELETE, "DELETE", 0, "Delete", ""}, + {OL_OP_TOGVIS, "TOGVIS", 0, "Toggle Visible", ""}, + {OL_OP_TOGSEL, "TOGSEL", 0, "Toggle Selectable", ""}, + {OL_OP_TOGREN, "TOGREN", 0, "Toggle Renderable", ""}, + {OL_OP_RENAME, "RENAME", 0, "Rename", ""}, + {OL_OP_ENDMARKER, NULL, 0, NULL, NULL} }; static int outliner_object_operation_exec(bContext *C, wmOperator *op) @@ -594,7 +622,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) event = RNA_enum_get(op->ptr, "type"); - if (event == 1) { + if (event == OL_OP_SELECT) { Scene *sce = scene; // to be able to delete, scenes are set... outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_cb); if (scene != sce) { @@ -604,12 +632,21 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) str = "Select Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } - else if (event == 2) { + else if (event == OL_OP_SELECT_HIERARCHY) { + Scene *sce = scene; // to be able to delete, scenes are set... + outliner_do_object_operation(C, scene, soops, &soops->tree, object_select_hierarchy_cb); + if (scene != sce) { + ED_screen_set_scene(C, CTX_wm_screen(C), sce); + } + str = "Select Object Hierarchy"; + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + } + else if (event == OL_OP_DESELECT) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_deselect_cb); str = "Deselect Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } - else if (event == 4) { + else if (event == OL_OP_DELETE) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_delete_cb); /* XXX: tree management normally happens from draw_outliner(), but when @@ -623,26 +660,26 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) str = "Delete Objects"; WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); } - else if (event == 5) { /* disabled, see above enum (ton) */ + else if (event == OL_OP_LOCALIZED) { /* disabled, see above enum (ton) */ outliner_do_object_operation(C, scene, soops, &soops->tree, id_local_cb); str = "Localized Objects"; } - else if (event == 6) { + else if (event == OL_OP_TOGVIS) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_visibility_cb); str = "Toggle Visibility"; WM_event_add_notifier(C, NC_SCENE | ND_OB_VISIBLE, scene); } - else if (event == 7) { + else if (event == OL_OP_TOGSEL) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_selectability_cb); str = "Toggle Selectability"; WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); } - else if (event == 8) { + else if (event == OL_OP_TOGREN) { outliner_do_object_operation(C, scene, soops, &soops->tree, object_toggle_renderability_cb); str = "Toggle Renderability"; WM_event_add_notifier(C, NC_SCENE | ND_OB_RENDER, scene); } - else if (event == 9) { + else if (event == OL_OP_RENAME) { outliner_do_object_operation(C, scene, soops, &soops->tree, item_rename_cb); str = "Rename Object"; } @@ -1229,7 +1266,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]) + TreeElement *te, const wmEvent *event, const float mval[2]) { ReportList *reports = CTX_wm_reports(C); // XXX... @@ -1259,7 +1296,9 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S WM_operator_name_call(C, "OUTLINER_OT_object_operation", WM_OP_INVOKE_REGION_WIN, NULL); } else if (idlevel) { - if (idlevel == -1 || datalevel) BKE_report(reports, RPT_WARNING, "Mixed selection"); + if (idlevel == -1 || datalevel) { + BKE_report(reports, RPT_WARNING, "Mixed selection"); + } else { if (idlevel == ID_GR) WM_operator_name_call(C, "OUTLINER_OT_group_operation", WM_OP_INVOKE_REGION_WIN, NULL); @@ -1268,7 +1307,9 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S } } else if (datalevel) { - if (datalevel == -1) BKE_report(reports, RPT_WARNING, "Mixed selection"); + if (datalevel == -1) { + BKE_report(reports, RPT_WARNING, "Mixed selection"); + } else { if (datalevel == TSE_ANIM_DATA) WM_operator_name_call(C, "OUTLINER_OT_animdata_operation", WM_OP_INVOKE_REGION_WIN, NULL); @@ -1295,7 +1336,7 @@ static int do_outliner_operation_event(bContext *C, Scene *scene, ARegion *ar, S } -static int outliner_operation(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { Scene *scene = CTX_data_scene(C); ARegion *ar = CTX_wm_region(C); diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index f723fbedc7b..19bc1db2b5d 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -64,6 +64,8 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLF_translation.h" + #include "BKE_fcurve.h" #include "BKE_main.h" #include "BKE_library.h" @@ -322,7 +324,7 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc * in order to not overflow short tselem->nr */ te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_COMBINED)); - te->name = "Combined"; + te->name = IFACE_("Combined"); te->directdata = &srl->passflag; /* save cpu cycles, but we add the first to invoke an open/close triangle */ @@ -331,71 +333,71 @@ static void outliner_add_passes(SpaceOops *soops, TreeElement *tenla, ID *id, Sc return; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_Z)); - te->name = "Z"; + te->name = IFACE_("Z"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_VECTOR)); - te->name = "Vector"; + te->name = IFACE_("Vector"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_NORMAL)); - te->name = "Normal"; + te->name = IFACE_("Normal"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_UV)); - te->name = "UV"; + te->name = IFACE_("UV"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_MIST)); - te->name = "Mist"; + te->name = IFACE_("Mist"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXOB)); - te->name = "Index Object"; + te->name = IFACE_("Index Object"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDEXMA)); - te->name = "Index Material"; + te->name = IFACE_("Index Material"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_RGBA)); - te->name = "Color"; + te->name = IFACE_("Color"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_DIFFUSE)); - te->name = "Diffuse"; + te->name = IFACE_("Diffuse"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SPEC)); - te->name = "Specular"; + te->name = IFACE_("Specular"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_SHADOW)); - te->name = "Shadow"; + te->name = IFACE_("Shadow"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_AO)); - te->name = "AO"; + te->name = IFACE_("AO"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFLECT)); - te->name = "Reflection"; + te->name = IFACE_("Reflection"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_REFRACT)); - te->name = "Refraction"; + te->name = IFACE_("Refraction"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_INDIRECT)); - te->name = "Indirect"; + te->name = IFACE_("Indirect"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_ENVIRONMENT)); - te->name = "Environment"; + te->name = IFACE_("Environment"); te->directdata = &srl->passflag; te = outliner_add_element(soops, &tenla->subtree, id, tenla, TSE_R_PASS, LOG2I(SCE_PASS_EMIT)); - te->name = "Emit"; + te->name = IFACE_("Emit"); te->directdata = &srl->passflag; } @@ -407,7 +409,7 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s TreeElement *tenla = outliner_add_element(soops, lb, sce, te, TSE_R_LAYER_BASE, 0); int a; - tenla->name = "RenderLayers"; + tenla->name = IFACE_("RenderLayers"); for (a = 0, srl = sce->r.layers.first; srl; srl = srl->next, a++) { TreeElement *tenlay = outliner_add_element(soops, &tenla->subtree, sce, te, TSE_R_LAYER, a); tenlay->name = srl->name; @@ -449,7 +451,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree TreeElement *ten; TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSE_BASE, 0); - tenla->name = "Pose"; + tenla->name = IFACE_("Pose"); /* channels undefined in editmode, but we want the 'tenla' pose icon itself */ if ((arm->edbo == NULL) && (ob->mode & OB_MODE_POSE)) { @@ -468,7 +470,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree TreeElement *tenla1 = outliner_add_element(soops, &ten->subtree, ob, ten, TSE_CONSTRAINT_BASE, 0); //char *str; - tenla1->name = "Constraints"; + tenla1->name = IFACE_("Constraints"); for (con = pchan->constraints.first; con; con = con->next, const_index++) { ten1 = outliner_add_element(soops, &tenla1->subtree, ob, tenla1, TSE_CONSTRAINT, const_index); #if 0 /* disabled as it needs to be reworked for recoded constraints system */ @@ -508,7 +510,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_POSEGRP_BASE, 0); int a = 0; - tenla->name = "Bone Groups"; + tenla->name = IFACE_("Bone Groups"); for (agrp = ob->pose->agroups.first; agrp; agrp = agrp->next, a++) { ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_POSEGRP, a); ten->name = agrp->name; @@ -527,7 +529,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_CONSTRAINT_BASE, 0); //char *str; - tenla->name = "Constraints"; + tenla->name = IFACE_("Constraints"); for (con = ob->constraints.first, a = 0; con; con = con->next, a++) { ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_CONSTRAINT, a); #if 0 /* disabled due to constraints system targets recode... code here needs review */ @@ -547,7 +549,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree TreeElement *temod = outliner_add_element(soops, &te->subtree, ob, te, TSE_MODIFIER_BASE, 0); int index; - temod->name = "Modifiers"; + temod->name = IFACE_("Modifiers"); for (index = 0, md = ob->modifiers.first; md; index++, md = md->next) { TreeElement *te = outliner_add_element(soops, &temod->subtree, ob, temod, TSE_MODIFIER, index); te->name = md->name; @@ -582,7 +584,7 @@ static void outliner_add_object_contents(SpaceOops *soops, TreeElement *te, Tree TreeElement *ten; TreeElement *tenla = outliner_add_element(soops, &te->subtree, ob, te, TSE_DEFGROUP_BASE, 0); - tenla->name = "Vertex Groups"; + tenla->name = IFACE_("Vertex Groups"); for (defgroup = ob->defbase.first, a = 0; defgroup; defgroup = defgroup->next, a++) { ten = outliner_add_element(soops, &tenla->subtree, ob, tenla, TSE_DEFGROUP, a); ten->name = defgroup->name; @@ -856,7 +858,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i AnimData *adt = (AnimData *)iat->adt; /* this element's info */ - te->name = "Animation"; + te->name = IFACE_("Animation"); te->directdata = adt; /* Action */ @@ -868,7 +870,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i ID *lastadded = NULL; FCurve *fcu; - ted->name = "Drivers"; + ted->name = IFACE_("Drivers"); for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { if (fcu->driver && fcu->driver->variables.first) { @@ -897,7 +899,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i NlaTrack *nlt; int a = 0; - tenla->name = "NLA Tracks"; + tenla->name = IFACE_("NLA Tracks"); for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { TreeElement *tenlt = outliner_add_element(soops, &tenla->subtree, nlt, tenla, TSE_NLA_TRACK, a); @@ -951,7 +953,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i if (strip->dir) te->name = strip->dir; else - te->name = "Strip None"; + te->name = IFACE_("Strip None"); te->directdata = strip; } else if (type == TSE_SEQUENCE_DUP) { @@ -970,7 +972,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i /* we do lazy build, for speed and to avoid infinite recusion */ if (ptr->data == NULL) { - te->name = "(empty)"; + te->name = IFACE_("(empty)"); } else if (type == TSE_RNA_STRUCT) { /* struct */ @@ -1096,7 +1098,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i ten->directdata = kmi; if (kmi->propvalue) { - ten->name = "Modal map, not yet"; + ten->name = IFACE_("Modal map, not yet"); } else { WM_operator_py_idname(opname, ot->idname); @@ -1257,19 +1259,23 @@ static int treesort_obtype_alpha(const void *v1, const void *v2) const tTreeSort *x1 = v1, *x2 = v2; /* first put objects last (hierarchy) */ - if (x1->idcode == ID_OB && x2->idcode != ID_OB) return 1; - else if (x2->idcode == ID_OB && x1->idcode != ID_OB) return -1; + if (x1->idcode == ID_OB && x2->idcode != ID_OB) { + return 1; + } + else if (x2->idcode == ID_OB && x1->idcode != ID_OB) { + return -1; + } else { /* 2nd we check ob type */ if (x1->idcode == ID_OB && x2->idcode == ID_OB) { - if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1; + if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return 1; else if (((Object *)x1->id)->type > ((Object *)x2->id)->type) return -1; else return 0; } else { int comp = strcmp(x1->name, x2->name); - if (comp > 0) return 1; + if (comp > 0) return 1; else if (comp < 0) return -1; return 0; } @@ -1502,7 +1508,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, SpaceOops *soops) /* current file first - mainvar provides tselem with unique pointer - not used */ ten = outliner_add_element(soops, &soops->tree, mainvar, NULL, TSE_ID_BASE, 0); - ten->name = "Current File"; + ten->name = IFACE_("Current File"); tselem = TREESTORE(ten); if (!tselem->used) diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 4bf88376b74..3849aaf78c1 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -90,7 +90,7 @@ static void outliner_main_area_init(wmWindowManager *wm, ARegion *ar) WM_event_add_dropbox_handler(&ar->handlers, lb); } -static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); @@ -135,7 +135,7 @@ static void outliner_parent_drop_copy(wmDrag *drag, wmDropBox *drop) RNA_string_set(drop->ptr, "child", id->name + 2); } -static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); @@ -176,7 +176,7 @@ static void outliner_parent_clear_copy(wmDrag *drag, wmDropBox *drop) RNA_enum_set(drop->ptr, "type", 0); } -static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); @@ -205,7 +205,7 @@ static void outliner_scene_drop_copy(wmDrag *drag, wmDropBox *drop) RNA_string_set(drop->ptr, "object", id->name + 2); } -static int outliner_material_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); @@ -316,6 +316,10 @@ static void outliner_main_area_listener(ARegion *ar, wmNotifier *wmn) /* all modifier actions now */ ED_region_tag_redraw(ar); break; + default: + /* Trigger update for NC_OBJECT itself */ + ED_region_tag_redraw(ar); + break; } break; case NC_GROUP: diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index 78a76532487..571779a7524 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -294,7 +294,7 @@ static int sequencer_add_scene_strip_exec(bContext *C, wmOperator *op) } -static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_add_scene_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!ED_operator_sequencer_active(C)) { BKE_report(op->reports, RPT_ERROR, "Sequencer area not active"); @@ -392,7 +392,7 @@ static int sequencer_add_movieclip_strip_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_add_movieclip_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!ED_operator_sequencer_active(C)) { BKE_report(op->reports, RPT_ERROR, "Sequencer area not active"); @@ -489,7 +489,7 @@ static int sequencer_add_mask_strip_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_add_mask_strip_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!ED_operator_sequencer_active(C)) { BKE_report(op->reports, RPT_ERROR, "Sequencer area not active"); @@ -602,7 +602,7 @@ static int sequencer_add_movie_strip_exec(bContext *C, wmOperator *op) } -static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sequencer_add_movie_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!ED_operator_sequencer_active(C)) { @@ -657,7 +657,7 @@ static int sequencer_add_sound_strip_exec(bContext *C, wmOperator *op) return sequencer_add_generic_strip_exec(C, op, BKE_sequencer_add_sound_strip); } -static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sequencer_add_sound_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!ED_operator_sequencer_active(C)) { @@ -769,7 +769,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sequencer_add_image_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (!ED_operator_sequencer_active(C)) { @@ -921,7 +921,7 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op) /* add color */ -static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { short is_type_set = RNA_struct_property_is_set(op->ptr, "type"); int type = -1; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 396878cbfeb..7ebe04f666b 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -813,7 +813,9 @@ static void UNUSED_FUNCTION(set_special_seq_update) (int val) if (val) { // XXX special_seq_update = find_nearest_seq(&x); } - else special_seq_update = NULL; + else { + special_seq_update = NULL; + } } ImBuf *sequencer_ibuf_get(struct Main *bmain, Scene *scene, SpaceSeq *sseq, int cfra, int frame_ofs) diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index 7be2d51a3c0..f0ed8d4107d 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -520,7 +520,7 @@ int seq_effect_find_selected(Scene *scene, Sequence *activeseq, int type, Sequen return 0; } if ((seq != activeseq) && (seq != seq2)) { - if (seq2 == NULL) seq2 = seq; + if (seq2 == NULL) seq2 = seq; else if (seq1 == NULL) seq1 = seq; else if (seq3 == NULL) seq3 = seq; else { @@ -889,7 +889,7 @@ static int insert_gap(Scene *scene, int gap, int cfra) return done; } -static void UNUSED_FUNCTION(touch_seq_files) (Scene * scene) +static void UNUSED_FUNCTION(touch_seq_files) (Scene *scene) { Sequence *seq; Editing *ed = BKE_sequencer_editing_get(scene, FALSE); @@ -946,7 +946,7 @@ static void set_filter_seq(Scene *scene) } #endif -static void UNUSED_FUNCTION(seq_remap_paths) (Scene * scene) +static void UNUSED_FUNCTION(seq_remap_paths) (Scene *scene) { Sequence *seq, *last_seq = BKE_sequencer_active_get(scene); Editing *ed = BKE_sequencer_editing_get(scene, FALSE); @@ -988,7 +988,7 @@ static void UNUSED_FUNCTION(seq_remap_paths) (Scene * scene) } -static void UNUSED_FUNCTION(no_gaps) (Scene * scene) +static void UNUSED_FUNCTION(no_gaps) (Scene *scene) { Editing *ed = BKE_sequencer_editing_get(scene, FALSE); int cfra, first = 0, done; @@ -1121,7 +1121,7 @@ static int sequencer_snap_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sequencer_snap_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); @@ -1546,7 +1546,7 @@ static int sequencer_cut_exec(bContext *C, wmOperator *op) } -static int sequencer_cut_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_cut_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); View2D *v2d = UI_view2d_fromcontext(C); @@ -1695,7 +1695,7 @@ static int sequencer_delete_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int sequencer_delete_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_delete_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); @@ -3105,7 +3105,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int sequencer_change_path_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int sequencer_change_path_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); Sequence *seq = BKE_sequencer_active_get(scene); diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c index 0d1ecb76d0e..3269e772be6 100644 --- a/source/blender/editors/space_sequencer/sequencer_select.c +++ b/source/blender/editors/space_sequencer/sequencer_select.c @@ -162,7 +162,7 @@ void select_surround_from_last(Scene *scene) } #endif -void ED_sequencer_select_sequence_single(Scene * scene, Sequence * seq, int deselect_all) +void ED_sequencer_select_sequence_single(Scene *scene, Sequence *seq, bool deselect_all) { Editing *ed = BKE_sequencer_editing_get(scene, FALSE); @@ -315,7 +315,7 @@ void SEQUENCER_OT_select_inverse(struct wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -static int sequencer_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { View2D *v2d = UI_view2d_fromcontext(C); Scene *scene = CTX_data_scene(C); @@ -552,8 +552,6 @@ void SEQUENCER_OT_select(wmOperatorType *ot) } - - /* run recursively to select linked */ static int select_more_less_seq__internal(Scene *scene, int sel, int linked) { @@ -670,7 +668,7 @@ void SEQUENCER_OT_select_less(wmOperatorType *ot) /* select pick linked operator (uses the mouse) */ -static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sequencer_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = CTX_data_scene(C); View2D *v2d = UI_view2d_fromcontext(C); diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 92b17393114..7dcd3a70870 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -85,7 +85,7 @@ static void sample_draw(const bContext *C, ARegion *ar, void *arg_info) } } -static void sample_apply(bContext *C, wmOperator *op, wmEvent *event) +static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); @@ -168,7 +168,7 @@ static void sample_exit(bContext *C, wmOperator *op) MEM_freeN(info); } -static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); SpaceSeq *sseq = CTX_wm_space_seq(C); @@ -189,7 +189,7 @@ static int sample_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int sample_modal(bContext *C, wmOperator *op, wmEvent *event) +static int sample_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 4c6b909882c..ffe89407715 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -373,7 +373,7 @@ static void sequencer_main_area_draw(const bContext *C, ARegion *ar) /* ************* dropboxes ************* */ -static int image_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int image_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -387,7 +387,7 @@ static int image_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) return 0; } -static int movie_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int movie_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); @@ -400,7 +400,7 @@ static int movie_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) return 0; } -static int sound_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int sound_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_text/space_text.c b/source/blender/editors/space_text/space_text.c index ff9d1329721..110e0ab5bc4 100644 --- a/source/blender/editors/space_text/space_text.c +++ b/source/blender/editors/space_text/space_text.c @@ -458,7 +458,7 @@ static void text_cursor(wmWindow *win, ScrArea *UNUSED(sa), ARegion *UNUSED(ar)) /* ************* dropboxes ************* */ -static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int text_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_PATH) if (ELEM(drag->icon, ICON_FILE_SCRIPT, ICON_FILE_BLANK)) /* rule might not work? */ diff --git a/source/blender/editors/space_text/text_autocomplete.c b/source/blender/editors/space_text/text_autocomplete.c index 7c18b5c283a..838ffb948b1 100644 --- a/source/blender/editors/space_text/text_autocomplete.c +++ b/source/blender/editors/space_text/text_autocomplete.c @@ -220,7 +220,7 @@ static GHash *text_autocomplete_build(Text *text) TextFormatType *tft; tft = ED_text_format_get(text); - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { const char *s = BLI_ghashIterator_getValue(iter); texttool_suggest_add(s, tft->format_identifier(s)); } @@ -282,7 +282,7 @@ static void confirm_suggestion(Text *text) /* -- */ -static int text_autocomplete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int text_autocomplete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { SpaceText *st = CTX_wm_space_text(C); Text *text = CTX_data_edit_text(C); @@ -313,7 +313,7 @@ static int text_autocomplete_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED static int doc_scroll = 0; -static int text_autocomplete_modal(bContext *C, wmOperator *op, wmEvent *event) +static int text_autocomplete_modal(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); ScrArea *sa = CTX_wm_area(C); diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index c264368e714..95fd7fce878 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -67,12 +67,14 @@ static void text_font_end(SpaceText *UNUSED(st)) { } -static int text_font_draw(SpaceText *UNUSED(st), int x, int y, const char *str) +static int text_font_draw(SpaceText *st, int x, int y, const char *str) { + int columns; + BLF_position(mono, x, y, 0); - BLF_draw(mono, str, BLF_DRAW_STR_DUMMY_MAX); + columns = BLF_draw_mono(mono, str, BLF_DRAW_STR_DUMMY_MAX, st->cwidth); - return BLF_width(mono, str); + return st->cwidth * columns; } static int text_font_draw_character(SpaceText *st, int x, int y, char c) @@ -85,10 +87,13 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c) static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c) { + int columns; + const size_t len = BLI_str_utf8_size_safe(c); BLF_position(mono, x, y, 0); - BLF_draw(mono, c, len); - return st->cwidth; + columns = BLF_draw_mono(mono, c, len, st->cwidth); + + return st->cwidth * columns; } #if 0 @@ -216,7 +221,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * } max = wrap_width(st, ar); - cursin = txt_utf8_offset_to_index(linein->line, cursin); + cursin = txt_utf8_offset_to_column(linein->line, cursin); while (linep) { start = 0; @@ -225,6 +230,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * *offc = 0; for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; + int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */ /* Mimic replacement of tabs */ ch = linep->line[j]; @@ -238,7 +244,9 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * } while (chars--) { - if (i - start >= max) { + if (i + columns - start > max) { + end = MIN2(end, i); + if (chop && linep == linein && i >= cursin) { if (i == cursin) { (*offl)++; @@ -261,7 +269,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * if (linep == linein && i >= cursin) return; } - i++; + i += columns; } } if (linep == linein) break; @@ -286,9 +294,10 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi end = max; chop = 1; *offc = 0; - cursin = txt_utf8_offset_to_index(linein->line, cursin); + cursin = txt_utf8_offset_to_column(linein->line, cursin); for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) { + int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */ /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -301,7 +310,9 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi chars = 1; while (chars--) { - if (i - start >= max) { + if (i + columns - start > max) { + end = MIN2(end, i); + if (chop && i >= cursin) { if (i == cursin) { (*offl)++; @@ -324,7 +335,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi if (i >= cursin) return; } - i++; + i += columns; } } } @@ -337,24 +348,35 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur) if (line[i] == '\t') a += st->tabnumber - a % st->tabnumber; else - a++; + a += BLI_str_utf8_char_width_safe(line + i); } return a; } -static const char *txt_utf8_get_nth(const char *str, int n) +static const char *txt_utf8_forward_columns(const char *str, int columns, int *padding) { - int pos = 0; - while (str[pos] && n--) { - pos += BLI_str_utf8_size_safe(str + pos); + int col; + const char *p = str; + while (*p) { + col = BLI_str_utf8_char_width(p); + if (columns - col < 0) + break; + columns -= col; + p += BLI_str_utf8_size_safe(p); + if (columns == 0) + break; } - return str + pos; + if (padding) + *padding = *p ? columns : 0; + return p; } static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w, const char *format, int skip) { FlattenString fs; - int basex, i, a, start, end, max, lines; /* view */ + int basex, lines; + int i, wrap, end, max, columns, padding; /* column */ + int a, fstart, fpos; /* utf8 chars */ int mi, ma, mstart, mend; /* mem */ char fmt_prev = 0xff; @@ -365,41 +387,46 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w basex = x; lines = 1; - start = 0; mstart = 0; - end = max; mend = txt_utf8_get_nth(str, max) - str; + fpos = fstart = 0; mstart = 0; + mend = txt_utf8_forward_columns(str, max, &padding) - str; + end = wrap = max - padding; - for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) { - if (i - start >= max) { + for (i = 0, mi = 0; str[mi]; i += columns, mi += BLI_str_utf8_size_safe(str + mi)) { + columns = BLI_str_utf8_char_width_safe(str + mi); + if (i + columns > end) { /* skip hidden part of line */ if (skip) { skip--; - start = end; mstart = mend; - end += max; mend = txt_utf8_get_nth(str + mend, max) - str; + fstart = fpos; mstart = mend; + mend = txt_utf8_forward_columns(str + mend, max, &padding) - str; + end = (wrap += max - padding); continue; } /* Draw the visible portion of text on the overshot line */ - for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) { + for (a = fstart, ma = mstart; ma < mend; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) { if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]); } x += text_font_draw_character_utf8(st, x, y, str + ma); + fpos++; } y -= st->lheight_dpi + TXT_LINE_SPACING; x = basex; lines++; - start = end; mstart = mend; - end += max; mend = txt_utf8_get_nth(str + mend, max) - str; + fstart = fpos; mstart = mend; + mend = txt_utf8_forward_columns(str + mend, max, &padding) - str; + end = (wrap += max - padding); if (y <= 0) break; } else if (str[mi] == ' ' || str[mi] == '-') { - end = i + 1; mend = mi + 1; + wrap = i + 1; mend = mi + 1; } } /* Draw the remaining text */ - for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) { + for (a = fstart, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) { if (fmt_prev != format[a]) format_draw_color(fmt_prev = format[a]); } @@ -412,53 +439,55 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w return lines; } -static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int draw, int x, int y, const char *format) +static void text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int x, int y, const char *format) { FlattenString fs; - int *acc, r = 0; - const char *in; + int columns, size, n, w = 0, padding, amount = 0; + const char *in = NULL; - int w = flatten_string(st, &fs, str); - if (w < cshift) { - flatten_string_free(&fs); - return 0; /* String is shorter than shift */ - } - - in = txt_utf8_get_nth(fs.buf, cshift); - acc = fs.accum + cshift; - w = w - cshift; + for (n = flatten_string(st, &fs, str), str = fs.buf; n > 0; n--) { + columns = BLI_str_utf8_char_width_safe(str); + size = BLI_str_utf8_size_safe(str); - if (draw) { - int amount = maxwidth ? MIN2(w, maxwidth) : w; - - if (st->showsyntax && format) { - int a, str_shift = 0; - char fmt_prev = 0xff; - format = format + cshift; - - for (a = 0; a < amount; a++) { - if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]); - x += text_font_draw_character_utf8(st, x, y, in + str_shift); - str_shift += BLI_str_utf8_size_safe(in + str_shift); + if (!in) { + if (w >= cshift) { + padding = w - cshift; + in = str; } + else if (format) + format++; } - else { - text_font_draw(st, x, y, in); + if (in) { + if (maxwidth && w + columns > cshift + maxwidth) + break; + amount++; + } + + w += columns; + str += size; + } + if (!in) { + flatten_string_free(&fs); + return; /* String is shorter than shift or ends with a padding */ + } + + x += st->cwidth * padding; + + if (st->showsyntax && format) { + int a, str_shift = 0; + char fmt_prev = 0xff; + + for (a = 0; a < amount; a++) { + if (format[a] != fmt_prev) format_draw_color(fmt_prev = format[a]); + x += text_font_draw_character_utf8(st, x, y, in + str_shift); + str_shift += BLI_str_utf8_size_safe(in + str_shift); } } else { - while (w-- && *acc++ < maxwidth) - r += st->cwidth; + text_font_draw(st, x, y, in); } flatten_string_free(&fs); - - if (cshift && r == 0) - return 0; - else if (st->showlinenrs) - return r + TXT_OFFSET + TEXTXLOC; - else - return r + TXT_OFFSET; } /************************ cache utilities *****************************/ @@ -672,25 +701,29 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str) start = 0; end = max; for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) { + int columns = BLI_str_utf8_char_width_safe(str + j); /* = 1 for tab */ + /* Mimic replacement of tabs */ ch = str[j]; if (ch == '\t') { chars = st->tabnumber - i % st->tabnumber; ch = ' '; } - else chars = 1; + else { + chars = 1; + } while (chars--) { - if (i - start >= max) { + if (i + columns - start > max) { lines++; - start = end; + start = MIN2(end, i); end += max; } else if (ch == ' ' || ch == '-') { end = i + 1; } - i++; + i += columns; } } @@ -712,7 +745,9 @@ int text_get_span_wrap(SpaceText *st, ARegion *ar, TextLine *from, TextLine *to) return ret; } - else return txt_get_span(from, to); + else { + return txt_get_span(from, to); + } } int text_get_total_lines(SpaceText *st, ARegion *ar) @@ -927,7 +962,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar) buf[i] = '\0'; if (lines >= 0) { y -= st->lheight_dpi; - text_draw(st, buf, 0, 0, 1, x + 4, y - 3, NULL); + text_draw(st, buf, 0, 0, x + 4, y - 3, NULL); } i = 0; br = DOC_WIDTH; lines++; } @@ -936,7 +971,7 @@ static void draw_documentation(SpaceText *st, ARegion *ar) buf[br] = '\0'; if (lines >= 0) { y -= st->lheight_dpi; - text_draw(st, buf, 0, 0, 1, x + 4, y - 3, NULL); + text_draw(st, buf, 0, 0, x + 4, y - 3, NULL); } p -= i - br - 1; /* Rewind pointer to last break */ i = 0; br = DOC_WIDTH; lines++; @@ -955,9 +990,9 @@ static void draw_documentation(SpaceText *st, ARegion *ar) static void draw_suggestion_list(SpaceText *st, ARegion *ar) { SuggItem *item, *first, *last, *sel; - TextLine *tmp; - char str[SUGG_LIST_WIDTH + 1]; - int w, boxw = 0, boxh, i, l, x, y, *top; + char str[SUGG_LIST_WIDTH * BLI_UTF8_MAX + 1]; + int offl, offc, vcurl, vcurc; + int w, boxw = 0, boxh, i, x, y, *top; const int lheight = st->lheight_dpi + TXT_LINE_SPACING; const int margin_x = 2; @@ -973,24 +1008,24 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar) sel = texttool_suggest_selected(); top = texttool_suggest_top(); - /* Count the visible lines to the cursor */ - for (tmp = st->text->curl, l = -st->top; tmp; tmp = tmp->prev, l++) ; - if (l < 0) return; - - if (st->showlinenrs) { - x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET + TEXTXLOC - 4; - } - else { - x = st->cwidth * (st->text->curc - st->left) + TXT_OFFSET - 4; - } + wrap_offset(st, ar, st->text->curl, st->text->curc, &offl, &offc); + vcurl = txt_get_span(st->text->lines.first, st->text->curl) - st->top + offl; + vcurc = text_get_char_pos(st, st->text->curl->line, st->text->curc) - st->left + offc; + + x = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + x += vcurc * st->cwidth - 4; + y = ar->winy - (vcurl + 1) * lheight - 2; + /* offset back so the start of the text lines up with the suggestions, * not essential but makes suggestions easier to follow */ x -= st->cwidth * (st->text->curc - text_find_identifier_start(st->text->curl->line, st->text->curc)); - y = ar->winy - lheight * l - 2; boxw = SUGG_LIST_WIDTH * st->cwidth + 20; boxh = SUGG_LIST_SIZE * lheight + 8; + if (x + boxw > ar->winx) + x = MAX2(0, ar->winx - boxw); + /* not needed but stands out nicer */ uiDrawBoxShadow(220, x, y - boxh, x + boxw, y); @@ -1003,12 +1038,13 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar) for (i = 0, item = first; i < *top && item->next; i++, item = item->next) ; for (i = 0; i < SUGG_LIST_SIZE && item; i++, item = item->next) { + int len = txt_utf8_forward_columns(item->name, SUGG_LIST_WIDTH, NULL) - item->name; y -= lheight; - BLI_strncpy(str, item->name, SUGG_LIST_WIDTH); + BLI_strncpy(str, item->name, len + 1); - w = BLF_width(mono, str); + w = st->cwidth * text_get_char_pos(st, str, len); if (item == sel) { UI_ThemeColor(TH_SHADE2); @@ -1016,7 +1052,7 @@ static void draw_suggestion_list(SpaceText *st, ARegion *ar) } format_draw_color(item->type); - text_draw(st, str, 0, 0, 1, x + margin_x, y - 1, NULL); + text_draw(st, str, 0, 0, x + margin_x, y - 1, NULL); if (item == last) break; } @@ -1378,7 +1414,7 @@ void draw_text_main(SpaceText *st, ARegion *ar) } else { /* draw unwrapped text */ - text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, 1, x, y, tmp->format); + text_draw(st, tmp->line, st->left, ar->winx / st->cwidth, x, y, tmp->format); y -= st->lheight_dpi + TXT_LINE_SPACING; } @@ -1435,8 +1471,6 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa) winx = ar->winx; break; } - - winx -= TXT_SCROLL_WIDTH; text_update_character_width(st); @@ -1454,10 +1488,11 @@ void text_scroll_to_cursor(SpaceText *st, ScrArea *sa) st->left = 0; } else { - x = text_draw(st, text->sell->line, st->left, text->selc, 0, 0, 0, NULL); + x = st->cwidth * (text_get_char_pos(st, text->sell->line, text->selc) - st->left); + winx -= TXT_OFFSET + (st->showlinenrs ? TEXTXLOC : 0) + TXT_SCROLL_WIDTH; - if (x == 0 || x > winx) - st->left = text->curc - 0.5 * winx / st->cwidth; + if (x <= 0 || x > winx) + st->left += (x - winx / 2) / st->cwidth; } if (st->top < 0) st->top = 0; diff --git a/source/blender/editors/space_text/text_format.c b/source/blender/editors/space_text/text_format.c index 3c7897200ed..b29c6420d60 100644 --- a/source/blender/editors/space_text/text_format.c +++ b/source/blender/editors/space_text/text_format.c @@ -144,7 +144,7 @@ int text_check_format_len(TextLine *line, unsigned int len) * Fill the string with formatting constant, * advancing \a str_p and \a fmt_p * - * \param len length in bytes + * \param len length in bytes of \a fmt_p to fill. */ void text_format_fill(const char **str_p, char **fmt_p, const char type, const int len) { diff --git a/source/blender/editors/space_text/text_format_lua.c b/source/blender/editors/space_text/text_format_lua.c index 6c72e043930..f74d1cf8e8b 100644 --- a/source/blender/editors/space_text/text_format_lua.c +++ b/source/blender/editors/space_text/text_format_lua.c @@ -237,7 +237,7 @@ static void txtfmt_lua_format_line(SpaceText *st, TextLine *line, const int do_n } /* Single line comment */ else if (*str == '-' && *(str + 1) == '-') { - text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format)); } else if (*str == '"' || *str == '\'') { /* Strings */ diff --git a/source/blender/editors/space_text/text_format_osl.c b/source/blender/editors/space_text/text_format_osl.c index 7d493eb1f62..c95929a720f 100644 --- a/source/blender/editors/space_text/text_format_osl.c +++ b/source/blender/editors/space_text/text_format_osl.c @@ -141,10 +141,10 @@ static int txtfmt_osl_find_specialvar(const char *string) int i, len; /* OSL shader types */ - if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len; - else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len; - else if (STR_LITERAL_STARTSWITH(string, "volume", len)) i = len; - else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len; + if (STR_LITERAL_STARTSWITH(string, "shader", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "surface", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "volume", len)) i = len; + else if (STR_LITERAL_STARTSWITH(string, "displacement", len)) i = len; else i = 0; /* If next source char is an identifier (eg. 'i' in "definate") no match */ @@ -252,7 +252,7 @@ static void txtfmt_osl_format_line(SpaceText *st, TextLine *line, const int do_n /* Deal with comments first */ if (*str == '/' && *(str + 1) == '/') { /* fill the remaining line */ - text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format)); } /* C-Style (multi-line) comments */ else if (*str == '/' && *(str + 1) == '*') { diff --git a/source/blender/editors/space_text/text_format_py.c b/source/blender/editors/space_text/text_format_py.c index 902d60dcb3e..9562d57041f 100644 --- a/source/blender/editors/space_text/text_format_py.c +++ b/source/blender/editors/space_text/text_format_py.c @@ -233,7 +233,7 @@ static void txtfmt_py_format_line(SpaceText *st, TextLine *line, const int do_ne /* Deal with comments first */ if (*str == '#') { /* fill the remaining line */ - text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(str - fs.buf)); + text_format_fill(&str, &fmt, FMT_TYPE_COMMENT, len - (int)(fmt - line->format)); } else if (*str == '"' || *str == '\'') { /* Strings */ diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index b45961bff11..cdbb3e7c600 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -72,7 +72,7 @@ /************************ poll ***************************/ -BLI_INLINE int text_pixel_x_to_index(SpaceText *st, const int x) +BLI_INLINE int text_pixel_x_to_column(SpaceText *st, const int x) { /* add half the char width so mouse cursor selection is inbetween letters */ return (x + (st->cwidth / 2)) / st->cwidth; @@ -278,7 +278,7 @@ static int text_open_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int text_open_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int text_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Text *text = CTX_data_edit_text(C); char *path = (text && text->name) ? text->name : G.main->name; @@ -539,7 +539,7 @@ static int text_save_as_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int text_save_as_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int text_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Text *text = CTX_data_edit_text(C); char *str; @@ -1011,7 +1011,7 @@ static int text_line_break_exec(bContext *C, wmOperator *UNUSED(op)) text_drawcache_tag_update(st, 0); // double check tabs/spaces before splitting the line - curts = setcurr_tab_spaces(text, space); + curts = txt_setcurr_tab_spaces(text, space); txt_split_curline(text); for (a = 0; a < curts; a++) { @@ -1407,25 +1407,31 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) { int chars; + int columns = BLI_str_utf8_char_width_safe(linein->line + j); /* = 1 for tab */ + /* Mimic replacement of tabs */ ch = linein->line[j]; if (ch == '\t') { chars = st->tabnumber - i % st->tabnumber; ch = ' '; } - else chars = 1; + else { + chars = 1; + } while (chars--) { - if (rell == 0 && i - start == relc) { + if (rell == 0 && i - start <= relc && i + columns - start > relc) { /* current position could be wrapped to next line */ /* this should be checked when end of current line would be reached */ selc = j; found = 1; } - else if (i - end == relc) { + else if (i - end <= relc && i + columns - end > relc) { curs = j; } - if (i - start >= max) { + if (i + columns - start > max) { + end = MIN2(end, i); + if (found) { /* exact cursor position was found, check if it's */ /* still on needed line (hasn't been wrapped) */ @@ -1441,7 +1447,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int chop = 1; rell--; - if (rell == 0 && i - start >= relc) { + if (rell == 0 && i + columns - start > relc) { selc = curs; loop = 0; break; @@ -1458,7 +1464,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int break; } - if (rell == 0 && i - start >= relc) { + if (rell == 0 && i + columns - start > relc) { selc = curs; loop = 0; break; @@ -1467,7 +1473,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int endj = j; chop = 0; } - i++; + i += columns; } } @@ -1585,20 +1591,26 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; + int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */ + /* Mimic replacement of tabs */ ch = (*linep)->line[j]; if (ch == '\t') { chars = st->tabnumber - i % st->tabnumber; ch = ' '; } - else chars = 1; + else { + chars = 1; + } while (chars--) { - if (i - start >= max) { + if (i + columns - start > max) { + end = MIN2(end, i); + *charp = endj; if (j >= oldc) { - if (ch == '\0') *charp = txt_utf8_index_to_offset((*linep)->line, start); + if (ch == '\0') *charp = txt_utf8_column_to_offset((*linep)->line, start); loop = 0; break; } @@ -1611,7 +1623,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) } else if (ch == ' ' || ch == '-' || ch == '\0') { if (j >= oldc) { - *charp = txt_utf8_index_to_offset((*linep)->line, start); + *charp = txt_utf8_column_to_offset((*linep)->line, start); loop = 0; break; } @@ -1620,7 +1632,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) endj = j + 1; chop = 0; } - i++; + i += columns; } } @@ -1651,16 +1663,22 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; + int columns = BLI_str_utf8_char_width_safe((*linep)->line + j); /* = 1 for tab */ + /* Mimic replacement of tabs */ ch = (*linep)->line[j]; if (ch == '\t') { chars = st->tabnumber - i % st->tabnumber; ch = ' '; } - else chars = 1; + else { + chars = 1; + } while (chars--) { - if (i - start >= max) { + if (i + columns - start > max) { + end = MIN2(end, i); + if (chop) endj = BLI_str_prev_char_utf8((*linep)->line + j) - (*linep)->line; if (endj >= oldc) { @@ -1684,7 +1702,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) endj = j; chop = 0; } - i++; + i += columns; } } @@ -1716,7 +1734,9 @@ static void txt_wrap_move_up(SpaceText *st, ARegion *ar, short sel) visible_lines = text_get_visible_lines(st, ar, (*linep)->line); *charp = text_get_cursor_rel(st, ar, *linep, visible_lines - 1, col); } - else *charp = 0; + else { + *charp = 0; + } } if (!sel) txt_pop_sel(text); @@ -1745,7 +1765,9 @@ static void txt_wrap_move_down(SpaceText *st, ARegion *ar, short sel) *linep = (*linep)->next; *charp = text_get_cursor_rel(st, ar, *linep, 0, col); } - else *charp = (*linep)->len; + else { + *charp = (*linep)->len; + } } if (!sel) txt_pop_sel(text); @@ -1927,7 +1949,7 @@ static int text_jump_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int text_jump_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int text_jump_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y); @@ -2085,7 +2107,7 @@ static int text_scroll_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static void text_scroll_apply(bContext *C, wmOperator *op, wmEvent *event) +static void text_scroll_apply(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); ARegion *ar = CTX_wm_region(C); @@ -2142,7 +2164,7 @@ static void scroll_exit(bContext *C, wmOperator *op) MEM_freeN(op->customdata); } -static int text_scroll_modal(bContext *C, wmOperator *op, wmEvent *event) +static int text_scroll_modal(bContext *C, wmOperator *op, const wmEvent *event) { TextScroll *tsc = op->customdata; SpaceText *st = CTX_wm_space_text(C); @@ -2182,7 +2204,7 @@ static int text_scroll_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int text_scroll_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int text_scroll_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); TextScroll *tsc; @@ -2259,7 +2281,7 @@ static int text_region_scroll_poll(bContext *C) return 1; } -static int text_scroll_bar_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int text_scroll_bar_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); ARegion *ar = CTX_wm_region(C); @@ -2342,7 +2364,7 @@ typedef struct SetSelection { short old[2]; } SetSelection; -static int flatten_len(SpaceText *st, const char *str) +static int flatten_width(SpaceText *st, const char *str) { int i, total = 0; @@ -2350,20 +2372,30 @@ static int flatten_len(SpaceText *st, const char *str) if (str[i] == '\t') { total += st->tabnumber - total % st->tabnumber; } - else total++; + else { + total += BLI_str_utf8_char_width_safe(str + i); + } } return total; } -static int flatten_index_to_offset(SpaceText *st, const char *str, int index) +static int flatten_column_to_offset(SpaceText *st, const char *str, int index) { - int i, j; - for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j)) + int i = 0, j = 0, col; + + while (*(str + j)) { if (str[j] == '\t') - i += st->tabnumber - i % st->tabnumber; + col = st->tabnumber - i % st->tabnumber; else - i++; + col = BLI_str_utf8_char_width_safe(str + j); + + if (i + col > index) + break; + + i += col; + j += BLI_str_utf8_size_safe(str + j); + } return j; } @@ -2390,7 +2422,7 @@ static TextLine *get_first_visible_line(SpaceText *st, ARegion *ar, int *y) static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, int y, int sel) { Text *text = st->text; - int max = wrap_width(st, ar); /* view */ + int max = wrap_width(st, ar); /* column */ int charp = -1; /* mem */ int loop = 1, found = 0; /* flags */ char ch; @@ -2399,12 +2431,13 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in TextLine *linep = get_first_visible_line(st, ar, &y); while (loop && linep) { - int i = 0, start = 0, end = max; /* view */ + int i = 0, start = 0, end = max; /* column */ int j = 0, curs = 0, endj = 0; /* mem */ int chop = 1; /* flags */ for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; + int columns = BLI_str_utf8_char_width_safe(linep->line + j); /* = 1 for tab */ /* Mimic replacement of tabs */ ch = linep->line[j]; @@ -2412,7 +2445,9 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in chars = st->tabnumber - i % st->tabnumber; ch = ' '; } - else chars = 1; + else { + chars = 1; + } while (chars--) { /* Gone too far, go back to last wrap point */ @@ -2422,17 +2457,19 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in break; /* Exactly at the cursor */ } - else if (y == 0 && i - start == x) { + else if (y == 0 && i - start <= x && i + columns - start > x) { /* current position could be wrapped to next line */ /* this should be checked when end of current line would be reached */ charp = curs = j; found = 1; /* Prepare curs for next wrap */ } - else if (i - end == x) { + else if (i - end <= x && i + columns - end > x) { curs = j; } - if (i - start >= max) { + if (i + columns - start > max) { + end = MIN2(end, i); + if (found) { /* exact cursor position was found, check if it's */ /* still on needed line (hasn't been wrapped) */ @@ -2449,7 +2486,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in y--; chop = 1; - if (y == 0 && i - start >= x) { + if (y == 0 && i + columns - start > x) { charp = curs; loop = 0; break; @@ -2461,7 +2498,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in break; } - if (y == 0 && i - start >= x) { + if (y == 0 && i + columns - start > x) { charp = curs; loop = 0; break; @@ -2470,7 +2507,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in endj = j; chop = 0; } - i++; + i += columns; } if (ch == '\0') break; @@ -2509,7 +2546,7 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int else x -= TXT_OFFSET; if (x < 0) x = 0; - x = text_pixel_x_to_index(st, x) + st->left; + x = text_pixel_x_to_column(st, x) + st->left; if (st->wordwrap) { text_cursor_set_to_pos_wrapped(st, ar, x, y, sel); @@ -2532,14 +2569,14 @@ static void text_cursor_set_to_pos(SpaceText *st, ARegion *ar, int x, int y, int } - w = flatten_len(st, (*linep)->line); - if (x < w) *charp = flatten_index_to_offset(st, (*linep)->line, x); + w = flatten_width(st, (*linep)->line); + if (x < w) *charp = flatten_column_to_offset(st, (*linep)->line, x); else *charp = (*linep)->len; } if (!sel) txt_pop_sel(text); } -static void text_cursor_set_apply(bContext *C, wmOperator *op, wmEvent *event) +static void text_cursor_set_apply(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); ARegion *ar = CTX_wm_region(C); @@ -2594,7 +2631,7 @@ static void text_cursor_set_exit(bContext *C, wmOperator *op) MEM_freeN(ssel); } -static int text_set_selection_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int text_set_selection_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); SetSelection *ssel; @@ -2619,7 +2656,7 @@ static int text_set_selection_invoke(bContext *C, wmOperator *op, wmEvent *event return OPERATOR_RUNNING_MODAL; } -static int text_set_selection_modal(bContext *C, wmOperator *op, wmEvent *event) +static int text_set_selection_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { case LEFTMOUSE: @@ -2675,7 +2712,7 @@ static int text_cursor_set_exec(bContext *C, wmOperator *op) return OPERATOR_PASS_THROUGH; } -static int text_cursor_set_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int text_cursor_set_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); @@ -2707,7 +2744,7 @@ void TEXT_OT_cursor_set(wmOperatorType *ot) /******************* line number operator **********************/ -static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int text_line_number_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { SpaceText *st = CTX_wm_space_text(C); Text *text = CTX_data_edit_text(C); @@ -2797,7 +2834,7 @@ static int text_insert_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event) { int ret; @@ -3100,7 +3137,7 @@ static int text_resolve_conflict_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int text_resolve_conflict_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Text *text = CTX_data_edit_text(C); uiPopupMenu *pup; diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt index 462619a7e8b..a04371a5ed9 100644 --- a/source/blender/editors/space_view3d/CMakeLists.txt +++ b/source/blender/editors/space_view3d/CMakeLists.txt @@ -54,6 +54,7 @@ set(SRC view3d_iterators.c view3d_ops.c view3d_project.c + view3d_ruler.c view3d_select.c view3d_snap.c view3d_toolbar.c diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 2cef10e1981..9000ccbf324 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -428,7 +428,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */ } else if (!has_mcol) { - if (tface) glColor3f(1.0, 1.0, 1.0); + if (tface) { + glColor3f(1.0, 1.0, 1.0); + } else { if (ma) { float col[3]; @@ -437,7 +439,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int glColor3fv(col); } - else glColor3f(1.0, 1.0, 1.0); + else { + glColor3f(1.0, 1.0, 1.0); + } } return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */ } diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 158b75c494a..743b53ce16c 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -615,7 +615,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char glColor4fv(ob->col); /* Draw the Image on the screen */ - glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); glDisable(GL_BLEND); @@ -812,17 +812,6 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa } for (vos = strings->first; vos; vos = vos->next) { - /* too slow, reading opengl info while drawing is very bad, - * better to see if we can use the zbuffer while in pixel space - campbell */ -#if 0 - if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) { - gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz); - glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth); - - if (uz > depth) - continue; - } -#endif if (vos->sco[0] != IS_CLIPPED) { const char *str = (char *)(vos + 1); @@ -3862,7 +3851,7 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas if (v3d->flag2 & V3D_BACKFACE_CULLING) { /* not all displists use same in/out normal direction convention */ glEnable(GL_CULL_FACE); - glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT); + glCullFace((base->object->type == OB_MBALL || base->object->derivedFinal) ? GL_BACK : GL_FRONT); } retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); @@ -3968,7 +3957,9 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix if (draw_as == PART_DRAW_AXIS) { copy_v3_v3(vec2, state->co); } - else sub_v3_v3v3(vec2, state->co, vec); + else { + sub_v3_v3v3(vec2, state->co, vec); + } add_v3_v3(vec, state->co); copy_v3_v3(pdd->vd, vec); pdd->vd += 3; @@ -3980,7 +3971,9 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix if (draw_as == PART_DRAW_AXIS) { copy_v3_v3(vec2, state->co); } - else sub_v3_v3v3(vec2, state->co, vec); + else { + sub_v3_v3v3(vec2, state->co, vec); + } add_v3_v3(vec, state->co); @@ -6055,8 +6048,10 @@ static void drawtexspace(Object *ob) copy_v3_v3(size, mb->size); copy_v3_v3(loc, mb->loc); } - else return; - + else { + return; + } + vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = loc[0] - size[0]; vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = loc[0] + size[0]; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 57755231240..d332fb9f8b3 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -48,10 +48,12 @@ #include "BKE_object.h" #include "BKE_screen.h" +#include "ED_render.h" #include "ED_space_api.h" #include "ED_screen.h" #include "ED_object.h" +#include "GPU_extensions.h" #include "GPU_material.h" #include "BIF_gl.h" @@ -350,7 +352,7 @@ static void view3d_free(SpaceLink *sl) /* spacetype; init callback */ -static void view3d_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) +static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) { } @@ -469,7 +471,22 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) } -static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static void view3d_main_area_exit(wmWindowManager *UNUSED(wm), ARegion *ar) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->render_engine) { + RE_engine_free(rv3d->render_engine); + rv3d->render_engine = NULL; + } + + if (rv3d->gpuoffscreen) { + GPU_offscreen_free(rv3d->gpuoffscreen); + rv3d->gpuoffscreen = NULL; + } +} + +static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_ID) { ID *id = (ID *)drag->poin; @@ -479,7 +496,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSE return 0; } -static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_ID) { ID *id = (ID *)drag->poin; @@ -489,7 +506,7 @@ static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UN return 0; } -static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_ID) { ID *id = (ID *)drag->poin; @@ -499,7 +516,7 @@ static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS return 0; } -static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) +static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event)) { if (drag->type == WM_DRAG_ID) { ID *id = (ID *)drag->poin; @@ -513,7 +530,7 @@ static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS return 0; } -static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { if (event->ctrl) return false; @@ -524,7 +541,7 @@ static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) return 0; } -static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { Base *base = ED_view3d_give_base_under_cursor(C, event->mval); @@ -535,7 +552,7 @@ static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) return 0; } -static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, wmEvent *event) +static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event) { Base *base = ED_view3d_give_base_under_cursor(C, event->mval); @@ -615,6 +632,10 @@ static void view3d_main_area_free(ARegion *ar) if (rv3d->sms) { MEM_freeN(rv3d->sms); } + if (rv3d->gpuoffscreen) { + GPU_offscreen_free(rv3d->gpuoffscreen); + } + MEM_freeN(rv3d); ar->regiondata = NULL; } @@ -633,6 +654,7 @@ static void *view3d_main_area_duplicate(void *poin) new->clipbb = MEM_dupallocN(rv3d->clipbb); new->depths = NULL; + new->gpuoffscreen = NULL; new->ri = NULL; new->render_engine = NULL; new->gpd = NULL; @@ -1216,6 +1238,7 @@ void ED_spacetype_view3d(void) art->keymapflag = ED_KEYMAP_GPENCIL; art->draw = view3d_main_area_draw; art->init = view3d_main_area_init; + art->exit = view3d_main_area_exit; art->free = view3d_main_area_free; art->duplicate = view3d_main_area_duplicate; art->listener = view3d_main_area_listener; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 4aaa3332252..8fdc9416513 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -219,15 +219,12 @@ void ED_view3d_clipping_enable(void) } } -static int view3d_clipping_test(const float vec[3], float clip[6][4]) +static int view3d_clipping_test(const float co[3], float clip[6][4]) { - float view[3]; - copy_v3_v3(view, vec); - - if (0.0f < clip[0][3] + dot_v3v3(view, clip[0])) - if (0.0f < clip[1][3] + dot_v3v3(view, clip[1])) - if (0.0f < clip[2][3] + dot_v3v3(view, clip[2])) - if (0.0f < clip[3][3] + dot_v3v3(view, clip[3])) + if (0.0f < clip[0][3] + dot_v3v3(co, clip[0])) + if (0.0f < clip[1][3] + dot_v3v3(co, clip[1])) + if (0.0f < clip[2][3] + dot_v3v3(co, clip[2])) + if (0.0f < clip[3][3] + dot_v3v3(co, clip[3])) return 0; return 1; @@ -235,9 +232,9 @@ static int view3d_clipping_test(const float vec[3], float clip[6][4]) /* for 'local' ED_view3d_clipping_local must run first * then all comparisons can be done in localspace */ -int ED_view3d_clipping_test(RegionView3D *rv3d, const float vec[3], const int is_local) +int ED_view3d_clipping_test(RegionView3D *rv3d, const float co[3], const bool is_local) { - return view3d_clipping_test(vec, is_local ? rv3d->clip_local : rv3d->clip); + return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip); } /* ********* end custom clipping *********** */ @@ -971,7 +968,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect) } static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *viewborder_r, short no_shift, short no_zoom) + rctf *r_viewborder, const bool no_shift, const bool no_zoom) { CameraParams params; rctf rect_view, rect_camera; @@ -995,25 +992,25 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV rect_camera = params.viewplane; /* get camera border within viewport */ - viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; - viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; - viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; - viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; + r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; + r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx; + r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; + r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy; } -void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float size_r[2]) +void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2]) { rctf viewborder; view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, TRUE, TRUE); - size_r[0] = BLI_rctf_size_x(&viewborder); - size_r[1] = BLI_rctf_size_y(&viewborder); + r_size[0] = BLI_rctf_size_x(&viewborder); + r_size[1] = BLI_rctf_size_y(&viewborder); } void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, - rctf *viewborder_r, short no_shift) + rctf *viewborder_r, const bool no_shift) { - view3d_camera_border(scene, ar, v3d, rv3d, viewborder_r, no_shift, FALSE); + view3d_camera_border(scene, ar, v3d, rv3d, viewborder_r, no_shift, false); } static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac) @@ -1316,11 +1313,6 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) { /* do nothing */ } - else if ((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) && - scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE)) - { - /* do nothing */ - } else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) && v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT)) { @@ -1356,7 +1348,35 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) if (multisample_enabled) glDisable(GL_MULTISAMPLE_ARB); - glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); + if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) { + /* for multisample we use an offscreen FBO. multisample drawing can fail + * with color coded selection drawing, and reading back depths from such + * a buffer can also cause a few seconds freeze on OS X / NVidia. */ + int w = BLI_rcti_size_x(&ar->winrct); + int h = BLI_rcti_size_y(&ar->winrct); + char error[256]; + + if (rv3d->gpuoffscreen) { + if (GPU_offscreen_width(rv3d->gpuoffscreen) != w || + GPU_offscreen_height(rv3d->gpuoffscreen) != h) + { + GPU_offscreen_free(rv3d->gpuoffscreen); + rv3d->gpuoffscreen = NULL; + } + } + + if (!rv3d->gpuoffscreen) { + rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error); + + if (!rv3d->gpuoffscreen) + fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error); + } + } + + if (rv3d->gpuoffscreen) + GPU_offscreen_bind(rv3d->gpuoffscreen); + else + glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct)); glClearColor(0.0, 0.0, 0.0, 0.0); if (v3d->zbuf) { @@ -1375,9 +1395,13 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) if (base && (base->lay & v3d->lay)) draw_object_backbufsel(scene, v3d, rv3d, base->object); + + if (rv3d->gpuoffscreen) + GPU_offscreen_unbind(rv3d->gpuoffscreen); + else + ar->swap = 0; /* mark invalid backbuf for wm draw */ v3d->flag &= ~V3D_INVALID_BACKBUF; - ar->swap = 0; /* mark invalid backbuf for wm draw */ G.f &= ~G_BACKBUFSEL; v3d->zbuf = FALSE; @@ -1394,6 +1418,21 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d) } +void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data) +{ + RegionView3D *rv3d = ar->regiondata; + + if (rv3d->gpuoffscreen) { + GPU_offscreen_bind(rv3d->gpuoffscreen); + glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); + glReadPixels(x, y, w, h, format, type, data); + GPU_offscreen_unbind(rv3d->gpuoffscreen); + } + else { + glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data); + } +} + void view3d_validate_backbuf(ViewContext *vc) { if (vc->v3d->flag & V3D_INVALID_BACKBUF) @@ -1409,12 +1448,9 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y) return 0; } - x += vc->ar->winrct.xmin; - y += vc->ar->winrct.ymin; - view3d_validate_backbuf(vc); - glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); + view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col); glReadBuffer(GL_BACK); if (ENDIAN_ORDER == B_ENDIAN) { @@ -1445,8 +1481,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax, view3d_validate_backbuf(vc); - glReadPixels(vc->ar->winrct.xmin + xminc, - vc->ar->winrct.ymin + yminc, + view3d_opengl_read_pixels(vc->ar, + xminc, yminc, (xmaxc - xminc + 1), (ymaxc - yminc + 1), GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); @@ -1573,7 +1609,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, float fac, asp, zoomx, zoomy; float x1, y1, x2, y2; - ImBuf *ibuf = NULL, *freeibuf; + ImBuf *ibuf = NULL, *freeibuf, *releaseibuf; Image *ima; MovieClip *clip; @@ -1583,6 +1619,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, continue; freeibuf = NULL; + releaseibuf = NULL; if (bgpic->source == V3D_BGPIC_IMAGE) { ima = bgpic->ima; if (ima == NULL) @@ -1593,7 +1630,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, } else { ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL); - freeibuf = ibuf; + releaseibuf = ibuf; } image_aspect[0] = ima->aspx; @@ -1608,7 +1645,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if (scene->camera) clip = BKE_object_movieclip_get(scene, scene->camera, 1); } - else clip = bgpic->clip; + else { + clip = bgpic->clip; + } if (clip == NULL) continue; @@ -1636,6 +1675,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */ if (freeibuf) IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, NULL); continue; } @@ -1708,10 +1749,12 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, float tvec[3]; float sco[2]; const float mval_f[2] = {1.0f, 0.0f}; + const float co_zero[3] = {0}; + float zfac; /* calc window coord */ - initgrabz(rv3d, 0.0, 0.0, 0.0); - ED_view3d_win_to_delta(ar, mval_f, tvec); + zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL); + ED_view3d_win_to_delta(ar, mval_f, tvec, zfac); fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */ fac = 1.0f / fac; @@ -1731,6 +1774,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) { if (freeibuf) IMB_freeImBuf(freeibuf); + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, NULL); continue; } @@ -1774,7 +1819,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, glPixelZoom(zoomx, zoomy); glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend); - glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect); + glaDrawPixelsAuto(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); glPixelZoom(1.0, 1.0); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); @@ -1789,9 +1834,10 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, glDepthMask(1); if (v3d->zbuf) glEnable(GL_DEPTH_TEST); - if (freeibuf) { + if (freeibuf) IMB_freeImBuf(freeibuf); - } + if (releaseibuf) + BKE_image_release_ibuf(ima, releaseibuf, NULL); } } } @@ -2102,7 +2148,7 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect) } if (d->damaged) { - glReadPixels(ar->winrct.xmin + d->x, ar->winrct.ymin + d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); + view3d_opengl_read_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); glGetDoublev(GL_DEPTH_RANGE, d->depth_range); d->damaged = FALSE; } @@ -2130,9 +2176,7 @@ void ED_view3d_depth_update(ARegion *ar) } if (d->damaged) { - glReadPixels(ar->winrct.xmin, ar->winrct.ymin, d->w, d->h, - GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); - + view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths); glGetDoublev(GL_DEPTH_RANGE, d->depth_range); d->damaged = 0; @@ -2999,7 +3043,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) #define VIEWGRAD_RES_Y 16 GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4]; - static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][2]; + static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3]; static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4]; static char buf_calculated = FALSE; @@ -3008,8 +3052,6 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings, &scene->display_settings); - glClear(GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); @@ -3029,6 +3071,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) /* -1..1 range */ grid_pos[x][y][0] = (xf - 0.5f) * 2.0f; grid_pos[x][y][1] = (yf - 0.5f) * 2.0f; + grid_pos[x][y][2] = 1.0; } } @@ -3082,15 +3125,22 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) } } + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); + glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(2, GL_FLOAT, 0, grid_pos); + glVertexPointer(3, GL_FLOAT, 0, grid_pos); glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col); glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices); + glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); + glDepthFunc(GL_LEQUAL); + glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); @@ -3112,9 +3162,6 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) } else { if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) { - /* only clear depth buffer here */ - glClear(GL_DEPTH_BUFFER_BIT); - glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); @@ -3122,17 +3169,22 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar) glPushMatrix(); glLoadIdentity(); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_ALWAYS); glShadeModel(GL_SMOOTH); glBegin(GL_QUADS); UI_ThemeColor(TH_LOW_GRAD); - glVertex2f(-1.0, -1.0); - glVertex2f(1.0, -1.0); + glVertex3f(-1.0, -1.0, 1.0); + glVertex3f(1.0, -1.0, 1.0); UI_ThemeColor(TH_HIGH_GRAD); - glVertex2f(1.0, 1.0); - glVertex2f(-1.0, 1.0); + glVertex3f(1.0, 1.0, 1.0); + glVertex3f(-1.0, 1.0, 1.0); glEnd(); glShadeModel(GL_FLAT); + glDepthFunc(GL_LEQUAL); + glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_PROJECTION); glPopMatrix(); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 5f54f0dcfc8..8c8332075a2 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -368,6 +368,7 @@ typedef struct ViewOpsData { float reverse, dist0, camzoom0; float grid, far; short axis_snap; /* view rotate only */ + float zfac; /* use for orbit selection and auto-dist */ float ofs[3], dyn_ofs[3]; @@ -407,7 +408,7 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3]) } -static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) +static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event) { static float lastofs[3] = {0, 0, 0}; RegionView3D *rv3d; @@ -504,7 +505,11 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec); - initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]); + { + float tvec[3]; + negate_v3_v3(tvec, rv3d->ofs); + vod->zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); + } vod->reverse = 1.0f; if (rv3d->persmat[2][1] < 0.0f) @@ -836,7 +841,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y) ED_region_tag_redraw(vod->ar); } -static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) +static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod = op->customdata; short event_code = VIEW_PASS; @@ -885,7 +890,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod; RegionView3D *rv3d; @@ -1092,7 +1097,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, RegionView3D * -- zooming * -- panning in rotationally-locked views */ -static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type != NDOF_MOTION) @@ -1174,7 +1179,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) } -static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type != NDOF_MOTION) @@ -1272,7 +1277,7 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot) /* -- "pan" navigation * -- zoom or dolly? */ -static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { if (event->type != NDOF_MOTION) return OPERATOR_CANCELLED; @@ -1366,7 +1371,7 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) /* * this is basically just the pan only code + the rotate only code crammed into one function that does both */ -static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->type != NDOF_MOTION) { return OPERATOR_CANCELLED; @@ -1508,7 +1513,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) mval_f[0] = x - vod->oldx; mval_f[1] = y - vod->oldy; - ED_view3d_win_to_delta(vod->ar, mval_f, dvec); + ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->zfac); add_v3_v3(vod->rv3d->ofs, dvec); @@ -1525,7 +1530,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y) } -static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) +static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod = op->customdata; @@ -1568,7 +1573,7 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod; @@ -1665,15 +1670,16 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) float tpos[3]; float mval_f[2]; float new_dist; + float zfac; negate_v3_v3(tpos, rv3d->ofs); - /* Project cursor position into 3D space */ - initgrabz(rv3d, tpos[0], tpos[1], tpos[2]); - mval_f[0] = (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2.0f; mval_f[1] = (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2.0f; - ED_view3d_win_to_delta(ar, mval_f, dvec); + + /* Project cursor position into 3D space */ + zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); /* Calculate view target position for dolly */ add_v3_v3v3(tvec, tpos, dvec); @@ -1788,7 +1794,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho } -static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) +static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod = op->customdata; short event_code = VIEW_PASS; @@ -1933,7 +1939,7 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf) } /* viewdolly_invoke() copied this function, changes here may apply there */ -static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod; @@ -2053,7 +2059,7 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv } -static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event) +static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod = op->customdata; short event_code = VIEW_PASS; @@ -2145,7 +2151,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op) } /* copied from viewzoom_invoke(), changes here may apply there */ -static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ViewOpsData *vod; @@ -2957,14 +2963,20 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) } else { float mval_f[2]; + float zfac; + /* We cant use the depth, fallback to the old way that dosnt set the center depth */ copy_v3_v3(new_ofs, rv3d->ofs); - initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]); + { + float tvec[3]; + negate_v3_v3(tvec, new_ofs); + zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL); + } mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f; mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f; - ED_view3d_win_to_delta(ar, mval_f, dvec); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); /* center the view to the center of the rectangle */ sub_v3_v3(new_ofs, dvec); } @@ -2997,7 +3009,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, const wmEvent *event) { View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -3415,16 +3427,19 @@ static int viewpan_exec(bContext *C, wmOperator *op) ARegion *ar = CTX_wm_region(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); float vec[3]; + const float co_zero[3] = {0.0f}; float mval_f[2] = {0.0f, 0.0f}; + float zfac; int pandir; pandir = RNA_enum_get(op->ptr, "type"); - initgrabz(rv3d, 0.0, 0.0, 0.0); - if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } - else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } - else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } - else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); } + zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL); + if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; } + else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; } + else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; } + else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; } + ED_view3d_win_to_delta(ar, mval_f, vec, zfac); add_v3_v3(rv3d->ofs, vec); if (rv3d->viewlock & RV3D_BOXVIEW) @@ -3506,7 +3521,7 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int background_image_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { View3D *v3d = CTX_wm_view3d(C); Image *ima = NULL; @@ -3661,7 +3676,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); ARegion *ar = CTX_wm_region(C); @@ -3713,15 +3728,16 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); float mval_fl[2]; - int flip; + float zfac; + bool flip; - flip = initgrabz(rv3d, fp[0], fp[1], fp[2]); + zfac = ED_view3d_calc_zfac(rv3d, fp, &flip); /* reset the depth based on the view offset (we _know_ the offset is infront of us) */ if (flip) { negate_v3_v3(fp, rv3d->ofs); /* re initialize, no need to check flip again */ - /* flip = */ initgrabz(rv3d, fp[0], fp[1], fp[2]); + zfac = ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ ); } if (ED_view3d_project_float_global(ar, fp, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { @@ -3736,17 +3752,17 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) if (depth_used == FALSE) { float dvec[3]; VECSUB2D(mval_fl, mval_fl, mval); - ED_view3d_win_to_delta(ar, mval_fl, dvec); + ED_view3d_win_to_delta(ar, mval_fl, dvec, zfac); sub_v3_v3(fp, dvec); } } else { - const float dx = ((float)(mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2); - const float dy = ((float)(mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2); + const float dx = ((float)(mval[0] - (ar->winx / 2))) * zfac / (ar->winx / 2); + const float dy = ((float)(mval[1] - (ar->winy / 2))) * zfac / (ar->winy / 2); const float fz = (rv3d->persmat[0][3] * fp[0] + rv3d->persmat[1][3] * fp[1] + rv3d->persmat[2][3] * fp[2] + - rv3d->persmat[3][3]) / rv3d->zfac; + rv3d->persmat[3][3]) / zfac; fp[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy + rv3d->persinv[2][0] * fz) - rv3d->ofs[0]; fp[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy + rv3d->persinv[2][1] * fz) - rv3d->ofs[1]; @@ -3755,7 +3771,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2]) } -static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -3794,7 +3810,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot) /* ***************** manipulator op ******************* */ -static int manipulator_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event) { View3D *v3d = CTX_wm_view3d(C); @@ -3830,7 +3846,7 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot) Transform_Properties(ot, P_CONSTRAINT); } -static int enable_manipulator_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { View3D *v3d = CTX_wm_view3d(C); diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index c2e75a1c5d9..700027d62a2 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -272,7 +272,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar), #define FLY_CANCEL 1 #define FLY_CONFIRM 2 -static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event) +static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); float upvec[3]; /* tmp */ @@ -486,7 +486,7 @@ static int flyEnd(bContext *C, FlyInfo *fly) return OPERATOR_CANCELLED; } -static void flyEvent(FlyInfo *fly, wmEvent *event) +static void flyEvent(FlyInfo *fly, const wmEvent *event) { if (event->type == TIMER && event->customdata == fly->timer) { fly->redraw = 1; @@ -1179,7 +1179,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly) return OPERATOR_FINISHED; } -static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event) { RegionView3D *rv3d = CTX_wm_region_view3d(C); FlyInfo *fly; @@ -1214,7 +1214,7 @@ static int fly_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) +static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event) { int exit_code; short do_draw = FALSE; diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index e078fa8eda1..430ed8698d7 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -28,7 +28,6 @@ * \ingroup spview3d */ - #include <string.h> #include <stdio.h> #include <stdlib.h> @@ -37,8 +36,6 @@ #include "DNA_object_types.h" #include "DNA_mesh_types.h" -#include "RNA_access.h" - #include "MEM_guardedalloc.h" #include "BLI_math.h" @@ -57,18 +54,19 @@ #include "BKE_screen.h" #include "BKE_tessmesh.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "WM_api.h" +#include "WM_types.h" + #include "ED_mesh.h" #include "ED_util.h" #include "ED_screen.h" #include "ED_transform.h" #include "ED_types.h" -#include "WM_api.h" -#include "WM_types.h" - -#include "RNA_define.h" -#include "RNA_enum_types.h" - #include "UI_interface.h" #include "UI_resources.h" @@ -209,7 +207,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op) /* applies shift and alt, lazy coding or ok? :) */ /* the local per-keymap-entry keymap will solve it */ -static int view3d_layers_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view3d_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (event->ctrl || event->oskey) return OPERATOR_PASS_THROUGH; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index d4cfa9076a6..26ed8e1885c 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -108,6 +108,9 @@ float ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]); void view3d_keymap(struct wmKeyConfig *keyconf); void VIEW3D_OT_fly(struct wmOperatorType *ot); +/* view3d_ruler.c */ +void VIEW3D_OT_ruler(struct wmOperatorType *ot); + /* drawanim.c */ void draw_motion_paths_init(View3D *v3d, struct ARegion *ar); void draw_motion_path_instance(Scene *scene, diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index bf1c5404c0e..e567ebda4b7 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -166,6 +166,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_localview); WM_operatortype_append(VIEW3D_OT_game_start); WM_operatortype_append(VIEW3D_OT_fly); + WM_operatortype_append(VIEW3D_OT_ruler); WM_operatortype_append(VIEW3D_OT_layers); WM_operatortype_append(VIEW3D_OT_copybuffer); WM_operatortype_append(VIEW3D_OT_pastebuffer); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index bc1656ff7c6..30a100283cc 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -73,7 +73,7 @@ void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r /** * \note use #ED_view3d_ob_project_mat_get to get projecting mat */ -void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3], float mat[4][4]) +void ED_view3d_project_float_v3_m4(const ARegion *ar, const float vec[3], float r_co[3], float mat[4][4]) { float vec4[4]; @@ -97,7 +97,7 @@ void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3 /* Clipping Projection Functions * ***************************** */ -eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base) +eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base) { eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT); @@ -113,8 +113,8 @@ eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base) * - 'rv3d->perspmat', is_local == FALSE * - 'rv3d->persmatob', is_local == TRUE */ -static eV3DProjStatus ed_view3d_project__internal(ARegion *ar, - float perspmat[4][4], const int is_local, /* normally hidden */ +static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar, + float perspmat[4][4], const bool is_local, /* normally hidden */ const float co[3], float r_co[2], const eV3DProjTest flag) { float vec4[4]; @@ -171,7 +171,7 @@ static eV3DProjStatus ed_view3d_project__internal(ARegion *ar, return V3D_PROJ_RET_OK; } -eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], const int is_local, +eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar, float perspmat[4][4], const bool is_local, const float co[3], short r_co[2], const eV3DProjTest flag) { float tvec[2]; @@ -190,7 +190,7 @@ eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], con return ret; } -eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const int is_local, +eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar, float perspmat[4][4], const bool is_local, const float co[3], int r_co[2], const eV3DProjTest flag) { float tvec[2]; @@ -209,7 +209,7 @@ eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const return ret; } -eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], const int is_local, +eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar, float perspmat[4][4], const bool is_local, const float co[3], float r_co[2], const eV3DProjTest flag) { float tvec[2]; @@ -228,39 +228,39 @@ eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], con } /* --- short --- */ -eV3DProjStatus ED_view3d_project_short_global(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) { RegionView3D *rv3d = ar->regiondata; return ED_view3d_project_short_ex(ar, rv3d->persmat, FALSE, co, r_co, flag); } /* object space, use ED_view3d_init_mats_rv3d before calling */ -eV3DProjStatus ED_view3d_project_short_object(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag) { RegionView3D *rv3d = ar->regiondata; return ED_view3d_project_short_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag); } /* --- int --- */ -eV3DProjStatus ED_view3d_project_int_global(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) { RegionView3D *rv3d = ar->regiondata; return ED_view3d_project_int_ex(ar, rv3d->persmat, FALSE, co, r_co, flag); } /* object space, use ED_view3d_init_mats_rv3d before calling */ -eV3DProjStatus ED_view3d_project_int_object(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag) { RegionView3D *rv3d = ar->regiondata; return ED_view3d_project_int_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag); } /* --- float --- */ -eV3DProjStatus ED_view3d_project_float_global(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) { RegionView3D *rv3d = ar->regiondata; return ED_view3d_project_float_ex(ar, rv3d->persmat, FALSE, co, r_co, flag); } /* object space, use ED_view3d_init_mats_rv3d before calling */ -eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) +eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag) { RegionView3D *rv3d = ar->regiondata; return ED_view3d_project_float_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag); @@ -271,28 +271,30 @@ eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], fl /* More Generic Window/Ray/Vector projection functions * *************************************************** */ -/* odd function, need to document better */ -int initgrabz(RegionView3D *rv3d, float x, float y, float z) +/** + * Caculate a depth value from \a co, use with #ED_view3d_win_to_delta + */ +float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip) { - int flip = FALSE; - if (rv3d == NULL) return flip; - rv3d->zfac = rv3d->persmat[0][3] * x + rv3d->persmat[1][3] * y + rv3d->persmat[2][3] * z + rv3d->persmat[3][3]; - if (rv3d->zfac < 0.0f) - flip = TRUE; + float zfac = mul_project_m4_v3_zfac((float (*)[4])rv3d->persmat, co); + + if (r_flip) { + *r_flip = (zfac < 0.0f); + } + /* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that - * (accounting for near zero values) - */ - if (rv3d->zfac < 1.e-6f && rv3d->zfac > -1.e-6f) rv3d->zfac = 1.0f; + * (accounting for near zero values) */ + if (zfac < 1.e-6f && zfac > -1.e-6f) { + zfac = 1.0f; + } /* Negative zfac means x, y, z was behind the camera (in perspective). - * This gives flipped directions, so revert back to ok default case. - */ - /* NOTE: I've changed this to flip zfac to be positive again for now so that GPencil draws ok - * Aligorith, 2009Aug31 */ - //if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f; - if (rv3d->zfac < 0.0f) rv3d->zfac = -rv3d->zfac; - - return flip; + * This gives flipped directions, so revert back to ok default case. */ + if (zfac < 0.0f) { + zfac = -zfac; + } + + return zfac; } /** @@ -306,7 +308,7 @@ int initgrabz(RegionView3D *rv3d, float x, float y, float z) * \param ray_start The world-space starting point of the segment. * \param ray_normal The normalized world-space direction of towards mval. */ -void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]) +void ED_view3d_win_to_ray(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3]) { float ray_end[3]; @@ -322,7 +324,7 @@ void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float r * \param coord The world-space location. * \param vec The resulting normalized vector. */ -void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float vec[3]) +void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3]) { if (rv3d->is_persp) { float p1[4], p2[4]; @@ -331,11 +333,11 @@ void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float p1[3] = 1.0f; copy_v3_v3(p2, p1); p2[3] = 1.0f; - mul_m4_v4(rv3d->viewmat, p2); + mul_m4_v4((float (*)[4])rv3d->viewmat, p2); mul_v3_fl(p2, 2.0f); - mul_m4_v4(rv3d->viewinv, p2); + mul_m4_v4((float (*)[4])rv3d->viewinv, p2); sub_v3_v3v3(vec, p1, p2); } @@ -352,7 +354,7 @@ void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float * \param mval The area relative location (such as event->mval converted to floats). * \param out The resulting world-space location. */ -void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]) +void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]) { RegionView3D *rv3d = ar->regiondata; @@ -384,19 +386,19 @@ void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[ /** * Calculate a 3d difference vector from 2d window offset. - * note that initgrabz() must be called first to determine + * note that ED_view3d_calc_zfac() must be called first to determine * the depth used to calculate the delta. * \param ar The region (used for the window width and height). * \param mval The area relative 2d difference (such as event->mval[0] - other_x). * \param out The resulting world-space delta. */ -void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3]) +void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3], const float zfac) { RegionView3D *rv3d = ar->regiondata; float dx, dy; - dx = 2.0f * mval[0] * rv3d->zfac / ar->winx; - dy = 2.0f * mval[1] * rv3d->zfac / ar->winy; + dx = 2.0f * mval[0] * zfac / ar->winx; + dy = 2.0f * mval[1] * zfac / ar->winy; out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy); out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy); @@ -408,7 +410,7 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3]) * This direction vector starts and the view in the direction of the 2d window coordinates. * In orthographic view all window coordinates yield the same vector. * - * \note doesn't rely on initgrabz + * \note doesn't rely on ED_view3d_calc_zfac * for perspective view, get the vector direction to * the mouse cursor as a normalized vector. * @@ -416,7 +418,7 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3]) * \param mval The area relative 2d location (such as event->mval converted to floats). * \param out The resulting normalized world-space direction vector. */ -void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3]) +void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3]) { RegionView3D *rv3d = ar->regiondata; @@ -433,7 +435,7 @@ void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3]) normalize_v3(out); } -void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +void ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d = ar->regiondata; @@ -472,7 +474,7 @@ void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], flo * \param ray_end The world-space end point of the segment. * \return success, FALSE if the segment is totally clipped. */ -int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) +int ED_view3d_win_to_segment_clip(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3]) { RegionView3D *rv3d = ar->regiondata; ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end); @@ -503,12 +505,12 @@ int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], /* Utility functions for projection * ******************************** */ -void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][4]) +void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pmat[4][4]) { float vmat[4][4]; - mult_m4_m4m4(vmat, rv3d->viewmat, ob->obmat); - mult_m4_m4m4(pmat, rv3d->winmat, vmat); + mult_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, ob->obmat); + mult_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat); } /** diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c new file mode 100644 index 00000000000..410d20a1dc0 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -0,0 +1,939 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/space_view3d/view3d_ruler.c + * \ingroup spview3d + */ + +/* defines VIEW3D_OT_ruler modal operator */ + +#include "DNA_scene_types.h" +#include "DNA_gpencil_types.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_math.h" +#include "BLI_blenlib.h" + +#include "BKE_context.h" +#include "BKE_unit.h" +#include "BKE_gpencil.h" + +#include "BIF_gl.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" +#include "ED_space_api.h" + +#include "BLF_api.h" +#include "BIF_glutil.h" + +#include "UI_resources.h" +#include "UI_interface.h" + +#include "view3d_intern.h" /* own include */ + + +/* -------------------------------------------------------------------- */ +/* Snapping (could be own function) */ +/* NOTE - this is not very nice use of transform snapping */ +#include "ED_transform.h" +#include "../transform/transform.h" + +static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2], + bool use_vert, bool use_edge, bool use_face) +{ + TransInfo t = {0}; + int dist = 12; /* snap dist */ + float r_no_dummy[3]; + bool ret = false; + char backup_snap_mode; + Base *backup_baseact; + + t.scene = CTX_data_scene(C); + t.view = CTX_wm_view3d(C); + t.ar = CTX_wm_region(C); + t.obedit = CTX_data_edit_object(C); + + backup_snap_mode = t.scene->toolsettings->snap_mode; + backup_baseact = t.scene->basact; + t.scene->basact = NULL; + + /* try snap edge, then face if it fails */ + if (use_vert) { + t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX; + ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL); + } + if (use_edge && (ret == false)) { + t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE; + ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL); + } + if (use_face && (ret == false)) { + t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE; + ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL); + } + + t.scene->toolsettings->snap_mode = backup_snap_mode; + t.scene->basact = backup_baseact; + + return ret; +} +/* done snapping */ + + +/* -------------------------------------------------------------------- */ +/* Ruler Item (we can have many) */ +enum { + RULERITEM_USE_ANGLE = (1 << 0), /* use protractor */ + RULERITEM_USE_RAYCAST = (1 << 1) +}; + +enum { + RULERITEM_DIRECTION_IN = 0, + RULERITEM_DIRECTION_OUT +}; + +#define RULER_PICK_DIST 75.0f +#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST) + +typedef struct RulerItem { + struct RulerItem *next, *prev; + + /* worldspace coords, middle being optional */ + float co[3][3]; + + /* selected coord */ + char co_index; /* 0 -> 2*/ + + int flag; + int raycast_dir; /* RULER_DIRECTION_* */ +} RulerItem; + +enum { + RULER_STATE_NORMAL = 0, + RULER_STATE_DRAG +}; + + +/* -------------------------------------------------------------------- */ +/* Ruler Info (one per session) */ + +typedef struct RulerInfo { + ListBase items; + int item_active; + int flag; + int snap_flag; + int state; + + /* --- */ + ARegion *ar; + void *draw_handle_pixel; +} RulerInfo; + +/* -------------------------------------------------------------------- */ +/* local functions */ +static RulerItem *ruler_item_add(RulerInfo *ruler_info) +{ + RulerItem *ruler_item = MEM_callocN(sizeof(RulerItem), "RulerItem"); + BLI_addtail(&ruler_info->items, ruler_item); + return ruler_item; +} + +static void ruler_item_remove(RulerInfo *ruler_info, RulerItem *ruler_item) +{ + BLI_remlink(&ruler_info->items, ruler_item); + MEM_freeN(ruler_item); +} + +static RulerItem *ruler_item_active_get(RulerInfo *ruler_info) +{ + return BLI_findlink(&ruler_info->items, ruler_info->item_active); +} + +static void ruler_item_active_set(RulerInfo *ruler_info, RulerItem *ruler_item) +{ + ruler_info->item_active = BLI_findindex(&ruler_info->items, ruler_item); +} + +static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit, + char *numstr, size_t numstr_size, int prec) +{ + const int do_split = unit->flag & USER_UNIT_OPT_SPLIT; + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + const float ruler_angle = angle_v3v3v3(ruler_item->co[0], + ruler_item->co[1], + ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle)); + } + else { + bUnit_AsString(numstr, numstr_size, + (double)ruler_angle, + prec, unit->system, B_UNIT_ROTATION, do_split, false); + } + } + else { + const float ruler_len = len_v3v3(ruler_item->co[0], + ruler_item->co[2]); + + if (unit->system == USER_UNIT_NONE) { + BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len); + } + else { + bUnit_AsString(numstr, numstr_size, + (double)(ruler_len * unit->scale_length), + prec, unit->system, B_UNIT_LENGTH, do_split, false); + } + } + +} + +static bool view3d_ruler_pick(RulerInfo *ruler_info, const float mval[2], + RulerItem **r_ruler_item, int *r_co_index) +{ + ARegion *ar = ruler_info->ar; + RulerItem *ruler_item; + + float dist_best = RULER_PICK_DIST_SQ; + RulerItem *ruler_item_best = NULL; + int co_index_best = -1; + + for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) { + float co_ss[3][2]; + float dist; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]), + dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2])); + if (dist < dist_best) { + dist_best = dist; + ruler_item_best = ruler_item; + + { + float dist_points[3] = {len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[1], mval), + len_squared_v2v2(co_ss[2], mval)}; + if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = min_axis_v3(dist_points); + } + else { + co_index_best = -1; + } + } + } + } + else { + dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]); + if (dist < dist_best) { + dist_best = dist; + ruler_item_best = ruler_item; + + { + float dist_points[2] = {len_squared_v2v2(co_ss[0], mval), + len_squared_v2v2(co_ss[2], mval)}; + if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) { + co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2; + } + else { + co_index_best = -1; + } + } + } + } + } + + if (ruler_item_best) { + *r_ruler_item = ruler_item_best; + *r_co_index = co_index_best; + return true; + } + else { + *r_ruler_item = NULL; + *r_co_index = -1; + return false; + } +} + +#define RULER_ID "RulerData3D" +static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info) +{ + Scene *scene = CTX_data_scene(C); + bGPDlayer *gpl; + bGPDframe *gpf; + bGPDstroke *gps; + RulerItem *ruler_item; + const char *ruler_name = RULER_ID; + bool change = false; + + if (scene->gpd == NULL) { + scene->gpd = gpencil_data_addnew("GPencil"); + } + + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl == NULL) { + gpl = gpencil_layer_addnew(scene->gpd, ruler_name, false); + gpl->thickness = 1; + gpl->flag |= GP_LAYER_HIDE; + } + + gpf = gpencil_layer_getframe(gpl, CFRA, true); + free_gpencil_strokes(gpf); + + for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) { + bGPDspoint *pt; + int j; + + /* allocate memory for a new stroke */ + gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke"); + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + gps->totpoints = 3; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j++) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt++; + } + } + else { + gps->totpoints = 2; + pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(&pt->x, ruler_item->co[j]); + pt->pressure = 1.0f; + pt++; + } + } + gps->flag = GP_STROKE_3DSPACE; + BLI_addtail(&gpf->strokes, gps); + change = true; + } + + return change; +} + +static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info) +{ + Scene *scene = CTX_data_scene(C); + bool change = false; + + if (scene->gpd) { + bGPDlayer *gpl; + const char *ruler_name = RULER_ID; + gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info)); + if (gpl) { + bGPDframe *gpf; + gpf = gpencil_layer_getframe(gpl, CFRA, false); + if (gpf) { + bGPDstroke *gps; + for (gps = gpf->strokes.first; gps; gps = gps->next) { + bGPDspoint *pt = gps->points; + int j; + if (gps->totpoints == 3) { + RulerItem *ruler_item = ruler_item_add(ruler_info); + for (j = 0; j < 3; j++) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + ruler_item->flag |= RULERITEM_USE_ANGLE; + change = true; + } + else if (gps->totpoints == 2) { + RulerItem *ruler_item = ruler_item_add(ruler_info); + for (j = 0; j < 3; j += 2) { + copy_v3_v3(ruler_item->co[j], &pt->x); + pt++; + } + change = true; + } + } + } + } + } + + return change; +} + +/* -------------------------------------------------------------------- */ +/* local callbacks */ + +static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg) +{ + Scene *scene = CTX_data_scene(C); + UnitSettings *unit = &scene->unit; + RulerItem *ruler_item; + RulerInfo *ruler_info = arg; + RegionView3D *rv3d = ruler_info->ar->regiondata; +// ARegion *ar = ruler_info->ar; + const float cap_size = 4.0f; + const float bg_margin = 4.0f * U.pixelsize; + const float bg_radius = 4.0f * U.pixelsize; + const float arc_size = 64.0f * U.pixelsize; +#define ARC_STEPS 24 + const int arc_steps = ARC_STEPS; + int i; + //unsigned int color_act = 0x666600; + unsigned int color_act = 0xffffff; + unsigned int color_base = 0x0; + unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80}; + unsigned char color_text[3]; + unsigned char color_wire[3]; + + /* anti-aliased lines for more consistent appearance */ + glEnable(GL_LINE_SMOOTH); + + BLF_enable(blf_mono_font, BLF_ROTATION); + BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi); + BLF_rotation(blf_mono_font, 0.0f); + + UI_GetThemeColor3ubv(TH_TEXT, color_text); + UI_GetThemeColor3ubv(TH_WIRE, color_wire); + + for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) { + const bool is_act = (i == ruler_info->item_active); + float dir_ruler[2]; + float co_ss[3][2]; + int j; + + /* should these be checked? - ok for now not to */ + for (j = 0; j < 3; j++) { + ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP); + } + + glEnable(GL_BLEND); + + cpack(is_act ? color_act : color_base); + + if (ruler_item->flag & RULERITEM_USE_ANGLE) { + glBegin(GL_LINE_STRIP); + for (j = 0; j < 3; j++) { + glVertex2fv(co_ss[j]); + } + glEnd(); + cpack(0xaaaaaa); + setlinestyle(3); + glBegin(GL_LINE_STRIP); + for (j = 0; j < 3; j++) { + glVertex2fv(co_ss[j]); + } + glEnd(); + setlinestyle(0); + + /* arc */ + { + float dir_tmp[3]; + float co_tmp[3]; + float arc_ss_coords[ARC_STEPS + 1][2]; + + float dir_a[3]; + float dir_b[3]; + float quat[4]; + float axis[3]; + float angle; + const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) * + min_fff(arc_size, + len_v2v2(co_ss[0], co_ss[1]) / 2.0f, + len_v2v2(co_ss[2], co_ss[1]) / 2.0f)); + + sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]); + sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]); + normalize_v3(dir_a); + normalize_v3(dir_b); + + cross_v3_v3v3(axis, dir_a, dir_b); + angle = angle_normalized_v3v3(dir_a, dir_b); + + axis_angle_to_quat(quat, axis, angle / arc_steps); + + copy_v3_v3(dir_tmp, dir_a); + + glColor3ubv(color_wire); + + for (j = 0; j <= arc_steps; j++) { + madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale); + ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP); + mul_qt_v3(quat, dir_tmp); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords); + glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1); + glDisableClientState(GL_VERTEX_ARRAY); + } + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + float pos[2]; + const int prec = 2; /* XXX, todo, make optional */ + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]); + + pos[0] = co_ss[1][0] + (cap_size * 2.0f); + pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f); + + /* draw text (bg) */ + glColor4ubv(color_back); + uiSetRoundBox(UI_CNR_ALL); + uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin, + pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], + bg_radius); + /* draw text */ + glColor3ubv(color_text); + BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); + BLF_rotation(blf_mono_font, 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + + /* capping */ + { + float rot_90_vec_a[2]; + float rot_90_vec_b[2]; + float cap[2]; + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]); + rot_90_vec_a[0] = -dir_ruler[1]; + rot_90_vec_a[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_a); + + sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]); + rot_90_vec_b[0] = -dir_ruler[1]; + rot_90_vec_b[1] = dir_ruler[0]; + normalize_v2(rot_90_vec_b); + + glEnable(GL_BLEND); + + glColor3ubv(color_wire); + + glBegin(GL_LINES); + + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size); + glVertex2fv(cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size); + glVertex2fv(cap); + + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size); + glVertex2fv(cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size); + glVertex2fv(cap); + + /* angle vertex */ + glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size); + glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size); + glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size); + glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size); + glEnd(); + + glDisable(GL_BLEND); + } + } + else { + glBegin(GL_LINE_STRIP); + for (j = 0; j < 3; j += 2) { + glVertex2fv(co_ss[j]); + } + glEnd(); + cpack(0xaaaaaa); + setlinestyle(3); + glBegin(GL_LINE_STRIP); + for (j = 0; j < 3; j += 2) { + glVertex2fv(co_ss[j]); + } + glEnd(); + setlinestyle(0); + + sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]); + + /* text */ + { + char numstr[256]; + float numstr_size[2]; + const int prec = 6; /* XXX, todo, make optional */ + float pos[2]; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + + BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]); + + mid_v2_v2v2(pos, co_ss[0], co_ss[2]); + + /* center text */ + pos[0] -= numstr_size[0] / 2.0f; + pos[1] -= numstr_size[1] / 2.0f; + + /* draw text (bg) */ + glColor4ubv(color_back); + uiSetRoundBox(UI_CNR_ALL); + uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin, + pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1], + bg_radius); + /* draw text */ + glColor3ubv(color_text); + BLF_position(blf_mono_font, pos[0], pos[1], 0.0f); + BLF_draw(blf_mono_font, numstr, sizeof(numstr)); + } + + /* capping */ + { + float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]}; + float cap[2]; + + normalize_v2(rot_90_vec); + + glEnable(GL_BLEND); + glColor3ubv(color_wire); + + glBegin(GL_LINES); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size); + glVertex2fv(cap); + madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size); + glVertex2fv(cap); + + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size); + glVertex2fv(cap); + madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size); + glVertex2fv(cap); + glEnd(); + + glDisable(GL_BLEND); + } + } + } + + glDisable(GL_LINE_SMOOTH); + + BLF_disable(blf_mono_font, BLF_ROTATION); + +#undef ARC_STEPS +} + +/* free, use for both cancel and finish */ +static void view3d_ruler_end(const struct bContext *UNUSED(C), RulerInfo *ruler_info) +{ + ED_region_draw_cb_exit(ruler_info->ar->type, ruler_info->draw_handle_pixel); +} + +static void view3d_ruler_free(RulerInfo *ruler_info) +{ + BLI_freelistN(&ruler_info->items); + MEM_freeN(ruler_info); +} + +static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], + const int xy[2]) +{ + view3d_get_view_aligned_coordinate(ruler_info->ar, r_co, xy, true); +} + +/* use for mousemove events */ +static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2], const bool do_snap) +{ + RulerItem *ruler_item = ruler_item_active_get(ruler_info); + + if (ruler_item) { + float *co = ruler_item->co[ruler_item->co_index]; + view3d_ruler_item_project(ruler_info, co, mval); + if (do_snap) { + const float mval_fl[2] = {UNPACK2(mval)}; + ED_view3d_snap_co(C, co, mval_fl, true, true, true); + } + return true; + } + else { + return false; + } +} + +static void view3d_ruler_header_update(ScrArea *sa) +{ + const char *text = "Ctrl+LMB: Add, " + "Del: Remove, " + "Ctrl+Drag: Snap, " + "Ctrl+C: Copy Value, " + "Enter: Store, " + "Esc: Cancel"; + + ED_area_headerprint(sa, text); +} + +/* -------------------------------------------------------------------- */ +/* Operator callbacks */ + +static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + ARegion *ar = CTX_wm_region(C); + RulerInfo *ruler_info; + + ruler_info = MEM_callocN(sizeof(RulerInfo), "RulerInfo"); + + if (view3d_ruler_from_gpencil(C, ruler_info)) { + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + } + + op->customdata = ruler_info; + + ruler_info->ar = ar; + ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel, + ruler_info, REGION_DRAW_POST_PIXEL); + + view3d_ruler_header_update(sa); + + WM_cursor_modal(win, BC_CROSSCURSOR); + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +static int view3d_ruler_cancel(bContext *C, wmOperator *op) +{ + RulerInfo *ruler_info = op->customdata; + + view3d_ruler_end(C, ruler_info); + view3d_ruler_free(ruler_info); + op->customdata = NULL; + + return OPERATOR_CANCELLED; +} + +static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + bool do_draw = false; + int exit_code = OPERATOR_RUNNING_MODAL; + RulerInfo *ruler_info = op->customdata; + ARegion *ar = ruler_info->ar; + RegionView3D *rv3d = ar->regiondata; + + (void)C; + + switch (event->type) { + case LEFTMOUSE: + if (event->val == KM_RELEASE) { + if (ruler_info->state == RULER_STATE_DRAG) { + /* rubber-band angle removal */ + RulerItem *ruler_item = ruler_item_active_get(ruler_info); + if (ruler_item && (ruler_item->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) { + if (!BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) { + ruler_item->flag &= ~RULERITEM_USE_ANGLE; + do_draw = true; + } + } + ruler_info->state = RULER_STATE_NORMAL; + } + } + else { + if (ruler_info->state == RULER_STATE_NORMAL) { + + if (event->ctrl || + /* weak - but user friendly */ + (ruler_info->items.first == NULL)) + { + /* Create new line */ + RulerItem *ruler_item; + /* check if we want to drag an existing point or add a new one */ + ruler_info->state = RULER_STATE_DRAG; + + ruler_item = ruler_item_add(ruler_info); + ruler_item_active_set(ruler_info, ruler_item); + + negate_v3_v3(ruler_item->co[0], rv3d->ofs); + view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval); + + /* snap the first point added, not essential but handy */ + { + ruler_item->co_index = 0; + view3d_ruler_item_mousemove(C, ruler_info, event->mval, true); + } + + copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); + ruler_item->co_index = 2; + + do_draw = true; + } + else { + float mval_fl[2] = {UNPACK2(event->mval)}; + RulerItem *ruler_item_pick; + int co_index; + + /* select and drag */ + if (view3d_ruler_pick(ruler_info, mval_fl, &ruler_item_pick, &co_index)) { + if (co_index == -1) { + if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) { + /* Add Center Point */ + ruler_item_active_set(ruler_info, ruler_item_pick); + ruler_item_pick->flag |= RULERITEM_USE_ANGLE; + ruler_item_pick->co_index = 1; + ruler_info->state = RULER_STATE_DRAG; + + /* find the factor */ + { + float co_ss[2][2]; + float fac; + + ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP); + ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP); + + fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]); + CLAMP(fac, 0.0f, 1.0f); + + interp_v3_v3v3(ruler_item_pick->co[1], + ruler_item_pick->co[0], + ruler_item_pick->co[2], fac); + } + + /* update the new location */ + view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0); + do_draw = true; + } + } + else { + ruler_item_active_set(ruler_info, ruler_item_pick); + ruler_item_pick->co_index = co_index; + ruler_info->state = RULER_STATE_DRAG; + do_draw = true; + } + } + else { + exit_code = OPERATOR_PASS_THROUGH; + } + + } + } + } + break; + case CKEY: + { + if (event->ctrl) { + RulerItem *ruler_item = ruler_item_active_get(ruler_info); + if (ruler_item) { + const int prec = 8; + char numstr[256]; + Scene *scene = CTX_data_scene(C); + UnitSettings *unit = &scene->unit; + + ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec); + WM_clipboard_text_set((void *) numstr, false); + } + } + } + case RIGHTCTRLKEY: + case LEFTCTRLKEY: + { + WM_event_add_mousemove(C); + break; + } + case MOUSEMOVE: + { + if (ruler_info->state == RULER_STATE_DRAG) { + if (view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0)) { + do_draw = true; + } + } + break; + } + case ESCKEY: + { + do_draw = true; + exit_code = OPERATOR_CANCELLED; + break; + } + case RETKEY: + { + view3d_ruler_to_gpencil(C, ruler_info); + do_draw = true; + exit_code = OPERATOR_FINISHED; + break; + } + case DELKEY: + { + if (event->val == KM_PRESS) { + if (ruler_info->state == RULER_STATE_NORMAL) { + RulerItem *ruler_item = ruler_item_active_get(ruler_info); + if (ruler_item) { + ruler_item_remove(ruler_info, ruler_item); + ruler_info->item_active = -1; + do_draw = true; + } + } + } + break; + } + default: + exit_code = OPERATOR_PASS_THROUGH; + break; + + } + + if (do_draw) { + ScrArea *sa = CTX_wm_area(C); + + view3d_ruler_header_update(sa); + + /* all 3d views draw rulers */ + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); + } + + if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) { + wmWindow *win = CTX_wm_window(C); + ScrArea *sa = CTX_wm_area(C); + + WM_cursor_restore(win); + + view3d_ruler_end(C, ruler_info); + view3d_ruler_free(ruler_info); + op->customdata = NULL; + + ED_area_headerprint(sa, NULL); + } + + return exit_code; +} + +void VIEW3D_OT_ruler(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "3D Ruler & Protractor"; + ot->description = "Interactive ruler"; + ot->idname = "VIEW3D_OT_ruler"; + + /* api callbacks */ + ot->invoke = view3d_ruler_invoke; + ot->cancel = view3d_ruler_cancel; + ot->modal = view3d_ruler_modal; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = 0; +} diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 24260898066..b441e48f59d 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -108,23 +108,23 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc) vc->obedit = CTX_data_edit_object(C); } -int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int mval[2], const short do_fallback) +/** + * Re-project \a fp so it stays on the same view-plane but is under \a mval (normally the cursor location). + */ +bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback) { + RegionView3D *rv3d = ar->regiondata; float dvec[3]; int mval_cpy[2]; eV3DProjStatus ret; - mval_cpy[0] = mval[0]; - mval_cpy[1] = mval[1]; - - ret = ED_view3d_project_int_global(vc->ar, fp, mval_cpy, V3D_PROJ_TEST_NOP); - - initgrabz(vc->rv3d, fp[0], fp[1], fp[2]); + ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP); if (ret == V3D_PROJ_RET_OK) { const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]), (float)(mval_cpy[1] - mval[1])}; - ED_view3d_win_to_delta(vc->ar, mval_f, dvec); + const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL); + ED_view3d_win_to_delta(ar, mval_f, dvec, zfac); sub_v3_v3(fp, dvec); return TRUE; @@ -132,11 +132,11 @@ int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int m else { /* fallback to the view center */ if (do_fallback) { - negate_v3_v3(fp, vc->rv3d->ofs); - return view3d_get_view_aligned_coordinate(vc, fp, mval, FALSE); + negate_v3_v3(fp, rv3d->ofs); + return view3d_get_view_aligned_coordinate(ar, fp, mval, false); } else { - return FALSE; + return false; } } } @@ -177,10 +177,9 @@ static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, int select) { BMVert *eve; BMIter iter; - int index = bm_wireoffs; + unsigned int index = bm_wireoffs; - eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); - for (; eve; eve = BM_iter_step(&iter), index++) { + for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter), index++) { if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) { if (EDBM_backbuf_check(index)) { BM_vert_select_set(em->bm, eve, select); @@ -209,7 +208,7 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select) { BMFace *efa; BMIter iter; - int index = 1; + unsigned int index = 1; efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL); for (; efa; efa = BM_iter_step(&iter), index++) { @@ -226,11 +225,11 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select) static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select) { MVert *mv = me->mvert; - int a; + unsigned int index; if (mv) { - for (a = 1; a <= me->totvert; a++, mv++) { - if (EDBM_backbuf_check(a)) { + for (index = 1; index <= me->totvert; index++, mv++) { + if (EDBM_backbuf_check(index)) { if (!(mv->flag & ME_HIDE)) { mv->flag = select ? (mv->flag | SELECT) : (mv->flag & ~SELECT); } @@ -243,11 +242,11 @@ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select) static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select) { MPoly *mpoly = me->mpoly; - int a; + unsigned int index; if (mpoly) { - for (a = 1; a <= me->totpoly; a++, mpoly++) { - if (EDBM_backbuf_check(a)) { + for (index = 1; index <= me->totpoly; index++, mpoly++) { + if (EDBM_backbuf_check(index)) { mpoly->flag = select ? (mpoly->flag | ME_FACE_SEL) : (mpoly->flag & ~ME_FACE_SEL); } } @@ -733,7 +732,7 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m MetaBall *mb = (MetaBall *)vc->obedit->data; if (extend == 0 && select) - BKE_mball_deselect_all(mb); + BKE_mball_deselect_all(mb); BLI_lasso_boundbox(&rect, mcords, moves); @@ -780,9 +779,6 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh } else { LassoSelectUserData data; - rcti rect; - - BLI_lasso_boundbox(&rect, mcords, moves); view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select); @@ -1054,7 +1050,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { /* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */ - if (strcmp(name, base->object->id.name + 2) == 0) { + if (STREQ(name, base->object->id.name + 2)) { ED_base_object_activate(C, base); ED_base_object_select(base, BA_SELECT); changed = 1; @@ -2230,7 +2226,7 @@ static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], shor /* ****** Mouse Select ****** */ -static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *obedit = CTX_data_edit_object(C); Object *obact = CTX_data_active_object(C); diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index bb5b7aa6911..d3bf8a30792 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -156,7 +156,7 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons { GHashIterator *iter = WM_operatortype_iter(); - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(iter); if (BLI_strcasestr(ot->name, str)) { diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index fba1ce328ba..b2e10fa8457 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -294,7 +294,7 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera } /* only meant for timer usage */ -static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { View3D *v3d = CTX_wm_view3d(C); RegionView3D *rv3d = CTX_wm_region_view3d(C); @@ -667,22 +667,29 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d) } /* copies logic of get_view3d_viewplane(), keep in sync */ -int ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend) +bool ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *r_clipsta, float *r_clipend, + const bool use_ortho_factor) { CameraParams params; BKE_camera_params_init(¶ms); BKE_camera_params_from_view3d(¶ms, v3d, rv3d); - if (clipsta) *clipsta = params.clipsta; - if (clipend) *clipend = params.clipend; + if (use_ortho_factor && params.is_ortho) { + const float fac = 2.0f / (params.clipend - params.clipsta); + params.clipsta *= fac; + params.clipend *= fac; + } + + if (r_clipsta) *r_clipsta = params.clipsta; + if (r_clipend) *r_clipend = params.clipend; return params.is_ortho; } /* also exposed in previewrender.c */ -int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, - rctf *viewplane, float *clipsta, float *clipend) +bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, + rctf *r_viewplane, float *r_clipsta, float *r_clipend) { CameraParams params; @@ -690,9 +697,9 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy, BKE_camera_params_from_view3d(¶ms, v3d, rv3d); BKE_camera_params_compute_viewplane(¶ms, winx, winy, 1.0f, 1.0f); - if (viewplane) *viewplane = params.viewplane; - if (clipsta) *clipsta = params.clipsta; - if (clipend) *clipend = params.clipend; + if (r_viewplane) *r_viewplane = params.viewplane; + if (r_clipsta) *r_clipsta = params.clipsta; + if (r_clipend) *r_clipend = params.clipend; return params.is_ortho; } @@ -791,7 +798,7 @@ static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short #define QUATSET(a, b, c, d, e) { a[0] = b; a[1] = c; a[2] = d; a[3] = e; } (void)0 -int ED_view3d_lock(RegionView3D *rv3d) +bool ED_view3d_lock(RegionView3D *rv3d) { switch (rv3d->view) { case RV3D_VIEW_BOTTOM: @@ -818,10 +825,10 @@ int ED_view3d_lock(RegionView3D *rv3d) QUATSET(rv3d->viewquat, 0.5, -0.5, -0.5, -0.5); break; default: - return FALSE; + return false; } - return TRUE; + return true; } /* don't set windows active in here, is used by renderwin too */ @@ -863,7 +870,9 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d) copy_v3_v3(vec, give_cursor(scene, v3d)); translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]); } - else translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); + else { + translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]); + } } } @@ -1558,11 +1567,7 @@ static void UNUSED_FUNCTION(view3d_align_axis_to_vector)(View3D *v3d, RegionView float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3]) { - return (rv3d->persmat[3][3] + ( - rv3d->persmat[0][3] * co[0] + - rv3d->persmat[1][3] * co[1] + - rv3d->persmat[2][3] * co[2]) - ) * rv3d->pixsize * U.pixelsize; + return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize; } float ED_view3d_radius_to_persp_dist(const float angle, const float radius) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index c8874d13cac..64e49abd761 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -98,6 +98,8 @@ #include "transform.h" +#define MAX_INFO_LEN 256 + static void drawTransformApply(const struct bContext *C, ARegion *ar, void *arg); static int doEdgeSlide(TransInfo *t, float perc); static int doVertSlide(TransInfo *t, float perc); @@ -183,7 +185,7 @@ void convertViewVec(TransInfo *t, float r_vec[3], int dx, int dy) { if ((t->spacetype == SPACE_VIEW3D) && (t->ar->regiontype == RGN_TYPE_WINDOW)) { const float mval_f[2] = {(float)dx, (float)dy}; - ED_view3d_win_to_delta(t->ar, mval_f, r_vec); + ED_view3d_win_to_delta(t->ar, mval_f, r_vec, t->zfac); } else if (t->spacetype == SPACE_IMAGE) { float aspx, aspy; @@ -864,7 +866,7 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm } } -int transformEvent(TransInfo *t, wmEvent *event) +int transformEvent(TransInfo *t, const wmEvent *event) { float mati[3][3] = MAT3_UNITY; char cmode = constraintModeToChar(t); @@ -1298,7 +1300,9 @@ int transformEvent(TransInfo *t, wmEvent *event) if (t->flag & T_AUTOIK) { transform_autoik_update(t, 1); } - else view_editmove(event->type); + else { + view_editmove(event->type); + } t->redraw = 1; break; case PADMINUS: @@ -1313,7 +1317,9 @@ int transformEvent(TransInfo *t, wmEvent *event) if (t->flag & T_AUTOIK) { transform_autoik_update(t, -1); } - else view_editmove(event->type); + else { + view_editmove(event->type); + } t->redraw = 1; break; case LEFTALTKEY: @@ -1854,7 +1860,7 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } /* note: caller needs to free 't' on a 0 return */ -int initTransform(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event, int mode) +int initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event, int mode) { int options = 0; PropertyRNA *prop; @@ -2654,11 +2660,12 @@ void initWarp(TransInfo *t) mid_v3_v3v3(t->center, min, max); - if (max[0] == min[0]) max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */ + if (max[0] == min[0]) + max[0] += 0.1f; /* not optimal, but flipping is better than invalid garbage (i.e. division by zero!) */ t->val = (max[0] - min[0]) / 2.0f; /* t->val is X dimension projected boundbox */ } -int handleEventWarp(TransInfo *t, wmEvent *event) +int handleEventWarp(TransInfo *t, const wmEvent *event) { int status = 0; @@ -2681,7 +2688,7 @@ int Warp(TransInfo *t, const int UNUSED(mval[2])) float vec[3], circumfac, dist, phi0, co, si, cursor[3], gcursor[3]; const float *curs; int i; - char str[50]; + char str[MAX_INFO_LEN]; curs = give_cursor(t->scene, t->view); /* @@ -2716,13 +2723,13 @@ int Warp(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Warp: %s"), c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %s"), c); circumfac = DEG2RADF(circumfac); } else { /* default header print */ - sprintf(str, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac)); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Warp: %.3f"), RAD2DEGF(circumfac)); } t->values[0] = circumfac; @@ -2799,7 +2806,7 @@ void initShear(TransInfo *t) t->flag |= T_NO_CONSTRAINT; } -int handleEventShear(TransInfo *t, wmEvent *event) +int handleEventShear(TransInfo *t, const wmEvent *event) { int status = 0; @@ -2840,7 +2847,7 @@ int Shear(TransInfo *t, const int UNUSED(mval[2])) float smat[3][3], tmat[3][3], totmat[3][3], persmat[3][3], persinv[3][3]; float value; int i; - char str[50]; + char str[MAX_INFO_LEN]; copy_m3_m4(persmat, t->viewmat); invert_m3_m3(persinv, persmat); @@ -2857,11 +2864,11 @@ int Shear(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Shear: %s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %s %s"), c, t->proptext); } else { /* default header print */ - sprintf(str, IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shear: %.3f %s (Press X or Y to set shear axis)"), value, t->proptext); } t->values[0] = value; @@ -2937,10 +2944,11 @@ void initResize(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerResize(TransInfo *t, float vec[3], char *str) { char tvec[NUM_STR_REP_LEN * 3]; - char *spos = str; + size_t ofs = 0; if (hasNumInput(&t->num)) { outputNumInput(&(t->num), tvec); } @@ -2949,37 +2957,36 @@ static void headerResize(TransInfo *t, float vec[3], char *str) BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); } - + if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - spos += sprintf(spos, IFACE_("Scale: %s%s %s"), &tvec[0], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s%s %s"), + &tvec[0], t->con.text, t->proptext); break; case 1: - spos += sprintf(spos, IFACE_("Scale: %s : %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], - t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s : %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); break; case 2: - spos += sprintf(spos, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale: %s : %s : %s%s %s"), &tvec[0], + &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } else { if (t->flag & T_2D_EDIT) { - spos += sprintf(spos, IFACE_("Scale X: %s Y: %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], - t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale X: %s Y: %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], t->con.text, t->proptext); } else { - spos += sprintf(spos, IFACE_("Scale X: %s Y: %s Z: %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Scale X: %s Y: %s Z: %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } - + if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - - (void)spos; } /* FLT_EPSILON is too small [#29633], 0.0000001f starts to flip */ @@ -3114,7 +3121,7 @@ int Resize(TransInfo *t, const int mval[2]) float size[3], mat[3][3]; float ratio; int i; - char str[200]; + char str[MAX_INFO_LEN]; /* for manipulator, center handle, the scaling can't be done relative to center */ if ((t->flag & T_USES_MANIPULATOR) && t->con.mode == 0) { @@ -3219,7 +3226,7 @@ int SkinResize(TransInfo *t, const int UNUSED(mval[2])) float size[3], mat[3][3]; float ratio; int i; - char str[200]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; size[0] = size[1] = size[2] = ratio; @@ -3313,7 +3320,7 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2])) float vec[3]; float ratio, radius; int i; - char str[64]; + char str[MAX_INFO_LEN]; TransData *td = t->data; ratio = t->values[0]; @@ -3335,11 +3342,11 @@ int ToSphere(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("To Sphere: %s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %s %s"), c, t->proptext); } else { /* default header print */ - sprintf(str, IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("To Sphere: %.4f %s"), ratio, t->proptext); } @@ -3528,7 +3535,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); /* this function works on end result */ - protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); + protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, + td->ext->irotAngle); } else { float eulmat[3][3]; @@ -3575,12 +3583,15 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself /* euler or quaternion? */ if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { - mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); - mat3_to_quat(quat, fmat); // Actual transform - - mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); - /* this function works on end result */ - protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + /* can be called for texture space translate for example, then opt out */ + if (td->ext->quat) { + mul_serie_m3(fmat, td->mtx, mat, td->smtx, NULL, NULL, NULL, NULL, NULL); + mat3_to_quat(quat, fmat); // Actual transform + + mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); + /* this function works on end result */ + protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); + } } else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { /* calculate effect based on quats */ @@ -3595,7 +3606,8 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); /* this function works on end result */ - protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, td->ext->irotAngle); + protectedAxisAngleBits(td->protectflag, td->ext->rotAxis, td->ext->rotAngle, td->ext->irotAxis, + td->ext->irotAngle); } else { float obmat[3][3]; @@ -3654,14 +3666,15 @@ static void applyRotation(TransInfo *t, float angle, float axis[3]) int Rotation(TransInfo *t, const int UNUSED(mval[2])) { - char str[128], *spos = str; - + char str[MAX_INFO_LEN]; + size_t ofs = 0; + float final; final = t->values[0]; - + snapGrid(t, &final); - + if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, t->axis, NULL); } @@ -3669,9 +3682,9 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) /* reset axis if constraint is not set */ copy_v3_v3(t->axis, t->axis_orig); } - + applySnapping(t, &final); - + if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; @@ -3679,19 +3692,19 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - spos += sprintf(spos, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %s %s %s"), &c[0], t->con.text, t->proptext); /* Clamp between -180 and 180 */ final = angle_wrap_rad(DEG2RADF(final)); } else { - spos += sprintf(spos, IFACE_("Rot: %.2f%s %s"), RAD2DEGF(final), t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Rot: %.2f%s %s"), + RAD2DEGF(final), t->con.text, t->proptext); } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - (void)spos; t->values[0] = final; @@ -3756,7 +3769,8 @@ static void applyTrackball(TransInfo *t, float axis1[3], float axis2[3], float a int Trackball(TransInfo *t, const int UNUSED(mval[2])) { - char str[128], *spos = str; + char str[MAX_INFO_LEN]; + size_t ofs = 0; float axis1[3], axis2[3]; float mat[3][3], totmat[3][3], smat[3][3]; float phi[2]; @@ -3778,19 +3792,20 @@ int Trackball(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - spos += sprintf(spos, IFACE_("Trackball: %s %s %s"), &c[0], &c[NUM_STR_REP_LEN], t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %s %s %s"), + &c[0], &c[NUM_STR_REP_LEN], t->proptext); phi[0] = DEG2RADF(phi[0]); phi[1] = DEG2RADF(phi[1]); } else { - spos += sprintf(spos, IFACE_("Trackball: %.2f %.2f %s"), RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Trackball: %.2f %.2f %s"), + RAD2DEGF(phi[0]), RAD2DEGF(phi[1]), t->proptext); } if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - (void)spos; vec_rot_to_mat3(smat, axis1, phi[0]); vec_rot_to_mat3(totmat, axis2, phi[1]); @@ -3854,9 +3869,10 @@ void initTranslation(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTranslation(TransInfo *t, float vec[3], char *str) { - char *spos = str; + size_t ofs = 0; char tvec[NUM_STR_REP_LEN * 3]; char distvec[NUM_STR_REP_LEN]; char autoik[NUM_STR_REP_LEN]; @@ -3877,29 +3893,30 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) int i, do_split = t->scene->unit.flag & USER_UNIT_OPT_SPLIT ? 1 : 0; for (i = 0; i < 3; i++) { - bUnit_AsString(&tvec[i * NUM_STR_REP_LEN], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, + bUnit_AsString(&tvec[NUM_STR_REP_LEN * i], NUM_STR_REP_LEN, dvec[i] * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, do_split, 1); } } else { - sprintf(&tvec[0], "%.4f", dvec[0]); - sprintf(&tvec[NUM_STR_REP_LEN], "%.4f", dvec[1]); - sprintf(&tvec[NUM_STR_REP_LEN * 2], "%.4f", dvec[2]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", dvec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", dvec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", dvec[2]); } } if (!(t->flag & T_2D_EDIT) && t->scene->unit.system) - bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system, B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0); + bUnit_AsString(distvec, sizeof(distvec), dist * t->scene->unit.scale_length, 4, t->scene->unit.system, + B_UNIT_LENGTH, t->scene->unit.flag & USER_UNIT_OPT_SPLIT, 0); else if (dist > 1e10f || dist < -1e10f) /* prevent string buffer overflow */ - sprintf(distvec, "%.4e", dist); + BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4e", dist); else - sprintf(distvec, "%.4f", dist); + BLI_snprintf(distvec, NUM_STR_REP_LEN, "%.4f", dist); if (t->flag & T_AUTOIK) { short chainlen = t->settings->autoik_chainlen; if (chainlen) - sprintf(autoik, IFACE_("AutoIK-Len: %d"), chainlen); + BLI_snprintf(autoik, NUM_STR_REP_LEN, IFACE_("AutoIK-Len: %d"), chainlen); else autoik[0] = '\0'; } @@ -3909,32 +3926,34 @@ static void headerTranslation(TransInfo *t, float vec[3], char *str) if (t->con.mode & CON_APPLY) { switch (t->num.idx_max) { case 0: - spos += sprintf(spos, "D: %s (%s)%s %s %s", &tvec[0], distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s (%s)%s %s %s", + &tvec[0], distvec, t->con.text, t->proptext, autoik); break; case 1: - spos += sprintf(spos, "D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s D: %s (%s)%s %s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext, autoik); break; case 2: - spos += sprintf(spos, "D: %s D: %s D: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "D: %s D: %s D: %s (%s)%s %s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, + t->con.text, t->proptext, autoik); } } else { if (t->flag & T_2D_EDIT) { - spos += sprintf(spos, "Dx: %s Dy: %s (%s)%s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - distvec, t->con.text, t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "Dx: %s Dy: %s (%s)%s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], distvec, t->con.text, t->proptext); } else { - spos += sprintf(spos, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, t->proptext, &autoik[0]); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "Dx: %s Dy: %s Dz: %s (%s)%s %s %s", + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], distvec, t->con.text, + t->proptext, autoik); } } - + if (t->flag & (T_PROP_EDIT | T_PROP_CONNECTED)) { - spos += sprintf(spos, IFACE_(" Proportional size: %.2f"), t->prop_size); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" Proportional size: %.2f"), t->prop_size); } - (void)spos; } static void applyTranslation(TransInfo *t, float vec[3]) @@ -4006,7 +4025,7 @@ static void applyTranslation(TransInfo *t, float vec[3]) /* uses t->vec to store actual translation in */ int Translation(TransInfo *t, const int UNUSED(mval[2])) { - char str[250]; + char str[MAX_INFO_LEN]; if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; @@ -4082,8 +4101,8 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { float distance; int i; - char str[128]; - char *str_p; + char str[MAX_INFO_LEN]; + size_t ofs = 0; TransData *td = t->data; distance = -t->values[0]; @@ -4093,31 +4112,30 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) applyNumInput(&t->num, &distance); /* header print for NumInput */ - str_p = str; - str_p += BLI_snprintf(str_p, sizeof(str), IFACE_("Shrink/Fatten:")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Shrink/Fatten:"), MAX_INFO_LEN - ofs); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), " %s", c); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", c); } else { /* default header print */ - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), " %.4f", distance); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %.4f", distance); } if (t->proptext[0]) { - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), " %s", t->proptext); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, " %s", t->proptext); } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), ", ("); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, ", ("); { wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_RESIZE); if (kmi) { - str_p += WM_keymap_item_to_string(kmi, str_p, sizeof(str) - (str_p - str)); + ofs += WM_keymap_item_to_string(kmi, str + ofs, MAX_INFO_LEN - ofs); } } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_(" or Alt) Even Thickness %s"), - (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); + BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Even Thickness %s"), + (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); /* done with header string */ @@ -4173,7 +4191,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; int i; - char str[50]; + char str[MAX_INFO_LEN]; float final; @@ -4188,7 +4206,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Tilt: %s° %s"), &c[0], t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %s° %s"), &c[0], t->proptext); final = DEG2RADF(final); @@ -4196,7 +4214,7 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; } else { - sprintf(str, IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Tilt: %.2f° %s"), RAD2DEGF(final), t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4247,7 +4265,7 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float ratio; int i; - char str[50]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; @@ -4260,10 +4278,10 @@ int CurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Shrink/Fatten: %s"), c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %s"), c); } else { - sprintf(str, IFACE_("Shrink/Fatten: %3f"), ratio); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Shrink/Fatten: %3f"), ratio); } for (i = 0; i < t->total; i++, td++) { @@ -4315,7 +4333,7 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) TransData *td; float ratio; int i, initial_feather = FALSE; - char str[50]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; @@ -4328,10 +4346,10 @@ int MaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Feather Shrink/Fatten: %s"), c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %s"), c); } else { - sprintf(str, IFACE_("Feather Shrink/Fatten: %3f"), ratio); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Feather Shrink/Fatten: %3f"), ratio); } /* detect if no points have feather yet */ @@ -4401,7 +4419,7 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) float vec[3], axis[3]; float distance; int i; - char str[128]; + char str[MAX_INFO_LEN]; TransData *td = t->data; distance = t->values[0]; @@ -4416,11 +4434,11 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %s%s %s"), c, t->con.text, t->proptext); } else { /* default header print */ - sprintf(str, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Push/Pull: %.4f%s %s"), distance, t->con.text, t->proptext); } t->values[0] = distance; @@ -4496,7 +4514,7 @@ void initBevel(TransInfo *t) } } -int handleEventBevel(TransInfo *t, wmEvent *event) +int handleEventBevel(TransInfo *t, const wmEvent *event) { if (event->val == KM_PRESS) { if (!G.editBMesh) return 0; @@ -4533,7 +4551,7 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2])) { float distance, d; int i; - char str[128]; + char str[MAX_INFO_LEN]; const char *mode; TransData *td = t->data; @@ -4552,11 +4570,11 @@ int Bevel(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Bevel - Dist: %s, Mode: %s (MMB to toggle))"), c, mode); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel - Dist: %s, Mode: %s (MMB to toggle))"), c, mode); } else { /* default header print */ - sprintf(str, IFACE_("Bevel - Dist: %.4f, Mode: %s (MMB to toggle))"), distance, mode); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel - Dist: %.4f, Mode: %s (MMB to toggle))"), distance, mode); } if (distance < 0) distance = -distance; @@ -4602,7 +4620,7 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float weight; int i; - char str[50]; + char str[MAX_INFO_LEN]; weight = t->values[0]; @@ -4620,16 +4638,16 @@ int BevelWeight(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); if (weight >= 0.0f) - sprintf(str, IFACE_("Bevel Weight: +%s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%s %s"), c, t->proptext); else - sprintf(str, IFACE_("Bevel Weight: %s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: %s %s"), c, t->proptext); } else { /* default header print */ if (weight >= 0.0f) - sprintf(str, IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: +%.3f %s"), weight, t->proptext); else - sprintf(str, IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Bevel Weight: %.3f %s"), weight, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4675,7 +4693,7 @@ int Crease(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float crease; int i; - char str[50]; + char str[MAX_INFO_LEN]; crease = t->values[0]; @@ -4693,16 +4711,16 @@ int Crease(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); if (crease >= 0.0f) - sprintf(str, IFACE_("Crease: +%s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%s %s"), c, t->proptext); else - sprintf(str, IFACE_("Crease: %s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: %s %s"), c, t->proptext); } else { /* default header print */ if (crease >= 0.0f) - sprintf(str, IFACE_("Crease: +%.3f %s"), crease, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: +%.3f %s"), crease, t->proptext); else - sprintf(str, IFACE_("Crease: %.3f %s"), crease, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Crease: %.3f %s"), crease, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -4746,6 +4764,7 @@ void initBoneSize(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerBoneSize(TransInfo *t, float vec[3], char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -4753,22 +4772,22 @@ static void headerBoneSize(TransInfo *t, float vec[3], char *str) outputNumInput(&(t->num), tvec); } else { - sprintf(&tvec[0], "%.4f", vec[0]); - sprintf(&tvec[NUM_STR_REP_LEN], "%.4f", vec[1]); - sprintf(&tvec[NUM_STR_REP_LEN * 2], "%.4f", vec[2]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", vec[0]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN], NUM_STR_REP_LEN, "%.4f", vec[1]); + BLI_snprintf(&tvec[NUM_STR_REP_LEN * 2], NUM_STR_REP_LEN, "%.4f", vec[2]); } /* hmm... perhaps the y-axis values don't need to be shown? */ if (t->con.mode & CON_APPLY) { if (t->num.idx_max == 0) - sprintf(str, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB: %s%s %s"), &tvec[0], t->con.text, t->proptext); else - sprintf(str, IFACE_("ScaleB: %s : %s : %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB: %s : %s : %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } else { - sprintf(str, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"), &tvec[0], &tvec[NUM_STR_REP_LEN], - &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleB X: %s Y: %s Z: %s%s %s"), + &tvec[0], &tvec[NUM_STR_REP_LEN], &tvec[NUM_STR_REP_LEN * 2], t->con.text, t->proptext); } } @@ -4798,7 +4817,7 @@ int BoneSize(TransInfo *t, const int mval[2]) float size[3], mat[3][3]; float ratio; int i; - char str[60]; + char str[MAX_INFO_LEN]; // TRANSFORM_FIX_ME MOVE TO MOUSE INPUT /* for manipulator, center handle, the scaling can't be done relative to center */ @@ -4871,7 +4890,7 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) TransData *td = t->data; float ratio; int i; - char str[50]; + char str[MAX_INFO_LEN]; ratio = t->values[0]; @@ -4884,10 +4903,10 @@ int BoneEnvelope(TransInfo *t, const int UNUSED(mval[2])) char c[NUM_STR_REP_LEN]; outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Envelope: %s"), c); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %s"), c); } else { - sprintf(str, IFACE_("Envelope: %3f"), ratio); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Envelope: %3f"), ratio); } for (i = 0; i < t->total; i++, td++) { @@ -5604,7 +5623,8 @@ void projectEdgeSlideData(TransInfo *t, bool is_final) f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f); } else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->down)) { - f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f); + f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, + (uintptr_t)e_sel->l->radial_next->f); } } @@ -5613,7 +5633,8 @@ void projectEdgeSlideData(TransInfo *t, bool is_final) f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->f); } else if (BM_vert_in_face(e_sel->l->radial_next->f, sv->up)) { - f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, (uintptr_t)e_sel->l->radial_next->f); + f_copy_flip = BLI_smallhash_lookup(&sld->origfaces, + (uintptr_t)e_sel->l->radial_next->f); } } @@ -5746,7 +5767,7 @@ void initEdgeSlide(TransInfo *t) t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } -int handleEventEdgeSlide(struct TransInfo *t, struct wmEvent *event) +int handleEventEdgeSlide(struct TransInfo *t, const struct wmEvent *event) { if (t->mode == TFM_EDGE_SLIDE) { EdgeSlideData *sld = t->customData; @@ -5929,12 +5950,15 @@ static int doEdgeSlide(TransInfo *t, float perc) int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[128]; + char str[MAX_INFO_LEN]; float final; EdgeSlideData *sld = t->customData; bool flipped = sld->flipped_vtx; bool is_proportional = sld->is_proportional; + const char *on_str = IFACE_("ON"); + const char *off_str = IFACE_("OFF"); + final = t->values[0]; snapGrid(t, &final); @@ -5949,12 +5973,12 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - BLI_snprintf(str, sizeof(str), IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"), - &c[0], !is_proportional ? IFACE_("ON") : IFACE_("OFF"), flipped ? IFACE_("ON") : IFACE_("OFF")); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %s (E)ven: %s, (F)lipped: %s"), + &c[0], !is_proportional ? on_str : off_str, flipped ? on_str : off_str); } else { - BLI_snprintf(str, sizeof(str), IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"), - final, !is_proportional ? IFACE_("ON") : IFACE_("OFF"), flipped ? IFACE_("ON") : IFACE_("OFF")); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Edge Slide: %.4f (E)ven: %s, (F)lipped: %s"), + final, !is_proportional ? on_str : off_str, flipped ? on_str : off_str); } CLAMP(final, -1.0f, 1.0f); @@ -5962,10 +5986,11 @@ int EdgeSlide(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = final; /*do stuff here*/ - if (t->customData) + if (t->customData) { doEdgeSlide(t, final); + } else { - strcpy(str, IFACE_("Invalid Edge Selection")); + BLI_strncpy(str, IFACE_("Invalid Edge Selection"), MAX_INFO_LEN); t->state = TRANS_CANCEL; } @@ -6249,7 +6274,7 @@ void initVertSlide(TransInfo *t) t->flag |= T_NO_CONSTRAINT | T_NO_PROJECT; } -int handleEventVertSlide(struct TransInfo *t, struct wmEvent *event) +int handleEventVertSlide(struct TransInfo *t, const struct wmEvent *event) { if (t->mode == TFM_VERT_SLIDE) { VertSlideData *sld = t->customData; @@ -6434,8 +6459,8 @@ static int doVertSlide(TransInfo *t, float perc) int VertSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[128]; - char *str_p; + char str[MAX_INFO_LEN]; + size_t ofs = 0; float final; VertSlideData *sld = t->customData; const bool flipped = sld->flipped_vtx; @@ -6443,6 +6468,9 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) const bool is_clamp = !(t->flag & T_ALT_TRANSFORM); const bool is_constrained = !(is_clamp == false || hasNumInput(&t->num)); + const char *on_str = IFACE_("ON"); + const char *off_str = IFACE_("OFF"); + final = t->values[0]; snapGrid(t, &final); @@ -6453,25 +6481,21 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) } /* header string */ - str_p = str; - str_p += BLI_snprintf(str_p, sizeof(str), IFACE_("Vert Slide: ")); + ofs += BLI_strncpy_rlen(str + ofs, IFACE_("Vert Slide: "), MAX_INFO_LEN - ofs); if (hasNumInput(&t->num)) { char c[NUM_STR_REP_LEN]; applyNumInput(&t->num, &final); outputNumInput(&(t->num), c); - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "%s", &c[0]); + ofs += BLI_strncpy_rlen(str + ofs, &c[0], MAX_INFO_LEN - ofs); } else { - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), "%.4f ", final); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, "%.4f ", final); } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_("(E)ven: %s, "), - !is_proportional ? IFACE_("ON") : IFACE_("OFF")); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(E)ven: %s, "), !is_proportional ? on_str : off_str); if (!is_proportional) { - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_("(F)lipped: %s, "), - flipped ? IFACE_("ON") : IFACE_("OFF")); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("(F)lipped: %s, "), flipped ? on_str : off_str); } - str_p += BLI_snprintf(str_p, sizeof(str) - (str_p - str), IFACE_("Alt or (C)lamp: %s"), - is_clamp ? IFACE_("ON") : IFACE_("OFF")); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Alt or (C)lamp: %s"), is_clamp ? on_str : off_str); /* done with header string */ /*do stuff here*/ @@ -6479,7 +6503,7 @@ int VertSlide(TransInfo *t, const int UNUSED(mval[2])) doVertSlide(t, final); } else { - strcpy(str, IFACE_("Invalid Vert Selection")); + BLI_strncpy(str, IFACE_("Invalid Vert Selection"), MAX_INFO_LEN); t->state = TRANS_CANCEL; } @@ -6515,7 +6539,7 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2])) { TransData *td = t->data; int i; - char str[50]; + char str[MAX_INFO_LEN]; float final; @@ -6530,12 +6554,12 @@ int BoneRoll(TransInfo *t, const int UNUSED(mval[2])) outputNumInput(&(t->num), c); - sprintf(str, IFACE_("Roll: %s"), &c[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %s"), &c[0]); final = DEG2RADF(final); } else { - sprintf(str, IFACE_("Roll: %.2f"), RAD2DEGF(final)); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Roll: %.2f"), RAD2DEGF(final)); } /* set roll values */ @@ -6577,7 +6601,7 @@ int BakeTime(TransInfo *t, const int mval[2]) TransData *td = t->data; float time; int i; - char str[50]; + char str[MAX_INFO_LEN]; float fac = 0.1f; @@ -6601,16 +6625,16 @@ int BakeTime(TransInfo *t, const int mval[2]) outputNumInput(&(t->num), c); if (time >= 0.0f) - sprintf(str, IFACE_("Time: +%s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%s %s"), c, t->proptext); else - sprintf(str, IFACE_("Time: %s %s"), c, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: %s %s"), c, t->proptext); } else { /* default header print */ if (time >= 0.0f) - sprintf(str, IFACE_("Time: +%.3f %s"), time, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: +%.3f %s"), time, t->proptext); else - sprintf(str, IFACE_("Time: %.3f %s"), time, t->proptext); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Time: %.3f %s"), time, t->proptext); } for (i = 0; i < t->total; i++, td++) { @@ -6652,7 +6676,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) TransData *td; float size[3], mat[3][3]; int i; - char str[200]; + char str[MAX_INFO_LEN]; /* * OPTIMIZATION: @@ -6670,7 +6694,7 @@ int Mirror(TransInfo *t, const int UNUSED(mval[2])) t->con.applySize(t, NULL, mat); } - sprintf(str, IFACE_("Mirror%s"), t->con.text); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("Mirror%s"), t->con.text); for (i = 0, td = t->data; i < t->total; i++, td++) { if (td->flag & TD_NOACTION) @@ -6787,29 +6811,29 @@ void initSeqSlide(TransInfo *t) t->num.increment = t->snap[1]; } -static void headerSeqSlide(TransInfo *t, float val[2], char *str, size_t str_len) +/* We assume str is MAX_INFO_LEN long. */ +static void headerSeqSlide(TransInfo *t, float val[2], char *str) { char tvec[NUM_STR_REP_LEN * 3]; - char *str_p; + size_t ofs = 0; if (hasNumInput(&t->num)) { outputNumInput(&(t->num), tvec); } else { - sprintf(&tvec[0], "%.0f, %.0f", val[0], val[1]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.0f, %.0f", val[0], val[1]); } - str_p = str; - str_p += BLI_snprintf(str, str_len, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_("Sequence Slide: %s%s, ("), &tvec[0], t->con.text); { wmKeyMapItem *kmi = WM_modalkeymap_find_propvalue(t->keymap, TFM_MODAL_TRANSLATE); if (kmi) { - str_p += WM_keymap_item_to_string(kmi, str_p, str_len - (str_p - str)); + ofs += WM_keymap_item_to_string(kmi, str + ofs, MAX_INFO_LEN - ofs); } } - str_p += BLI_snprintf(str_p, str_len - (str_p - str), IFACE_(" or Alt) Expand to fit %s"), - (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); + ofs += BLI_snprintf(str + ofs, MAX_INFO_LEN - ofs, IFACE_(" or Alt) Expand to fit %s"), + (t->flag & T_ALT_TRANSFORM) ? IFACE_("ON") : IFACE_("OFF")); } static void applySeqSlide(TransInfo *t, float val[2]) @@ -6837,7 +6861,7 @@ static void applySeqSlide(TransInfo *t, float val[2]) int SeqSlide(TransInfo *t, const int UNUSED(mval[2])) { - char str[200]; + char str[MAX_INFO_LEN]; if (t->con.mode & CON_APPLY) { float pvec[3] = {0.0f, 0.0f, 0.0f}; @@ -6853,7 +6877,7 @@ int SeqSlide(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = floor(t->values[0] + 0.5f); t->values[1] = floor(t->values[1] + 0.5f); - headerSeqSlide(t, t->values, str, sizeof(str)); + headerSeqSlide(t, t->values, str); applySeqSlide(t, t->values); recalcData(t); @@ -6953,7 +6977,11 @@ static void doAnimEdit_SnapFrame(TransInfo *t, TransData *td, TransData2D *td2d, #if 0 /* 'do_time' disabled for now */ const Scene *scene = t->scene; - const short do_time = 0; //getAnimEdit_DrawTime(t); // NOTE: this works, but may be confusing behavior given the option's label, hence disabled +#if 0 /* NOTE: this works, but may be confusing behavior given the option's label, hence disabled */ + const short do_time = getAnimEdit_DrawTime(t); +#else + const short do_time = 0; +#endif const double secf = FPS; #endif double val; @@ -7041,6 +7069,7 @@ void initTimeTranslate(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTimeTranslate(TransInfo *t, char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -7069,12 +7098,12 @@ static void headerTimeTranslate(TransInfo *t, char *str) } if (autosnap == SACTSNAP_FRAME) - sprintf(&tvec[0], "%d.00 (%.4f)", (int)val, val); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%d.00 (%.4f)", (int)val, val); else - sprintf(&tvec[0], "%.4f", val); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); } - sprintf(str, IFACE_("DeltaX: %s"), &tvec[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("DeltaX: %s"), &tvec[0]); } static void applyTimeTranslate(TransInfo *t, float UNUSED(sval)) @@ -7138,7 +7167,7 @@ int TimeTranslate(TransInfo *t, const int mval[2]) { View2D *v2d = (View2D *)t->view; float cval[2], sval[2]; - char str[200]; + char str[MAX_INFO_LEN]; /* calculate translation amount from mouse movement - in 'time-grid space' */ UI_view2d_region_to_view(v2d, mval[0], mval[0], &cval[0], &cval[1]); @@ -7196,6 +7225,7 @@ void initTimeSlide(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTimeSlide(TransInfo *t, float sval, char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -7212,10 +7242,10 @@ static void headerTimeSlide(TransInfo *t, float sval, char *str) val = 2.0f * (cval - sval) / (maxx - minx); CLAMP(val, -1.0f, 1.0f); - sprintf(&tvec[0], "%.4f", val); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", val); } - sprintf(str, IFACE_("TimeSlide: %s"), &tvec[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("TimeSlide: %s"), &tvec[0]); } static void applyTimeSlide(TransInfo *t, float sval) @@ -7271,7 +7301,7 @@ int TimeSlide(TransInfo *t, const int mval[2]) float cval[2], sval[2]; float minx = *((float *)(t->customData)); float maxx = *((float *)(t->customData) + 1); - char str[200]; + char str[MAX_INFO_LEN]; /* calculate mouse co-ordinates */ UI_view2d_region_to_view(v2d, mval[0], mval[1], &cval[0], &cval[1]); @@ -7338,6 +7368,7 @@ void initTimeScale(TransInfo *t) t->num.increment = t->snap[1]; } +/* We assume str is MAX_INFO_LEN long. */ static void headerTimeScale(TransInfo *t, char *str) { char tvec[NUM_STR_REP_LEN * 3]; @@ -7345,9 +7376,9 @@ static void headerTimeScale(TransInfo *t, char *str) if (hasNumInput(&t->num)) outputNumInput(&(t->num), tvec); else - sprintf(&tvec[0], "%.4f", t->values[0]); + BLI_snprintf(&tvec[0], NUM_STR_REP_LEN, "%.4f", t->values[0]); - sprintf(str, IFACE_("ScaleX: %s"), &tvec[0]); + BLI_snprintf(str, MAX_INFO_LEN, IFACE_("ScaleX: %s"), &tvec[0]); } static void applyTimeScale(TransInfo *t) @@ -7392,7 +7423,7 @@ static void applyTimeScale(TransInfo *t) int TimeScale(TransInfo *t, const int UNUSED(mval[2])) { - char str[200]; + char str[MAX_INFO_LEN]; /* handle numeric-input stuff */ t->vec[0] = t->values[0]; @@ -7423,3 +7454,5 @@ bool checkUseLocalCenter_GraphEdit(TransInfo *t) { return ((t->around == V3D_LOCAL) && !ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)); } + +#undef MAX_INFO_LEN diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index dbf56f658ac..a551ef5008e 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -288,7 +288,7 @@ typedef struct TransInfo { float fac; /* factor for distance based transform */ int (*transform)(struct TransInfo *, const int *); /* transform function pointer */ - int (*handleEvent)(struct TransInfo *, struct wmEvent *); + int (*handleEvent)(struct TransInfo *, const struct wmEvent *); /* event handler function pointer RETURN 1 if redraw is needed */ int total; /* total number of transformed data */ TransData *data; /* transformed data (array) */ @@ -354,6 +354,7 @@ typedef struct TransInfo { struct wmTimer *animtimer; struct wmKeyMap *keymap; /* so we can do lookups for header text */ int mval[2]; /* current mouse position */ + float zfac; /* use for 3d view */ struct Object *obedit; void *draw_handle_apply; void *draw_handle_view; @@ -474,9 +475,9 @@ typedef struct TransInfo { #define POINT_INIT 4 #define MULTI_POINTS 8 -int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, struct wmEvent *event, int mode); +int initTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op, const struct wmEvent *event, int mode); void saveTransform(struct bContext *C, struct TransInfo *t, struct wmOperator *op); -int transformEvent(TransInfo *t, struct wmEvent *event); +int transformEvent(TransInfo *t, const struct wmEvent *event); void transformApply(struct bContext *C, TransInfo *t); int transformEnd(struct bContext *C, TransInfo *t); @@ -491,11 +492,11 @@ void applyAspectRatio(TransInfo *t, float *vec); void removeAspectRatio(TransInfo *t, float *vec); void initWarp(TransInfo *t); -int handleEventWarp(TransInfo *t, struct wmEvent *event); +int handleEventWarp(TransInfo *t, const struct wmEvent *event); int Warp(TransInfo *t, const int mval[2]); void initShear(TransInfo *t); -int handleEventShear(TransInfo *t, struct wmEvent *event); +int handleEventShear(TransInfo *t, const struct wmEvent *event); int Shear(TransInfo *t, const int mval[2]); void initResize(TransInfo *t); @@ -532,7 +533,7 @@ void initPushPull(TransInfo *t); int PushPull(TransInfo *t, const int mval[2]); void initBevel(TransInfo *t); -int handleEventBevel(TransInfo *t, struct wmEvent *event); +int handleEventBevel(TransInfo *t, const struct wmEvent *event); int Bevel(TransInfo *t, const int mval[2]); void initBevelWeight(TransInfo *t); @@ -551,11 +552,11 @@ void initBoneRoll(TransInfo *t); int BoneRoll(TransInfo *t, const int mval[2]); void initEdgeSlide(TransInfo *t); -int handleEventEdgeSlide(TransInfo *t, struct wmEvent *event); +int handleEventEdgeSlide(TransInfo *t, const struct wmEvent *event); int EdgeSlide(TransInfo *t, const int mval[2]); void initVertSlide(TransInfo *t); -int handleEventVertSlide(TransInfo *t, struct wmEvent *event); +int handleEventVertSlide(TransInfo *t, const struct wmEvent *event); int VertSlide(TransInfo *t, const int mval[2]); void initTimeTranslate(TransInfo *t); @@ -658,7 +659,7 @@ void initSnapping(struct TransInfo *t, struct wmOperator *op); void applyProject(TransInfo *t); void applySnapping(TransInfo *t, float *vec); void resetSnapping(TransInfo *t); -int handleSnapping(TransInfo *t, struct wmEvent *event); +int handleSnapping(TransInfo *t, const struct wmEvent *event); void drawSnapping(const struct bContext *C, TransInfo *t); int usingSnappingNormal(TransInfo *t); int validSnappingNormal(TransInfo *t); @@ -687,7 +688,7 @@ typedef enum { void initMouseInput(TransInfo *t, MouseInput *mi, const int center[2], const int mval[2]); void initMouseInputMode(TransInfo *t, MouseInput *mi, MouseInputMode mode); -int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, struct wmEvent *event); +int handleMouseInput(struct TransInfo *t, struct MouseInput *mi, const struct wmEvent *event); void applyMouseInput(struct TransInfo *t, struct MouseInput *mi, const int mval[2], float output[3]); void setCustomPoints(TransInfo *t, MouseInput *mi, const int start[2], const int end[2]); @@ -695,7 +696,7 @@ void setInputPostFct(MouseInput *mi, void (*post)(struct TransInfo *t, float val /*********************** Generics ********************************/ -int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, struct wmEvent *event); +int initTransInfo(struct bContext *C, TransInfo *t, struct wmOperator *op, const struct wmEvent *event); void postTrans (struct bContext *C, TransInfo *t); void resetTransRestrictions(TransInfo *t); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index c4d61472f18..f3026205ea2 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -29,19 +29,17 @@ * \ingroup edtransform */ - #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #ifndef WIN32 -#include <unistd.h> +# include <unistd.h> #else -#include <io.h> +# include <io.h> #endif - #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" @@ -53,13 +51,13 @@ #include "BKE_context.h" -#include "ED_image.h" -#include "ED_view3d.h" - #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_string.h" +#include "ED_image.h" +#include "ED_view3d.h" + #include "BLF_translation.h" #include "UI_resources.h" @@ -867,11 +865,11 @@ static void setNearestAxis2d(TransInfo *t) /* no correction needed... just use whichever one is lower */ if (abs(t->mval[0] - t->con.imval[0]) < abs(t->mval[1] - t->con.imval[1]) ) { t->con.mode |= CON_AXIS1; - BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along Y axis")); + BLI_strncpy(t->con.text, IFACE_(" along Y axis"), sizeof(t->con.text)); } else { t->con.mode |= CON_AXIS0; - BLI_snprintf(t->con.text, sizeof(t->con.text), IFACE_(" along X axis")); + BLI_strncpy(t->con.text, IFACE_(" along X axis"), sizeof(t->con.text)); } } @@ -892,9 +890,9 @@ static void setNearestAxis3d(TransInfo *t) * and to overflow the short integers. * The formula used is a bit stupid, just a simplification of the subtraction * of two 2D points 30 pixels apart (that's the last factor in the formula) after - * projecting them with window_to_3d_delta and then get the length of that vector. + * projecting them with ED_view3d_win_to_delta and then get the length of that vector. */ - zfac = t->persmat[0][3] * t->center[0] + t->persmat[1][3] * t->center[1] + t->persmat[2][3] * t->center[2] + t->persmat[3][3]; + zfac = mul_project_m4_v3_zfac(t->persmat, t->center); zfac = len_v3(t->persinv[0]) * 2.0f / t->ar->winx * zfac * 30.0f; for (i = 0; i < 3; i++) { diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 57816e7546c..b8a39cae381 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -223,7 +223,9 @@ static void set_prop_dist(TransInfo *t, short with_dist) tob->rdist = dist; } } - else break; // by definition transdata has selected items in beginning + else { + break; /* by definition transdata has selected items in beginning */ + } } if (with_dist) { tob->dist = tob->rdist; @@ -1291,7 +1293,7 @@ static void calc_distanceCurveVerts(TransData *head, TransData *tail) } } else { - td->dist = MAXFLOAT; + td->dist = FLT_MAX; td->flag |= TD_NOTCONNECTED; } } @@ -2048,7 +2050,9 @@ static void createTransEditVerts(TransInfo *t) if (propmode & T_PROP_CONNECTED) dists = MEM_mallocN(em->bm->totvert * sizeof(float), "scratch nears"); } - else t->total = countsel; + else { + t->total = countsel; + } tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)"); if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { @@ -2127,7 +2131,7 @@ static void createTransEditVerts(TransInfo *t) } else { tob->flag |= TD_NOTCONNECTED; - tob->dist = MAXFLOAT; + tob->dist = FLT_MAX; } } @@ -2363,7 +2367,7 @@ static void UVsToTransData(SpaceImage *sima, TransData *td, TransData2D *td2d, f td->dist = 0.0; } else { - td->dist = MAXFLOAT; + td->dist = FLT_MAX; } unit_m3(td->mtx); unit_m3(td->smtx); @@ -3500,7 +3504,7 @@ static void bezt_to_transdata(TransData *td, TransData2D *td2d, AnimData *adt, B td->dist = 0.0f; } else - td->dist = MAXFLOAT; + td->dist = FLT_MAX; if (ishandle) td->flag |= TD_NOTIMESNAP; @@ -3584,7 +3588,9 @@ static void createTransGraphEditData(bContext *C, TransInfo *t) if (ELEM3(t->mode, TFM_TRANSLATION, TFM_TIME_TRANSLATE, TFM_TIME_SLIDE)) { /* for 'normal' pivots - just include anything that is selected. * this works a bit differently in translation modes */ - if (sel2) count++; + if (sel2) { + count++; + } else { if (sel1) count++; if (sel3) count++; @@ -6594,7 +6600,7 @@ void createTransData(bContext *C, TransInfo *t) sort_trans_data_dist(t); } } - else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) { + else if (ob && (ob->mode & (OB_MODE_ALL_PAINT))) { /* sculpt mode and project paint have own undo stack * transform ops redo clears sculpt/project undo stack. * diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index c2a331f5249..2a3b0bc8726 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1012,7 +1012,7 @@ void resetTransRestrictions(TransInfo *t) } /* the *op can be NULL */ -int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, wmEvent *event) +int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *event) { Scene *sce = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); @@ -1669,7 +1669,7 @@ void calculateCenter(TransInfo *t) projectIntView(t, axis, t->center2d); - /* rotate only needs correct 2d center, grab needs initgrabz() value */ + /* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */ if (t->mode == TFM_TRANSLATION) { copy_v3_v3(t->center, axis); copy_v3_v3(t->con.center, t->center); @@ -1679,18 +1679,16 @@ void calculateCenter(TransInfo *t) } if (t->spacetype == SPACE_VIEW3D) { - /* initgrabz() defines a factor for perspective depth correction, used in window_to_3d_delta() */ + /* ED_view3d_calc_zfac() defines a factor for perspective depth correction, used in ED_view3d_win_to_delta() */ + float vec[3]; if (t->flag & (T_EDIT | T_POSE)) { Object *ob = t->obedit ? t->obedit : t->poseobj; - float vec[3]; - - copy_v3_v3(vec, t->center); - mul_m4_v3(ob->obmat, vec); - initgrabz(t->ar->regiondata, vec[0], vec[1], vec[2]); + mul_v3_m4v3(vec, ob->obmat, t->center); } else { - initgrabz(t->ar->regiondata, t->center[0], t->center[1], t->center[2]); + copy_v3_v3(vec, t->center); } + t->zfac = ED_view3d_calc_zfac(t->ar->regiondata, vec, NULL); } } diff --git a/source/blender/editors/transform/transform_input.c b/source/blender/editors/transform/transform_input.c index 4e9a54692a5..4943a3a2fe7 100644 --- a/source/blender/editors/transform/transform_input.c +++ b/source/blender/editors/transform/transform_input.c @@ -393,7 +393,7 @@ void applyMouseInput(TransInfo *t, MouseInput *mi, const int mval[2], float outp } } -int handleMouseInput(TransInfo *t, MouseInput *mi, wmEvent *event) +int handleMouseInput(TransInfo *t, MouseInput *mi, const wmEvent *event) { int redraw = TREDRAW_NOTHING; diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 54fb567b8a2..bea1f9da057 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -856,7 +856,7 @@ static void axis_sort_v3(const float axis_values[3], int r_axis_order[3]) } else { if (v[1] < v[2]) { SWAP_AXIS(0, 1); } - else { SWAP_AXIS(0, 2); } + else { SWAP_AXIS(0, 2); } } if (v[2] < v[1]) { SWAP_AXIS(1, 2); } @@ -1293,7 +1293,9 @@ static void draw_manipulator_scale(View3D *v3d, RegionView3D *rv3d, int moving, dz = 1.0; } - else dz = 1.0f - 4.0f * cusize; + else { + dz = 1.0f - 4.0f * cusize; + } if (moving) { float matt[4][4]; @@ -1739,8 +1741,12 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl dep = buffer[4 * a + 1]; val = buffer[4 * a + 3]; - if (val == MAN_TRANS_C) return MAN_TRANS_C; - else if (val == MAN_SCALE_C) return MAN_SCALE_C; + if (val == MAN_TRANS_C) { + return MAN_TRANS_C; + } + else if (val == MAN_SCALE_C) { + return MAN_SCALE_C; + } else { if (val & MAN_ROT_C) { if (minvalrot == 0 || dep < mindeprot) { @@ -1767,7 +1773,7 @@ static int manipulator_selectbuf(ScrArea *sa, ARegion *ar, const int mval[2], fl /* return 0; nothing happened */ -int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op) +int BIF_do_manipulator(bContext *C, const struct wmEvent *event, wmOperator *op) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; @@ -1855,8 +1861,15 @@ int BIF_do_manipulator(bContext *C, struct wmEvent *event, wmOperator *op) //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_resize", 0), event, op->ptr, NULL, FALSE); } else if (drawflags == MAN_ROT_T) { /* trackball need special case, init is different */ - WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, op->ptr); - //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, op->ptr, NULL, FALSE); + /* Do not pass op->ptr!!! trackball has no "constraint" properties! + * See [#34621], it's a miracle it did not cause more problems!!! */ + /* However, we need to copy the "release_confirm" property... */ + PointerRNA props_ptr; + WM_operator_properties_create(&props_ptr, "TRANSFORM_OT_trackball"); + RNA_boolean_set(&props_ptr, "release_confirm", RNA_boolean_get(op->ptr, "release_confirm")); + + WM_operator_name_call(C, "TRANSFORM_OT_trackball", WM_OP_INVOKE_DEFAULT, &props_ptr); + //wm_operator_invoke(C, WM_operatortype_find("TRANSFORM_OT_trackball", 0), event, NULL, NULL, FALSE); } else if (drawflags & MAN_ROT_C) { switch (drawflags) { diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 0392c0f47a2..60b0c655691 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -24,16 +24,11 @@ * \ingroup edtransform */ - #include "MEM_guardedalloc.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - #include "BLI_math.h" #include "BLI_utildefines.h" @@ -44,6 +39,10 @@ #include "BKE_armature.h" #include "BKE_report.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + #include "WM_api.h" #include "WM_types.h" @@ -166,7 +165,7 @@ static int select_orientation_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int select_orientation_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPopupMenu *pup; uiLayout *layout; @@ -213,7 +212,7 @@ static int delete_orientation_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int delete_orientation_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int delete_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return delete_orientation_exec(C, op); } @@ -269,7 +268,7 @@ static int create_orientation_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int create_orientation_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int create_orientation_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return create_orientation_exec(C, op); } @@ -301,7 +300,7 @@ static void transformops_exit(bContext *C, wmOperator *op) G.moving = 0; } -static int transformops_data(bContext *C, wmOperator *op, wmEvent *event) +static int transformops_data(bContext *C, wmOperator *op, const wmEvent *event) { int retval = 1; if (op->customdata == NULL) { @@ -335,7 +334,7 @@ static int transformops_data(bContext *C, wmOperator *op, wmEvent *event) return retval; /* return 0 on error */ } -static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) +static int transform_modal(bContext *C, wmOperator *op, const wmEvent *event) { int exit_code; @@ -402,7 +401,7 @@ static int transform_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int transform_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int transform_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (!transformops_data(C, op, event)) { G.moving = 0; @@ -431,7 +430,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) /* Make this not hidden when there's a nice axis selection widget */ RNA_def_property_flag(prop, PROP_HIDDEN); RNA_def_property_ui_text(prop, "Axis", "The axis around which the transformation occurs"); - } if (flags & P_CONSTRAINT) { @@ -439,8 +437,6 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) prop = RNA_def_property(ot->srna, "constraint_orientation", PROP_ENUM, PROP_NONE); RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation"); RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf); - - } if (flags & P_MIRROR) { @@ -558,6 +554,8 @@ static void TRANSFORM_OT_skin_resize(struct wmOperatorType *ot) static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Trackball"; ot->description = "Trackball style rotation of selected items"; @@ -571,7 +569,9 @@ static void TRANSFORM_OT_trackball(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_screenactive; - RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); + /* Maybe we could use float_vector_xyz here too? */ + prop = RNA_def_float_vector(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); + RNA_def_property_subtype(prop, PROP_ANGLE); Transform_Properties(ot, P_PROPORTIONAL | P_MIRROR | P_SNAP); } @@ -841,7 +841,7 @@ static void TRANSFORM_OT_seq_slide(struct wmOperatorType *ot) ot->cancel = transform_cancel; ot->poll = ED_operator_sequencer_active; - RNA_def_float_vector(ot->srna, "value", 2, VecOne, -FLT_MAX, FLT_MAX, "Angle", "", -FLT_MAX, FLT_MAX); + RNA_def_float_vector_xyz(ot->srna, "value", 2, NULL, -FLT_MAX, FLT_MAX, "Vector", "", -FLT_MAX, FLT_MAX); Transform_Properties(ot, P_SNAP); } diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index e507d062b0e..4fe36a15802 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -89,7 +89,7 @@ static TransformOrientation *findOrientationName(ListBase *lb, const char *name) return NULL; } -static int uniqueOrientationNameCheck(void *arg, const char *name) +static bool uniqueOrientationNameCheck(void *arg, const char *name) { return findOrientationName((ListBase *)arg, name) != NULL; } @@ -409,14 +409,16 @@ const char *BIF_menustringTransformOrientation(const bContext *C, const char *ti int i = V3D_MANIP_CUSTOM; char *str_menu, *p; const int elem_size = MAX_NAME + 4; + size_t str_menu_size; title = IFACE_(title); - str_menu = MEM_callocN(strlen(menu) + strlen(title) + 1 + elem_size * BIF_countTransformOrientation(C), "UserTransSpace from matrix"); + str_menu_size = strlen(menu) + strlen(title) + 1 + (elem_size * BIF_countTransformOrientation(C)); + str_menu = MEM_callocN(str_menu_size, "UserTransSpace from matrix"); + p = str_menu; - - p += sprintf(str_menu, "%s", title); - p += sprintf(p, "%s", menu); + p += BLI_strncpy_rlen(p, title, str_menu_size); + p += BLI_strncpy_rlen(p, menu, str_menu_size - (p - str_menu)); for (ts = transform_spaces->first; ts; ts = ts->next) { p += sprintf(p, "|%s %%x%d", ts->name, i++); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 2efd35327c7..c92cd77449e 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -47,8 +47,6 @@ #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" -#include "RNA_access.h" - #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -62,6 +60,10 @@ #include "BKE_tessmesh.h" #include "BKE_mesh.h" +#include "RNA_access.h" + +#include "WM_types.h" + #include "ED_armature.h" #include "ED_image.h" #include "ED_mesh.h" @@ -69,8 +71,6 @@ #include "ED_uvedit.h" #include "ED_view3d.h" -#include "WM_types.h" - #include "UI_resources.h" #include "UI_view2d.h" @@ -103,7 +103,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]); /****************** IMPLEMENTATIONS *********************/ -static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode); +static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode); static NodeBorder snapNodeBorder(int snap_node_mode); #if 0 @@ -260,7 +260,7 @@ void drawSnapping(const struct bContext *C, TransInfo *t) } } -int handleSnapping(TransInfo *t, wmEvent *event) +int handleSnapping(TransInfo *t, const wmEvent *event) { int status = 0; @@ -807,7 +807,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3]) /********************** CALC **************************/ -static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo * t, float *UNUSED(vec)) +static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo *t, float *UNUSED(vec)) { snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS); } @@ -818,7 +818,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) float loc[3]; float no[3]; float mval[2]; - int found = 0; + bool found = false; int dist = SNAP_MIN_DISTANCE; // Use a user defined value here mval[0] = t->mval[0]; @@ -901,7 +901,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) no[0] = 0.0; no[1] = 0.0; no[2] = 1.0; - found = 1; + found = true; } BLI_freelistN(&depth_peels); @@ -910,7 +910,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect); } - if (found == 1) { + if (found == true) { float tangent[3]; sub_v3_v3v3(tangent, loc, t->tsnap.snapPoint); @@ -1144,13 +1144,13 @@ static void TargetSnapClosest(TransInfo *t) } } -static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3], - const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3], + const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; int result; - int retval = 0; + bool retval = false; copy_v3_v3(ray_end, ray_normal_local); mul_v3_fl(ray_end, 2000); @@ -1206,7 +1206,7 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh float n1[3], n2[3]; *r_depth = new_depth; - retval = 1; + retval = true; sub_v3_v3v3(edge_loc, v1co, v2co); sub_v3_v3v3(vec, intersect, v2co); @@ -1231,11 +1231,11 @@ static int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], sh return retval; } -static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3], - const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3], + const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { - int retval = 0; + bool retval = false; float dvec[3]; sub_v3_v3v3(dvec, vco, ray_start_local); @@ -1262,7 +1262,7 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4] if (new_dist <= *r_dist && new_depth < *r_depth) { *r_depth = new_depth; - retval = 1; + retval = true; copy_v3_v3(r_loc, location); @@ -1279,13 +1279,13 @@ static int snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4] return retval; } -static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth) +static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float mval[2], + float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth) { float imat[4][4]; float ray_start_local[3], ray_normal_local[3]; - int retval = 0; + bool retval = false; invert_m4_m4(imat, obmat); @@ -1342,11 +1342,11 @@ static int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm return retval; } -static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { - int retval = 0; + bool retval = false; int totvert = dm->getNumVerts(dm); int totface = dm->getNumTessFaces(dm); @@ -1514,12 +1514,12 @@ static int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh return retval; } -static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) +static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float mval[2], + float r_loc[3], float r_no[3], int *r_dist, float *r_depth) { ToolSettings *ts = scene->toolsettings; - int retval = 0; + bool retval = false; if (ob->type == OB_MESH) { BMEditMesh *em; @@ -1546,12 +1546,12 @@ static int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, flo return retval; } -static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2], - int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2], + int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) { Base *base; - float depth = FLT_MAX; - int retval = 0; + float depth = (FLT_MAX / 2.0f); /* use half of flt-max so we can scale up without an exception */ + bool retval = false; float ray_start[3], ray_normal[3]; ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); @@ -1602,12 +1602,12 @@ static int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, c return retval; } -int snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +bool snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) { return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, r_dist, r_loc, r_no, mode); } -int snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +bool snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; @@ -1667,11 +1667,11 @@ static void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float n peel->flag = 0; } -static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], - const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]), - ListBase *depth_peels) +static bool peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], + const float ray_start[3], const float ray_normal[3], const float UNUSED(mval[2]), + ListBase *depth_peels) { - int retval = 0; + bool retval = false; int totvert = dm->getNumVerts(dm); int totface = dm->getNumTessFaces(dm); @@ -1776,10 +1776,11 @@ static int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[4][4], return retval; } -static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, const float mval[2], SnapMode mode) +static bool peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, + ListBase *depth_peels, const float mval[2], SnapMode mode) { Base *base; - int retval = 0; + bool retval = false; float ray_start[3], ray_normal[3]; ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); @@ -1798,7 +1799,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L if (dob->type == OB_MESH) { BMEditMesh *em; DerivedMesh *dm = NULL; - int val; + bool val; if (dob != obedit) { dm = mesh_get_derived_final(scene, dob, CD_MASK_BAREMESH); @@ -1822,7 +1823,7 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L } if (ob->type == OB_MESH) { - int val = 0; + bool val = false; if (ob != obedit && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT))) { DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); @@ -1850,12 +1851,12 @@ static int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, L return retval; } -int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode) +bool peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, const float mval[2], SnapMode mode) { return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval, mode); } -int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode) +bool peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], SnapMode mode) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; @@ -1865,7 +1866,7 @@ int peelObjectsContext(bContext *C, ListBase *depth_peels, const float mval[2], /******************** NODES ***********************************/ -static int snapNodeTest(View2D *v2d, bNode *node, SnapMode mode) +static bool snapNodeTest(View2D *v2d, bNode *node, SnapMode mode) { /* node is use for snapping only if a) snap mode matches and b) node is inside the view */ return ((mode == SNAP_NOT_SELECTED && !(node->flag & NODE_SELECT)) || @@ -1887,12 +1888,12 @@ static NodeBorder snapNodeBorder(int snap_node_mode) return 0; } -static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2], - float r_loc[2], int *r_dist, char *r_node_border) +static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2], + float r_loc[2], int *r_dist, char *r_node_border) { View2D *v2d = &ar->v2d; NodeBorder border = snapNodeBorder(ts->snap_node_mode); - int retval = 0; + bool retval = false; rcti totr; int new_dist; @@ -1905,7 +1906,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_LEFT; - retval = 1; + retval = true; } } @@ -1915,7 +1916,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_RIGHT; - retval = 1; + retval = true; } } @@ -1925,7 +1926,7 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_BOTTOM; - retval = 1; + retval = true; } } @@ -1935,19 +1936,19 @@ static int snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNo UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]); *r_dist = new_dist; *r_node_border = NODE_TOP; - retval = 1; + retval = true; } } return retval; } -static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2], +static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) { bNodeTree *ntree = snode->edittree; bNode *node; - int retval = 0; + bool retval = false; *r_node_border = 0; @@ -1959,12 +1960,12 @@ static int snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int return retval; } -int snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +bool snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) { return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode); } -int snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +bool snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) { Scene *scene = CTX_data_scene(C); return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode); diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index f0f31b1e793..73062c57526 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -187,8 +187,7 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha if (G.relbase_valid) { char local_name[FILE_MAXDIR + FILE_MAX], fi[FILE_MAX]; - BLI_strncpy(local_name, abs_name, sizeof(local_name)); - BLI_splitdirstring(local_name, fi); + BLI_split_file_part(abs_name, fi, sizeof(fi)); BLI_snprintf(local_name, sizeof(local_name), "//%s/%s", folder, fi); if (strcmp(abs_name, local_name) != 0) { switch (checkPackedFile(local_name, pf)) { diff --git a/source/blender/editors/util/editmode_undo.c b/source/blender/editors/util/editmode_undo.c index c8c26ed771d..7f4e05ddefa 100644 --- a/source/blender/editors/util/editmode_undo.c +++ b/source/blender/editors/util/editmode_undo.c @@ -246,7 +246,9 @@ void undo_editmode_step(bContext *C, int step) } else if (step == 1) { - if (curundo == NULL || curundo->prev == NULL) error("No more steps to undo"); + if (curundo == NULL || curundo->prev == NULL) { + error("No more steps to undo"); + } else { if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name); curundo = curundo->prev; @@ -256,7 +258,9 @@ void undo_editmode_step(bContext *C, int step) else { /* curundo has to remain current situation! */ - if (curundo == NULL || curundo->next == NULL) error("No more steps to redo"); + if (curundo == NULL || curundo->next == NULL) { + error("No more steps to redo"); + } else { undo_restore(curundo->next, curundo->getdata(C), obedit->data); curundo = curundo->next; diff --git a/source/blender/editors/util/numinput.c b/source/blender/editors/util/numinput.c index 0ec16ead35d..98a1b54c452 100644 --- a/source/blender/editors/util/numinput.c +++ b/source/blender/editors/util/numinput.c @@ -163,7 +163,7 @@ void applyNumInput(NumInput *n, float *vec) } } -char handleNumInput(NumInput *n, wmEvent *event) +char handleNumInput(NumInput *n, const wmEvent *event) { float Val = 0; short idx = n->idx, idx_max = n->idx_max; diff --git a/source/blender/editors/util/undo.c b/source/blender/editors/util/undo.c index ac2ee21d09d..fc603f7a593 100644 --- a/source/blender/editors/util/undo.c +++ b/source/blender/editors/util/undo.c @@ -475,7 +475,7 @@ static EnumPropertyItem *rna_undo_itemf(bContext *C, int undosys, int *totitem) } -static int undo_history_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int undo_history_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { int undosys, totitem = 0; diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index ea7e17af086..ba4879b38ca 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -50,6 +50,7 @@ #include "BKE_tessmesh.h" #include "BLI_array.h" +#include "BLI_buffer.h" #include "BIF_gl.h" #include "BIF_glutil.h" @@ -177,6 +178,9 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); + BLI_buffer_declare_static(vec2f, tf_uv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BLI_buffer_declare_static(vec2f, tf_uvorig_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + ED_space_image_get_uv_aspect(sima, &aspx, &aspy); switch (sima->dt_uvstretch) { @@ -186,8 +190,8 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { const int efa_len = efa->len; - float (*tf_uv)[2] = BLI_array_alloca(tf_uv, efa_len); - float (*tf_uvorig)[2] = BLI_array_alloca(tf_uvorig, efa_len); + float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len); + float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len); tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { @@ -229,8 +233,8 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { const int efa_len = efa->len; - float (*tf_uv)[2] = BLI_array_alloca(tf_uv, efa_len); - float (*tf_uvorig)[2] = BLI_array_alloca(tf_uvorig, efa_len); + float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len); + float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len); area = BM_face_calc_area(efa) / totarea; @@ -268,6 +272,11 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe { float a; + BLI_buffer_declare_static(float, uvang_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BLI_buffer_declare_static(float, ang_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BLI_buffer_declare_static(vec3f, av_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + BLI_buffer_declare_static(vec2f, auv_buf, BLI_BUFFER_NOP, BM_DEFAULT_NGON_STACK_SIZE); + col[3] = 0.5f; /* hard coded alpha, not that nice */ glShadeModel(GL_SMOOTH); @@ -277,12 +286,12 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe if (uvedit_face_visible_test(scene, ima, efa, tf)) { const int efa_len = efa->len; - float (*tf_uv)[2] = BLI_array_alloca(tf_uv, efa_len); - float (*tf_uvorig)[2] = BLI_array_alloca(tf_uvorig, efa_len); - float *uvang = BLI_array_alloca(uvang, efa_len); - float *ang = BLI_array_alloca(ang, efa_len); - float (*av)[3] = BLI_array_alloca(av, efa_len); /* use for 2d and 3d angle vectors */ - float (*auv)[2] = BLI_array_alloca(auv, efa_len); + float (*tf_uv)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uv_buf, vec2f, efa_len); + float (*tf_uvorig)[2] = (float (*)[2])BLI_buffer_resize_data(&tf_uvorig_buf, vec2f, efa_len); + float *uvang = BLI_buffer_resize_data(&uvang_buf, float, efa_len); + float *ang = BLI_buffer_resize_data(&ang_buf, float, efa_len); + float (*av)[3] = (float (*)[3])BLI_buffer_resize_data(&av_buf, vec3f, efa_len); + float (*auv)[2] = (float (*)[2])BLI_buffer_resize_data(&auv_buf, vec2f, efa_len); int j; BM_elem_flag_enable(efa, BM_ELEM_TAG); @@ -329,11 +338,19 @@ static void draw_uvs_stretch(SpaceImage *sima, Scene *scene, BMEditMesh *em, MTe } } + BLI_buffer_free(&uvang_buf); + BLI_buffer_free(&ang_buf); + BLI_buffer_free(&av_buf); + BLI_buffer_free(&auv_buf); + glShadeModel(GL_FLAT); break; } } + + BLI_buffer_free(&tf_uv_buf); + BLI_buffer_free(&tf_uvorig_buf); } static void draw_uvs_other(Scene *scene, Object *obedit, Image *curimage) diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index fbb6250c05b..85375bcaf83 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -2236,7 +2236,7 @@ static int select_exec(bContext *C, wmOperator *op) return mouse_select(C, co, extend, loop); } -static int select_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float co[2]; @@ -2281,7 +2281,7 @@ static int select_loop_exec(bContext *C, wmOperator *op) return mouse_select(C, co, extend, loop); } -static int select_loop_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float co[2]; @@ -2314,7 +2314,7 @@ static void UV_OT_select_loop(wmOperatorType *ot) /* ******************** linked select operator **************** */ -static int select_linked_internal(bContext *C, wmOperator *op, wmEvent *event, int pick) +static int select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, int pick) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); @@ -2384,7 +2384,7 @@ static void UV_OT_select_linked(wmOperatorType *ot) "Extend", "Extend selection rather than clearing the existing selection"); } -static int select_linked_pick_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) { return select_linked_internal(C, op, event, 1); } @@ -3748,7 +3748,7 @@ static int set_2d_cursor_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int set_2d_cursor_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) { ARegion *ar = CTX_wm_region(C); float location[2]; @@ -3799,7 +3799,7 @@ static int set_tile_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int set_tile_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int set_tile_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); Image *ima = CTX_data_edit_image(C); diff --git a/source/blender/editors/uvedit/uvedit_smart_stitch.c b/source/blender/editors/uvedit/uvedit_smart_stitch.c index 5bb8105cd14..4c56a016176 100644 --- a/source/blender/editors/uvedit/uvedit_smart_stitch.c +++ b/source/blender/editors/uvedit/uvedit_smart_stitch.c @@ -41,6 +41,7 @@ #include "DNA_meshdata_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_math_vector.h" @@ -1748,7 +1749,7 @@ static int stitch_init(bContext *C, wmOperator *op) state->total_separate_edges = total_edges; /* fill the edges with data */ - for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) { + for (i = 0, BLI_ghashIterator_init(ghi, edge_hash); BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) { edges[i++] = *((UvEdge *)BLI_ghashIterator_getKey(ghi)); } @@ -1910,7 +1911,7 @@ static int stitch_init(bContext *C, wmOperator *op) return 1; } -static int stitch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int stitch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Object *obedit = CTX_data_edit_object(C); if (!stitch_init(C, op)) @@ -2000,7 +2001,7 @@ static int stitch_exec(bContext *C, wmOperator *op) } } -static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState *state) +static void stitch_select(bContext *C, Scene *scene, const wmEvent *event, StitchState *state) { /* add uv under mouse to processed uv's */ float co[2]; @@ -2034,7 +2035,7 @@ static void stitch_select(bContext *C, Scene *scene, wmEvent *event, StitchState } } -static int stitch_modal(bContext *C, wmOperator *op, wmEvent *event) +static int stitch_modal(bContext *C, wmOperator *op, const wmEvent *event) { StitchState *state; Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/uvedit/uvedit_unwrap_ops.c b/source/blender/editors/uvedit/uvedit_unwrap_ops.c index 4ddf4bd6a5c..9de43fc9d6b 100644 --- a/source/blender/editors/uvedit/uvedit_unwrap_ops.c +++ b/source/blender/editors/uvedit/uvedit_unwrap_ops.c @@ -654,7 +654,7 @@ static int minimize_stretch_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int minimize_stretch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { MinStretch *ms; @@ -670,7 +670,7 @@ static int minimize_stretch_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED( return OPERATOR_RUNNING_MODAL; } -static int minimize_stretch_modal(bContext *C, wmOperator *op, wmEvent *event) +static int minimize_stretch_modal(bContext *C, wmOperator *op, const wmEvent *event) { MinStretch *ms = op->customdata; diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index faeb0f721f4..485f5d65853 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -50,21 +50,22 @@ set(SRC intern/gpu_codegen.c intern/gpu_draw.c intern/gpu_extensions.c - intern/gpu_fixed_material.c intern/gpu_material.c + intern/gpu_simple_shader.c GPU_buffers.h GPU_draw.h GPU_extensions.h GPU_material.h + GPU_simple_shader.h intern/gpu_codegen.h ) -data_to_c_simple(shaders/gpu_shader_fixed_fragment.glsl SRC) -data_to_c_simple(shaders/gpu_shader_fixed_vertex.glsl SRC) data_to_c_simple(shaders/gpu_shader_material.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_sep_gaussian_blur_vert.glsl SRC) +data_to_c_simple(shaders/gpu_shader_simple_frag.glsl SRC) +data_to_c_simple(shaders/gpu_shader_simple_vert.glsl SRC) data_to_c_simple(shaders/gpu_shader_vertex.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_frag.glsl SRC) data_to_c_simple(shaders/gpu_shader_vsm_store_vert.glsl SRC) diff --git a/source/blender/gpu/GPU_extensions.h b/source/blender/gpu/GPU_extensions.h index 7492304bd40..0ae45775473 100644 --- a/source/blender/gpu/GPU_extensions.h +++ b/source/blender/gpu/GPU_extensions.h @@ -157,6 +157,8 @@ void GPU_offscreen_free(GPUOffScreen *ofs); void GPU_offscreen_bind(GPUOffScreen *ofs); void GPU_offscreen_unbind(GPUOffScreen *ofs); void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels); +int GPU_offscreen_width(GPUOffScreen *ofs); +int GPU_offscreen_height(GPUOffScreen *ofs); /* GPU Shader * - only for fragment shaders now @@ -201,30 +203,6 @@ typedef struct GPUVertexAttribs { int totlayer; } GPUVertexAttribs; -/* Fixed Function Materials */ - -typedef enum GPUFixedMaterialOption { - GPU_FIXED_COLOR_MATERIAL = (1<<0), /* replace diffuse with glcolor */ - GPU_FIXED_SOLID_LIGHTING = (1<<1), /* use solid lighting (only 3 directional lights) */ - GPU_FIXED_SCENE_LIGHTING = (1<<2), /* use scene lighting (up to 8 arbitrary lights) */ - GPU_FIXED_TWO_SIDED = (1<<3), /* flip normals towards viewer */ - GPU_FIXED_TEXTURE_2D = (1<<4), /* use 2D texture to replace diffuse color */ - - GPU_FIXED_OPTIONS_NUM = 5, - GPU_FIXED_OPTION_COMBINATIONS = (1<<GPU_FIXED_OPTIONS_NUM) -} GPUFixedMaterialOption; - -void GPU_fixed_materials_init(void); -void GPU_fixed_materials_exit(void); - -void GPU_fixed_material_shader_bind(int options); -void GPU_fixed_material_shader_unbind(void); - -void GPU_fixed_material_colors(const float diffuse[3], const float specular[3], - int shininess, float alpha); - -bool GPU_fixed_material_need_normals(void); - #ifdef __cplusplus } #endif diff --git a/source/blender/gpu/GPU_simple_shader.h b/source/blender/gpu/GPU_simple_shader.h new file mode 100644 index 00000000000..c8fb1f09b04 --- /dev/null +++ b/source/blender/gpu/GPU_simple_shader.h @@ -0,0 +1,89 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file GPU_simple_shader.h + * \ingroup gpu + */ + +#ifndef __GPU_SIMPLE_SHADER_H__ +#define __GPU_SIMPLE_SHADER_H__ + +#include "BLI_utildefines.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Fixed Function Shader */ + +typedef enum GPUSimpleShaderOption { + GPU_SHADER_OVERRIDE_DIFFUSE = (1<<0), /* replace diffuse with glcolor */ + GPU_SHADER_LIGHTING = (1<<1), /* use lighting */ + GPU_SHADER_TWO_SIDED = (1<<2), /* flip normals towards viewer */ + GPU_SHADER_TEXTURE_2D = (1<<3), /* use 2D texture to replace diffuse color */ + + GPU_SHADER_SOLID_LIGHTING = (1<<4), /* use faster lighting (set automatically) */ + GPU_SHADER_OPTIONS_NUM = 5, + GPU_SHADER_OPTION_COMBINATIONS = (1<<GPU_SHADER_OPTIONS_NUM) +} GPUSimpleShaderOption; + +void GPU_simple_shaders_init(void); +void GPU_simple_shaders_exit(void); + +void GPU_simple_shader_bind(int options); +void GPU_simple_shader_unbind(void); + +void GPU_simple_shader_colors(const float diffuse[3], const float specular[3], + int shininess, float alpha); + +bool GPU_simple_shader_need_normals(void); + +/* Fixed Function Lighting */ + +typedef struct GPULightData { + float position[4]; + float diffuse[4]; + float specular[4]; + + float constant_attenuation; + float linear_attenuation; + float quadratic_attenuation; + + float spot_direction[3]; + float spot_cutoff; + float spot_exponent; +} GPULightData; + +void GPU_simple_shader_light_set(int light_num, GPULightData *light); +void GPU_simple_shader_light_set_viewer(bool local); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/source/blender/gpu/SConscript b/source/blender/gpu/SConscript index ccea40c0909..6e3722e403a 100644 --- a/source/blender/gpu/SConscript +++ b/source/blender/gpu/SConscript @@ -44,19 +44,19 @@ if env['WITH_BF_SMOKE']: defs.append('WITH_SMOKE') if env['WITH_BF_DDS']: - defs.append('WITH_DDS') + defs.append('WITH_DDS') # generated data files import os sources.extend(( - os.path.join(env['DATA_SOURCES'], "gpu_shader_fixed_fragment.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_fixed_vertex.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), - os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), - )) + os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_frag.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_simple_vert.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_material.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_frag.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_sep_gaussian_blur_vert.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_vertex.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_frag.glsl.c"), + os.path.join(env['DATA_SOURCES'], "gpu_shader_vsm_store_vert.glsl.c"), + )) env.BlenderLib ( 'bf_gpu', sources, Split(incs), defines = defs, libtype=['core','player'], priority=[160,110] ) diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 59953659a2c..840b16a4567 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -197,7 +197,7 @@ static char *gpu_generate_function_prototyps(GHash *hash) * generated code, to avoid have to add the actual code & recompile all */ ghi = BLI_ghashIterator_new(hash); - for (; !BLI_ghashIterator_isDone(ghi); BLI_ghashIterator_step(ghi)) { + for (; BLI_ghashIterator_notDone(ghi); BLI_ghashIterator_step(ghi)) { name = BLI_ghashIterator_getValue(ghi); function = BLI_ghashIterator_getValue(ghi); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index c631f7efbe9..fc3bf75e784 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -189,30 +189,21 @@ void GPU_render_text(MTFace *tface, int mode, /* Checking powers of two for images since opengl 1.x requires it */ -static int is_pow2_limit(int num) +static bool is_power_of_2_resolution(int w, int h) { - /* take texture clamping into account */ - - /* XXX: texturepaint not global! */ -#if 0 - if (G.f & G_TEXTUREPAINT) - return 1;*/ -#endif + return is_power_of_2_i(w) && is_power_of_2_i(h); +} - if (U.glreslimit != 0 && num > U.glreslimit) - return 0; +static bool is_over_resolution_limit(int w, int h) +{ + if (U.glreslimit != 0) + return (w > U.glreslimit || h > U.glreslimit); - return is_power_of_2_i(num); + return false; } -static int smaller_pow2_limit(int num) +static int smaller_power_of_2_limit(int num) { - /* XXX: texturepaint not global! */ -#if 0 - if (G.f & G_TEXTUREPAINT) - return 1;*/ -#endif - /* take texture clamping into account */ if (U.glreslimit != 0 && num > U.glreslimit) return U.glreslimit; @@ -670,7 +661,7 @@ int GPU_verify_image(Image *ima, ImageUser *iuser, int tftile, int compare, int } /* Image *ima can be NULL */ -void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima) +void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float *frect, int rectw, int recth, int mipmap, int use_high_bit_depth, Image *ima) { unsigned int *scalerect = NULL; float *fscalerect = NULL; @@ -681,9 +672,10 @@ void GPU_create_gl_tex(unsigned int *bind, unsigned int *pix, float * frect, int /* scale if not a power of two. this is not strictly necessary for newer * GPUs (OpenGL version >= 2.0) since they support non-power-of-two-textures * Then don't bother scaling for hardware that supports NPOT textures! */ - if (!GPU_non_power_of_two_support() && (!is_pow2_limit(rectw) || !is_pow2_limit(recth))) { - rectw= smaller_pow2_limit(rectw); - recth= smaller_pow2_limit(recth); + if ((!GPU_non_power_of_two_support() && !is_power_of_2_resolution(rectw, recth)) || + is_over_resolution_limit(rectw, recth)) { + rectw= smaller_power_of_2_limit(rectw); + recth= smaller_power_of_2_limit(recth); if (use_high_bit_depth) { fscalerect= MEM_mallocN(rectw*recth*sizeof(*fscalerect)*4, "fscalerect"); @@ -772,7 +764,7 @@ int GPU_upload_dxt_texture(ImBuf *ibuf) return FALSE; } - if (!is_power_of_2_i(width) || !is_power_of_2_i(height)) { + if (!is_power_of_2_resolution(width, height)) { printf("Unable to load non-power-of-two DXT image resolution, falling back to uncompressed\n"); return FALSE; } diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index 56aa4b222cb..c7a421a49fc 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -44,6 +44,7 @@ #include "GPU_draw.h" #include "GPU_extensions.h" +#include "GPU_simple_shader.h" #include "gpu_codegen.h" #include <stdlib.h> @@ -206,14 +207,14 @@ void GPU_extensions_init(void) GG.os = GPU_OS_UNIX; #endif - GPU_fixed_materials_init(); + GPU_simple_shaders_init(); } void GPU_extensions_exit(void) { gpu_extensions_init = 0; GPU_codegen_exit(); - GPU_fixed_materials_exit(); + GPU_simple_shaders_exit(); } int GPU_glsl_support(void) @@ -904,10 +905,8 @@ void GPU_framebuffer_texture_bind(GPUFrameBuffer *UNUSED(fb), GPUTexture *tex, i glMatrixMode(GL_PROJECTION); glPushMatrix(); - glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glLoadIdentity(); } void GPU_framebuffer_texture_unbind(GPUFrameBuffer *UNUSED(fb), GPUTexture *UNUSED(tex)) @@ -1095,6 +1094,16 @@ void GPU_offscreen_read_pixels(GPUOffScreen *ofs, int type, void *pixels) glReadPixels(0, 0, ofs->w, ofs->h, GL_RGBA, type, pixels); } +int GPU_offscreen_width(GPUOffScreen *ofs) +{ + return ofs->w; +} + +int GPU_offscreen_height(GPUOffScreen *ofs) +{ + return ofs->h; +} + /* GPUShader */ struct GPUShader { @@ -1127,6 +1136,19 @@ static void shader_print_errors(const char *task, char *log, const char *code) fprintf(stderr, "%s\n", log); } +static const char *gpu_shader_standard_defines(void) +{ + /* some useful defines to detect GPU type */ + if(GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_ANY, GPU_DRIVER_ANY)) + return "#define GPU_ATI\n"; + else if(GPU_type_matches(GPU_DEVICE_NVIDIA, GPU_OS_ANY, GPU_DRIVER_ANY)) + return "#define GPU_NVIDIA\n"; + else if(GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) + return "#define GPU_INTEL\n"; + + return ""; +} + GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const char *libcode, const char *defines) { GLint status; @@ -1155,9 +1177,11 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const } if (vertexcode) { - const char *source[2]; + const char *source[3]; int num_source = 0; + source[num_source++] = gpu_shader_standard_defines(); + if (defines) source[num_source++] = defines; if (vertexcode) source[num_source++] = vertexcode; @@ -1177,9 +1201,11 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const } if (fragcode) { - const char *source[3]; + const char *source[4]; int num_source = 0; + source[num_source++] = gpu_shader_standard_defines(); + if (defines) source[num_source++] = defines; if (libcode) source[num_source++] = libcode; if (fragcode) source[num_source++] = fragcode; @@ -1264,7 +1290,7 @@ void GPU_shader_bind(GPUShader *shader) GPU_print_error("Post Shader Bind"); } -void GPU_shader_unbind() +void GPU_shader_unbind(void) { GPU_print_error("Pre Shader Unbind"); glUseProgramObjectARB(0); diff --git a/source/blender/gpu/intern/gpu_fixed_material.c b/source/blender/gpu/intern/gpu_fixed_material.c deleted file mode 100644 index d5a04c88e89..00000000000 --- a/source/blender/gpu/intern/gpu_fixed_material.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2013 Blender Foundation. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): Brecht Van Lommel. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/gpu/intern/gpu_fixed_material.c - * \ingroup gpu - */ - -/* GLSL shaders to replace fixed function OpenGL materials and lighting. These - * are deprecated in newer OpenGL versions and missing in OpenGL ES 2.0. Also, - * two sided lighting is no longer natively supported on NVidia cards which - * results in slow software fallback. - * - * Todo: - * - Replace glLight and glMaterial functions entirely with GLSL uniforms, to - * make OpenGL ES 2.0 work. - * - Replace glTexCoord and glColor with generic attributes. - * - Optimize for case where fewer than 3 or 8 lights are used. - * - Optimize for case where specular is not used. - * - Optimize for case where no texture matrix is used. - */ - -#include "GL/glew.h" - -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "DNA_mesh_types.h" -#include "DNA_object_types.h" - -#include "GPU_extensions.h" - -/* Fixed function material types */ - -static struct { - GPUShader *cached_shaders[GPU_FIXED_OPTION_COMBINATIONS]; - bool failed_shaders[GPU_FIXED_OPTION_COMBINATIONS]; - - bool need_normals; -} GPU_MATERIAL_STATE; - -/* Init / exit */ - -void GPU_fixed_materials_init() -{ - memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE)); -} - -void GPU_fixed_materials_exit() -{ - int i; - - for (i = 0; i < GPU_FIXED_OPTION_COMBINATIONS; i++) - if (GPU_MATERIAL_STATE.cached_shaders[i]) - GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]); -} - -/* Shader lookup / create */ - -static GPUShader *gpu_fixed_material_shader(int options) -{ - /* glsl code */ - extern char datatoc_gpu_shader_fixed_vertex_glsl[]; - extern char datatoc_gpu_shader_fixed_fragment_glsl[]; - - /* cached shaders */ - GPUShader *shader = GPU_MATERIAL_STATE.cached_shaders[options]; - - if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) { - /* create shader if it doesn't exist yet */ - char defines[64*GPU_FIXED_OPTIONS_NUM] = ""; - - if (options & GPU_FIXED_COLOR_MATERIAL) - strcat(defines, "#define USE_COLOR\n"); - if (options & GPU_FIXED_TWO_SIDED) - strcat(defines, "#define USE_TWO_SIDED\n"); - if (options & GPU_FIXED_SOLID_LIGHTING) - strcat(defines, "#define USE_SOLID_LIGHTING\n"); - if (options & GPU_FIXED_SCENE_LIGHTING) - strcat(defines, "#define USE_SCENE_LIGHTING\n"); - if (options & GPU_FIXED_TEXTURE_2D) - strcat(defines, "#define USE_TEXTURE\n"); - - shader = GPU_shader_create( - datatoc_gpu_shader_fixed_vertex_glsl, - datatoc_gpu_shader_fixed_fragment_glsl, - NULL, defines); - - if (shader) { - /* set texture map to first texture unit */ - if (options & GPU_FIXED_TEXTURE_2D) - glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0); - - GPU_MATERIAL_STATE.cached_shaders[options] = shader; - } - else - GPU_MATERIAL_STATE.failed_shaders[options] = true; - } - - return shader; -} - -/* Bind / unbind */ - -void GPU_fixed_material_shader_bind(int options) -{ - if (GPU_glsl_support()) { - GPUShader *shader = gpu_fixed_material_shader(options); - - if (shader) - GPU_shader_bind(shader); - } - else { - if (options & (GPU_FIXED_SOLID_LIGHTING|GPU_FIXED_SCENE_LIGHTING)) - glEnable(GL_LIGHTING); - - if (options & GPU_FIXED_TWO_SIDED) - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); - - if (options & GPU_FIXED_COLOR_MATERIAL) { - glEnable(GL_COLOR_MATERIAL); - glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); - } - - if (options & GPU_FIXED_TEXTURE_2D) - glEnable(GL_TEXTURE_2D); - } - - /* temporary hack, should be solved outside of this file */ - GPU_MATERIAL_STATE.need_normals = (options & (GPU_FIXED_SOLID_LIGHTING|GPU_FIXED_SCENE_LIGHTING)); -} - -void GPU_fixed_material_shader_unbind() -{ - if (GPU_glsl_support()) { - GPU_shader_unbind(); - } - else { - glDisable(GL_LIGHTING); - glDisable(GL_COLOR_MATERIAL); - glDisable(GL_TEXTURE_2D); - glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); - } -} - -/* Material Colors */ - -void GPU_fixed_material_colors(const float diffuse[3], const float specular[3], - int shininess, float alpha) -{ - float gl_diffuse[4], gl_specular[4]; - - copy_v3_v3(gl_diffuse, diffuse); - gl_diffuse[3] = alpha; - - copy_v3_v3(gl_specular, specular); - gl_specular[3] = 1.0f; - - glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); - glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specular); - glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128)); -} - -bool GPU_fixed_material_need_normals() -{ - return GPU_MATERIAL_STATE.need_normals; -} - diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index d7ac6febfb7..636c44d3e80 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1035,7 +1035,7 @@ static void do_material_tex(GPUShadeInput *shi) GPU_link(mat, "mtex_image", texco, GPU_image(tex->ima, &tex->iuser, FALSE), &tin, &trgb); rgbnor= TEX_RGB; - talpha = (tex->ima->flag & IMA_IGNORE_ALPHA) == 0; + talpha = ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0); } else { continue; diff --git a/source/blender/gpu/intern/gpu_simple_shader.c b/source/blender/gpu/intern/gpu_simple_shader.c new file mode 100644 index 00000000000..b29d6c2e681 --- /dev/null +++ b/source/blender/gpu/intern/gpu_simple_shader.c @@ -0,0 +1,283 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Brecht Van Lommel. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/gpu/intern/gpu_simple_shader.c + * \ingroup gpu + */ + +/* GLSL shaders to replace fixed function OpenGL materials and lighting. These + * are deprecated in newer OpenGL versions and missing in OpenGL ES 2.0. Also, + * two sided lighting is no longer natively supported on NVidia cards which + * results in slow software fallback. + * + * Todo: + * - Replace glLight and glMaterial functions entirely with GLSL uniforms, to + * make OpenGL ES 2.0 work. + * - Replace glTexCoord and glColor with generic attributes. + * - Optimize for case where fewer than 3 or 8 lights are used. + * - Optimize for case where specular is not used. + * - Optimize for case where no texture matrix is used. + */ + +#include "GL/glew.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_mesh_types.h" +#include "DNA_object_types.h" + +#include "GPU_extensions.h" +#include "GPU_simple_shader.h" + +/* State */ + +#define NUM_OPENGL_LIGHTS 8 + +static struct { + GPUShader *cached_shaders[GPU_SHADER_OPTION_COMBINATIONS]; + bool failed_shaders[GPU_SHADER_OPTION_COMBINATIONS]; + + bool need_normals; + + int lights_enabled; + int lights_directional; +} GPU_MATERIAL_STATE; + +/* Init / exit */ + +void GPU_simple_shaders_init(void) +{ + memset(&GPU_MATERIAL_STATE, 0, sizeof(GPU_MATERIAL_STATE)); +} + +void GPU_simple_shaders_exit(void) +{ + int i; + + for (i = 0; i < GPU_SHADER_OPTION_COMBINATIONS; i++) + if (GPU_MATERIAL_STATE.cached_shaders[i]) + GPU_shader_free(GPU_MATERIAL_STATE.cached_shaders[i]); +} + +/* Shader lookup / create */ + +static bool solid_compatible_lighting(void) +{ + int enabled = GPU_MATERIAL_STATE.lights_enabled; + int directional = GPU_MATERIAL_STATE.lights_directional; + + /* more than 3 lights? */ + if (enabled >= (1 << 3)) + return false; + + /* all directional? */ + return ((directional & enabled) == enabled); +} + +#if 0 +static int detect_options() +{ + GLint two_sided; + int options = 0; + + if (glIsEnabled(GL_TEXTURE_2D)) + options |= GPU_SHADER_TEXTURE_2D; + if (glIsEnabled(GL_COLOR_MATERIAL)) + options |= GPU_SHADER_OVERRIDE_DIFFUSE; + + if (glIsEnabled(GL_LIGHTING)) + options |= GPU_SHADER_LIGHTING; + + glGetIntegerv(GL_LIGHT_MODEL_TWO_SIDE, &two_sided); + if (two_sided == GL_TRUE) + options |= GPU_SHADER_TWO_SIDED; + + return options; +} +#endif + +static GPUShader *gpu_simple_shader(int options) +{ + /* glsl code */ + extern char datatoc_gpu_shader_simple_vert_glsl[]; + extern char datatoc_gpu_shader_simple_frag_glsl[]; + GPUShader *shader; + + /* detect if we can do faster lighting for solid draw mode */ + if (options & GPU_SHADER_LIGHTING) + if (solid_compatible_lighting()) + options |= GPU_SHADER_SOLID_LIGHTING; + + /* cached shaders */ + shader = GPU_MATERIAL_STATE.cached_shaders[options]; + + if (!shader && !GPU_MATERIAL_STATE.failed_shaders[options]) { + /* create shader if it doesn't exist yet */ + char defines[64*GPU_SHADER_OPTIONS_NUM] = ""; + + if (options & GPU_SHADER_OVERRIDE_DIFFUSE) + strcat(defines, "#define USE_COLOR\n"); + if (options & GPU_SHADER_TWO_SIDED) + strcat(defines, "#define USE_TWO_SIDED\n"); + if (options & GPU_SHADER_TEXTURE_2D) + strcat(defines, "#define USE_TEXTURE\n"); + + if (options & GPU_SHADER_SOLID_LIGHTING) + strcat(defines, "#define USE_SOLID_LIGHTING\n"); + else if (options & GPU_SHADER_LIGHTING) + strcat(defines, "#define USE_SCENE_LIGHTING\n"); + + shader = GPU_shader_create( + datatoc_gpu_shader_simple_vert_glsl, + datatoc_gpu_shader_simple_frag_glsl, + NULL, defines); + + if (shader) { + /* set texture map to first texture unit */ + if (options & GPU_SHADER_TEXTURE_2D) + glUniform1i(GPU_shader_get_uniform(shader, "texture_map"), 0); + + GPU_MATERIAL_STATE.cached_shaders[options] = shader; + } + else + GPU_MATERIAL_STATE.failed_shaders[options] = true; + } + + return shader; +} + +/* Bind / unbind */ + +void GPU_simple_shader_bind(int options) +{ + if (GPU_glsl_support()) { + GPUShader *shader = gpu_simple_shader(options); + + if (shader) + GPU_shader_bind(shader); + } + else { + // XXX where does this fit, depends on ortho/persp? + + if (options & GPU_SHADER_LIGHTING) + glEnable(GL_LIGHTING); + + if (options & GPU_SHADER_TWO_SIDED) + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); + + if (options & GPU_SHADER_OVERRIDE_DIFFUSE) { + glEnable(GL_COLOR_MATERIAL); + glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE); + } + + if (options & GPU_SHADER_TEXTURE_2D) + glEnable(GL_TEXTURE_2D); + } + + /* temporary hack, should be solved outside of this file */ + GPU_MATERIAL_STATE.need_normals = (options & GPU_SHADER_LIGHTING); +} + +void GPU_simple_shader_unbind(void) +{ + if (GPU_glsl_support()) { + GPU_shader_unbind(); + } + else { + glDisable(GL_LIGHTING); + glDisable(GL_COLOR_MATERIAL); + glDisable(GL_TEXTURE_2D); + glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); + } +} + +/* Material Colors */ + +void GPU_simple_shader_colors(const float diffuse[3], const float specular[3], + int shininess, float alpha) +{ + float gl_diffuse[4], gl_specular[4]; + + copy_v3_v3(gl_diffuse, diffuse); + gl_diffuse[3] = alpha; + + copy_v3_v3(gl_specular, specular); + gl_specular[3] = 1.0f; + + glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gl_diffuse); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gl_specular); + glMateriali(GL_FRONT_AND_BACK, GL_SHININESS, CLAMPIS(shininess, 1, 128)); +} + +bool GPU_simple_shader_need_normals(void) +{ + return GPU_MATERIAL_STATE.need_normals; +} + +void GPU_simple_shader_light_set(int light_num, GPULightData *light) +{ + int light_bit = (1 << light_num); + + GPU_MATERIAL_STATE.lights_enabled &= ~light_bit; + GPU_MATERIAL_STATE.lights_directional &= ~light_bit; + + if (light) { + glEnable(GL_LIGHT0+light_num); + + glLightfv(GL_LIGHT0+light_num, GL_POSITION, light->position); + glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, light->diffuse); + glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, light->specular); + + glLightf(GL_LIGHT0+light_num, GL_CONSTANT_ATTENUATION, light->constant_attenuation); + glLightf(GL_LIGHT0+light_num, GL_LINEAR_ATTENUATION, light->linear_attenuation); + glLightf(GL_LIGHT0+light_num, GL_QUADRATIC_ATTENUATION, light->quadratic_attenuation); + + glLightfv(GL_LIGHT0+light_num, GL_SPOT_DIRECTION, light->spot_direction); + glLightf(GL_LIGHT0+light_num, GL_SPOT_CUTOFF, light->spot_cutoff); + glLightf(GL_LIGHT0+light_num, GL_SPOT_EXPONENT, light->spot_exponent); + + GPU_MATERIAL_STATE.lights_enabled |= light_bit; + if(light->position[3] == 0.0f) + GPU_MATERIAL_STATE.lights_directional |= light_bit; + } + else { + const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + + glLightfv(GL_LIGHT0+light_num, GL_POSITION, zero); + glLightfv(GL_LIGHT0+light_num, GL_DIFFUSE, zero); + glLightfv(GL_LIGHT0+light_num, GL_SPECULAR, zero); + + glDisable(GL_LIGHT0+light_num); + } +} + +void GPU_simple_shader_light_set_viewer(bool local) +{ + glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, (local)? GL_TRUE: GL_FALSE); +} + diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 8fc18bf8726..4fc04175bba 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -233,7 +233,7 @@ void math_pow(float val1, float val2, out float outval) else { float val2_mod_1 = mod(abs(val2), 1.0); - if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) + if (val2_mod_1 > 0.999 || val2_mod_1 < 0.001) outval = compatible_pow(val1, floor(val2 + 0.5)); else outval = 0.0; diff --git a/source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl b/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl index 9610e0cf5aa..9610e0cf5aa 100644 --- a/source/blender/gpu/shaders/gpu_shader_fixed_fragment.glsl +++ b/source/blender/gpu/shaders/gpu_shader_simple_frag.glsl diff --git a/source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl index 612f9cff6aa..9491eaa672d 100644 --- a/source/blender/gpu/shaders/gpu_shader_fixed_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_simple_vert.glsl @@ -29,11 +29,9 @@ void main() gl_Position = gl_ProjectionMatrix * co; -#ifdef __GLSL_CG_DATA_TYPES - // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards. - // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with - // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). - // gl_ClipVerte is supported up to GLSL 1.20. +#ifdef GPU_NVIDIA + // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA + // graphic cards, while on ATI it can cause a software fallback. gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; #endif diff --git a/source/blender/gpu/shaders/gpu_shader_vertex.glsl b/source/blender/gpu/shaders/gpu_shader_vertex.glsl index 9e0db44ed31..8741a13ea9b 100644 --- a/source/blender/gpu/shaders/gpu_shader_vertex.glsl +++ b/source/blender/gpu/shaders/gpu_shader_vertex.glsl @@ -10,11 +10,9 @@ void main() varnormal = normalize(gl_NormalMatrix * gl_Normal); gl_Position = gl_ProjectionMatrix * co; - // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA graphic cards. - // gl_ClipVertex works only on NVIDIA graphic cards so we have to check with - // __GLSL_CG_DATA_TYPES if a NVIDIA graphic card is used (Cg support). - // gl_ClipVerte is supported up to GLSL 1.20. -#ifdef __GLSL_CG_DATA_TYPES +#ifdef GPU_NVIDIA + // Setting gl_ClipVertex is necessary to get glClipPlane working on NVIDIA + // graphic cards, while on ATI it can cause a software fallback. gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex; #endif diff --git a/source/blender/ikplugin/intern/iksolver_plugin.c b/source/blender/ikplugin/intern/iksolver_plugin.c index 67f0694797b..9ec115f10e8 100644 --- a/source/blender/ikplugin/intern/iksolver_plugin.c +++ b/source/blender/ikplugin/intern/iksolver_plugin.c @@ -200,7 +200,9 @@ static void make_dmats(bPoseChannel *pchan) invert_m4_m4(iR_parmat, pchan->parent->pose_mat); mult_m4_m4m4(pchan->chan_mat, iR_parmat, pchan->pose_mat); // delta mat } - else copy_m4_m4(pchan->chan_mat, pchan->pose_mat); + else { + copy_m4_m4(pchan->chan_mat, pchan->pose_mat); + } } /* applies IK matrix to pchan, IK is done separated */ diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h index a19433dbd2f..48c14fc07f2 100644 --- a/source/blender/imbuf/IMB_imbuf.h +++ b/source/blender/imbuf/IMB_imbuf.h @@ -338,6 +338,12 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned /** * + * \attention Defined in scaling.c + */ +void IMB_scaleImBuf_threaded(struct ImBuf *ibuf, unsigned int newx, unsigned int newy); + +/** + * * \attention Defined in writeimage.c */ short IMB_saveiff(struct ImBuf *ibuf, const char *filepath, int flags); diff --git a/source/blender/imbuf/IMB_imbuf_types.h b/source/blender/imbuf/IMB_imbuf_types.h index dde8d4d4ab7..a3629d079a3 100644 --- a/source/blender/imbuf/IMB_imbuf_types.h +++ b/source/blender/imbuf/IMB_imbuf_types.h @@ -179,6 +179,7 @@ typedef struct ImBuf { * Note that the lower 11 bits is used for storing custom flags */ #define IB_CUSTOM_FLAGS_MASK 0x7ff +#define IB_ALPHA_MASK 0xff #define PNG (1 << 30) #define TGA (1 << 28) diff --git a/source/blender/imbuf/SConscript b/source/blender/imbuf/SConscript index f76da8cd9d0..453cf6a509e 100644 --- a/source/blender/imbuf/SConscript +++ b/source/blender/imbuf/SConscript @@ -53,7 +53,7 @@ else: if env['WITH_BF_TIFF']: defs.append('WITH_TIFF') else: - sources.remove(os.path.join('intern', 'tiff.c')) + sources.remove(os.path.join('intern', 'tiff.c')) if env['WITH_BF_DDS']: defs.append('WITH_DDS') @@ -64,7 +64,7 @@ if env['WITH_BF_CINEON']: if env['WITH_BF_HDR']: defs.append('WITH_HDR') else: - sources.remove(os.path.join('intern', 'radiance_hdr.c')) + sources.remove(os.path.join('intern', 'radiance_hdr.c')) if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') @@ -74,7 +74,7 @@ if env['WITH_BF_OPENJPEG']: defs.append('WITH_OPENJPEG') incs += ' ' + env['BF_OPENJPEG_INC'] else: - sources.remove(os.path.join('intern', 'jp2.c')) + sources.remove(os.path.join('intern', 'jp2.c')) if env['WITH_BF_REDCODE']: defs.append('WITH_REDCODE') diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index e2a8e1e3442..c372e125a66 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -36,11 +36,14 @@ struct OCIO_ConstProcessorRcPtr; struct ImBuf; +#define MAX_COLORSPACE_NAME 64 +#define MAX_COLORSPACE_DESCRIPTION 512 + typedef struct ColorSpace { struct ColorSpace *next, *prev; int index; - char name[64]; - char description[64]; + char name[MAX_COLORSPACE_NAME]; + char description[MAX_COLORSPACE_DESCRIPTION]; struct OCIO_ConstProcessorRcPtr *to_scene_linear; struct OCIO_ConstProcessorRcPtr *from_scene_linear; @@ -52,7 +55,7 @@ typedef struct ColorSpace { typedef struct ColorManagedDisplay { struct ColorManagedDisplay *next, *prev; int index; - char name[64]; + char name[MAX_COLORSPACE_NAME]; ListBase views; struct OCIO_ConstProcessorRcPtr *to_scene_linear; @@ -62,7 +65,7 @@ typedef struct ColorManagedDisplay { typedef struct ColorManagedView { struct ColorManagedView *next, *prev; int index; - char name[64]; + char name[MAX_COLORSPACE_NAME]; } ColorManagedView; /* ** Initialization / De-initialization ** */ diff --git a/source/blender/imbuf/intern/IMB_indexer.h b/source/blender/imbuf/intern/IMB_indexer.h index 9c95531e90d..d114df945ae 100644 --- a/source/blender/imbuf/intern/IMB_indexer.h +++ b/source/blender/imbuf/intern/IMB_indexer.h @@ -116,9 +116,6 @@ void IMB_indexer_close(struct anim_index * idx); void IMB_free_indices(struct anim * anim); -int IMB_anim_index_get_frame_index( - struct anim *anim, IMB_Timecode_Type tc, int position); - struct anim *IMB_anim_open_proxy( struct anim *anim, IMB_Proxy_Size preview_size); struct anim_index * IMB_anim_open_index( diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c index 8d79482ed18..4ef1f962a0f 100644 --- a/source/blender/imbuf/intern/anim_movie.c +++ b/source/blender/imbuf/intern/anim_movie.c @@ -64,9 +64,9 @@ #include <io.h> #endif +#include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_path_util.h" -#include "BLI_utildefines.h" #include "BLI_math_base.h" #include "MEM_guardedalloc.h" @@ -822,10 +822,10 @@ static int ffmpeg_decode_video_frame(struct anim *anim) if (rval == AVERROR_EOF) { /* this sets size and data fields to zero, - which is necessary to decode the remaining data - in the decoder engine after EOF. It also prevents a memory - leak, since av_read_frame spills out a full size packet even - on EOF... (and: it's save to call on NULL packets) */ + * which is necessary to decode the remaining data + * in the decoder engine after EOF. It also prevents a memory + * leak, since av_read_frame spills out a full size packet even + * on EOF... (and: it's save to call on NULL packets) */ av_free_packet(&anim->next_packet); diff --git a/source/blender/imbuf/intern/bmp.c b/source/blender/imbuf/intern/bmp.c index 32733668052..856124ab5cb 100644 --- a/source/blender/imbuf/intern/bmp.c +++ b/source/blender/imbuf/intern/bmp.c @@ -29,6 +29,7 @@ * \ingroup imbuf */ +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "imbuf.h" @@ -60,6 +61,7 @@ typedef struct BMPINFOHEADER { unsigned int biClrImportant; } BMPINFOHEADER; +#if 0 typedef struct BMPHEADER { unsigned short biType; unsigned int biSize; @@ -67,6 +69,7 @@ typedef struct BMPHEADER { unsigned short biRes2; unsigned int biOffBits; } BMPHEADER; +#endif #define BMP_FILEHEADER_SIZE 14 @@ -125,6 +128,7 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co int x, y, depth, skip, i; unsigned char *bmp, *rect; unsigned short col; + double xppm, yppm; (void)size; /* unused */ @@ -144,6 +148,8 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co x = LITTLE_LONG(bmi.biWidth); y = LITTLE_LONG(bmi.biHeight); depth = LITTLE_SHORT(bmi.biBitCount); + xppm = LITTLE_LONG(bmi.biXPelsPerMeter); + yppm = LITTLE_LONG(bmi.biYPelsPerMeter); #if 0 printf("skip: %d, x: %d y: %d, depth: %d (%x)\n", skip, x, y, @@ -199,6 +205,8 @@ struct ImBuf *imb_bmp_decode(unsigned char *mem, size_t size, int flags, char co } if (ibuf) { + ibuf->ppm[0] = xppm; + ibuf->ppm[1] = yppm; ibuf->ftype = BMP; } @@ -250,8 +258,8 @@ int imb_savebmp(struct ImBuf *ibuf, const char *name, int flags) putShortLSB(24, ofile); putIntLSB(0, ofile); putIntLSB(bytesize + BMP_FILEHEADER_SIZE + sizeof(infoheader), ofile); - putIntLSB(0, ofile); - putIntLSB(0, ofile); + putIntLSB((int)(ibuf->ppm[0] + 0.5), ofile); + putIntLSB((int)(ibuf->ppm[1] + 0.5), ofile); putIntLSB(0, ofile); putIntLSB(0, ofile); diff --git a/source/blender/imbuf/intern/cineon/cineon_dpx.c b/source/blender/imbuf/intern/cineon/cineon_dpx.c index ba84063f317..48bda418d82 100644 --- a/source/blender/imbuf/intern/cineon/cineon_dpx.c +++ b/source/blender/imbuf/intern/cineon/cineon_dpx.c @@ -70,30 +70,23 @@ static struct ImBuf *imb_load_dpx_cineon(unsigned char *mem, size_t size, int us logImageGetSize(image, &width, &height, &depth); - if (width == 0 || height == 0) { - logImageClose(image); - return 0; - } - ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat | flags); if (ibuf == 0) { logImageClose(image); return 0; } - if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { - /* Conversion not possible (probably because the format is unsupported) */ - logImageClose(image); - MEM_freeN(ibuf); - return 0; + if (!(flags & IB_test)) { + if (logImageGetDataRGBA(image, ibuf->rect_float, 1) != 0) { + logImageClose(image); + IMB_freeImBuf(ibuf); + return 0; + } + IMB_flipy(ibuf); } logImageClose(image); ibuf->ftype = use_cineon ? CINEON : DPX; - IMB_flipy(ibuf); - - if (flags & IB_rect) - IMB_rect_from_float(ibuf); if (flags & IB_alphamode_detect) ibuf->flags |= IB_alphamode_premul; @@ -141,7 +134,7 @@ static int imb_save_dpx_cineon(ImBuf *ibuf, const char *filename, int use_cineon if (ibuf->rect_float != 0 && bitspersample != 8) { /* don't use the float buffer to save 8 bpp picture to prevent color banding - (there's no dithering algorithm behing the logImageSetDataRGBA function) */ + * (there's no dithering algorithm behing the logImageSetDataRGBA function) */ fbuf = (float *)MEM_mallocN(ibuf->x * ibuf->y * 4 * sizeof(float), "fbuf in imb_save_dpx_cineon"); diff --git a/source/blender/imbuf/intern/cineon/cineonlib.c b/source/blender/imbuf/intern/cineon/cineonlib.c index b858251a6b9..4b9ca1dd539 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.c +++ b/source/blender/imbuf/intern/cineon/cineonlib.c @@ -196,6 +196,13 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t cineon->width = swap_uint(header.imageHeader.element[0].pixels_per_line, cineon->isMSB); cineon->height = swap_uint(header.imageHeader.element[0].lines_per_image, cineon->isMSB); + + if (cineon->width == 0 || cineon->height == 0) { + if (verbose) printf("Cineon: Wrong image dimension: %dx%d\n", cineon->width, cineon->height); + logImageClose(cineon); + return 0; + } + cineon->depth = header.imageHeader.elements_per_image; cineon->srcFormat = format_Cineon; @@ -205,6 +212,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t cineon->numElements = header.imageHeader.elements_per_image; else { if (verbose) printf("Cineon: Data interleave not supported: %d\n", header.imageHeader.interleave); + logImageClose(cineon); return 0; } @@ -235,6 +243,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t } else { if (verbose) printf("Cineon: Cineon image depth unsupported: %d\n", cineon->depth); + logImageClose(cineon); return 0; } @@ -264,6 +273,7 @@ LogImageFile *cineonOpen(const unsigned char *byteStuff, int fromMemory, size_t default: /* Not supported */ if (verbose) printf("Cineon: packing unsupported: %d\n", header.imageHeader.packing); + logImageClose(cineon); return 0; } diff --git a/source/blender/imbuf/intern/cineon/dpxlib.c b/source/blender/imbuf/intern/cineon/dpxlib.c index aeebf46a632..10c90b1b891 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.c +++ b/source/blender/imbuf/intern/cineon/dpxlib.c @@ -192,8 +192,21 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf dpx->srcFormat = format_DPX; dpx->numElements = swap_ushort(header.imageHeader.elements_per_image, dpx->isMSB); + if (dpx->numElements == 0) { + if (verbose) printf("DPX: Wrong number of elements: %d\n", dpx->numElements); + logImageClose(dpx); + return 0; + } + dpx->width = swap_uint(header.imageHeader.pixels_per_line, dpx->isMSB); dpx->height = swap_uint(header.imageHeader.lines_per_element, dpx->isMSB); + + if (dpx->width == 0 || dpx->height == 0) { + if (verbose) printf("DPX: Wrong image dimension: %dx%d\n", dpx->width, dpx->height); + logImageClose(dpx); + return 0; + } + dpx->depth = 0; for (i = 0; i < dpx->numElements; i++) { @@ -242,8 +255,23 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf } dpx->element[i].bitsPerSample = header.imageHeader.element[i].bits_per_sample; + if (dpx->element[i].bitsPerSample != 1 && dpx->element[i].bitsPerSample != 8 && + dpx->element[i].bitsPerSample != 10 && dpx->element[i].bitsPerSample != 12 && + dpx->element[i].bitsPerSample != 16) + { + if (verbose) printf("DPX: Unsupported bitsPerSample for elements %d: %d\n", i, dpx->element[i].bitsPerSample); + logImageClose(dpx); + return 0; + } + dpx->element[i].maxValue = powf(2, dpx->element[i].bitsPerSample) - 1.0f; + dpx->element[i].packing = swap_ushort(header.imageHeader.element[i].packing, dpx->isMSB); + if (dpx->element[i].packing > 2) { + if (verbose) printf("DPX: Unsupported packing for element %d: %d\n", i, dpx->element[i].packing); + logImageClose(dpx); + return 0; + } /* Sometimes, the offset is not set correctly in the header */ dpx->element[i].dataOffset = swap_uint(header.imageHeader.element[i].data_offset, dpx->isMSB); @@ -323,7 +351,6 @@ LogImageFile *dpxOpen(const unsigned char *byteStuff, int fromMemory, size_t buf (dpx->referenceWhite == DPX_UNDEFINED_R32 || dpx->referenceWhite <= dpx->referenceBlack || isnan(dpx->referenceWhite)) || (dpx->gamma == DPX_UNDEFINED_R32 || dpx->gamma <= 0 || isnan(dpx->gamma))) { - dpx->referenceBlack = 95.0f / 1023.0f * dpx->element[0].maxValue; dpx->referenceWhite = 685.0f / 1023.0f * dpx->element[0].maxValue; dpx->gamma = 1.7f; diff --git a/source/blender/imbuf/intern/cineon/logImageCore.c b/source/blender/imbuf/intern/cineon/logImageCore.c index 3911e5c2ef3..332ad913d19 100644 --- a/source/blender/imbuf/intern/cineon/logImageCore.c +++ b/source/blender/imbuf/intern/cineon/logImageCore.c @@ -374,7 +374,7 @@ int logImageGetDataRGBA(LogImageFile *logImage, float *data, int dataIsLinearRGB LogImageElement mergedElement; /* Determine the depth of the picture and if there's a separate alpha element. - If the element is supported, load it into an unsigned ints array. */ + * If the element is supported, load it into an unsigned ints array. */ memset(&elementData, 0, 8 * sizeof(float *)); hasAlpha = 0; diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index cfeacff7f4a..505ba2599df 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -71,7 +71,6 @@ /*********************** Global declarations *************************/ -#define MAX_COLORSPACE_NAME 64 #define DISPLAY_BUFFER_CHANNELS 4 /* ** list of all supported color spaces, displays and views */ @@ -1700,7 +1699,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int { ImBuf *colormanaged_ibuf = ibuf; int do_colormanagement; - int is_movie = BKE_imtype_is_movie(image_format_data->imtype); + bool is_movie = BKE_imtype_is_movie(image_format_data->imtype); int requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype); int do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA; @@ -1854,6 +1853,14 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet applied_view_settings = &default_view_settings; } + /* early out: no float buffer and byte buffer is already in display space, + * let's just use if + */ + if (ibuf->rect_float == NULL && ibuf->rect_colorspace) { + if (is_ibuf_rect_in_display_space(ibuf, applied_view_settings, display_settings)) + return (unsigned char *) ibuf->rect; + } + colormanage_view_settings_to_cache(&cache_view_settings, applied_view_settings); colormanage_display_settings_to_cache(&cache_display_settings, display_settings); diff --git a/source/blender/imbuf/intern/dds/BlockDXT.cpp b/source/blender/imbuf/intern/dds/BlockDXT.cpp index db2ca5969ec..348e1e9f53a 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.cpp +++ b/source/blender/imbuf/intern/dds/BlockDXT.cpp @@ -250,7 +250,7 @@ void BlockDXT1::decodeBlockNV5x(ColorBlock * block) const } } -void BlockDXT1::setIndices(int * idx) +void BlockDXT1::setIndices(int *idx) { indices = 0; for (uint i = 0; i < 16; i++) { @@ -595,7 +595,7 @@ void BlockCTX1::decodeBlock(ColorBlock * block) const } } -void BlockCTX1::setIndices(int * idx) +void BlockCTX1::setIndices(int *idx) { indices = 0; for (uint i = 0; i < 16; i++) { diff --git a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp index ccf72f9af86..df15cb3e357 100644 --- a/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp +++ b/source/blender/imbuf/intern/dds/DirectDrawSurface.cpp @@ -1092,7 +1092,7 @@ void DirectDrawSurface::setUserVersion(int version) header.setUserVersion(version); } -void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap) +void DirectDrawSurface::mipmap(Image *img, uint face, uint mipmap) { stream.seek(offset(face, mipmap)); @@ -1158,7 +1158,7 @@ void* DirectDrawSurface::readData(uint &rsize) return data; } -void DirectDrawSurface::readLinearImage(Image * img) +void DirectDrawSurface::readLinearImage(Image *img) { const uint w = img->width(); @@ -1204,7 +1204,7 @@ void DirectDrawSurface::readLinearImage(Image * img) } } -void DirectDrawSurface::readBlockImage(Image * img) +void DirectDrawSurface::readBlockImage(Image *img) { const uint w = img->width(); @@ -1246,7 +1246,7 @@ static Color32 buildNormal(uint8 x, uint8 y) } -void DirectDrawSurface::readBlock(ColorBlock * rgba) +void DirectDrawSurface::readBlock(ColorBlock *rgba) { uint fourcc = header.pf.fourcc; diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index 660643530ba..4f63d17dc90 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -241,7 +241,7 @@ int FlipDXTCImage(unsigned int width, unsigned int height, unsigned int levels, memcpy(line2, temp_line, row_bytes); } - delete temp_line; + delete[] temp_line; } // mip levels are contiguous. diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 56e5be7c12a..002ffd409a2 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -361,17 +361,16 @@ int IMB_timecode_to_array_index(IMB_Timecode_Type tc) * - rebuild helper functions * ---------------------------------------------------------------------- */ -static void get_index_dir(struct anim *anim, char *index_dir) +static void get_index_dir(struct anim *anim, char *index_dir, size_t index_dir_len) { if (!anim->index_dir[0]) { char fname[FILE_MAXFILE]; - BLI_strncpy(index_dir, anim->name, FILE_MAXDIR); - BLI_splitdirstring(index_dir, fname); - BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, "BL_proxy"); - BLI_join_dirfile(index_dir, FILE_MAXDIR, index_dir, fname); + BLI_split_dirfile(anim->name, index_dir, fname, index_dir_len, sizeof(fname)); + BLI_join_dirfile(index_dir, index_dir_len, index_dir, "BL_proxy"); + BLI_join_dirfile(index_dir, index_dir_len, index_dir, fname); } else { - BLI_strncpy(index_dir, anim->index_dir, FILE_MAXDIR); + BLI_strncpy(index_dir, anim->index_dir, index_dir_len); } } @@ -396,7 +395,7 @@ static void get_proxy_filename(struct anim *anim, IMB_Proxy_Size preview_size, BLI_snprintf(proxy_temp_name, sizeof(proxy_temp_name), "proxy_%d%s_part.avi", (int) (proxy_fac[i] * 100), stream_suffix); - get_index_dir(anim, index_dir); + get_index_dir(anim, index_dir, sizeof(index_dir)); BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, temp ? proxy_temp_name : proxy_name); @@ -425,7 +424,7 @@ static void get_tc_filename(struct anim *anim, IMB_Timecode_Type tc, BLI_snprintf(index_name, 256, index_names[i], stream_suffix); - get_index_dir(anim, index_dir); + get_index_dir(anim, index_dir, sizeof(index_dir)); BLI_join_dirfile(fname, FILE_MAXFILE + FILE_MAXDIR, index_dir, index_name); @@ -492,7 +491,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg( rv->of = avformat_alloc_context(); rv->of->oformat = av_guess_format("avi", NULL, NULL); - BLI_snprintf(rv->of->filename, sizeof(rv->of->filename), "%s", fname); + BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename)); fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename); diff --git a/source/blender/imbuf/intern/iris.c b/source/blender/imbuf/intern/iris.c index 47bd3e54a6f..ac1bb246dce 100644 --- a/source/blender/imbuf/intern/iris.c +++ b/source/blender/imbuf/intern/iris.c @@ -32,6 +32,7 @@ #include <string.h> +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 6a5b534c688..bf0e4187aa6 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -37,6 +37,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_fileops.h" @@ -120,10 +121,12 @@ static void jpeg_error(j_common_ptr cinfo) * INPUT HANDLER FROM MEMORY *---------------------------------------------------------- */ +#if 0 typedef struct { unsigned char *buffer; int filled; } buffer_struct; +#endif typedef struct { struct jpeg_source_mgr pub; /* public fields */ diff --git a/source/blender/imbuf/intern/moviecache.c b/source/blender/imbuf/intern/moviecache.c index d5aa635f548..a168c9c3051 100644 --- a/source/blender/imbuf/intern/moviecache.c +++ b/source/blender/imbuf/intern/moviecache.c @@ -145,7 +145,7 @@ static void check_unused_keys(MovieCache *cache) GHashIterator *iter; iter = BLI_ghashIterator_new(cache->hash); - while (!BLI_ghashIterator_isDone(iter)) { + while (BLI_ghashIterator_notDone(iter)) { MovieCacheKey *key = BLI_ghashIterator_getKey(iter); MovieCacheItem *item = BLI_ghashIterator_getValue(iter); int remove = 0; @@ -408,7 +408,7 @@ void IMB_moviecache_cleanup(MovieCache *cache, int (cleanup_check_cb) (void *use GHashIterator *iter; iter = BLI_ghashIterator_new(cache->hash); - while (!BLI_ghashIterator_isDone(iter)) { + while (BLI_ghashIterator_notDone(iter)) { MovieCacheKey *key = BLI_ghashIterator_getKey(iter); int remove; @@ -457,7 +457,7 @@ void IMB_moviecache_get_cache_segments(MovieCache *cache, int proxy, int render_ iter = BLI_ghashIterator_new(cache->hash); a = 0; - while (!BLI_ghashIterator_isDone(iter)) { + while (BLI_ghashIterator_notDone(iter)) { MovieCacheKey *key = BLI_ghashIterator_getKey(iter); MovieCacheItem *item = BLI_ghashIterator_getValue(iter); int framenr, curproxy, curflags; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index 1b7aa1e7e63..043bb8da83c 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -85,6 +85,7 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include <ImfCompression.h> #include <ImfCompressionAttribute.h> #include <ImfStringAttribute.h> +#include <ImfStandardAttributes.h> using namespace Imf; using namespace Imath; @@ -302,6 +303,9 @@ static void openexr_header_metadata(Header *header, struct ImBuf *ibuf) for (info = ibuf->metadata; info; info = info->next) header->insert(info->key, StringAttribute(info->value)); + + if (ibuf->ppm[0] > 0.0f) + addXDensity(*header, ibuf->ppm[0] / 39.3700787f); /* 1 meter = 39.3700787 inches */ } static int imb_save_openexr_half(struct ImBuf *ibuf, const char *name, int flags) @@ -886,6 +890,8 @@ static int imb_exr_split_channel_name(ExrChannel *echan, char *layname, char *pa /* some multilayers have the combined buffer with names A B G R saved */ if (name[1] == 0) { echan->chan_id = name[0]; + layname[0] = '\0'; + strcpy(passname, "Combined"); return 1; } @@ -1142,6 +1148,12 @@ struct ImBuf *imb_load_openexr(unsigned char *mem, size_t size, int flags, char const int is_alpha = exr_has_alpha(file); ibuf = IMB_allocImBuf(width, height, is_alpha ? 32 : 24, 0); + + if (hasXDensity(file->header())) { + ibuf->ppm[0] = xDensity(file->header()) * 39.3700787f; + ibuf->ppm[1] = ibuf->ppm[0] * file->header().pixelAspectRatio(); + } + ibuf->ftype = OPENEXR; if (!(flags & IB_test)) { diff --git a/source/blender/imbuf/intern/png.c b/source/blender/imbuf/intern/png.c index 68385f22a7a..a7e05612472 100644 --- a/source/blender/imbuf/intern/png.c +++ b/source/blender/imbuf/intern/png.c @@ -33,6 +33,7 @@ #include "png.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_math.h" diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index d09adeb09b5..d45438e2853 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -43,6 +43,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "imbuf.h" @@ -318,7 +319,9 @@ static int fwritecolrs(FILE *file, int width, int channels, unsigned char *ibufs putc((unsigned char)(128 + cnt), file); putc(rgbe_scan[beg][i], file); } - else cnt = 0; + else { + cnt = 0; + } } } MEM_freeN(rgbe_scan); diff --git a/source/blender/imbuf/intern/readimage.c b/source/blender/imbuf/intern/readimage.c index 4d47d883444..d73fa9a7ab7 100644 --- a/source/blender/imbuf/intern/readimage.c +++ b/source/blender/imbuf/intern/readimage.c @@ -43,12 +43,11 @@ #endif #include <stdlib.h> +#include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLI_utildefines.h" - #include "imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 0b739b9fe92..8b60d1a96df 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -121,6 +121,27 @@ static void blend_color_darken(char cp[3], const char cp1[3], const char cp2[3], } } +static void blend_color_erase_alpha(char cp[4], const char cp1[4], const char cp2[4], const int fac) +{ + int temp = (cp1[3] - fac * cp2[3] / 255); + + cp[0] = cp1[0]; + cp[1] = cp1[1]; + cp[2] = cp1[2]; + cp[3] = (temp < 0) ? 0 : temp; +} + +static void blend_color_add_alpha(char cp[4], const char cp1[4], const char cp2[4], const int fac) +{ + int temp = (cp1[3] + fac * cp2[3] / 255); + + cp[0] = cp1[0]; + cp[1] = cp1[1]; + cp[2] = cp1[2]; + cp[3] = (temp < 0) ? 0 : temp; +} + + unsigned int IMB_blend_color(unsigned int src1, unsigned int src2, int fac, IMB_BlendMode mode) { unsigned int dst; @@ -230,6 +251,26 @@ static void blend_color_darken_float(float cp[3], const float cp1[3], const floa blend_color_mix_float(cp, cp1, cp2, fac); } +static void blend_color_erase_alpha_float(float cp[4], const float cp1[4], const float cp2[4], const float fac) +{ + cp[0] = cp1[0]; + cp[1] = cp1[1]; + cp[2] = cp1[2]; + + cp[3] = (cp1[3] - fac * cp2[3]); + if (cp[3] < 0.0f) cp[3] = 0.0f; +} + +static void blend_color_add_alpha_float(float cp[4], const float cp1[4], const float cp2[4], const float fac) +{ + cp[0] = cp1[0]; + cp[1] = cp1[1]; + cp[2] = cp1[2]; + + cp[3] = (cp1[3] + fac * cp2[3]); + if (cp[3] < 0.0f) cp[3] = 0.0f; +} + void IMB_blend_color_float(float *dst, float *src1, float *src2, float fac, IMB_BlendMode mode) { if (fac == 0) { @@ -326,12 +367,18 @@ void IMB_rectcpy(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, IMB_BLEND_COPY); } +typedef void (*IMB_blend_func)(char *dst, const char *src1, const char *src2, const int fac); +typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2, const float fac); + + void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height, IMB_BlendMode mode) { unsigned int *drect = NULL, *srect = NULL, *dr, *sr; float *drectf = NULL, *srectf = NULL, *drf, *srf; int do_float, do_char, srcskip, destskip, x; + IMB_blend_func func = NULL; + IMB_blend_func_float func_float = NULL; if (dbuf == NULL) return; @@ -427,13 +474,52 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, } } else { + switch (mode) { + case IMB_BLEND_MIX: + func = blend_color_mix; + func_float = blend_color_mix_float; + break; + case IMB_BLEND_ADD: + func = blend_color_add; + func_float = blend_color_add_float; + break; + case IMB_BLEND_SUB: + func = blend_color_sub; + func_float = blend_color_sub_float; + break; + case IMB_BLEND_MUL: + func = blend_color_mul; + func_float = blend_color_mul_float; + break; + case IMB_BLEND_LIGHTEN: + func = blend_color_lighten; + func_float = blend_color_lighten_float; + break; + case IMB_BLEND_DARKEN: + func = blend_color_darken; + func_float = blend_color_darken_float; + break; + case IMB_BLEND_ERASE_ALPHA: + func = blend_color_erase_alpha; + func_float = blend_color_erase_alpha_float; + break; + case IMB_BLEND_ADD_ALPHA: + func = blend_color_add_alpha; + func_float = blend_color_add_alpha_float; + break; + default: + break; + } + /* blend */ for (; height > 0; height--) { if (do_char) { dr = drect; sr = srect; - for (x = width; x > 0; x--, dr++, sr++) - *dr = IMB_blend_color(*dr, *sr, ((char *)sr)[3], mode); + for (x = width; x > 0; x--, dr++, sr++) { + if (*sr & IB_ALPHA_MASK) + func((char *)dr, (char *)dr, (char *)sr, ((char *)sr)[3]); + } drect += destskip; srect += srcskip; @@ -442,9 +528,10 @@ void IMB_rectblend(struct ImBuf *dbuf, struct ImBuf *sbuf, int destx, if (do_float) { drf = drectf; srf = srectf; - for (x = width; x > 0; x--, drf += 4, srf += 4) - IMB_blend_color_float(drf, drf, srf, srf[3], mode); - + for (x = width; x > 0; x--, drf += 4, srf += 4) { + if (srf[3] != 0) + func_float(drf, drf, srf, srf[3]); + } drectf += destskip * 4; srectf += srcskip * 4; } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 1050d3f8715..51619e18980 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -34,6 +34,7 @@ #include "BLI_utildefines.h" #include "BLI_math_color.h" +#include "BLI_math_interp.h" #include "MEM_guardedalloc.h" #include "imbuf.h" @@ -1604,3 +1605,113 @@ struct ImBuf *IMB_scalefastImBuf(struct ImBuf *ibuf, unsigned int newx, unsigned return(ibuf); } +/* ******** threaded scaling ******** */ + +typedef struct ScaleTreadInitData { + ImBuf *ibuf; + + unsigned int newx; + unsigned int newy; + + unsigned char *byte_buffer; + float *float_buffer; +} ScaleTreadInitData; + +typedef struct ScaleThreadData { + ImBuf *ibuf; + + unsigned int newx; + unsigned int newy; + + int start_line; + int tot_line; + + unsigned char *byte_buffer; + float *float_buffer; +} ScaleThreadData; + +static void scale_thread_init(void *data_v, int start_line, int tot_line, void *init_data_v) +{ + ScaleThreadData *data = (ScaleThreadData *) data_v; + ScaleTreadInitData *init_data = (ScaleTreadInitData *) init_data_v; + + data->ibuf = init_data->ibuf; + + data->newx = init_data->newx; + data->newy = init_data->newy; + + data->start_line = start_line; + data->tot_line = tot_line; + + data->byte_buffer = init_data->byte_buffer; + data->float_buffer = init_data->float_buffer; +} + +static void *do_scale_thread(void *data_v) +{ + ScaleThreadData *data = (ScaleThreadData *) data_v; + ImBuf *ibuf = data->ibuf; + int i; + float factor_x = (float) ibuf->x / data->newx; + float factor_y = (float) ibuf->y / data->newy; + + for (i = 0; i < data->tot_line; i++) { + int y = data->start_line + i; + int x; + + for (x = 0; x < data->newx; x++) { + float u = (float) x * factor_x; + float v = (float) y * factor_y; + int offset = y * data->newx + x; + + if (data->byte_buffer) { + unsigned char *pixel = data->byte_buffer + 4 * offset; + BLI_bilinear_interpolation_char((unsigned char *) ibuf->rect, pixel, ibuf->x, ibuf->y, 4, u, v); + } + + if (data->float_buffer) { + float *pixel = data->float_buffer + ibuf->channels * offset; + BLI_bilinear_interpolation_fl(ibuf->rect_float, pixel, ibuf->x, ibuf->y, ibuf->channels, u, v); + } + } + } + + return NULL; +} + +void IMB_scaleImBuf_threaded(ImBuf *ibuf, unsigned int newx, unsigned int newy) +{ + ScaleTreadInitData init_data = {0}; + + /* prepare initialization data */ + init_data.ibuf = ibuf; + + init_data.newx = newx; + init_data.newy = newy; + + if (ibuf->rect) + init_data.byte_buffer = MEM_mallocN(4 * newx * newy * sizeof(char), "threaded scale byte buffer"); + + if (ibuf->rect_float) + init_data.float_buffer = MEM_mallocN(ibuf->channels * newx * newy * sizeof(float), "threaded scale float buffer"); + + /* actual scaling threads */ + IMB_processor_apply_threaded(newy, sizeof(ScaleThreadData), &init_data, + scale_thread_init, do_scale_thread); + + /* alter image buffer */ + ibuf->x = newx; + ibuf->y = newy; + + if (ibuf->rect) { + imb_freerectImBuf(ibuf); + ibuf->mall |= IB_rect; + ibuf->rect = (unsigned int *) init_data.byte_buffer; + } + + if (ibuf->rect_float) { + imb_freerectfloatImBuf(ibuf); + ibuf->mall |= IB_rectfloat; + ibuf->rect_float = init_data.float_buffer; + } +} diff --git a/source/blender/imbuf/intern/targa.c b/source/blender/imbuf/intern/targa.c index eaad77f1ff9..0c30af60388 100644 --- a/source/blender/imbuf/intern/targa.c +++ b/source/blender/imbuf/intern/targa.c @@ -34,6 +34,7 @@ # include <io.h> #endif +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "MEM_guardedalloc.h" @@ -76,8 +77,8 @@ static int tga_out1(unsigned int data, FILE *file) uchar *p; p = (uchar *) &data; - if (putc(p[0], file) == EOF) return(EOF); - return (~EOF); + if (putc(p[0], file) == EOF) return EOF; + return ~EOF; } static int tga_out2(unsigned int data, FILE *file) @@ -85,9 +86,9 @@ static int tga_out2(unsigned int data, FILE *file) uchar *p; p = (uchar *) &data; - if (putc(p[0], file) == EOF) return(EOF); - if (putc(p[1], file) == EOF) return(EOF); - return (~EOF); + if (putc(p[0], file) == EOF) return EOF; + if (putc(p[1], file) == EOF) return EOF; + return ~EOF; } @@ -96,10 +97,10 @@ static int tga_out3(unsigned int data, FILE *file) uchar *p; p = (uchar *) &data; - if (putc(p[2], file) == EOF) return(EOF); - if (putc(p[1], file) == EOF) return(EOF); - if (putc(p[0], file) == EOF) return(EOF); - return (~EOF); + if (putc(p[2], file) == EOF) return EOF; + if (putc(p[1], file) == EOF) return EOF; + if (putc(p[0], file) == EOF) return EOF; + return ~EOF; } @@ -109,11 +110,11 @@ static int tga_out4(unsigned int data, FILE *file) p = (uchar *) &data; /* order = bgra */ - if (putc(p[2], file) == EOF) return(EOF); - if (putc(p[1], file) == EOF) return(EOF); - if (putc(p[0], file) == EOF) return(EOF); - if (putc(p[3], file) == EOF) return(EOF); - return (~EOF); + if (putc(p[2], file) == EOF) return EOF; + if (putc(p[1], file) == EOF) return EOF; + if (putc(p[0], file) == EOF) return EOF; + if (putc(p[3], file) == EOF) return EOF; + return ~EOF; } static short makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE *)) @@ -153,9 +154,9 @@ static short makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE last = copy; if (copy >= 128) last = 128; copy -= last; - if (fputc(last - 1, file) == EOF) return(0); + if (fputc(last - 1, file) == EOF) return 0; do { - if (out(*rect++, file) == EOF) return(0); + if (out(*rect++, file) == EOF) return 0; } while (--last != 0); } rectstart = rect; @@ -176,23 +177,23 @@ static short makebody_tga(ImBuf *ibuf, FILE *file, int (*out)(unsigned int, FILE while (copy) { if (copy > 128) { - if (fputc(255, file) == EOF) return(0); + if (fputc(255, file) == EOF) return 0; copy -= 128; } else { if (copy == 1) { - if (fputc(0, file) == EOF) return(0); + if (fputc(0, file) == EOF) return 0; } - else if (fputc(127 + copy, file) == EOF) return(0); + else if (fputc(127 + copy, file) == EOF) return 0; copy = 0; } - if (out(last, file) == EOF) return(0); + if (out(last, file) == EOF) return 0; } copy = TRUE; } } } - return (1); + return 1; } static int dumptarga(struct ImBuf *ibuf, FILE *file) @@ -200,15 +201,15 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file) int size; uchar *rect; - if (ibuf == NULL) return (0); - if (ibuf->rect == NULL) return (0); + if (ibuf == NULL) return 0; + if (ibuf->rect == NULL) return 0; size = ibuf->x * ibuf->y; rect = (uchar *) ibuf->rect; if (ibuf->planes <= 8) { while (size > 0) { - if (putc(*rect, file) == EOF) return (0); + if (putc(*rect, file) == EOF) return 0; size--; rect += 4; } @@ -216,7 +217,7 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file) else if (ibuf->planes <= 16) { while (size > 0) { putc(rect[0], file); - if (putc(rect[1], file) == EOF) return (0); + if (putc(rect[1], file) == EOF) return 0; size--; rect += 4; } @@ -225,7 +226,7 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file) while (size > 0) { putc(rect[2], file); putc(rect[1], file); - if (putc(rect[0], file) == EOF) return (0); + if (putc(rect[0], file) == EOF) return 0; size--; rect += 4; } @@ -235,14 +236,16 @@ static int dumptarga(struct ImBuf *ibuf, FILE *file) putc(rect[2], file); putc(rect[1], file); putc(rect[0], file); - if (putc(rect[3], file) == EOF) return (0); + if (putc(rect[3], file) == EOF) return 0; size--; rect += 4; } } - else return (0); - - return (1); + else { + return 0; + } + + return 1; } @@ -284,7 +287,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags) if (fwrite(buf, 1, 18, fildes) != 18) { fclose(fildes); - return (0); + return 0; } if (ibuf->ftype == RAWTGA) { @@ -308,7 +311,7 @@ int imb_savetarga(struct ImBuf *ibuf, const char *name, int flags) } fclose(fildes); - return (ok); + return ok; } @@ -328,7 +331,7 @@ static int checktarga(TARGA *tga, unsigned char *mem) tga->pixsize = mem[16]; tga->imgdes = mem[17]; - if (tga->maptyp > 1) return(0); + if (tga->maptyp > 1) return 0; switch (tga->imgtyp) { case 1: /* raw cmap */ case 2: /* raw rgb */ @@ -338,14 +341,14 @@ static int checktarga(TARGA *tga, unsigned char *mem) case 11: /* b&w */ break; default: - return(0); + return 0; } - if (tga->mapsize && tga->mapbits > 32) return(0); - if (tga->xsize <= 0 || tga->xsize >= 8192) return(0); - if (tga->ysize <= 0 || tga->ysize >= 8192) return(0); - if (tga->pixsize > 32) return(0); - if (tga->pixsize == 0) return(0); - return(1); + if (tga->mapsize && tga->mapbits > 32) return 0; + if (tga->xsize <= 0 || tga->xsize >= 8192) return 0; + if (tga->ysize <= 0 || tga->ysize >= 8192) return 0; + if (tga->pixsize > 32) return 0; + if (tga->pixsize == 0) return 0; + return 1; } int imb_is_a_targa(unsigned char *buf) @@ -556,14 +559,16 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors unsigned int *rect, *cmap = NULL /*, mincol = 0*/, maxcol = 0; uchar *cp = (uchar *) &col; - if (checktarga(&tga, mem) == 0) return(NULL); + if (checktarga(&tga, mem) == 0) { + return NULL; + } colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE); if (flags & IB_test) ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, tga.pixsize, 0); else ibuf = IMB_allocImBuf(tga.xsize, tga.ysize, (tga.pixsize + 0x7) & ~0x7, IB_rect); - if (ibuf == NULL) return(NULL); + if (ibuf == NULL) return NULL; ibuf->ftype = TGA; mem = mem + 18 + tga.numid; @@ -612,7 +617,9 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors } } - if (flags & IB_test) return (ibuf); + if (flags & IB_test) { + return ibuf; + } if (tga.imgtyp != 1 && tga.imgtyp != 9) { /* happens sometimes (beuh) */ if (cmap) { @@ -692,5 +699,5 @@ ImBuf *imb_loadtarga(unsigned char *mem, size_t mem_size, int flags, char colors if (ibuf->rect) IMB_convert_rgba_to_abgr(ibuf); - return(ibuf); + return ibuf; } diff --git a/source/blender/imbuf/intern/thumbs.c b/source/blender/imbuf/intern/thumbs.c index c1d80ad9067..51c6c2fc2d9 100644 --- a/source/blender/imbuf/intern/thumbs.c +++ b/source/blender/imbuf/intern/thumbs.c @@ -34,6 +34,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_path_util.h" #include "BLI_fileops.h" @@ -422,7 +423,7 @@ void IMB_thumb_delete(const char *path, ThumbSize size) return; } if (BLI_exists(thumb)) { - BLI_delete(thumb, 0, 0); + BLI_delete(thumb, false, false); } } } @@ -447,7 +448,7 @@ ImBuf *IMB_thumb_manage(const char *path, ThumbSize size, ThumbSource source) if (BLI_exists(thumb)) { /* clear out of date fail case */ if (BLI_file_older(thumb, path)) { - BLI_delete(thumb, 0, 0); + BLI_delete(thumb, false, false); } else { return NULL; diff --git a/source/blender/imbuf/intern/util.c b/source/blender/imbuf/intern/util.c index 549a95e383d..68d1c906a1f 100644 --- a/source/blender/imbuf/intern/util.c +++ b/source/blender/imbuf/intern/util.c @@ -41,9 +41,9 @@ #include <stdlib.h> +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLI_utildefines.h" #include "BLI_string.h" #include "DNA_userdef_types.h" diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 62d696ec255..147791b4835 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -71,6 +71,8 @@ typedef struct Brush { int size; /* brush diameter */ int flag; /* general purpose flag */ float jitter; /* jitter the position of the brush */ + int jitter_absolute; /* absolute jitter in pixels */ + int pad; int spacing; /* spacing of paint operations */ int smooth_stroke_radius; /* turning radius (in pixels) for smooth stroke */ float smooth_stroke_factor; /* higher values limit fast changes in the stroke direction */ @@ -137,7 +139,8 @@ typedef enum BrushFlags { /* temporary flag which sets up automatically for correct brush * drawing when inverted modal operator is running */ - BRUSH_INVERTED = (1 << 29) + BRUSH_INVERTED = (1 << 29), + BRUSH_ABSOLUTE_JITTER = (1 << 30) } BrushFlags; /* Brush.sculpt_tool */ diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index ac75b03c742..96d71288c62 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -71,6 +71,8 @@ void *DNA_struct_reconstruct(struct SDNA *newsdna, struct SDNA *oldsdna, char *c int DNA_elem_array_size(const char *astr, int len); int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); +bool DNA_struct_elem_find(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); + int DNA_elem_type_size(const eSDNA_Type elem_nr); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 117eac0e42b..66685c131d4 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -744,6 +744,8 @@ typedef struct SolidifyModifierData { float offset; /* new surface offset level*/ float offset_fac; /* midpoint of the offset */ float offset_fac_vg; /* factor for the minimum weight to use when vgroups are used, avoids 0.0 weights giving duplicate geometry */ + float offset_clamp; /* clamp offset based on surrounding geometry */ + float pad; float crease_inner; float crease_outer; float crease_rim; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 62c997b72c6..2e24b6ed78d 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -279,6 +279,8 @@ typedef struct bNodeTree { short render_quality; /* Quality setting when rendering */ int chunksize; /* tile size for compositor engine */ + rctf viewer_border; + ListBase inputs, outputs; /* external sockets for group nodes */ /* execution data */ @@ -313,6 +315,7 @@ typedef struct bNodeTree { #define NTREE_COM_OPENCL 2 /* use opencl */ #define NTREE_TWO_PASS 4 /* two pass */ #define NTREE_COM_GROUPNODE_BUFFER 8 /* use groupnode buffers */ +#define NTREE_VIEWER_BORDER 16 /* use a border for viewer nodes */ /* XXX not nice, but needed as a temporary flags * for group updates after library linking. @@ -857,4 +860,7 @@ typedef struct NodeShaderNormalMap { /* image */ #define CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT 1 +/* viewer and cmposite output */ +#define CMP_NODE_OUTPUT_IGNORE_ALPHA 1 + #endif diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index aa395dd0493..702df31f832 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -904,20 +904,25 @@ typedef struct UnifiedPaintSettings { /* rake rotation */ /* record movement of mouse so that rake can start at an intuitive angle */ - float last_x, last_y; - float last_angle; + float last_rake[2]; + int pad; - float special_rotation; + float brush_rotation; // all this below is used to communicate with the cursor drawing routine int draw_anchored; int anchored_size; - float anchored_location[3]; float anchored_initial_mouse[2]; /* drawing pressure */ int draw_pressure; float pressure_value; + + /* position of mouse, used to sample the texture */ + float tex_mouse[2]; + /* radius of brush, premultiplied with pressure. + * In case of anchored brushes contains that radius */ + float pixel_radius; } UnifiedPaintSettings; typedef enum { @@ -1534,7 +1539,6 @@ typedef enum SculptFlags { // #define IMAGEPAINT_DRAW_TOOL_DRAWING 4 // deprecated /* projection painting only */ -#define IMAGEPAINT_PROJECT_DISABLE 8 /* Non projection 3D painting */ #define IMAGEPAINT_PROJECT_XRAY 16 #define IMAGEPAINT_PROJECT_BACKFACE 32 #define IMAGEPAINT_PROJECT_FLAT 64 diff --git a/source/blender/makesdna/DNA_texture_types.h b/source/blender/makesdna/DNA_texture_types.h index ea4f281efd6..dd63e6aad59 100644 --- a/source/blender/makesdna/DNA_texture_types.h +++ b/source/blender/makesdna/DNA_texture_types.h @@ -340,7 +340,7 @@ typedef struct ColorMapping { /* imaflag */ #define TEX_INTERPOL 1 -#define TEX_USEALPHA 2 /* deprecated, used for versioning only */ +#define TEX_USEALPHA 2 #define TEX_MIPMAP 4 #define TEX_IMAROT 16 #define TEX_CALCALPHA 32 diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 0e5f0aea401..950483ba3ff 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -229,7 +229,7 @@ typedef struct ThemeSpace { char wire[4], select[4]; char lamp[4], speaker[4], empty[4], camera[4], pad[8]; char active[4], group[4], group_active[4], transform[4]; - char vertex[4], vertex_select[4]; + char vertex[4], vertex_select[4], vertex_unreferenced[4]; char edge[4], edge_select[4]; char edge_seam[4], edge_sharp[4], edge_facesel[4], edge_crease[4]; char face[4], face_select[4]; /* solid faces */ @@ -270,6 +270,7 @@ typedef struct ThemeSpace { char handle_vertex[4]; char handle_vertex_select[4]; + char pad2[4]; char handle_vertex_size; @@ -453,7 +454,7 @@ typedef struct UserDef { short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */ - short pad4; + short image_gpubuffer_limit; /* If set, amount of mega-pixels to use for texture drawing of images */ float glalphaclip; diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index d9d6db5ff91..294c47aa9db 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -107,6 +107,7 @@ typedef struct RegionView3D { struct RenderInfo *ri; struct RenderEngine *render_engine; struct ViewDepths *depths; + void *gpuoffscreen; /* animated smooth view */ struct SmoothView3DStore *sms; @@ -118,7 +119,6 @@ typedef struct RegionView3D { float viewquat[4]; /* view rotation, must be kept normalized */ float dist; /* distance from 'ofs' along -viewinv[2] vector, where result is negative as is 'ofs' */ - float zfac; /* initgrabz() result */ float camdx, camdy; /* camera view offsets, 1.0 = viewplane moves entire width/height */ float pixsize; /* runtime only */ float ofs[3]; /* view center & orbit pivot, negative of worldspace location, @@ -129,10 +129,11 @@ typedef struct RegionView3D { char persp; char view; char viewlock; + char pad[4]; short twdrawflag; short rflag; - + /* last view (use when switching out of camera view) */ float lviewquat[4]; diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 86014c4e80e..1225821102a 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -1314,6 +1314,22 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch return (int)((intptr_t)cp); } +bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name) +{ + + const int SDNAnr = DNA_struct_find_nr(sdna, stype); + + if (SDNAnr >= 0) { + const short * const spo = sdna->structs[SDNAnr]; + char * const cp = find_elem(sdna, vartype, name, spo, NULL, NULL); + + if (cp) return true; + return (int)((intptr_t)cp); + } + return false; +} + + /** * Returns the size in bytes of a primitive type. */ diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index dd65ce53b92..acc6597d2c7 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -255,7 +255,9 @@ static int add_type(const char *str, int len) } /* append new type */ - if (nr_types == 0) cp = typedata; + if (nr_types == 0) { + cp = typedata; + } else { cp = types[nr_types - 1] + strlen(types[nr_types - 1]) + 1; } @@ -401,7 +403,9 @@ static int add_name(const char *str) } /* append new type */ - if (nr_names == 0) cp = namedata; + if (nr_names == 0) { + cp = namedata; + } else { cp = names[nr_names - 1] + strlen(names[nr_names - 1]) + 1; } diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 821b429e75c..770508cd625 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -392,7 +392,6 @@ extern StructRNA RNA_MouseSensor; extern StructRNA RNA_MovieSequence; extern StructRNA RNA_MovieClipSequence; extern StructRNA RNA_MovieTracking; -extern StructRNA RNA_MovieTrackingTrack; extern StructRNA RNA_MovieTrackingObject; extern StructRNA RNA_MovieTrackingTrack; extern StructRNA RNA_MulticamSequence; @@ -703,10 +702,10 @@ PropertyRNA *RNA_struct_name_property(StructRNA *type); PropertyRNA *RNA_struct_iterator_property(StructRNA *type); StructRNA *RNA_struct_base(StructRNA *type); -int RNA_struct_is_ID(StructRNA *type); -int RNA_struct_is_a(StructRNA *type, StructRNA *srna); +bool RNA_struct_is_ID(StructRNA *type); +bool RNA_struct_is_a(StructRNA *type, StructRNA *srna); -int RNA_struct_undo_check(StructRNA *type); +bool RNA_struct_undo_check(StructRNA *type); StructRegisterFunc RNA_struct_register(StructRNA *type); StructUnregisterFunc RNA_struct_unregister(StructRNA *type); @@ -718,13 +717,13 @@ void RNA_struct_py_type_set(StructRNA *srna, void *py_type); void *RNA_struct_blender_type_get(StructRNA *srna); void RNA_struct_blender_type_set(StructRNA *srna, void *blender_type); -struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create); -int RNA_struct_idprops_check(StructRNA *srna); -int RNA_struct_idprops_register_check(StructRNA *type); -int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier); +struct IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create); +bool RNA_struct_idprops_check(StructRNA *srna); +bool RNA_struct_idprops_register_check(StructRNA *type); +bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier); PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier); -int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test); +bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test); /* lower level functions for access to type properties */ const struct ListBase *RNA_struct_type_properties(StructRNA *srna); @@ -751,12 +750,12 @@ 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(PropertyRNA *prop); -int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension); -int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[]); +int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop); +bool RNA_property_array_check(PropertyRNA *prop); +int RNA_property_multi_array_length(PointerRNA *ptr, PropertyRNA *prop, int dimension); +int RNA_property_array_dimension(PointerRNA *ptr, PropertyRNA *prop, int length[]); char RNA_property_array_item_char(PropertyRNA *prop, int index); -int RNA_property_array_item_index(PropertyRNA *prop, char name); +int RNA_property_array_item_index(PropertyRNA *prop, char name); int RNA_property_string_maxlength(PropertyRNA *prop); @@ -776,31 +775,31 @@ void RNA_property_float_ui_range(PointerRNA *ptr, PropertyRNA *prop, float *soft int RNA_property_float_clamp(PointerRNA *ptr, PropertyRNA *prop, float *value); int RNA_property_int_clamp(PointerRNA *ptr, PropertyRNA *prop, int *value); -int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier); -int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier); -int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name); -int RNA_enum_description(EnumPropertyItem *item, const int value, const char **description); +bool RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier); +int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier); +bool RNA_enum_name(EnumPropertyItem *item, const int value, const char **r_name); +bool RNA_enum_description(EnumPropertyItem *item, const int value, const char **description); void RNA_property_enum_items(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free); void RNA_property_enum_items_gettexted(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, EnumPropertyItem **item, int *totitem, int *free); -int RNA_property_enum_value(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value); -int RNA_property_enum_identifier(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier); -int RNA_property_enum_name(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name); +bool RNA_property_enum_value(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value); +bool RNA_property_enum_identifier(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier); +bool RNA_property_enum_name(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name); int RNA_property_enum_bitflag_identifiers(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier); StructRNA *RNA_property_pointer_type(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_pointer_poll(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *value); -int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop); -int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index); -int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */ -int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop); -int RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop); -int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop); /* slow, use with care */ +bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop); +bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index); +bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop); /* without lib check, only checks the flag */ +bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop); +bool RNA_property_animated(PointerRNA *ptr, PropertyRNA *prop); +bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop); /* slow, use with care */ void RNA_property_update(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop); void RNA_property_update_main(struct Main *bmain, struct Scene *scene, PointerRNA *ptr, PropertyRNA *prop); -int RNA_property_update_check(struct PropertyRNA *prop); +bool RNA_property_update_check(struct PropertyRNA *prop); void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene); @@ -865,7 +864,7 @@ int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, Poi int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr); int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr); int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const int key, const PointerRNA *assign_ptr); -int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr); +bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr); /* efficient functions to set properties for arrays */ int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array); @@ -879,13 +878,13 @@ RawPropertyType RNA_property_raw_type(PropertyRNA *prop); void RNA_property_pointer_add(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_pointer_remove(PointerRNA *ptr, PropertyRNA *prop); void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr); -int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key); +bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key); void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop); -int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos); +bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos); /* copy/reset */ -int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index); -int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index); +bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index); +bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index); /* Path * @@ -924,36 +923,36 @@ char *RNA_path_property_py(struct PointerRNA *ptr, struct PropertyRNA *prop, int * There is no support for pointers and collections here yet, these can be * added when ID properties support them. */ -int RNA_boolean_get(PointerRNA *ptr, const char *name); +int RNA_boolean_get(PointerRNA *ptr, const char *name); void RNA_boolean_set(PointerRNA *ptr, const char *name, int value); void RNA_boolean_get_array(PointerRNA *ptr, const char *name, int *values); void RNA_boolean_set_array(PointerRNA *ptr, const char *name, const int *values); -int RNA_int_get(PointerRNA *ptr, const char *name); +int RNA_int_get(PointerRNA *ptr, const char *name); void RNA_int_set(PointerRNA *ptr, const char *name, int value); void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values); void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values); float RNA_float_get(PointerRNA *ptr, const char *name); -void RNA_float_set(PointerRNA *ptr, const char *name, float value); -void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values); -void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values); +void RNA_float_set(PointerRNA *ptr, const char *name, float value); +void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values); +void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values); -int RNA_enum_get(PointerRNA *ptr, const char *name); +int RNA_enum_get(PointerRNA *ptr, const char *name); void RNA_enum_set(PointerRNA *ptr, const char *name, int value); void RNA_enum_set_identifier(PointerRNA *ptr, const char *name, const char *id); -int RNA_enum_is_equal(struct bContext *C, PointerRNA *ptr, const char *name, const char *enumname); +bool RNA_enum_is_equal(struct bContext *C, PointerRNA *ptr, const char *name, const char *enumname); /* lower level functions that don't use a PointerRNA */ -int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value); -int RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier); -int RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *icon); -int RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **name); +bool RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *r_value); +bool RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **r_identifier); +bool RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *r_icon); +bool RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **r_name); -void RNA_string_get(PointerRNA *ptr, const char *name, char *value); +void RNA_string_get(PointerRNA *ptr, const char *name, char *value); char *RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen); -int RNA_string_length(PointerRNA *ptr, const char *name); -void RNA_string_set(PointerRNA *ptr, const char *name, const char *value); +int RNA_string_length(PointerRNA *ptr, const char *name); +void RNA_string_set(PointerRNA *ptr, const char *name, const char *value); /** * Retrieve the named property from PointerRNA. @@ -964,7 +963,7 @@ void RNA_pointer_set(PointerRNA *ptr, const char *name, PointerRNA ptr_value); void RNA_pointer_add(PointerRNA *ptr, const char *name); void RNA_collection_begin(PointerRNA *ptr, const char *name, CollectionPropertyIterator *iter); -int RNA_collection_length(PointerRNA *ptr, const char *name); +int RNA_collection_length(PointerRNA *ptr, const char *name); void RNA_collection_add(PointerRNA *ptr, const char *name, PointerRNA *r_value); void RNA_collection_clear(PointerRNA *ptr, const char *name); @@ -1014,11 +1013,11 @@ void RNA_collection_clear(PointerRNA *ptr, const char *name); } /* check if the idproperty exists, for operators */ -int RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, int use_ghost); -int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop); -int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int use_ghost); -int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier); -int RNA_property_is_idprop(PropertyRNA *prop); +bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost); +bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop); +bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost); +bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier); +bool RNA_property_is_idprop(PropertyRNA *prop); /* python compatible string representation of this property, (must be freed!) */ char *RNA_property_as_string(struct bContext *C, PointerRNA *ptr, PropertyRNA *prop, int index); @@ -1063,21 +1062,27 @@ int RNA_parameter_length_get_data(ParameterList *parms, PropertyRNA *parm, void void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length); void RNA_parameter_length_set_data(ParameterList *parms, PropertyRNA *parm, void *data, int length); -int RNA_function_call(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms); -int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, ParameterList *parms); +int RNA_function_call(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, + FunctionRNA *func, ParameterList *parms); +int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, + const char *identifier, ParameterList *parms); -int RNA_function_call_direct(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, const char *format, ...) +int RNA_function_call_direct(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, + FunctionRNA *func, const char *format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 5, 6))) #endif ; -int RNA_function_call_direct_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, const char *format, ...) +int RNA_function_call_direct_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, + const char *identifier, const char *format, ...) #ifdef __GNUC__ __attribute__ ((format(printf, 5, 6))) #endif ; -int RNA_function_call_direct_va(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, FunctionRNA *func, const char *format, va_list args); -int RNA_function_call_direct_va_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, const char *identifier, const char *format, va_list args); +int RNA_function_call_direct_va(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, + FunctionRNA *func, const char *format, va_list args); +int RNA_function_call_direct_va_lookup(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, + const char *identifier, const char *format, va_list args); /* ID */ diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 54d2efcf4cf..b69c95d0363 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -88,7 +88,8 @@ typedef enum PropertyUnit { PROP_UNIT_ROTATION = (5 << 16), /* radians */ PROP_UNIT_TIME = (6 << 16), /* frame */ PROP_UNIT_VELOCITY = (7 << 16), /* m/s */ - PROP_UNIT_ACCELERATION = (8 << 16) /* m/(s^2) */ + PROP_UNIT_ACCELERATION = (8 << 16), /* m/(s^2) */ + PROP_UNIT_CAMERA = (9 << 16) /* mm */ } PropertyUnit; #define RNA_SUBTYPE_UNIT(subtype) ((subtype) & 0x00FF0000) @@ -122,6 +123,7 @@ typedef enum PropertySubType { PROP_TIME = 17 | PROP_UNIT_TIME, /* distance in 3d space, don't use for pixel distance for eg. */ PROP_DISTANCE = 18 | PROP_UNIT_LENGTH, + PROP_DISTANCE_CAMERA = 19 | PROP_UNIT_CAMERA, /* number arrays */ PROP_COLOR = 20, diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 3cd75ab10f0..0d5c1eb2352 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -24,7 +24,6 @@ * \ingroup RNA */ - #include <float.h> #include <limits.h> #include <stdio.h> @@ -34,6 +33,8 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_types.h" @@ -2450,6 +2451,7 @@ static const char *rna_property_subtypename(PropertySubType type) case PROP_ANGLE: return "PROP_ANGLE"; case PROP_TIME: return "PROP_TIME"; case PROP_DISTANCE: return "PROP_DISTANCE"; + case PROP_DISTANCE_CAMERA: return "PROP_DISTANCE_CAMERA"; case PROP_COLOR: return "PROP_COLOR"; case PROP_TRANSLATION: return "PROP_TRANSLATION"; case PROP_DIRECTION: return "PROP_DIRECTION"; @@ -2490,6 +2492,7 @@ static const char *rna_property_subtype_unit(PropertySubType type) case PROP_UNIT_TIME: return "PROP_UNIT_TIME"; case PROP_UNIT_VELOCITY: return "PROP_UNIT_VELOCITY"; case PROP_UNIT_ACCELERATION: return "PROP_UNIT_ACCELERATION"; + case PROP_UNIT_CAMERA: return "PROP_UNIT_CAMERA"; default: return "PROP_UNIT_UNKNOWN"; } } @@ -3172,7 +3175,9 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE fprintf(f, "\t(PropertyRNA *)&rna_%s_%s, ", base->identifier, prop->identifier); } - else fprintf(f, "\tNULL, "); + else { + fprintf(f, "\tNULL, "); + } prop = srna->iteratorproperty; base = srna; diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 18281d4d251..1716864f23f 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -24,18 +24,19 @@ * \ingroup RNA */ - #include <stdlib.h> #include <stdio.h> -#include "RNA_access.h" -#include "RNA_define.h" - #include "DNA_ID.h" #include "DNA_vfont_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" +#include "BLI_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" + #include "WM_types.h" #include "rna_internal.h" @@ -105,7 +106,7 @@ void rna_ID_name_set(PointerRNA *ptr, const char *value) { ID *id = (ID *)ptr->data; BLI_strncpy_utf8(id->name + 2, value, sizeof(id->name) - 2); - test_idbutton(id->name + 2); + test_idbutton(id->name); } static int rna_ID_name_editable(PointerRNA *ptr) @@ -205,7 +206,7 @@ StructRNA *rna_ID_refine(PointerRNA *ptr) return ID_code_to_RNA_type(GS(id->name)); } -IDProperty *rna_ID_idprops(PointerRNA *ptr, int create) +IDProperty *rna_ID_idprops(PointerRNA *ptr, bool create) { return IDP_GetProperties(ptr->data, create); } @@ -224,7 +225,7 @@ void rna_ID_fake_user_set(PointerRNA *ptr, int value) } } -IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, int UNUSED(create)) +IDProperty *rna_PropertyGroup_idprops(PointerRNA *ptr, bool UNUSED(create)) { return ptr->data; } @@ -269,7 +270,7 @@ static ID *rna_ID_copy(ID *id) { ID *newid; - if (id_copy(id, &newid, 0)) { + if (id_copy(id, &newid, false)) { if (newid) id_us_min(newid); return newid; } diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 6035326e0ae..f3efbd0d53e 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -52,12 +52,11 @@ #include "BKE_main.h" #include "BKE_report.h" - -#include "WM_api.h" - #include "RNA_access.h" #include "RNA_define.h" +#include "WM_api.h" + /* flush updates */ #include "DNA_object_types.h" #include "BKE_depsgraph.h" @@ -258,7 +257,7 @@ static IDProperty *rna_idproperty_ui(PropertyRNA *prop) return NULL; } -IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create) +IDProperty *RNA_struct_idprops(PointerRNA *ptr, bool create) { StructRNA *type = ptr->type; @@ -268,9 +267,9 @@ IDProperty *RNA_struct_idprops(PointerRNA *ptr, int create) return NULL; } -int RNA_struct_idprops_check(StructRNA *srna) +bool RNA_struct_idprops_check(StructRNA *srna) { - return (srna && srna->idproperties) ? 1 : 0; + return (srna && srna->idproperties); } static IDProperty *rna_idproperty_find(PointerRNA *ptr, const char *name) @@ -299,15 +298,15 @@ static int rna_ensure_property_array_length(PointerRNA *ptr, PropertyRNA *prop) } } -static int rna_ensure_property_array_check(PropertyRNA *prop) +static bool rna_ensure_property_array_check(PropertyRNA *prop) { if (prop->magic == RNA_MAGIC) { - return (prop->getlength || prop->totarraylength) ? 1 : 0; + return (prop->getlength || prop->totarraylength); } else { IDProperty *idprop = (IDProperty *)prop; - return idprop->type == IDP_ARRAY ? 1 : 0; + return (idprop->type == IDP_ARRAY); } } @@ -329,7 +328,7 @@ static void rna_ensure_property_multi_array_length(PointerRNA *ptr, PropertyRNA } } -static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop) +static bool rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDProperty *idprop) { /* this verifies if the idproperty actually matches the property * description and otherwise removes it. this is to ensure that @@ -339,40 +338,40 @@ static int rna_idproperty_verify_valid(PointerRNA *ptr, PropertyRNA *prop, IDPro switch (idprop->type) { case IDP_IDPARRAY: if (prop->type != PROP_COLLECTION) - return 0; + return false; break; case IDP_ARRAY: if (rna_ensure_property_array_length(ptr, prop) != idprop->len) - return 0; + return false; if (idprop->subtype == IDP_FLOAT && prop->type != PROP_FLOAT) - return 0; + return false; if (idprop->subtype == IDP_INT && !ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) - return 0; + return false; break; case IDP_INT: if (!ELEM3(prop->type, PROP_BOOLEAN, PROP_INT, PROP_ENUM)) - return 0; + return false; break; case IDP_FLOAT: case IDP_DOUBLE: if (prop->type != PROP_FLOAT) - return 0; + return false; break; case IDP_STRING: if (prop->type != PROP_STRING) - return 0; + return false; break; case IDP_GROUP: if (prop->type != PROP_POINTER) - return 0; + return false; break; default: - return 0; + return false; } - return 1; + return true; } static PropertyRNA *typemap[IDP_NUMTYPES] = { @@ -549,23 +548,23 @@ StructRNA *RNA_struct_base(StructRNA *type) return type->base; } -int RNA_struct_is_ID(StructRNA *type) +bool RNA_struct_is_ID(StructRNA *type) { return (type->flag & STRUCT_ID) != 0; } -int RNA_struct_undo_check(StructRNA *type) +bool RNA_struct_undo_check(StructRNA *type) { return (type->flag & STRUCT_UNDO) != 0; } -int RNA_struct_idprops_register_check(StructRNA *type) +bool RNA_struct_idprops_register_check(StructRNA *type) { return (type->flag & STRUCT_NO_IDPROPERTIES) == 0; } /* remove an id-property */ -int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier) +bool RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier) { IDProperty *group = RNA_struct_idprops(ptr, 0); @@ -576,25 +575,25 @@ int RNA_struct_idprops_unset(PointerRNA *ptr, const char *identifier) IDP_FreeProperty(idp); MEM_freeN(idp); - return 1; + return true; } } - return 0; + return false; } -int RNA_struct_is_a(StructRNA *type, StructRNA *srna) +bool RNA_struct_is_a(StructRNA *type, StructRNA *srna) { StructRNA *base; if (!type) - return 0; + return false; /* ptr->type is always maximally refined */ for (base = type; base; base = base->base) if (base == srna) - return 1; + return true; - return 0; + return false; } PropertyRNA *RNA_struct_find_property(PointerRNA *ptr, const char *identifier) @@ -637,13 +636,13 @@ static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna) return prop; } -int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test) +bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test) { /* note, prop_test could be freed memory, only use for comparison */ /* validate the RNA is ok */ PropertyRNA *iterprop; - int found = FALSE; + bool found = false; iterprop = RNA_struct_iterator_property(ptr->type); @@ -651,7 +650,7 @@ int RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test) { /* PropertyRNA *prop = itemptr.data; */ if (prop_test == (PropertyRNA *)itemptr.data) { - found = TRUE; + found = true; break; } } @@ -812,7 +811,7 @@ int RNA_property_array_length(PointerRNA *ptr, PropertyRNA *prop) return rna_ensure_property_array_length(ptr, prop); } -int RNA_property_array_check(PropertyRNA *prop) +bool RNA_property_array_check(PropertyRNA *prop) { return rna_ensure_property_array_check(prop); } @@ -845,6 +844,8 @@ char RNA_property_array_item_char(PropertyRNA *prop, int index) const char *coloritem = "RGBA"; PropertySubType subtype = rna_ensure_property(prop)->subtype; + BLI_assert(index >= 0); + /* get string to use for array index */ if ((index < 4) && ELEM(subtype, PROP_QUATERNION, PROP_AXISANGLE)) { return quatitem[index]; @@ -1272,17 +1273,18 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA } -int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *value) +bool RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const char *identifier, int *r_value) { EnumPropertyItem *item, *item_array; - int free, found; + int free; + bool found; RNA_property_enum_items(C, ptr, prop, &item_array, NULL, &free); if (item_array) { for (item = item_array; item->identifier; item++) { if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) { - *value = item->value; + *r_value = item->value; break; } } @@ -1294,97 +1296,100 @@ int RNA_property_enum_value(bContext *C, PointerRNA *ptr, PropertyRNA *prop, con } } else { - found = 0; + found = false; } return found; } -int RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier) +bool RNA_enum_identifier(EnumPropertyItem *item, const int value, const char **identifier) { for (; item->identifier; item++) { if (item->identifier[0] && item->value == value) { *identifier = item->identifier; - return 1; + return true; } } - return 0; + return false; } -int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **identifier) +int RNA_enum_bitflag_identifiers(EnumPropertyItem *item, const int value, const char **r_identifier) { int index = 0; for (; item->identifier; item++) { if (item->identifier[0] && item->value & value) { - identifier[index++] = item->identifier; + r_identifier[index++] = item->identifier; } } - identifier[index] = NULL; + r_identifier[index] = NULL; return index; } -int RNA_enum_name(EnumPropertyItem *item, const int value, const char **name) +bool RNA_enum_name(EnumPropertyItem *item, const int value, const char **r_name) { for (; item->identifier; item++) { if (item->identifier[0] && item->value == value) { - *name = item->name; - return 1; + *r_name = item->name; + return true; } } - return 0; + return false; } -int RNA_enum_description(EnumPropertyItem *item, const int value, const char **description) +bool RNA_enum_description(EnumPropertyItem *item, const int value, const char **r_description) { for (; item->identifier; item++) { if (item->identifier[0] && item->value == value) { - *description = item->description; - return 1; + *r_description = item->description; + return true; } } - return 0; + return false; } -int RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, - const char **identifier) +bool RNA_property_enum_identifier(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, + const char **identifier) { EnumPropertyItem *item = NULL; - int result, free; + int free; RNA_property_enum_items(C, ptr, prop, &item, NULL, &free); if (item) { + bool result; result = RNA_enum_identifier(item, value, identifier); if (free) MEM_freeN(item); return result; } - return 0; + return false; } -int RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name) +bool RNA_property_enum_name(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **name) { EnumPropertyItem *item = NULL; - int result, free; + int free; RNA_property_enum_items(C, ptr, prop, &item, NULL, &free); if (item) { + bool result; result = RNA_enum_name(item, value, name); if (free) MEM_freeN(item); return result; } - return 0; + return false; } int RNA_property_enum_bitflag_identifiers(bContext *C, PointerRNA *ptr, PropertyRNA *prop, const int value, const char **identifier) { EnumPropertyItem *item = NULL; - int result, free; + int free; RNA_property_enum_items(C, ptr, prop, &item, NULL, &free); if (item) { + int result; result = RNA_enum_bitflag_identifiers(item, value, identifier); if (free) MEM_freeN(item); @@ -1415,7 +1420,7 @@ int RNA_property_ui_icon(PropertyRNA *prop) return rna_ensure_property(prop)->icon; } -int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop) +bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop) { ID *id = ptr->id.data; int flag; @@ -1425,21 +1430,23 @@ int RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop) return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION)); } -int RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop) +bool RNA_property_editable_flag(PointerRNA *ptr, PropertyRNA *prop) { int flag; prop = rna_ensure_property(prop); flag = prop->editable ? prop->editable(ptr) : prop->flag; - return (flag & PROP_EDITABLE); + return (flag & PROP_EDITABLE) != 0; } /* same as RNA_property_editable(), except this checks individual items in an array */ -int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index) +bool RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index) { ID *id; int flag; + BLI_assert(index >= 0); + prop = rna_ensure_property(prop); flag = prop->flag; @@ -1455,34 +1462,34 @@ int RNA_property_editable_index(PointerRNA *ptr, PropertyRNA *prop, int index) return (flag & PROP_EDITABLE) && (!id || !id->lib || (prop->flag & PROP_LIB_EXCEPTION)); } -int RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop) +bool RNA_property_animateable(PointerRNA *ptr, PropertyRNA *prop) { /* check that base ID-block can support animation data */ if (!id_type_can_have_animdata(ptr->id.data)) - return 0; + return false; prop = rna_ensure_property(prop); if (!(prop->flag & PROP_ANIMATABLE)) - return 0; + return false; - return (prop->flag & PROP_EDITABLE); + return (prop->flag & PROP_EDITABLE) != 0; } -int RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop)) +bool RNA_property_animated(PointerRNA *UNUSED(ptr), PropertyRNA *UNUSED(prop)) { /* would need to ask animation system */ - return 0; + return false; } /* this function is to check if its possible to create a valid path from the ID * its slow so don't call in a loop */ -int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) +bool RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) { char *path = RNA_path_from_ID_to_property(ptr, prop); - int ret = 0; + bool ret = false; if (path) { PointerRNA id_ptr; @@ -1493,9 +1500,6 @@ int RNA_property_path_from_ID_check(PointerRNA *ptr, PropertyRNA *prop) if (RNA_path_resolve(&id_ptr, path, &r_ptr, &r_prop) == TRUE) { ret = (prop == r_prop); } - else { - ret = FALSE; - } MEM_freeN(path); } @@ -1540,7 +1544,7 @@ static void rna_property_update(bContext *C, Main *bmain, Scene *scene, PointerR /* must keep in sync with 'rna_property_update' * note, its possible this returns a false positive in the case of PROP_CONTEXT_UPDATE * but this isn't likely to be a performance problem. */ -int RNA_property_update_check(PropertyRNA *prop) +bool RNA_property_update_check(PropertyRNA *prop) { return (prop->magic != RNA_MAGIC || prop->update || prop->noteflag); } @@ -1670,7 +1674,7 @@ int RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); if ((idprop = rna_idproperty_check(&prop, ptr))) return IDP_Int(idprop); @@ -1688,7 +1692,7 @@ void RNA_property_boolean_set(PointerRNA *ptr, PropertyRNA *prop, int value) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); /* just in case other values are passed */ if (value) value = 1; @@ -1721,7 +1725,7 @@ void RNA_property_boolean_get_array(PointerRNA *ptr, PropertyRNA *prop, int *val IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (prop->arraydimension == 0) @@ -1747,7 +1751,8 @@ int RNA_property_boolean_get_index(PointerRNA *ptr, PropertyRNA *prop, int index int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_boolean_get_array(ptr, prop, tmp); @@ -1771,7 +1776,7 @@ void RNA_property_boolean_set_array(PointerRNA *ptr, PropertyRNA *prop, const in IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (prop->arraydimension == 0) @@ -1809,7 +1814,8 @@ void RNA_property_boolean_set_index(PointerRNA *ptr, PropertyRNA *prop, int inde int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_boolean_get_array(ptr, prop, tmp); @@ -1832,7 +1838,7 @@ int RNA_property_boolean_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop) BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); return bprop->defaultvalue; } @@ -1842,7 +1848,7 @@ void RNA_property_boolean_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA BoolPropertyRNA *bprop = (BoolPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if (prop->arraydimension == 0) values[0] = bprop->defaultvalue; @@ -1858,7 +1864,8 @@ int RNA_property_boolean_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_BOOLEAN); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_boolean_get_default_array(ptr, prop, tmp); @@ -1882,7 +1889,7 @@ int RNA_property_int_get(PointerRNA *ptr, PropertyRNA *prop) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); if ((idprop = rna_idproperty_check(&prop, ptr))) return IDP_Int(idprop); @@ -1900,7 +1907,7 @@ void RNA_property_int_set(PointerRNA *ptr, PropertyRNA *prop, int value) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); /* useful to check on bad values but set function should clamp */ /* BLI_assert(RNA_property_int_clamp(ptr, prop, &value) == 0); */ @@ -1932,7 +1939,7 @@ void RNA_property_int_get_array(PointerRNA *ptr, PropertyRNA *prop, int *values) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (prop->arraydimension == 0) @@ -1995,7 +2002,8 @@ int RNA_property_int_get_index(PointerRNA *ptr, PropertyRNA *prop, int index) int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_int_get_array(ptr, prop, tmp); @@ -2019,7 +2027,7 @@ void RNA_property_int_set_array(PointerRNA *ptr, PropertyRNA *prop, const int *v IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (prop->arraydimension == 0) @@ -2059,7 +2067,8 @@ void RNA_property_int_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, i int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_int_get_array(ptr, prop, tmp); @@ -2088,7 +2097,7 @@ void RNA_property_int_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA *pr IntPropertyRNA *iprop = (IntPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_INT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if (prop->arraydimension == 0) values[0] = iprop->defaultvalue; @@ -2103,6 +2112,10 @@ int RNA_property_int_get_default_index(PointerRNA *ptr, PropertyRNA *prop, int i int tmp[RNA_MAX_ARRAY_LENGTH]; int len = rna_ensure_property_array_length(ptr, prop); + BLI_assert(RNA_property_type(prop) == PROP_INT); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); + if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_int_get_default_array(ptr, prop, tmp); return tmp[index]; @@ -2125,7 +2138,7 @@ float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (idprop->type == IDP_FLOAT) @@ -2147,7 +2160,7 @@ void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value) IDProperty *idprop; BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); /* useful to check on bad values but set function should clamp */ /* BLI_assert(RNA_property_float_clamp(ptr, prop, &value) == 0); */ @@ -2186,7 +2199,7 @@ void RNA_property_float_get_array(PointerRNA *ptr, PropertyRNA *prop, float *val int i; BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (prop->arraydimension == 0) @@ -2254,7 +2267,8 @@ float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_float_get_array(ptr, prop, tmp); @@ -2270,7 +2284,6 @@ float RNA_property_float_get_index(PointerRNA *ptr, PropertyRNA *prop, int index return value; } - } void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const float *values) @@ -2280,7 +2293,7 @@ void RNA_property_float_set_array(PointerRNA *ptr, PropertyRNA *prop, const floa int i; BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if ((idprop = rna_idproperty_check(&prop, ptr))) { if (prop->arraydimension == 0) { @@ -2331,7 +2344,8 @@ void RNA_property_float_set_index(PointerRNA *ptr, PropertyRNA *prop, int index, int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_float_get_array(ptr, prop, tmp); @@ -2354,7 +2368,7 @@ float RNA_property_float_get_default(PointerRNA *UNUSED(ptr), PropertyRNA *prop) FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) == 0); + BLI_assert(RNA_property_array_check(prop) == false); return fprop->defaultvalue; } @@ -2364,7 +2378,7 @@ void RNA_property_float_get_default_array(PointerRNA *UNUSED(ptr), PropertyRNA * FloatPropertyRNA *fprop = (FloatPropertyRNA *)prop; BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); if (prop->arraydimension == 0) values[0] = fprop->defaultvalue; @@ -2380,7 +2394,8 @@ float RNA_property_float_get_default_index(PointerRNA *ptr, PropertyRNA *prop, i int len = rna_ensure_property_array_length(ptr, prop); BLI_assert(RNA_property_type(prop) == PROP_FLOAT); - BLI_assert(RNA_property_array_check(prop) != 0); + BLI_assert(RNA_property_array_check(prop) != false); + BLI_assert(index >= 0); if (len <= RNA_MAX_ARRAY_LENGTH) { RNA_property_float_get_default_array(ptr, prop, tmp); @@ -2864,7 +2879,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA } } -int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) +bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) { IDProperty *idprop; /* CollectionPropertyRNA *cprop = (CollectionPropertyRNA *)prop; */ @@ -2889,10 +2904,11 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) IDP_ResizeIDPArray(idprop, len - 1); } - return 1; + return true; + } + else if (prop->flag & PROP_IDPROPERTY) { + return true; } - else if (prop->flag & PROP_IDPROPERTY) - return 1; /* py api calls directly */ #if 0 @@ -2904,15 +2920,15 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) RNA_parameter_list_free(¶ms); } - return 0; + return false; } /*else printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/ #endif - return 0; + return false; } -int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos) +bool RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, int pos) { IDProperty *idprop; @@ -2934,12 +2950,13 @@ int RNA_property_collection_move(PointerRNA *ptr, PropertyRNA *prop, int key, in memcpy(&array[pos], &tmp, sizeof(IDProperty)); } - return 1; + return true; + } + else if (prop->flag & PROP_IDPROPERTY) { + return true; } - else if (prop->flag & PROP_IDPROPERTY) - return 1; - return 0; + return false; } void RNA_property_collection_clear(PointerRNA *ptr, PropertyRNA *prop) @@ -3066,7 +3083,7 @@ int RNA_property_collection_assign_int(PointerRNA *ptr, PropertyRNA *prop, const return 0; } -int RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr) +bool RNA_property_collection_type_get(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr) { BLI_assert(RNA_property_type(prop) == PROP_COLLECTION); @@ -4557,7 +4574,7 @@ void RNA_enum_set_identifier(PointerRNA *ptr, const char *name, const char *id) } } -int RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname) +bool RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char *enumname) { PropertyRNA *prop = RNA_struct_find_property(ptr, name); EnumPropertyItem *item; @@ -4574,60 +4591,60 @@ int RNA_enum_is_equal(bContext *C, PointerRNA *ptr, const char *name, const char MEM_freeN(item); printf("%s: %s.%s item %s not found.\n", __func__, ptr->type->identifier, name, enumname); - return 0; + return false; } else { printf("%s: %s.%s not found.\n", __func__, ptr->type->identifier, name); - return 0; + return false; } } -int RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value) +bool RNA_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *r_value) { for (; item->identifier; item++) { if (strcmp(item->identifier, identifier) == 0) { - *value = item->value; - return 1; + *r_value = item->value; + return true; } } - return 0; + return false; } -int RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **identifier) +bool RNA_enum_id_from_value(EnumPropertyItem *item, int value, const char **r_identifier) { for (; item->identifier; item++) { if (item->value == value) { - *identifier = item->identifier; - return 1; + *r_identifier = item->identifier; + return true; } } - return 0; + return false; } -int RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *icon) +bool RNA_enum_icon_from_value(EnumPropertyItem *item, int value, int *r_icon) { for (; item->identifier; item++) { if (item->value == value) { - *icon = item->icon; - return 1; + *r_icon = item->icon; + return true; } } - return 0; + return false; } -int RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **name) +bool RNA_enum_name_from_value(EnumPropertyItem *item, int value, const char **r_name) { for (; item->identifier; item++) { if (item->value == value) { - *name = item->name; - return 1; + *r_name = item->name; + return true; } } - return 0; + return false; } void RNA_string_get(PointerRNA *ptr, const char *name, char *value) @@ -4758,29 +4775,29 @@ int RNA_collection_length(PointerRNA *ptr, const char *name) } } -int RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, int use_ghost) +bool RNA_property_is_set_ex(PointerRNA *ptr, PropertyRNA *prop, bool use_ghost) { if (prop->flag & PROP_IDPROPERTY) { IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier); - return ((idprop != NULL) && (use_ghost == FALSE || !(idprop->flag & IDP_FLAG_GHOST))); + return ((idprop != NULL) && (use_ghost == false || !(idprop->flag & IDP_FLAG_GHOST))); } else { - return 1; + return true; } } -int RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop) +bool RNA_property_is_set(PointerRNA *ptr, PropertyRNA *prop) { if (prop->flag & PROP_IDPROPERTY) { IDProperty *idprop = rna_idproperty_find(ptr, prop->identifier); return ((idprop != NULL) && !(idprop->flag & IDP_FLAG_GHOST)); } else { - return 1; + return true; } } -int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int use_ghost) +bool RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, bool use_ghost) { PropertyRNA *prop = RNA_struct_find_property(ptr, identifier); @@ -4794,7 +4811,7 @@ int RNA_struct_property_is_set_ex(PointerRNA *ptr, const char *identifier, int u } } -int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier) +bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier) { PropertyRNA *prop = RNA_struct_find_property(ptr, identifier); @@ -4808,7 +4825,7 @@ int RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier) } } -int RNA_property_is_idprop(PropertyRNA *prop) +bool RNA_property_is_idprop(PropertyRNA *prop) { return (prop->magic != RNA_MAGIC); } @@ -5887,7 +5904,7 @@ int RNA_function_call_direct_va_lookup(bContext *C, ReportList *reports, Pointer return 0; } -int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) +bool RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) { int len; @@ -5915,7 +5932,7 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) int value = RNA_property_boolean_get_default(ptr, prop); RNA_property_boolean_set(ptr, prop, value); } - return 1; + return true; case PROP_INT: if (len) { if (index == -1) { @@ -5935,7 +5952,7 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) int value = RNA_property_int_get_default(ptr, prop); RNA_property_int_set(ptr, prop, value); } - return 1; + return true; case PROP_FLOAT: if (len) { if (index == -1) { @@ -5955,12 +5972,12 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) float value = RNA_property_float_get_default(ptr, prop); RNA_property_float_set(ptr, prop, value); } - return 1; + return true; case PROP_ENUM: { int value = RNA_property_enum_get_default(ptr, prop); RNA_property_enum_set(ptr, prop, value); - return 1; + return true; } case PROP_STRING: @@ -5968,23 +5985,23 @@ int RNA_property_reset(PointerRNA *ptr, PropertyRNA *prop, int index) char *value = RNA_property_string_get_default_alloc(ptr, prop, NULL, 0); RNA_property_string_set(ptr, prop, value); MEM_freeN(value); - return 1; + return true; } case PROP_POINTER: { PointerRNA value = RNA_property_pointer_get_default(ptr, prop); RNA_property_pointer_set(ptr, prop, value); - return 1; + return true; } default: /* FIXME: are there still any cases that haven't been handled? comment out "default" block to check :) */ - return 0; + return false; } } -int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index) +bool RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, int index) { int len, fromlen; @@ -5993,7 +6010,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i fromlen = RNA_property_array_length(fromptr, prop); if (len != fromlen) - return 0; + return false; /* get and set the default values as appropriate for the various types */ switch (RNA_property_type(prop)) { @@ -6016,7 +6033,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i int value = RNA_property_boolean_get(fromptr, prop); RNA_property_boolean_set(ptr, prop, value); } - return 1; + return true; case PROP_INT: if (len) { if (index == -1) { @@ -6036,7 +6053,7 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i int value = RNA_property_int_get(fromptr, prop); RNA_property_int_set(ptr, prop, value); } - return 1; + return true; case PROP_FLOAT: if (len) { if (index == -1) { @@ -6056,31 +6073,31 @@ int RNA_property_copy(PointerRNA *ptr, PointerRNA *fromptr, PropertyRNA *prop, i float value = RNA_property_float_get(fromptr, prop); RNA_property_float_set(ptr, prop, value); } - return 1; + return true; case PROP_ENUM: { int value = RNA_property_enum_get(fromptr, prop); RNA_property_enum_set(ptr, prop, value); - return 1; + return true; } case PROP_POINTER: { PointerRNA value = RNA_property_pointer_get(fromptr, prop); RNA_property_pointer_set(ptr, prop, value); - return 1; + return true; } case PROP_STRING: { char *value = RNA_property_string_get_alloc(fromptr, prop, NULL, 0, NULL); RNA_property_string_set(ptr, prop, value); MEM_freeN(value); - return 1; + return true; } default: - return 0; + return false; } - return 0; + return false; } /* use RNA_warning macro which includes __func__ suffix */ diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 457066aed7c..e9bf40a58b1 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -24,15 +24,8 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_scene_types.h" @@ -43,6 +36,12 @@ #include "BKE_action.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index fe4a23cb393..2c022e80ddd 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -27,22 +27,23 @@ #include <stdlib.h> -#include "RNA_define.h" -#include "RNA_access.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" #include "DNA_constraint_types.h" #include "DNA_object_types.h" #include "DNA_actuator_types.h" #include "DNA_scene_types.h" /* for MAXFRAME */ -#include "WM_types.h" - #include "BLI_utildefines.h" #include "BLF_translation.h" +#include "RNA_define.h" +#include "RNA_access.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + +#include "WM_types.h" + /* Always keep in alphabetical order */ EnumPropertyItem actuator_type_items[] = { {ACT_ACTION, "ACTION", 0, "Action", ""}, diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index d6ea53f6ab3..50f156dd985 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -26,12 +26,6 @@ #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_scene_types.h" @@ -40,10 +34,16 @@ #include "MEM_guardedalloc.h" -#include "ED_keyframing.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" #include "WM_types.h" +#include "ED_keyframing.h" + /* exported for use in API */ EnumPropertyItem keyingset_path_grouping_items[] = { {KSP_GROUP_NAMED, "NAMED", 0, "Named Group", ""}, @@ -895,6 +895,7 @@ static void rna_def_animdata(BlenderRNA *brna) srna = RNA_def_struct(brna, "AnimData", NULL); RNA_def_struct_ui_text(srna, "Animation Data", "Animation data for datablock"); + RNA_def_struct_ui_icon(srna, ICON_ANIM_DATA); /* NLA */ prop = RNA_def_property(srna, "nla_tracks", PROP_COLLECTION, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_animviz.c b/source/blender/makesrna/intern/rna_animviz.c index 68075823a86..9f8f30b00a7 100644 --- a/source/blender/makesrna/intern/rna_animviz.c +++ b/source/blender/makesrna/intern/rna_animviz.c @@ -24,19 +24,20 @@ * \ingroup RNA */ - #include <stdlib.h> #include "RNA_define.h" -#include "rna_internal.h" - #include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" + #include "MEM_guardedalloc.h" +#include "rna_internal.h" + #include "WM_types.h" /* Which part of bone(s) get baked */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 6c48ed25b60..1bc6c7e4f6f 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -207,7 +207,7 @@ static char *rna_Bone_path(PointerRNA *ptr) return BLI_sprintfN("bones[\"%s\"]", bone->name); } -static IDProperty *rna_Bone_idprops(PointerRNA *ptr, int create) +static IDProperty *rna_Bone_idprops(PointerRNA *ptr, bool create) { Bone *bone = ptr->data; @@ -219,7 +219,7 @@ static IDProperty *rna_Bone_idprops(PointerRNA *ptr, int create) return bone->prop; } -static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, int create) +static IDProperty *rna_EditBone_idprops(PointerRNA *ptr, bool create) { EditBone *ebone = ptr->data; diff --git a/source/blender/makesrna/intern/rna_boid.c b/source/blender/makesrna/intern/rna_boid.c index 63f4e480468..9d44ae87b57 100644 --- a/source/blender/makesrna/intern/rna_boid.c +++ b/source/blender/makesrna/intern/rna_boid.c @@ -29,20 +29,21 @@ * \ingroup RNA */ - #include <float.h> #include <limits.h> #include <stdlib.h> -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_scene_types.h" #include "DNA_boid_types.h" #include "DNA_object_types.h" #include "DNA_particle_types.h" +#include "BLI_utildefines.h" + +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index c995d3b52c7..8480427c433 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -24,14 +24,11 @@ * \ingroup RNA */ - #include <stdlib.h> #include <assert.h> #include "RNA_define.h" -#include "rna_internal.h" - #include "DNA_brush_types.h" #include "DNA_texture_types.h" #include "DNA_scene_types.h" @@ -39,6 +36,8 @@ #include "BLI_math.h" +#include "rna_internal.h" + #include "IMB_imbuf.h" #include "WM_types.h" @@ -107,7 +106,7 @@ EnumPropertyItem brush_image_tool_items[] = { #include "WM_api.h" -static int rna_SculptCapabilities_has_accumulate_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_accumulate_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM6(br->sculpt_tool, @@ -115,19 +114,19 @@ static int rna_SculptCapabilities_has_accumulate_get(PointerRNA *ptr) SCULPT_TOOL_DRAW, SCULPT_TOOL_INFLATE, SCULPT_TOOL_LAYER); } -static int rna_SculptCapabilities_has_auto_smooth_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_auto_smooth_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return !ELEM(br->sculpt_tool, SCULPT_TOOL_MASK, SCULPT_TOOL_SMOOTH); } -static int rna_SculptCapabilities_has_height_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_height_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return br->sculpt_tool == SCULPT_TOOL_LAYER; } -static int rna_SculptCapabilities_has_jitter_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_jitter_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return (!(br->flag & BRUSH_ANCHORED) && @@ -137,13 +136,13 @@ static int rna_SculptCapabilities_has_jitter_get(PointerRNA *ptr) SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)); } -static int rna_SculptCapabilities_has_normal_weight_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_normal_weight_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK); } -static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr) +static int rna_BrushCapabilities_has_overlay_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->mtex.brush_map_mode, @@ -151,38 +150,43 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr) MTEX_MAP_MODE_TILED); } -static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_persistence_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return br->sculpt_tool == SCULPT_TOOL_LAYER; } -static int rna_SculptCapabilities_has_pinch_factor_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_pinch_factor_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->sculpt_tool, SCULPT_TOOL_BLOB, SCULPT_TOOL_CREASE); } -static int rna_SculptCapabilities_has_plane_offset_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_plane_offset_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM5(br->sculpt_tool, SCULPT_TOOL_CLAY, SCULPT_TOOL_CLAY_STRIPS, SCULPT_TOOL_FILL, SCULPT_TOOL_FLATTEN, SCULPT_TOOL_SCRAPE); } -static int rna_SculptCapabilities_has_random_texture_angle_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_random_texture_angle_get(PointerRNA *ptr) +{ + Brush *br = (Brush *)ptr->data; + return (!ELEM4(br->sculpt_tool, + SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, + SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)); +} + +static int rna_BrushCapabilities_has_random_texture_angle_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return (ELEM(br->mtex.brush_map_mode, MTEX_MAP_MODE_VIEW, MTEX_MAP_MODE_AREA) && - !(br->flag & BRUSH_ANCHORED) && - !ELEM4(br->sculpt_tool, - SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, - SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)); + !(br->flag & BRUSH_ANCHORED)); } -static int rna_SculptCapabilities_has_sculpt_plane_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_sculpt_plane_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return !ELEM4(br->sculpt_tool, SCULPT_TOOL_INFLATE, @@ -190,7 +194,7 @@ static int rna_SculptCapabilities_has_sculpt_plane_get(PointerRNA *ptr) SCULPT_TOOL_SMOOTH); } -static int rna_SculptCapabilities_has_secondary_color_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_secondary_color_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM10(br->sculpt_tool, @@ -200,7 +204,7 @@ static int rna_SculptCapabilities_has_secondary_color_get(PointerRNA *ptr) SCULPT_TOOL_SCRAPE); } -static int rna_SculptCapabilities_has_smooth_stroke_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_smooth_stroke_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return (!(br->flag & BRUSH_ANCHORED) && @@ -210,7 +214,7 @@ static int rna_SculptCapabilities_has_smooth_stroke_get(PointerRNA *ptr) SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)); } -static int rna_SculptCapabilities_has_space_attenuation_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_space_attenuation_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ((br->flag & BRUSH_SPACE) && @@ -218,22 +222,19 @@ static int rna_SculptCapabilities_has_space_attenuation_get(PointerRNA *ptr) SCULPT_TOOL_SMOOTH, SCULPT_TOOL_SNAKE_HOOK)); } -static int rna_SculptCapabilities_has_spacing_get(PointerRNA *ptr) +static int rna_BrushCapabilities_has_spacing_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; - return (!(br->flag & BRUSH_ANCHORED) && - !ELEM4(br->sculpt_tool, - SCULPT_TOOL_GRAB, SCULPT_TOOL_ROTATE, - SCULPT_TOOL_SNAKE_HOOK, SCULPT_TOOL_THUMB)); + return (!(br->flag & BRUSH_ANCHORED)); } -static int rna_SculptCapabilities_has_strength_get(PointerRNA *ptr) +static int rna_SculptToolCapabilities_has_strength_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return !ELEM(br->sculpt_tool, SCULPT_TOOL_GRAB, SCULPT_TOOL_SNAKE_HOOK); } -static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr) +static int rna_BrushCapabilities_has_texture_angle_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM3(br->mtex.brush_map_mode, @@ -242,7 +243,7 @@ static int rna_SculptCapabilities_has_texture_angle_get(PointerRNA *ptr) MTEX_MAP_MODE_TILED); } -static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr) +static int rna_BrushCapabilities_has_texture_angle_source_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->mtex.brush_map_mode, @@ -250,9 +251,14 @@ static int rna_SculptCapabilities_has_texture_angle_source_get(PointerRNA *ptr) MTEX_MAP_MODE_AREA); } -static PointerRNA rna_Brush_sculpt_capabilities_get(PointerRNA *ptr) +static PointerRNA rna_Sculpt_sculpt_tool_capabilities_get(PointerRNA *ptr) +{ + return rna_pointer_inherit_refine(ptr, &RNA_SculptToolCapabilities, ptr->id.data); +} + +static PointerRNA rna_Brush_capabilities_get(PointerRNA *ptr) { - return rna_pointer_inherit_refine(ptr, &RNA_SculptCapabilities, ptr->id.data); + return rna_pointer_inherit_refine(ptr, &RNA_BrushCapabilities, ptr->id.data); } static void rna_Brush_reset_icon(Brush *br, const char *UNUSED(type)) @@ -464,41 +470,66 @@ static void rna_def_sculpt_capabilities(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - srna = RNA_def_struct(brna, "SculptCapabilities", NULL); + srna = RNA_def_struct(brna, "SculptToolCapabilities", NULL); RNA_def_struct_sdna(srna, "Brush"); RNA_def_struct_nested(brna, srna, "Brush"); RNA_def_struct_ui_text(srna, "Sculpt Capabilities", "Read-only indications of which brush operations " "are supported by the current sculpt tool"); +#define SCULPT_TOOL_CAPABILITY(prop_name_, ui_name_) \ + prop = RNA_def_property(srna, #prop_name_, \ + PROP_BOOLEAN, PROP_NONE); \ + RNA_def_property_clear_flag(prop, PROP_EDITABLE); \ + RNA_def_property_boolean_funcs(prop, "rna_SculptToolCapabilities_" \ + #prop_name_ "_get", NULL); \ + RNA_def_property_ui_text(prop, ui_name_, NULL) + + SCULPT_TOOL_CAPABILITY(has_accumulate, "Has Accumulate"); + SCULPT_TOOL_CAPABILITY(has_auto_smooth, "Has Auto Smooth"); + SCULPT_TOOL_CAPABILITY(has_height, "Has Height"); + SCULPT_TOOL_CAPABILITY(has_jitter, "Has Jitter"); + SCULPT_TOOL_CAPABILITY(has_normal_weight, "Has Crease/Pinch Factor"); + SCULPT_TOOL_CAPABILITY(has_persistence, "Has Persistence"); + SCULPT_TOOL_CAPABILITY(has_pinch_factor, "Has Pinch Factor"); + SCULPT_TOOL_CAPABILITY(has_plane_offset, "Has Plane Offset"); + SCULPT_TOOL_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle"); + SCULPT_TOOL_CAPABILITY(has_sculpt_plane, "Has Sculpt Plane"); + SCULPT_TOOL_CAPABILITY(has_secondary_color, "Has Secondary Color"); + SCULPT_TOOL_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke"); + SCULPT_TOOL_CAPABILITY(has_space_attenuation, "Has Space Attenuation"); + SCULPT_TOOL_CAPABILITY(has_strength, "Has Strength"); + +#undef SCULPT_CAPABILITY +} + +static void rna_def_brush_capabilities(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "BrushCapabilities", NULL); + RNA_def_struct_sdna(srna, "Brush"); + RNA_def_struct_nested(brna, srna, "Brush"); + RNA_def_struct_ui_text(srna, "Brush Capabilities", + "Read-only indications of which brush operations " + "are supported by the current brush"); + #define BRUSH_CAPABILITY(prop_name_, ui_name_) \ prop = RNA_def_property(srna, #prop_name_, \ PROP_BOOLEAN, PROP_NONE); \ RNA_def_property_clear_flag(prop, PROP_EDITABLE); \ - RNA_def_property_boolean_funcs(prop, "rna_SculptCapabilities_" \ + RNA_def_property_boolean_funcs(prop, "rna_BrushCapabilities_" \ #prop_name_ "_get", NULL); \ RNA_def_property_ui_text(prop, ui_name_, NULL) - BRUSH_CAPABILITY(has_accumulate, "Has Accumulate"); - BRUSH_CAPABILITY(has_auto_smooth, "Has Auto Smooth"); - BRUSH_CAPABILITY(has_height, "Has Height"); - BRUSH_CAPABILITY(has_jitter, "Has Jitter"); - BRUSH_CAPABILITY(has_normal_weight, "Has Crease/Pinch Factor"); BRUSH_CAPABILITY(has_overlay, "Has Overlay"); - BRUSH_CAPABILITY(has_persistence, "Has Persistence"); - BRUSH_CAPABILITY(has_pinch_factor, "Has Pinch Factor"); - BRUSH_CAPABILITY(has_plane_offset, "Has Plane Offset"); BRUSH_CAPABILITY(has_random_texture_angle, "Has Random Texture Angle"); - BRUSH_CAPABILITY(has_sculpt_plane, "Has Sculpt Plane"); - BRUSH_CAPABILITY(has_secondary_color, "Has Secondary Color"); - BRUSH_CAPABILITY(has_smooth_stroke, "Has Smooth Stroke"); - BRUSH_CAPABILITY(has_space_attenuation, "Has Space Attenuation"); - BRUSH_CAPABILITY(has_spacing, "Has Spacing"); - BRUSH_CAPABILITY(has_strength, "Has Strength"); BRUSH_CAPABILITY(has_texture_angle, "Has Texture Angle"); BRUSH_CAPABILITY(has_texture_angle_source, "Has Texture Angle Source"); + BRUSH_CAPABILITY(has_spacing, "Has Spacing"); -#undef SCULPT_CAPABILITY +#undef BRUSH_CAPABILITY } static void rna_def_brush(BlenderRNA *brna) @@ -634,10 +665,17 @@ static void rna_def_brush(BlenderRNA *brna) prop = RNA_def_property(srna, "jitter", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "jitter"); - RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_range(prop, 0.0f, 1000.0f); + RNA_def_property_ui_range(prop, 0.0f, 2.0f, 0.1, 4); RNA_def_property_ui_text(prop, "Jitter", "Jitter the position of the brush while painting"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "jitter_absolute", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "jitter_absolute"); + RNA_def_property_range(prop, 0, 1000000); + RNA_def_property_ui_text(prop, "Jitter", "Jitter the position of the brush in pixels while painting"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "spacing", PROP_INT, PROP_PERCENTAGE); RNA_def_property_int_sdna(prop, NULL, "spacing"); RNA_def_property_range(prop, 1, 1000); @@ -794,6 +832,11 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Rake", "Rotate the brush texture to match the stroke direction"); RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_relative_jitter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BRUSH_ABSOLUTE_JITTER); + RNA_def_property_ui_text(prop, "Absolute Jitter", "Jittering happens in screen space, not relative to brush size"); + RNA_def_property_update(prop, 0, "rna_Brush_update"); + prop = RNA_def_property(srna, "use_random_rotation", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", BRUSH_RANDOM_ROTATION); RNA_def_property_ui_text(prop, "Random Rotation", "Rotate the brush texture at random"); @@ -957,11 +1000,17 @@ static void rna_def_brush(BlenderRNA *brna) RNA_def_property_ui_range(prop, -1.0f, 1.0f, 10.0f, 3); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, "rna_Brush_update"); + prop = RNA_def_property(srna, "brush_capabilities", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_NEVER_NULL); + RNA_def_property_struct_type(prop, "BrushCapabilities"); + RNA_def_property_pointer_funcs(prop, "rna_Brush_capabilities_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Brush Capabilities", "Brush's capabilities"); + /* brush capabilities (mode-dependent) */ prop = RNA_def_property(srna, "sculpt_capabilities", PROP_POINTER, PROP_NONE); RNA_def_property_flag(prop, PROP_NEVER_NULL); - RNA_def_property_struct_type(prop, "SculptCapabilities"); - RNA_def_property_pointer_funcs(prop, "rna_Brush_sculpt_capabilities_get", NULL, NULL, NULL); + RNA_def_property_struct_type(prop, "SculptToolCapabilities"); + RNA_def_property_pointer_funcs(prop, "rna_Sculpt_sculpt_tool_capabilities_get", NULL, NULL, NULL); RNA_def_property_ui_text(prop, "Sculpt Capabilities", "Brush's capabilities in sculpt mode"); } @@ -1023,6 +1072,7 @@ static void rna_def_operator_stroke_element(BlenderRNA *brna) void RNA_def_brush(BlenderRNA *brna) { rna_def_brush(brna); + rna_def_brush_capabilities(brna); rna_def_sculpt_capabilities(brna); rna_def_brush_texture_slot(brna); rna_def_operator_stroke_element(brna); diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 5f11663c057..5743fcf2b9f 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -24,17 +24,16 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_camera_types.h" #include "BLI_math.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_types.h" #ifdef RNA_RUNTIME @@ -186,20 +185,20 @@ void RNA_def_camera(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Clip End", "Camera far clipping distance"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); - prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "lens", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_float_sdna(prop, NULL, "lens"); RNA_def_property_range(prop, 1.0f, 5000.0f); RNA_def_property_ui_text(prop, "Focal Length", "Perspective Camera lens value in millimeters"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); - prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "sensor_width", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_float_sdna(prop, NULL, "sensor_x"); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2); RNA_def_property_ui_text(prop, "Sensor Width", "Horizontal size of the image sensor area in millimeters"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_update"); - prop = RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_NONE); + prop = RNA_def_property(srna, "sensor_height", PROP_FLOAT, PROP_DISTANCE_CAMERA); RNA_def_property_float_sdna(prop, NULL, "sensor_y"); RNA_def_property_range(prop, 1.0f, FLT_MAX); RNA_def_property_ui_range(prop, 1.0f, 100.f, 1, 2); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 69de86da007..1bf15fd0838 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -24,14 +24,9 @@ * \ingroup RNA */ - #include <stdlib.h> #include <limits.h> -#include "RNA_define.h" - -#include "rna_internal.h" - #include "BKE_cloth.h" #include "BKE_modifier.h" @@ -39,6 +34,10 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index f32f28e8143..c5f6744bcbe 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -24,16 +24,17 @@ * \ingroup RNA */ - #include <stdlib.h> #include <stdio.h> -#include "RNA_define.h" -#include "rna_internal.h" - #include "DNA_color_types.h" #include "DNA_texture_types.h" +#include "BLI_utildefines.h" + +#include "RNA_define.h" +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" @@ -415,7 +416,8 @@ static void rna_ColorManagedDisplaySettings_display_device_set(struct PointerRNA } } -static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) +static EnumPropertyItem *rna_ColorManagedDisplaySettings_display_device_itemf(bContext *UNUSED(C), PointerRNA *ptr, + PropertyRNA *UNUSED(prop), int *free) { EnumPropertyItem *items = NULL; int totitem = 0; @@ -462,7 +464,8 @@ static void rna_ColorManagedViewSettings_view_transform_set(PointerRNA *ptr, int } } -static EnumPropertyItem *rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) +static EnumPropertyItem *rna_ColorManagedViewSettings_view_transform_itemf(bContext *C, PointerRNA *ptr, + PropertyRNA *UNUSED(prop), int *free) { Scene *scene = CTX_data_scene(C); EnumPropertyItem *items = NULL; @@ -509,7 +512,8 @@ static void rna_ColorManagedColorspaceSettings_colorspace_set(struct PointerRNA } } -static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *C, PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) +static EnumPropertyItem *rna_ColorManagedColorspaceSettings_colorspace_itemf(bContext *UNUSED(C), PointerRNA *ptr, + PropertyRNA *UNUSED(prop), int *free) { EnumPropertyItem *items = NULL; int totitem = 0; @@ -1015,6 +1019,7 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "ColorManagedInputColorspaceSettings", "Input color space settings"); prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE); + RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); RNA_def_property_enum_items(prop, color_space_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get", "rna_ColorManagedColorspaceSettings_colorspace_set", @@ -1026,6 +1031,7 @@ static void rna_def_colormanage(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "ColorManagedSequencerColorspaceSettings", "Input color space settings"); prop = RNA_def_property(srna, "name", PROP_ENUM, PROP_NONE); + RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); RNA_def_property_enum_items(prop, color_space_items); RNA_def_property_enum_funcs(prop, "rna_ColorManagedColorspaceSettings_colorspace_get", "rna_ColorManagedColorspaceSettings_colorspace_set", diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 956483890f5..4ced8326560 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -24,13 +24,8 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_define.h" - -#include "rna_internal.h" - #include "BLI_math.h" #include "BLF_translation.h" @@ -41,46 +36,73 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "ED_object.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_types.h" +#include "ED_object.h" + /* please keep the names in sync with constraint.c */ EnumPropertyItem constraint_type_items[] = { {0, "", 0, N_("Motion Tracking"), ""}, {CONSTRAINT_TYPE_CAMERASOLVER, "CAMERA_SOLVER", ICON_CONSTRAINT_DATA, "Camera Solver", ""}, {CONSTRAINT_TYPE_OBJECTSOLVER, "OBJECT_SOLVER", ICON_CONSTRAINT_DATA, "Object Solver", ""}, - {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""}, + {CONSTRAINT_TYPE_FOLLOWTRACK, "FOLLOW_TRACK", ICON_CONSTRAINT_DATA, "Follow Track", ""}, {0, "", 0, N_("Transform"), ""}, - {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", ""}, - {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation", ""}, - {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale", ""}, - {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms", ""}, - {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", ""}, - {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location", ""}, - {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation", ""}, - {CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale", ""}, - {CONSTRAINT_TYPE_SAMEVOL, "MAINTAIN_VOLUME", ICON_CONSTRAINT_DATA, "Maintain Volume", ""}, - {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation", ""}, + {CONSTRAINT_TYPE_LOCLIKE, "COPY_LOCATION", ICON_CONSTRAINT_DATA, "Copy Location", + "Copy the location of a target (with an optional offset), so that they move together"}, + {CONSTRAINT_TYPE_ROTLIKE, "COPY_ROTATION", ICON_CONSTRAINT_DATA, "Copy Rotation", + "Copy the rotation of a target (with an optional offset), so that they rotate together"}, + {CONSTRAINT_TYPE_SIZELIKE, "COPY_SCALE", ICON_CONSTRAINT_DATA, "Copy Scale", + "Copy the scale factors of a target (with an optional offset), so that they are scaled by the same amount"}, + {CONSTRAINT_TYPE_TRANSLIKE, "COPY_TRANSFORMS", ICON_CONSTRAINT_DATA, "Copy Transforms", + "Copy all the transformations of a target, so that they move together"}, + {CONSTRAINT_TYPE_DISTLIMIT, "LIMIT_DISTANCE", ICON_CONSTRAINT_DATA, "Limit Distance", + "Restrict movements to within a certain distance of a target (at the time of constraint evaluation only)"}, + {CONSTRAINT_TYPE_LOCLIMIT, "LIMIT_LOCATION", ICON_CONSTRAINT_DATA, "Limit Location", + "Restrict movement along each axis within given ranges"}, + {CONSTRAINT_TYPE_ROTLIMIT, "LIMIT_ROTATION", ICON_CONSTRAINT_DATA, "Limit Rotation", + "Restrict rotation along each axis within given ranges"}, + {CONSTRAINT_TYPE_SIZELIMIT, "LIMIT_SCALE", ICON_CONSTRAINT_DATA, "Limit Scale", + "Restrict scaling along each axis with given ranges"}, + {CONSTRAINT_TYPE_SAMEVOL, "MAINTAIN_VOLUME", ICON_CONSTRAINT_DATA, "Maintain Volume", + "Compensate for scaling one axis by applying suitable scaling to the other two axes"}, + {CONSTRAINT_TYPE_TRANSFORM, "TRANSFORM", ICON_CONSTRAINT_DATA, "Transformation", + "Use one transform property from target to control another (or same) property on owner"}, {0, "", 0, N_("Tracking"), ""}, - {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To", ""}, + {CONSTRAINT_TYPE_CLAMPTO, "CLAMP_TO", ICON_CONSTRAINT_DATA, "Clamp To", + "Restrict movements to lie along a curve by remapping location along curve's longest axis"}, {CONSTRAINT_TYPE_DAMPTRACK, "DAMPED_TRACK", ICON_CONSTRAINT_DATA, "Damped Track", - "Tracking by taking the shortest path"}, - {CONSTRAINT_TYPE_KINEMATIC, "IK", ICON_CONSTRAINT_DATA, "Inverse Kinematics", ""}, + "Point towards a target by performing the smallest rotation necessary"}, + {CONSTRAINT_TYPE_KINEMATIC, "IK", ICON_CONSTRAINT_DATA, "Inverse Kinematics", + "Control a chain of bones by specifying the endpoint target (Bones only)"}, {CONSTRAINT_TYPE_LOCKTRACK, "LOCKED_TRACK", ICON_CONSTRAINT_DATA, "Locked Track", - "Tracking along a single axis"}, - {CONSTRAINT_TYPE_SPLINEIK, "SPLINE_IK", ICON_CONSTRAINT_DATA, "Spline IK", ""}, - {CONSTRAINT_TYPE_STRETCHTO, "STRETCH_TO", ICON_CONSTRAINT_DATA, "Stretch To", ""}, - {CONSTRAINT_TYPE_TRACKTO, "TRACK_TO", ICON_CONSTRAINT_DATA, "Track To", - "Legacy tracking constraint prone to twisting artifacts"}, + "Rotate around the specified ('locked') axis to point towards a target"}, + {CONSTRAINT_TYPE_SPLINEIK, "SPLINE_IK", ICON_CONSTRAINT_DATA, "Spline IK", + "Align chain of bones along a curve (Bones only)"}, + {CONSTRAINT_TYPE_STRETCHTO, "STRETCH_TO", ICON_CONSTRAINT_DATA, "Stretch To", + "Stretch along Y-Axis to point towards a target"}, + {CONSTRAINT_TYPE_TRACKTO, "TRACK_TO", ICON_CONSTRAINT_DATA, "Track To", + "Legacy tracking constraint prone to twisting artifacts"}, {0, "", 0, N_("Relationship"), ""}, - {CONSTRAINT_TYPE_ACTION, "ACTION", ICON_CONSTRAINT_DATA, "Action", ""}, - {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of", ""}, - {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor", ""}, - {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path", ""}, - {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", ""}, - {CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint", ""}, - {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", ""}, - {CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap", ""}, + {CONSTRAINT_TYPE_ACTION, "ACTION", ICON_CONSTRAINT_DATA, "Action", + "Use transform property of target to look up pose for owner from an Action"}, + {CONSTRAINT_TYPE_CHILDOF, "CHILD_OF", ICON_CONSTRAINT_DATA, "Child Of", + "Make target the 'detachable' parent of owner"}, + {CONSTRAINT_TYPE_MINMAX, "FLOOR", ICON_CONSTRAINT_DATA, "Floor", + "Use position (and optionally rotation) of target to define a 'wall' or 'floor' that the owner can not cross"}, + {CONSTRAINT_TYPE_FOLLOWPATH, "FOLLOW_PATH", ICON_CONSTRAINT_DATA, "Follow Path", + "Use to animate an object/bone following a path"}, + {CONSTRAINT_TYPE_PIVOT, "PIVOT", ICON_CONSTRAINT_DATA, "Pivot", + "Change pivot point for transforms (buggy)"}, + {CONSTRAINT_TYPE_RIGIDBODYJOINT, "RIGID_BODY_JOINT", ICON_CONSTRAINT_DATA, "Rigid Body Joint", + "Use to define a Rigid Body Constraint (for Game Engine use only)"}, + {CONSTRAINT_TYPE_PYTHON, "SCRIPT", ICON_CONSTRAINT_DATA, "Script", + "Custom constraint(s) written in Python (Not yet implemented)"}, + {CONSTRAINT_TYPE_SHRINKWRAP, "SHRINKWRAP", ICON_CONSTRAINT_DATA, "Shrinkwrap", + "Restrict movements to surface of target mesh"}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_context.c b/source/blender/makesrna/intern/rna_context.c index 4204506e67b..d7a679e9702 100644 --- a/source/blender/makesrna/intern/rna_context.c +++ b/source/blender/makesrna/intern/rna_context.c @@ -24,17 +24,17 @@ * \ingroup RNA */ - #include <stdlib.h> #include "DNA_ID.h" #include "DNA_userdef_types.h" +#include "BLI_utildefines.h" +#include "BKE_context.h" + #include "RNA_access.h" #include "RNA_define.h" -#include "BKE_context.h" - #include "rna_internal.h" /* own include */ #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_controller.c b/source/blender/makesrna/intern/rna_controller.c index c59e376da82..472cc6e89e6 100644 --- a/source/blender/makesrna/intern/rna_controller.c +++ b/source/blender/makesrna/intern/rna_controller.c @@ -24,15 +24,18 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "WM_types.h" +#include "DNA_object_types.h" +#include "DNA_controller_types.h" + +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_object_types.h" -#include "DNA_controller_types.h" + +#include "WM_types.h" EnumPropertyItem controller_type_items[] = { {CONT_LOGIC_AND, "LOGIC_AND", 0, "And", "Logic And"}, diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index b7ef76eeaf3..dba33bb9ab5 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -26,11 +26,6 @@ #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_material_types.h" @@ -40,6 +35,11 @@ #include "BKE_font.h" +#include "RNA_access.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_types.h" #include "BKE_curve.h" diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c index a505ae0dec2..8d30a0be0f1 100644 --- a/source/blender/makesrna/intern/rna_dynamicpaint.c +++ b/source/blender/makesrna/intern/rna_dynamicpaint.c @@ -24,14 +24,9 @@ * \ingroup RNA */ - #include <stdlib.h> #include <limits.h> -#include "RNA_define.h" - -#include "rna_internal.h" - #include "BLI_math_base.h" #include "BKE_modifier.h" @@ -43,6 +38,10 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_types.h" EnumPropertyItem prop_dynamicpaint_type_items[] = { diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index a91832268e2..f6f8b14d0e2 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -24,15 +24,8 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -43,6 +36,12 @@ #include "BKE_action.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_types.h" #include "ED_keyframing.h" diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 84ff53ee68f..9ff83daa2f8 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -28,6 +28,7 @@ #include "DNA_object_fluidsim.h" +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "RNA_define.h" diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 9461a816652..7156b76bab2 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -24,19 +24,20 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_gpencil_types.h" #include "DNA_scene_types.h" #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_types.h" #ifdef RNA_RUNTIME @@ -547,7 +548,9 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", GP_LAYER_NO_XRAY); RNA_def_property_ui_text(prop, "X Ray", "Make the layer draw in front of objects"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); - + + + /* Layers API */ func = RNA_def_function(srna, "clear", "rna_GPencil_layer_clear"); RNA_def_function_ui_description(func, "Remove all the grease pencil layer data"); } diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index 4baf46fd0b5..1ac59f9caed 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -24,15 +24,16 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "DNA_group_types.h" + +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_group_types.h" - #ifdef RNA_RUNTIME #include "DNA_scene_types.h" diff --git a/source/blender/makesrna/intern/rna_image.c b/source/blender/makesrna/intern/rna_image.c index be462e20ee7..81136193883 100644 --- a/source/blender/makesrna/intern/rna_image.c +++ b/source/blender/makesrna/intern/rna_image.c @@ -24,21 +24,22 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_image_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" + #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_image.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_types.h" #include "WM_api.h" @@ -454,7 +455,6 @@ static void rna_def_imageuser(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "offset"); RNA_def_property_ui_text(prop, "Offset", "Offset the number of the frame to use in the animation"); RNA_def_property_update(prop, 0, "rna_ImageUser_update"); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); prop = RNA_def_property(srna, "frame_start", PROP_INT, PROP_TIME); RNA_def_property_int_sdna(prop, NULL, "sfra"); diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index 5d45e0d23b6..c1769f02974 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -34,13 +34,15 @@ #include <string.h> #include <time.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - #include "DNA_packedFile_types.h" +#include "BLI_utildefines.h" + #include "BIF_gl.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + #include "rna_internal.h" /* own include */ #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 1c0909c946f..550a3d8f353 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -24,12 +24,13 @@ * \ingroup RNA */ - #ifndef __RNA_INTERNAL_H__ #define __RNA_INTERNAL_H__ #include "UI_resources.h" +#include "BLI_utildefines.h" + #include "rna_internal_types.h" #define RNA_MAGIC ((int)~0) @@ -211,9 +212,9 @@ void rna_ID_name_get(struct PointerRNA *ptr, char *value); int rna_ID_name_length(struct PointerRNA *ptr); void rna_ID_name_set(struct PointerRNA *ptr, const char *value); struct StructRNA *rna_ID_refine(struct PointerRNA *ptr); -struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, int create); +struct IDProperty *rna_ID_idprops(struct PointerRNA *ptr, bool create); void rna_ID_fake_user_set(struct PointerRNA *ptr, int value); -struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, int create); +struct IDProperty *rna_PropertyGroup_idprops(struct PointerRNA *ptr, bool create); void rna_PropertyGroup_unregister(struct Main *bmain, struct StructRNA *type); struct StructRNA *rna_PropertyGroup_register(struct Main *bmain, struct ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, @@ -422,6 +423,4 @@ int rna_IDMaterials_assign_int(struct PointerRNA *ptr, int key, const struct Poi void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values); void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values); -#endif /* __RNA_INTERNAL_H__ */ - - +#endif /* __RNA_INTERNAL_H__ */ diff --git a/source/blender/makesrna/intern/rna_internal_types.h b/source/blender/makesrna/intern/rna_internal_types.h index 43ec09de010..1dce89c343d 100644 --- a/source/blender/makesrna/intern/rna_internal_types.h +++ b/source/blender/makesrna/intern/rna_internal_types.h @@ -66,7 +66,7 @@ typedef void (*ContextPropUpdateFunc)(struct bContext *C, struct PointerRNA *ptr typedef void (*ContextUpdateFunc)(struct bContext *C, struct PointerRNA *ptr); typedef int (*EditableFunc)(struct PointerRNA *ptr); typedef int (*ItemEditableFunc)(struct PointerRNA *ptr, int index); -typedef struct IDProperty *(*IDPropertiesFunc)(struct PointerRNA *ptr, int create); +typedef struct IDProperty *(*IDPropertiesFunc)(struct PointerRNA *ptr, bool create); typedef struct StructRNA *(*StructRefineFunc)(struct PointerRNA *ptr); typedef char *(*StructPathFunc)(struct PointerRNA *ptr); diff --git a/source/blender/makesrna/intern/rna_key.c b/source/blender/makesrna/intern/rna_key.c index 33bbaeec282..1577019f22a 100644 --- a/source/blender/makesrna/intern/rna_key.c +++ b/source/blender/makesrna/intern/rna_key.c @@ -24,14 +24,8 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_ID.h" #include "DNA_scene_types.h" #include "DNA_curve_types.h" @@ -39,6 +33,13 @@ #include "DNA_lattice_types.h" #include "DNA_mesh_types.h" +#include "BLI_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #ifdef RNA_RUNTIME #include <stddef.h> diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index 660f6fc6ab7..912f4d914cb 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -24,20 +24,20 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "BLI_math_base.h" + +#include "BLF_translation.h" + #include "RNA_define.h" #include "RNA_enum_types.h" - #include "rna_internal.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" #include "DNA_texture_types.h" -#include "BLI_math_base.h" - #ifdef RNA_RUNTIME #include "MEM_guardedalloc.h" @@ -364,6 +364,7 @@ static void rna_def_lamp(BlenderRNA *brna) prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, lamp_type_items); RNA_def_property_ui_text(prop, "Type", "Type of Lamp"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_LAMP); RNA_def_property_update(prop, 0, "rna_Lamp_draw_update"); prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE); diff --git a/source/blender/makesrna/intern/rna_lattice.c b/source/blender/makesrna/intern/rna_lattice.c index e4a29d9c674..b2790a25e47 100644 --- a/source/blender/makesrna/intern/rna_lattice.c +++ b/source/blender/makesrna/intern/rna_lattice.c @@ -24,19 +24,19 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_curve_types.h" #include "DNA_key_types.h" #include "DNA_lattice_types.h" #include "DNA_meshdata_types.h" +#include "BLI_utildefines.h" + +#include "RNA_define.h" +#include "RNA_enum_types.h" +#include "rna_internal.h" + #ifdef RNA_RUNTIME #include "DNA_object_types.h" diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 32db099c0c0..06a7b4aa11b 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -27,6 +27,7 @@ #include <stdlib.h> #include <string.h> +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "RNA_define.h" diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 75ad64b1f29..de7911aeccb 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -36,8 +36,8 @@ #include "DNA_ID.h" #include "DNA_modifier_types.h" -#include "BLI_path_util.h" #include "BLI_utildefines.h" +#include "BLI_path_util.h" #include "RNA_define.h" #include "RNA_access.h" diff --git a/source/blender/makesrna/intern/rna_mask.c b/source/blender/makesrna/intern/rna_mask.c index 3f23a376ea3..72b0030ee23 100644 --- a/source/blender/makesrna/intern/rna_mask.c +++ b/source/blender/makesrna/intern/rna_mask.c @@ -31,6 +31,10 @@ #include "MEM_guardedalloc.h" +#include "DNA_mask_types.h" +#include "DNA_object_types.h" /* SELECT */ +#include "DNA_scene_types.h" + #include "BKE_movieclip.h" #include "BKE_tracking.h" @@ -39,10 +43,6 @@ #include "rna_internal.h" -#include "DNA_mask_types.h" -#include "DNA_object_types.h" /* SELECT */ -#include "DNA_scene_types.h" - #include "WM_types.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/makesrna/intern/rna_material.c b/source/blender/makesrna/intern/rna_material.c index 35173c290de..d1c81200e6a 100644 --- a/source/blender/makesrna/intern/rna_material.c +++ b/source/blender/makesrna/intern/rna_material.c @@ -24,17 +24,16 @@ * \ingroup RNA */ - #include <float.h> #include <stdlib.h> +#include "DNA_material_types.h" +#include "DNA_texture_types.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_material_types.h" -#include "DNA_texture_types.h" - #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 2fcec014a9c..73d77c2d0c4 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -28,28 +28,27 @@ * \ingroup RNA */ - #include <stdlib.h> #include "MEM_guardedalloc.h" -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_types.h" - -#include "rna_internal.h" - #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" -#include "WM_types.h" - #include "BLI_array.h" #include "BLI_math_base.h" #include "BLI_math_rotation.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_types.h" + +#include "rna_internal.h" + +#include "WM_types.h" + #ifdef RNA_RUNTIME #include "DNA_scene_types.h" @@ -552,7 +551,7 @@ DEFINE_CUSTOMDATA_LAYER_COLLECTION_ACTIVEITEM(uv_layer, ldata, CD_MLOOPUV, rende /* MeshUVLoopLayer */ -static char *rna_MeshUVLoopLayer_path(PointerRNA * ptr) +static char *rna_MeshUVLoopLayer_path(PointerRNA *ptr) { return BLI_sprintfN("uv_layers[\"%s\"]", ((CustomDataLayer *)ptr->data)->name); } diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index 4813f25dea7..f38151fd721 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -24,18 +24,19 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "DNA_mesh_types.h" +#include "DNA_meta_types.h" + +#include "BLI_utildefines.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" #include "rna_internal.h" -#include "DNA_mesh_types.h" -#include "DNA_meta_types.h" - #ifdef RNA_RUNTIME #include "BLI_math.h" diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 810999033a4..fa436e30200 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -29,11 +29,6 @@ #include <limits.h> #include <stdlib.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_armature_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" @@ -53,6 +48,11 @@ #include "BKE_multires.h" #include "BKE_smoke.h" /* For smokeModifier_free & smokeModifier_createType */ +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" @@ -2593,6 +2593,13 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Factor", "Amount to deform object"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "factor"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -10, 10, 1, 3); + RNA_def_property_ui_text(prop, "Angle", "Angle of deformation"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "limits", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "limit"); RNA_def_property_array(prop, 2); @@ -2641,6 +2648,13 @@ static void rna_def_modifier_solidify(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Thickness", "Thickness of the shell"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "thickness_clamp", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "offset_clamp"); + RNA_def_property_range(prop, 0, 100.0); + RNA_def_property_ui_range(prop, 0, 2.0, 0.1, 4); + RNA_def_property_ui_text(prop, "Clamp", "Offset clamp based on geometry scale"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "thickness_vertex_group", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "offset_fac_vg"); RNA_def_property_range(prop, 0.0, 1.0); diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index 3b018591455..cc3d5e5ca5e 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -25,7 +25,6 @@ * \ingroup RNA */ - #include <stdlib.h> #include <limits.h> @@ -34,13 +33,13 @@ #include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "DNA_movieclip_types.h" +#include "DNA_scene_types.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_movieclip_types.h" -#include "DNA_scene_types.h" - #include "WM_types.h" #include "IMB_imbuf_types.h" diff --git a/source/blender/makesrna/intern/rna_nla.c b/source/blender/makesrna/intern/rna_nla.c index 2b7f6a182a0..9afaad96019 100644 --- a/source/blender/makesrna/intern/rna_nla.c +++ b/source/blender/makesrna/intern/rna_nla.c @@ -24,20 +24,21 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_anim_types.h" #include "DNA_action_types.h" #include "DNA_scene_types.h" +#include "BLI_utildefines.h" + #include "MEM_guardedalloc.h" +#include "RNA_access.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 73fe5f3a48d..933b7a78b59 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -27,13 +27,6 @@ #include <stdlib.h> #include <string.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" -#include "rna_internal_types.h" - #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" @@ -54,7 +47,15 @@ #include "BKE_texture.h" #include "BKE_idprop.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" +#include "rna_internal_types.h" + #include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" #include "WM_types.h" @@ -521,6 +522,38 @@ static void rna_Node_material_update(Main *bmain, Scene *scene, PointerRNA *ptr) node_update(bmain, scene, ntree, node); } +static void rna_NodeTree_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + + /* when using border, make it so no old data from outside of + * border is hanging around + * ideally shouldn't be in RNA callback, but how to teach + * compo to only clear frame when border usage is actually + * toggling + */ + if (ntree->flag & NTREE_VIEWER_BORDER) { + Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf) { + if (ibuf->rect) + memset(ibuf->rect, 0, 4 * ibuf->x * ibuf->y); + + if (ibuf->rect_float) + memset(ibuf->rect_float, 0, 4 * ibuf->x * ibuf->y * sizeof(float)); + + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + } + + BKE_image_release_ibuf(ima, ibuf, lock); + } + + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + WM_main_add_notifier(NC_SCENE | ND_NODES, &ntree->id); +} + static void rna_NodeGroup_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->id.data; @@ -1009,6 +1042,16 @@ static bNodeSocket *rna_NodeTree_output_expose(bNodeTree *ntree, ReportList *rep return NULL; } +static void rna_Image_Node_update_id(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + + node->update |= NODE_UPDATE_ID; + node_update(bmain, scene, ntree, node); + node->update &= ~NODE_UPDATE_ID; +} + static void rna_Mapping_Node_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNode *node = ptr->data; @@ -1193,7 +1236,7 @@ static void rna_ShaderNodeScript_bytecode_set(PointerRNA *ptr, const char *value nss->bytecode = NULL; } -static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create) +static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, bool create) { bNode *node = (bNode *)ptr->data; NodeShaderScript *nss = node->storage; @@ -2411,7 +2454,7 @@ static void def_cmp_image(StructRNA *srna) RNA_def_property_struct_type(prop, "Image"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Image", ""); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Image_Node_update_id"); prop = RNA_def_property(srna, "use_straight_alpha_output", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "custom1", CMP_NODE_IMAGE_USE_STRAIGHT_OUTPUT); @@ -4091,7 +4134,7 @@ static void def_cmp_viewer(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", 1); + RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", CMP_NODE_OUTPUT_IGNORE_ALPHA); RNA_def_property_ui_text(prop, "Use Alpha", "Colors are treated alpha premultiplied, or colors output straight (alpha gets set to 1)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -4101,7 +4144,7 @@ static void def_cmp_composite(StructRNA *srna) PropertyRNA *prop; prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", 1); + RNA_def_property_boolean_negative_sdna(prop, NULL, "custom2", CMP_NODE_OUTPUT_IGNORE_ALPHA); RNA_def_property_ui_text(prop, "Use Alpha", "Colors are treated alpha premultiplied, or colors output straight (alpha gets set to 1)"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } @@ -4985,6 +5028,11 @@ static void rna_def_composite_nodetree(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_TWO_PASS); RNA_def_property_ui_text(prop, "Two Pass", "Use two pass execution during editing: first calculate fast nodes, " "second pass calculate all nodes"); + + prop = RNA_def_property(srna, "use_viewer_border", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", NTREE_VIEWER_BORDER); + RNA_def_property_ui_text(prop, "Viewer Border", "Use boundaries for viewer nodes and composite backdrop"); + RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update"); } static void rna_def_shader_nodetree(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 2c736df1ed2..531794f7ab4 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -24,16 +24,9 @@ * \ingroup RNA */ - #include <stdio.h> #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_action_types.h" #include "DNA_customdata_types.h" #include "DNA_controller_types.h" @@ -52,6 +45,12 @@ #include "BKE_tessmesh.h" #include "BKE_group.h" /* needed for object_in_group() */ +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "BLO_sys_types.h" /* needed for intptr_t used in ED_mesh.h */ #include "ED_mesh.h" diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index ec974df54d5..ab8b54334fe 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -24,13 +24,8 @@ * \ingroup RNA */ - #include <stdlib.h> -#include "RNA_define.h" - -#include "rna_internal.h" - #include "DNA_cloth_types.h" #include "DNA_object_types.h" #include "DNA_object_force.h" @@ -38,6 +33,10 @@ #include "DNA_scene_types.h" #include "DNA_smoke_types.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" @@ -484,7 +483,7 @@ static void rna_FieldSettings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), part->pd->tex = NULL; } - if (part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) { + if (part->pd2 && part->pd2->forcefield != PFIELD_TEXTURE && part->pd2->tex) { part->pd2->tex->id.us--; part->pd2->tex = NULL; } diff --git a/source/blender/makesrna/intern/rna_packedfile.c b/source/blender/makesrna/intern/rna_packedfile.c index e691ca46c69..a72188591a1 100644 --- a/source/blender/makesrna/intern/rna_packedfile.c +++ b/source/blender/makesrna/intern/rna_packedfile.c @@ -24,15 +24,16 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "BLI_utildefines.h" + +#include "DNA_packedFile_types.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_packedFile_types.h" - EnumPropertyItem unpack_method_items[] = { {PF_USE_LOCAL, "USE_LOCAL", 0, "Use Local File", ""}, {PF_WRITE_LOCAL, "WRITE_LOCAL", 0, "Write Local File (overwrite existing)", ""}, diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 4bf5de03b05..c675aa6ebc3 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -27,16 +27,10 @@ * \ingroup RNA */ - #include <stdio.h> #include <stdlib.h> #include <limits.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_material_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -48,6 +42,11 @@ #include "DNA_boid_types.h" #include "DNA_texture_types.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_types.h" #include "WM_api.h" diff --git a/source/blender/makesrna/intern/rna_pose.c b/source/blender/makesrna/intern/rna_pose.c index 1ed675962f3..6a1b3d4cfc5 100644 --- a/source/blender/makesrna/intern/rna_pose.c +++ b/source/blender/makesrna/intern/rna_pose.c @@ -159,7 +159,7 @@ static void rna_BoneGroup_name_set(PointerRNA *ptr, const char *value) BLI_uniquename(&ob->pose->agroups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name)); } -static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, int create) +static IDProperty *rna_PoseBone_idprops(PointerRNA *ptr, bool create) { bPoseChannel *pchan = ptr->data; @@ -444,7 +444,7 @@ static void rna_pose_bgroup_name_index_set(PointerRNA *ptr, const char *value, s int a; for (a = 1, grp = pose->agroups.first; grp; grp = grp->next, a++) { - if (strcmp(grp->name, value) == 0) { + if (STREQ(grp->name, value)) { *index = a; return; } @@ -459,7 +459,7 @@ static void rna_pose_pgroup_name_set(PointerRNA *ptr, const char *value, char *r bActionGroup *grp; for (grp = pose->agroups.first; grp; grp = grp->next) { - if (strcmp(grp->name, value) == 0) { + if (STREQ(grp->name, value)) { BLI_strncpy(result, value, maxlen); return; } diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index e2e373d8beb..8cf352311f7 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -28,6 +28,7 @@ #include "DNA_scene_types.h" +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "RNA_define.h" @@ -225,6 +226,20 @@ static StructRNA *rna_RenderEngine_refine(PointerRNA *ptr) return (engine->type && engine->type->ext.srna) ? engine->type->ext.srna : &RNA_RenderEngine; } +static PointerRNA rna_RenderEngine_render_get(PointerRNA *ptr) +{ + RenderEngine *engine = (RenderEngine *)ptr->data; + + if (engine->re) { + RenderData *r = RE_engine_get_render_data(engine->re); + + return rna_pointer_inherit_refine(ptr, &RNA_RenderSettings, r); + } + else { + return rna_pointer_inherit_refine(ptr, &RNA_RenderSettings, NULL); + } +} + static void rna_RenderResult_layers_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) { RenderResult *rr = (RenderResult *)ptr->data; @@ -406,6 +421,12 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "resolution_y"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* Render Data */ + prop = RNA_def_property(srna, "render", PROP_POINTER, PROP_NONE); + RNA_def_property_struct_type(prop, "RenderSettings"); + RNA_def_property_pointer_funcs(prop, "rna_RenderEngine_render_get", NULL, NULL, NULL); + RNA_def_property_ui_text(prop, "Render Data", ""); + prop = RNA_def_property(srna, "use_highlight_tiles", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", RE_ENGINE_HIGHLIGHT_TILES); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 9bd20d854e7..17b01de1eeb 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -24,11 +24,12 @@ * \ingroup RNA */ - #include <stdlib.h> #include "DNA_ID.h" +#include "BLI_utildefines.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" @@ -65,6 +66,7 @@ EnumPropertyItem property_subtype_items[] = { {PROP_ANGLE, "ANGLE", 0, "Angle", ""}, {PROP_TIME, "TIME", 0, "Time", ""}, {PROP_DISTANCE, "DISTANCE", 0, "Distance", ""}, + {PROP_DISTANCE_CAMERA, "DISTANCE_CAMERA", 0, "Camera Distance", ""}, /* number arrays */ {PROP_COLOR, "COLOR", 0, "Color", ""}, @@ -96,6 +98,7 @@ EnumPropertyItem property_unit_items[] = { {PROP_UNIT_TIME, "TIME", 0, "Time", ""}, {PROP_UNIT_VELOCITY, "VELOCITY", 0, "Velocity", ""}, {PROP_UNIT_ACCELERATION, "ACCELERATION", 0, "Acceleration", ""}, + {PROP_UNIT_CAMERA, "CAMERA", 0, "Camera", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 906c8853179..23a3c2188da 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -26,11 +26,6 @@ #include <stdlib.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_brush_types.h" #include "DNA_group_types.h" #include "DNA_modifier_types.h" @@ -49,6 +44,11 @@ #include "BKE_tessmesh.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + /* Include for Bake Options */ #include "RE_engine.h" #include "RE_pipeline.h" @@ -3578,8 +3578,9 @@ static void rna_def_scene_ffmpeg_settings(BlenderRNA *brna) {CODEC_ID_THEORA, "THEORA", 0, "Theora", ""}, {CODEC_ID_FLV1, "FLASH", 0, "Flash Video", ""}, {CODEC_ID_FFV1, "FFV1", 0, "FFmpeg video codec #1", ""}, - {CODEC_ID_QTRLE, "QTRLE", 0, "QTRLE", ""}, + {CODEC_ID_QTRLE, "QTRLE", 0, "QT rle / QT Animation", ""}, {CODEC_ID_DNXHD, "DNXHD", 0, "DNxHD", ""}, + {CODEC_ID_PNG, "PNG", 0, "PNG", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_scene_api.c b/source/blender/makesrna/intern/rna_scene_api.c index b3619330e7a..82f054e62e0 100644 --- a/source/blender/makesrna/intern/rna_scene_api.c +++ b/source/blender/makesrna/intern/rna_scene_api.c @@ -32,6 +32,7 @@ #include <stdlib.h> #include <stdio.h> +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "RNA_define.h" @@ -114,12 +115,13 @@ static void rna_Scene_collada_export( int use_ngons, int use_object_instantiation, int sort_by_name, + int export_transformation_type, int second_life) { collada_export(scene, filepath, apply_modifiers, export_mesh_type, selected, include_children, include_armatures, include_shapekeys, deform_bones_only, active_uv_only, include_uv_textures, include_material_textures, - use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, second_life); + use_texture_copies, use_ngons, use_object_instantiation, sort_by_name, export_transformation_type, second_life); } #endif @@ -165,6 +167,10 @@ void RNA_api_scene(StructRNA *srna) parm = RNA_def_boolean(func, "use_object_instantiation", 1, "Use Object Instances", "Instantiate multiple Objects from same Data"); parm = RNA_def_boolean(func, "sort_by_name", 0, "Sort by Object name", "Sort exported data by Object name"); parm = RNA_def_boolean(func, "second_life", 0, "Export for Second Life", "Compatibility mode for Second Life"); + + parm = RNA_def_int(func, "export_transformation_type", 0, INT_MIN, INT_MAX, + "Transformation", "Transformation type for translation, scale and rotation", INT_MIN, INT_MAX); + RNA_def_function_ui_description(func, "Export to collada file"); #endif } diff --git a/source/blender/makesrna/intern/rna_sculpt_paint.c b/source/blender/makesrna/intern/rna_sculpt_paint.c index e0687295c70..b8b4ad5bb76 100644 --- a/source/blender/makesrna/intern/rna_sculpt_paint.c +++ b/source/blender/makesrna/intern/rna_sculpt_paint.c @@ -451,12 +451,7 @@ static void rna_def_image_paint(BlenderRNA *brna) RNA_def_struct_path_func(srna, "rna_ImagePaintSettings_path"); RNA_def_struct_ui_text(srna, "Image Paint", "Properties of image and texture painting mode"); - /* booleans */ - prop = RNA_def_property(srna, "use_projection", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_DISABLE); - RNA_def_property_ui_text(prop, "Project Paint", - "Use projection painting for improved consistency in the brush strokes"); - + /* booleans */ prop = RNA_def_property(srna, "use_occlude", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", IMAGEPAINT_PROJECT_XRAY); RNA_def_property_ui_text(prop, "Occlude", "Only paint onto the faces directly under the brush (slower)"); diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 6097fa2ae96..547d0ff78c9 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -24,19 +24,20 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "DNA_constraint_types.h" +#include "DNA_object_types.h" +#include "DNA_sensor_types.h" + +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "RNA_enum_types.h" #include "RNA_access.h" #include "rna_internal.h" -#include "DNA_constraint_types.h" -#include "DNA_object_types.h" -#include "DNA_sensor_types.h" - #include "WM_types.h" /* Always keep in alphabetical order */ diff --git a/source/blender/makesrna/intern/rna_sensor_api.c b/source/blender/makesrna/intern/rna_sensor_api.c index d920cbef4a2..476f0589bc9 100644 --- a/source/blender/makesrna/intern/rna_sensor_api.c +++ b/source/blender/makesrna/intern/rna_sensor_api.c @@ -28,15 +28,17 @@ * \ingroup RNA */ - #include <stdlib.h> #include <stdio.h> -#include "WM_types.h" +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "rna_internal.h" /* own include */ +#include "WM_types.h" + #ifdef RNA_RUNTIME #include "BKE_sca.h" diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index a2704619ee6..9b81f042358 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -24,16 +24,9 @@ * \ingroup RNA */ - #include <stdlib.h> #include <limits.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_anim_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -49,6 +42,12 @@ #include "MEM_guardedalloc.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_types.h" #include "BLF_translation.h" diff --git a/source/blender/makesrna/intern/rna_sequencer_api.c b/source/blender/makesrna/intern/rna_sequencer_api.c index 386263c784e..0c58d5cab6b 100644 --- a/source/blender/makesrna/intern/rna_sequencer_api.c +++ b/source/blender/makesrna/intern/rna_sequencer_api.c @@ -28,17 +28,17 @@ #include <stdio.h> #include <string.h> +#include "DNA_scene_types.h" +#include "DNA_sequence_types.h" + +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "RNA_access.h" #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_scene_types.h" -#include "DNA_sequence_types.h" - -#include "BLI_utildefines.h" - #ifdef RNA_RUNTIME //#include "DNA_anim_types.h" diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index f1f4c13731f..4bfc54c25ed 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -24,16 +24,10 @@ * \ingroup RNA */ - #include <stdlib.h> #include "MEM_guardedalloc.h" -#include "RNA_access.h" -#include "RNA_define.h" - -#include "rna_internal.h" - #include "BLF_translation.h" #include "BKE_key.h" @@ -49,6 +43,11 @@ #include "DNA_mask_types.h" #include "DNA_view3d_types.h" +#include "RNA_access.h" +#include "RNA_define.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" @@ -3340,6 +3339,7 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "view"); RNA_def_property_enum_items(prop, view_items); RNA_def_property_ui_text(prop, "View", "Type of the clip editor view"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_CLIP, "rna_SpaceClipEditor_view_type_update"); /* show pattern */ @@ -3513,6 +3513,7 @@ static void rna_def_space_clip(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "gpencil_src"); RNA_def_property_enum_items(prop, gpencil_source_items); RNA_def_property_ui_text(prop, "Grease Pencil Source", "Where the grease pencil comes from"); + RNA_def_property_translation_context(prop, BLF_I18NCONTEXT_ID_MOVIECLIP); RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); /* pivot point */ diff --git a/source/blender/makesrna/intern/rna_text_api.c b/source/blender/makesrna/intern/rna_text_api.c index 5f67f367195..de398bc10a6 100644 --- a/source/blender/makesrna/intern/rna_text_api.c +++ b/source/blender/makesrna/intern/rna_text_api.c @@ -24,10 +24,11 @@ * \ingroup RNA */ - #include <stdlib.h> #include <stdio.h> +#include "BLI_utildefines.h" + #include "RNA_define.h" #include "rna_internal.h" /* own include */ diff --git a/source/blender/makesrna/intern/rna_texture.c b/source/blender/makesrna/intern/rna_texture.c index e007fe67c0b..d86e5fd0d9c 100644 --- a/source/blender/makesrna/intern/rna_texture.c +++ b/source/blender/makesrna/intern/rna_texture.c @@ -24,16 +24,10 @@ * \ingroup RNA */ - #include <float.h> #include <stdio.h> #include <stdlib.h> -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_brush_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" @@ -48,6 +42,11 @@ #include "BKE_node.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + #include "WM_api.h" #include "WM_types.h" @@ -1196,6 +1195,11 @@ static void rna_def_texture_image(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Flip Axis", "Flip the texture's X and Y axis"); RNA_def_property_update(prop, 0, "rna_Texture_update"); + prop = RNA_def_property(srna, "use_alpha", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_USEALPHA); + RNA_def_property_ui_text(prop, "Use Alpha", "Use the alpha channel information in the image"); + RNA_def_property_update(prop, 0, "rna_Texture_update"); + prop = RNA_def_property(srna, "use_calculate_alpha", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "imaflag", TEX_CALCALPHA); RNA_def_property_ui_text(prop, "Calculate Alpha", "Calculate an alpha channel based on RGB values in the image"); diff --git a/source/blender/makesrna/intern/rna_texture_api.c b/source/blender/makesrna/intern/rna_texture_api.c index 218fda361fa..10ac5a9548a 100644 --- a/source/blender/makesrna/intern/rna_texture_api.c +++ b/source/blender/makesrna/intern/rna_texture_api.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <string.h> +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "RNA_define.h" diff --git a/source/blender/makesrna/intern/rna_timeline.c b/source/blender/makesrna/intern/rna_timeline.c index 3842fe95894..a732b550261 100644 --- a/source/blender/makesrna/intern/rna_timeline.c +++ b/source/blender/makesrna/intern/rna_timeline.c @@ -24,15 +24,14 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "DNA_scene_types.h" + #include "RNA_define.h" #include "rna_internal.h" -#include "DNA_scene_types.h" - #include "WM_types.h" #ifdef RNA_RUNTIME diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 798395b9fef..6f0478b5eec 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -113,6 +113,7 @@ static void rna_tracking_active_object_index_set(PointerRNA *ptr, int value) MovieClip *clip = (MovieClip *)ptr->id.data; clip->tracking.objectnr = value; + BKE_tracking_dopesheet_tag_update(&clip->tracking); } static void rna_tracking_active_object_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index e5585b4f72d..05056574a71 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -29,6 +29,8 @@ #include "DNA_screen_types.h" +#include "BLF_translation.h" + #include "RNA_define.h" #include "rna_internal.h" @@ -226,6 +228,7 @@ static StructRNA *rna_Panel_register(Main *bmain, ReportList *reports, void *dat memcpy(pt, &dummypt, sizeof(dummypt)); pt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, pt->idname, &RNA_Panel); + RNA_def_struct_translation_context(pt->ext.srna, pt->translation_context); pt->ext.data = data; pt->ext.call = call; pt->ext.free = free; @@ -573,6 +576,7 @@ static StructRNA *rna_Menu_register(Main *bmain, ReportList *reports, void *data } mt->ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, mt->idname, &RNA_Menu); + RNA_def_struct_translation_context(mt->ext.srna, mt->translation_context); mt->ext.data = data; mt->ext.call = call; mt->ext.free = free; @@ -773,6 +777,7 @@ static void rna_def_panel(BlenderRNA *brna) RNA_def_struct_sdna(srna, "Panel"); RNA_def_struct_refine_func(srna, "rna_Panel_refine"); RNA_def_struct_register_funcs(srna, "rna_Panel_register", "rna_Panel_unregister", NULL); + RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_DEFAULT); /* poll */ func = RNA_def_function(srna, "poll", NULL); @@ -819,7 +824,13 @@ static void rna_def_panel(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Label", "The panel label, shows up in the panel header at the right of the " "triangle used to collapse the panel"); - + + prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->translation_context"); + RNA_def_property_string_default(prop, BLF_I18NCONTEXT_DEFAULT); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_define_verify_sdna(TRUE); + prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "type->space_type"); RNA_def_property_enum_items(prop, space_type_items); @@ -956,6 +967,7 @@ static void rna_def_menu(BlenderRNA *brna) RNA_def_struct_sdna(srna, "Menu"); RNA_def_struct_refine_func(srna, "rna_Menu_refine"); RNA_def_struct_register_funcs(srna, "rna_Menu_register", "rna_Menu_unregister", NULL); + RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_DEFAULT); /* poll */ func = RNA_def_function(srna, "poll", NULL); @@ -972,7 +984,7 @@ static void rna_def_menu(BlenderRNA *brna) parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_define_verify_sdna(0); /* not in sdna */ + RNA_define_verify_sdna(FALSE); /* not in sdna */ prop = RNA_def_property(srna, "layout", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "layout"); @@ -994,6 +1006,11 @@ static void rna_def_menu(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REGISTER); RNA_def_property_ui_text(prop, "Label", "The menu label"); + prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->translation_context"); + RNA_def_property_string_default(prop, BLF_I18NCONTEXT_DEFAULT); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->description"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 0ce98e0b364..0204fa5367b 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -595,7 +595,7 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "label", "rna_uiItemL"); RNA_def_function_ui_description(func, "Item. Display text and/or icon in the layout"); - api_ui_item_common(func); + api_ui_item_common(func); parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED); RNA_def_property_ui_text(parm, "Icon Value", "Override automatic icon of the item " diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 6c6bb560192..c7b5d30e4d1 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -26,12 +26,6 @@ #include <stdlib.h> -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - -#include "rna_internal.h" - #include "DNA_curve_types.h" #include "DNA_space_types.h" #include "DNA_userdef_types.h" @@ -39,16 +33,22 @@ #include "DNA_view3d_types.h" #include "DNA_scene_types.h" -#include "WM_api.h" -#include "WM_types.h" - #include "BLI_utildefines.h" -#include "BLF_translation.h" - #include "BKE_sound.h" #include "BKE_addon.h" +#include "RNA_access.h" +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "rna_internal.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "BLF_translation.h" + #ifdef WITH_CYCLES static EnumPropertyItem compute_device_type_items[] = { {USER_COMPUTE_DEVICE_NONE, "NONE", 0, "None", "Don't use compute device"}, @@ -278,7 +278,8 @@ static void rna_UserDef_weight_color_update(Main *bmain, Scene *scene, PointerRN { Object *ob; - vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL); + bTheme *btheme = UI_GetTheme(); + vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, btheme->tv3d.vertex_unreferenced); for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ob->mode & OB_MODE_WEIGHT_PAINT) @@ -442,7 +443,7 @@ static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), Poi } #endif -static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, int create) +static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, bool create) { if (create && !ptr->data) { IDPropertyTemplate val = {0}; @@ -1164,6 +1165,11 @@ static void rna_def_userdef_theme_spaces_vertex(StructRNA *srna) RNA_def_property_range(prop, 1, 10); RNA_def_property_ui_text(prop, "Vertex Size", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "vertex_unreferenced", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Vertex Group Unreferenced", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_spaces_edge(StructRNA *srna) @@ -3464,6 +3470,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "GPU Mipmap Generation", "Generate Image Mipmaps on the GPU"); RNA_def_property_update(prop, 0, "rna_userdef_gl_gpu_mipmaps"); + prop = RNA_def_property(srna, "image_gpubuffer_limit", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "image_gpubuffer_limit"); + RNA_def_property_range(prop, 0, 128); + RNA_def_property_ui_text(prop, "Image GPU draw limit", "If set, amount of Mega Pixels to use for drawing Images as GPU textures"); + + prop = RNA_def_property(srna, "use_vertex_buffer_objects", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "gameflags", USER_DISABLE_VBO); RNA_def_property_ui_text(prop, "VBOs", diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 0c1c5d8f64a..f42197ec0a9 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -24,20 +24,23 @@ * \ingroup RNA */ - #include <stdlib.h> +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLI_utildefines.h" + +#include "BLF_translation.h" + #include "RNA_access.h" #include "RNA_define.h" #include "RNA_enum_types.h" #include "rna_internal.h" -#include "DNA_screen_types.h" -#include "DNA_space_types.h" -#include "DNA_userdef_types.h" -#include "DNA_windowmanager_types.h" - #include "WM_types.h" EnumPropertyItem event_keymouse_value_items[] = { @@ -466,7 +469,7 @@ static StructRNA *rna_OperatorProperties_refine(PointerRNA *ptr) return ptr->type; } -static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, int create) +static IDProperty *rna_OperatorProperties_idprops(PointerRNA *ptr, bool create) { if (create && !ptr->data) { IDPropertyTemplate val = {0}; @@ -946,7 +949,7 @@ static int operator_check(bContext *C, wmOperator *op) return result; } -static int operator_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int operator_invoke(bContext *C, wmOperator *op, const wmEvent *event) { extern FunctionRNA rna_Operator_invoke_func; @@ -973,7 +976,7 @@ static int operator_invoke(bContext *C, wmOperator *op, wmEvent *event) } /* same as invoke */ -static int operator_modal(bContext *C, wmOperator *op, wmEvent *event) +static int operator_modal(bContext *C, wmOperator *op, const wmEvent *event) { extern FunctionRNA rna_Operator_modal_func; @@ -1049,6 +1052,7 @@ void macro_wrapper(wmOperatorType *ot, void *userdata); static char _operator_idname[OP_MAX_TYPENAME]; static char _operator_name[OP_MAX_TYPENAME]; static char _operator_descr[RNA_DYN_DESCR_MAX]; +static char _operator_ctxt[RNA_DYN_DESCR_MAX]; static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void *data, const char *identifier, StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free) { @@ -1062,10 +1066,13 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */ dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */ dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */ + dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */ RNA_pointer_create(NULL, &RNA_Operator, &dummyop, &dummyotr); /* clear in case they are left unset */ _operator_idname[0] = _operator_name[0] = _operator_descr[0] = '\0'; + /* We have to set default op context! */ + strcpy(_operator_ctxt, BLF_I18NCONTEXT_OPERATOR_DEFAULT); /* validate the python class */ if (validate(&dummyotr, data, have_function) != 0) @@ -1116,9 +1123,10 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * int idlen = strlen(_operator_idname) + 4; int namelen = strlen(_operator_name) + 1; int desclen = strlen(_operator_descr) + 1; + int ctxtlen = strlen(_operator_ctxt) + 1; char *ch; /* 2 terminators and 3 to convert a.b -> A_OT_b */ - ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen), "_operator_idname"); + ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen), "_operator_idname"); WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */ dummyot.idname = ch; ch += idlen; @@ -1127,6 +1135,9 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * ch += namelen; strcpy(ch, _operator_descr); dummyot.description = ch; + ch += desclen; + strcpy(ch, _operator_ctxt); + dummyot.translation_context = ch; } } @@ -1143,6 +1154,7 @@ static StructRNA *rna_Operator_register(Main *bmain, ReportList *reports, void * /* create a new operator type */ dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator); RNA_def_struct_flag(dummyot.ext.srna, STRUCT_NO_IDPROPERTIES); /* operator properties are registered separately */ + RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context); dummyot.ext.data = data; dummyot.ext.call = call; dummyot.ext.free = free; @@ -1181,8 +1193,14 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v dummyot.idname = _operator_idname; /* only assigne the pointer, string is NULL'd */ dummyot.name = _operator_name; /* only assigne the pointer, string is NULL'd */ dummyot.description = _operator_descr; /* only assigne the pointer, string is NULL'd */ + dummyot.translation_context = _operator_ctxt; /* only assigne the pointer, string is NULL'd */ RNA_pointer_create(NULL, &RNA_Macro, &dummyop, &dummyotr); + /* clear in case they are left unset */ + _operator_idname[0] = _operator_name[0] = _operator_descr[0] = '\0'; + /* We have to set default op context! */ + strcpy(_operator_ctxt, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + /* validate the python class */ if (validate(&dummyotr, data, have_function) != 0) return NULL; @@ -1192,9 +1210,10 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v int idlen = strlen(_operator_idname) + 4; int namelen = strlen(_operator_name) + 1; int desclen = strlen(_operator_descr) + 1; + int ctxtlen = strlen(_operator_ctxt) + 1; char *ch; /* 2 terminators and 3 to convert a.b -> A_OT_b */ - ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen), "_operator_idname"); + ch = MEM_callocN(sizeof(char) * (idlen + namelen + desclen + ctxtlen), "_operator_idname"); WM_operator_bl_idname(ch, _operator_idname); /* convert the idname from python */ dummyot.idname = ch; ch += idlen; @@ -1203,6 +1222,9 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v ch += namelen; strcpy(ch, _operator_descr); dummyot.description = ch; + ch += desclen; + strcpy(ch, _operator_ctxt); + dummyot.translation_context = ch; } if (strlen(identifier) >= sizeof(dummyop.idname)) { @@ -1223,6 +1245,7 @@ static StructRNA *rna_MacroOperator_register(Main *bmain, ReportList *reports, v /* create a new operator type */ dummyot.ext.srna = RNA_def_struct_ptr(&BLENDER_RNA, dummyot.idname, &RNA_Operator); + RNA_def_struct_translation_context(dummyot.ext.srna, dummyot.translation_context); dummyot.ext.data = data; dummyot.ext.call = call; dummyot.ext.free = free; @@ -1272,6 +1295,16 @@ static void rna_Operator_bl_label_set(PointerRNA *ptr, const char *value) assert(!"setting the bl_label on a non-builtin operator"); } +static void rna_Operator_bl_translation_context_set(PointerRNA *ptr, const char *value) +{ + wmOperator *data = (wmOperator *)(ptr->data); + char *str = (char *)data->type->translation_context; + if (!str[0]) + BLI_strncpy(str, value, RNA_DYN_DESCR_MAX); /* utf8 already ensured */ + else + assert(!"setting the bl_translation_context on a non-builtin operator"); +} + static void rna_Operator_bl_description_set(PointerRNA *ptr, const char *value) { wmOperator *data = (wmOperator *)(ptr->data); @@ -1302,6 +1335,7 @@ static void rna_def_operator(BlenderRNA *brna) #ifdef WITH_PYTHON RNA_def_struct_register_funcs(srna, "rna_Operator_register", "rna_Operator_unregister", "rna_Operator_instance"); #endif + RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1340,6 +1374,14 @@ static void rna_def_operator(BlenderRNA *brna) /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */ RNA_def_property_flag(prop, PROP_REGISTER); + prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->translation_context"); + RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_translation_context_set"); + RNA_def_property_string_default(prop, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */ + prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->description"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ @@ -1376,6 +1418,7 @@ static void rna_def_macro_operator(BlenderRNA *brna) RNA_def_struct_register_funcs(srna, "rna_MacroOperator_register", "rna_Operator_unregister", "rna_Operator_instance"); #endif + RNA_def_struct_translation_context(srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); @@ -1404,6 +1447,14 @@ static void rna_def_macro_operator(BlenderRNA *brna) /* RNA_def_property_clear_flag(prop, PROP_EDITABLE); */ RNA_def_property_flag(prop, PROP_REGISTER); + prop = RNA_def_property(srna, "bl_translation_context", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->translation_context"); + RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_Operator_bl_translation_context_set"); + RNA_def_property_string_default(prop, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL); + RNA_def_property_clear_flag(prop, PROP_NEVER_NULL); /* check for NULL */ + prop = RNA_def_property(srna, "bl_description", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "type->description"); RNA_def_property_string_maxlength(prop, RNA_DYN_DESCR_MAX); /* else it uses the pointer size! */ diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index b7895cc0e2d..64c5f7ae220 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -86,6 +86,16 @@ static void rna_event_timer_remove(struct wmWindowManager *wm, wmTimer *timer) WM_event_remove_timer(wm, timer->win, timer); } +/* wrap these because of 'const wmEvent *' */ +static int rna_Operator_confirm(bContext *C, wmOperator *op, wmEvent *event) +{ + return WM_operator_confirm(C, op, event); +} +static int rna_Operator_props_popup(bContext *C, wmOperator *op, wmEvent *event) +{ + return WM_operator_props_popup(C, op, event); +} + 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, int head) { @@ -266,7 +276,7 @@ void RNA_api_wm(StructRNA *srna) /* invoke functions, for use with python */ - func = RNA_def_function(srna, "invoke_props_popup", "WM_operator_props_popup"); + func = RNA_def_function(srna, "invoke_props_popup", "rna_Operator_props_popup"); RNA_def_function_ui_description(func, "Operator popup invoke"); rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN); @@ -284,7 +294,7 @@ void RNA_api_wm(StructRNA *srna) RNA_def_function_ui_description(func, "Operator popup invoke"); rna_generic_op_invoke(func, WM_GEN_INVOKE_SIZE | WM_GEN_INVOKE_RETURN); - func = RNA_def_function(srna, "invoke_confirm", "WM_operator_confirm"); + func = RNA_def_function(srna, "invoke_confirm", "rna_Operator_confirm"); RNA_def_function_ui_description(func, "Operator confirmation"); rna_generic_op_invoke(func, WM_GEN_INVOKE_EVENT | WM_GEN_INVOKE_RETURN); diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 3ca2c364345..bc65b27be0c 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -338,7 +338,6 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, /* offset matrix */ float offset[4][4]; float final_offset[4][4]; - float tmp_mat[4][4]; float length = amd->length; int count = amd->count, maxVerts; int *indexMap = NULL; @@ -418,6 +417,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, unit_m4(final_offset); for (j = 0; j < count - 1; j++) { + float tmp_mat[4][4]; mult_m4_m4m4(tmp_mat, offset, final_offset); copy_m4_m4(final_offset, tmp_mat); } diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 1942fe12a54..b14c4ba0ad1 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -160,7 +160,8 @@ static DerivedMesh *applyModifier(ModifierData *md, struct Object *ob, } BM_mesh_bevel(bm, bmd->value, bmd->res, - vertex_only, bmd->lim_flags & BME_BEVEL_WEIGHT, dvert, vgroup); + vertex_only, bmd->lim_flags & BME_BEVEL_WEIGHT, true, + dvert, vgroup); result = CDDM_from_bmesh(bm, TRUE); diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index c5a756733f5..0f5f9db2ee6 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -230,7 +230,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *UNUSED(ob), /* copy the vertices across */ for (hashIter = BLI_ghashIterator_new(vertHash); - !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_notDone(hashIter); BLI_ghashIterator_step(hashIter) ) { diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 54f3efcc84c..808dfbae810 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -155,7 +155,6 @@ static void copyData(ModifierData *md, ModifierData *target) if (clmd->sim_parms->effector_weights) tclmd->sim_parms->effector_weights = MEM_dupallocN(clmd->sim_parms->effector_weights); tclmd->coll_parms = MEM_dupallocN(clmd->coll_parms); - tclmd->point_cache = BKE_ptcache_copy_list(&tclmd->ptcaches, &clmd->ptcaches, FALSE); tclmd->clothObject = NULL; } diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 62da82a2af1..743cd1a829e 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -100,7 +100,6 @@ static void delete_void_pointer(void *data) { if (data) { MEM_freeN(data); - data = NULL; } } @@ -242,7 +241,7 @@ static CustomDataMask required_data_mask(Object *UNUSED(ob), ModifierData *md) static float average_area_quad_v3(float *v1, float *v2, float *v3, float *v4) { - float areaq = 0.0f; + float areaq; areaq = area_tri_v3(v1, v2, v3) + area_tri_v3(v1, v2, v4) + area_tri_v3(v1, v3, v4); return areaq / 2.0f; } @@ -520,7 +519,7 @@ static void fill_laplacian_matrix(LaplacianSystem *sys) } } -static void validate_solution(LaplacianSystem * sys, short flag, float lambda, float lambda_border) +static void validate_solution(LaplacianSystem *sys, short flag, float lambda, float lambda_border) { int i; float lam; diff --git a/source/blender/modifiers/intern/MOD_mask.c b/source/blender/modifiers/intern/MOD_mask.c index 23ce8cdeb21..b86802340dc 100644 --- a/source/blender/modifiers/intern/MOD_mask.c +++ b/source/blender/modifiers/intern/MOD_mask.c @@ -316,7 +316,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* using ghash-iterators, map data into new mesh */ /* vertices */ for (hashIter = BLI_ghashIterator_new(vertHash); - !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_notDone(hashIter); BLI_ghashIterator_step(hashIter) ) { MVert source; @@ -334,7 +334,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* edges */ for (hashIter = BLI_ghashIterator_new(edgeHash); - !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_notDone(hashIter); BLI_ghashIterator_step(hashIter)) { MEdge source; @@ -355,7 +355,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, /* faces */ for (hashIter = BLI_ghashIterator_new(polyHash); - !BLI_ghashIterator_isDone(hashIter); + BLI_ghashIterator_notDone(hashIter); BLI_ghashIterator_step(hashIter) ) { int oldIndex = GET_INT_FROM_POINTER(BLI_ghashIterator_getKey(hashIter)); diff --git a/source/blender/modifiers/intern/MOD_meshcache_pc2.c b/source/blender/modifiers/intern/MOD_meshcache_pc2.c index 1ecb347d174..b20f62a8e77 100644 --- a/source/blender/modifiers/intern/MOD_meshcache_pc2.c +++ b/source/blender/modifiers/intern/MOD_meshcache_pc2.c @@ -62,7 +62,7 @@ static bool meshcache_read_pc2_head(FILE *fp, const int verts_tot, } #ifdef __BIG_ENDIAN__ - BLI_endian_switch_int32_array(&pc2_head->huh, (sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int)); + BLI_endian_switch_int32_array(&pc2_head->file_version, (sizeof(*pc2_head) - sizeof(pc2_head->header)) / sizeof(int)); #endif if (pc2_head->verts_tot != verts_tot) { diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 4984682455a..63dcb5d942d 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -209,7 +209,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, if (psys == NULL || psys->totpart == 0) return derivedData; } - else return derivedData; + else { + return derivedData; + } if (pimd->flag & eParticleInstanceFlag_Parents) totpart += psys->totpart; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 81c53185825..c10e10350db 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -869,7 +869,7 @@ static DerivedMesh *subdivide_base(DerivedMesh *orig) if (vg) { vg->def_nr = dv1->dw[j].def_nr; vg->w1 = dv1->dw[j].weight; - vg->w1 = dv2->dw[k].weight; + vg->w2 = dv2->dw[k].weight; } } } diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index a198eaf8ca9..9cdd52f2375 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -251,7 +251,8 @@ static DerivedMesh *applyModifier( const float ofs_new = smd->offset + ofs_orig; const float offset_fac_vg = smd->offset_fac_vg; const float offset_fac_vg_inv = 1.0f - smd->offset_fac_vg; - const int do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0; + const bool do_flip = (smd->flag & MOD_SOLIDIFY_FLIP) != 0; + const bool do_clamp = (smd->offset_clamp != 0.0f); /* weights */ MDeformVert *dvert, *dv = NULL; @@ -423,6 +424,20 @@ static DerivedMesh *applyModifier( float scalar_short; float scalar_short_vgroup; + /* for clamping */ + float *vert_lens = NULL; + const float offset = fabsf(smd->offset) * smd->offset_clamp; + const float offset_sq = offset * offset; + + if (do_clamp) { + vert_lens = MEM_callocN(sizeof(float) * numVerts, "vert_lens"); + fill_vn_fl(vert_lens, numVerts, FLT_MAX); + for (i = 0; i < numEdges; i++) { + const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); + vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len); + vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len); + } + } if (ofs_new != 0.0f) { scalar_short = scalar_short_vgroup = ofs_new / 32767.0f; @@ -435,6 +450,16 @@ static DerivedMesh *applyModifier( scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short; dv++; } + if (do_clamp) { + /* always reset becaise we may have set before */ + if (dv == NULL) { + scalar_short_vgroup = scalar_short; + } + if (vert_lens[i] < offset_sq) { + float scalar = sqrtf(vert_lens[i]) / offset; + scalar_short_vgroup *= scalar; + } + } madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup); } } @@ -450,9 +475,23 @@ static DerivedMesh *applyModifier( scalar_short_vgroup = (offset_fac_vg + (scalar_short_vgroup * offset_fac_vg_inv)) * scalar_short; dv++; } + if (do_clamp) { + /* always reset becaise we may have set before */ + if (dv == NULL) { + scalar_short_vgroup = scalar_short; + } + if (vert_lens[i] < offset_sq) { + float scalar = sqrtf(vert_lens[i]) / offset; + scalar_short_vgroup *= scalar; + } + } madd_v3v3short_fl(mv->co, mv->no, scalar_short_vgroup); } } + + if (do_clamp) { + MEM_freeN(vert_lens); + } } else { /* make a face normal layer if not present */ @@ -540,6 +579,25 @@ static DerivedMesh *applyModifier( } } + if (do_clamp) { + float *vert_lens = MEM_callocN(sizeof(float) * numVerts, "vert_lens"); + const float offset = fabsf(smd->offset) * smd->offset_clamp; + const float offset_sq = offset * offset; + fill_vn_fl(vert_lens, numVerts, FLT_MAX); + for (i = 0; i < numEdges; i++) { + const float ed_len = len_squared_v3v3(mvert[medge[i].v1].co, mvert[medge[i].v2].co); + vert_lens[medge[i].v1] = min_ff(vert_lens[medge[i].v1], ed_len); + vert_lens[medge[i].v2] = min_ff(vert_lens[medge[i].v2], ed_len); + } + for (i = 0; i < numVerts; i++) { + if (vert_lens[i] < offset_sq) { + float scalar = sqrtf(vert_lens[i]) / offset; + vert_angles[i] *= scalar; + } + } + MEM_freeN(vert_lens); + } + if (ofs_new) { mv = mvert + (((ofs_new >= ofs_orig) == do_flip) ? numVerts : 0); diff --git a/source/blender/nodes/composite/nodes/node_composite_outputFile.c b/source/blender/nodes/composite/nodes/node_composite_outputFile.c index dff09b93845..d9a146ddaad 100644 --- a/source/blender/nodes/composite/nodes/node_composite_outputFile.c +++ b/source/blender/nodes/composite/nodes/node_composite_outputFile.c @@ -31,6 +31,7 @@ #include <string.h> +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "node_composite_util.h" @@ -44,7 +45,7 @@ /* **************** OUTPUT FILE ******************** */ /* find unique path */ -static int unique_path_unique_check(void *arg, const char *name) +static bool unique_path_unique_check(void *arg, const char *name) { struct {ListBase *lb; bNodeSocket *sock;} *data= arg; bNodeSocket *sock; @@ -52,10 +53,10 @@ static int unique_path_unique_check(void *arg, const char *name) if (sock != data->sock) { NodeImageMultiFileSocket *sockdata = sock->storage; if (strcmp(sockdata->path, name)==0) - return 1; + return true; } } - return 0; + return false; } void ntreeCompositOutputFileUniquePath(ListBase *list, bNodeSocket *sock, const char defname[], char delim) { @@ -73,7 +74,7 @@ void ntreeCompositOutputFileUniquePath(ListBase *list, bNodeSocket *sock, const } /* find unique EXR layer */ -static int unique_layer_unique_check(void *arg, const char *name) +static bool unique_layer_unique_check(void *arg, const char *name) { struct {ListBase *lb; bNodeSocket *sock;} *data= arg; bNodeSocket *sock; @@ -81,10 +82,10 @@ static int unique_layer_unique_check(void *arg, const char *name) if (sock != data->sock) { NodeImageMultiFileSocket *sockdata = sock->storage; if (strcmp(sockdata->layer, name)==0) - return 1; + return true; } } - return 0; + return false; } void ntreeCompositOutputFileUniqueLayer(ListBase *list, bNodeSocket *sock, const char defname[], char delim) { diff --git a/source/blender/nodes/composite/nodes/node_composite_trackpos.c b/source/blender/nodes/composite/nodes/node_composite_trackpos.c index 8014e879894..1583680720a 100644 --- a/source/blender/nodes/composite/nodes/node_composite_trackpos.c +++ b/source/blender/nodes/composite/nodes/node_composite_trackpos.c @@ -34,8 +34,8 @@ #include "node_composite_util.h" static bNodeSocketTemplate cmp_node_trackpos_out[] = { - { SOCK_FLOAT, 1, N_("X")}, - { SOCK_FLOAT, 1, N_("Y")}, + { SOCK_FLOAT, 0, N_("X")}, + { SOCK_FLOAT, 0, N_("Y")}, { -1, 0, "" } }; diff --git a/source/blender/python/bmesh/bmesh_py_ops.c b/source/blender/python/bmesh/bmesh_py_ops.c index 0a2091af5df..cc87d34d769 100644 --- a/source/blender/python/bmesh/bmesh_py_ops.c +++ b/source/blender/python/bmesh/bmesh_py_ops.c @@ -159,7 +159,7 @@ static PyObject *bpy_bmesh_ops_fakemod_getattro(PyObject *UNUSED(self), PyObject const char *opname = _PyUnicode_AsString(pyname); for (i = 0; i < tot; i++) { - if (strcmp(bmo_opdefines[i]->opname, opname) == 0) { + if (STREQ(bmo_opdefines[i]->opname, opname)) { return bpy_bmesh_op_CreatePyObject(opname); } } diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index fad3e4a35cd..4d728b76707 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -727,7 +727,7 @@ PyObject *BPy_BMO_call(BPy_BMeshOpFunc *self, PyObject *args, PyObject *kw) return NULL; } - slot = BMO_slot_get(bmop.slots_in, slot_name); + slot = BMO_slot_get(bmop.slots_in, slot_name); /* now assign the value */ if (bpy_slot_from_py(bm, &bmop, slot, value, diff --git a/source/blender/python/bmesh/bmesh_py_types.h b/source/blender/python/bmesh/bmesh_py_types.h index 8e6d04ec9ba..f02b94be526 100644 --- a/source/blender/python/bmesh/bmesh_py_types.h +++ b/source/blender/python/bmesh/bmesh_py_types.h @@ -168,7 +168,7 @@ int BPy_BMElem_CheckHType(PyTypeObject *type, const char htype); char *BPy_BMElem_StringFromHType_ex(const char htype, char ret[32]); char *BPy_BMElem_StringFromHType(const char htype); -void bpy_bm_generic_invalidate(BPy_BMGeneric *self); +// void bpy_bm_generic_invalidate(BPy_BMGeneric *self); int bpy_bm_generic_valid_check(BPy_BMGeneric *self); int bpy_bm_generic_valid_check_source(BPy_BMGeneric *self, BMesh *bm_source, const char *error_prefix); diff --git a/source/blender/python/bmesh/bmesh_py_types_meshdata.h b/source/blender/python/bmesh/bmesh_py_types_meshdata.h index c9e8dce97a0..8280e5c3bc5 100644 --- a/source/blender/python/bmesh/bmesh_py_types_meshdata.h +++ b/source/blender/python/bmesh/bmesh_py_types_meshdata.h @@ -51,9 +51,6 @@ PyObject *BPy_BMTexPoly_CreatePyObject(struct MTexPoly *mloopuv); int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value); PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data); -int BPy_BMLoopUV_AssignPyObject(struct MLoopUV *data, PyObject *value); -PyObject *BPy_BMLoopUV_CreatePyObject(struct MLoopUV *data); - int BPy_BMLoopColor_AssignPyObject(struct MLoopCol *data, PyObject *value); PyObject *BPy_BMLoopColor_CreatePyObject(struct MLoopCol *data); diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index a0e2f1a0854..85bb8125a3a 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -470,7 +470,9 @@ const char *BPy_IDProperty_Map_ValidateAndCreate(PyObject *name_obj, IDProperty Py_XDECREF(keys); Py_XDECREF(vals); } - else return "invalid property value"; + else { + return "invalid property value"; + } if (group->type == IDP_IDPARRAY) { IDP_AppendArray(group, prop); diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 56d9e2ac0dd..2876d7666f4 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -751,7 +751,7 @@ void *PyC_RNA_AsPointer(PyObject *value, const char *type_name) PyObject *as_pointer; PyObject *pointer; - if (!strcmp(Py_TYPE(value)->tp_name, type_name) && + if (STREQ(Py_TYPE(value)->tp_name, type_name) && (as_pointer = PyObject_GetAttrString(value, "as_pointer")) != NULL && PyCallable_Check(as_pointer)) { @@ -804,7 +804,7 @@ char *PyC_FlagSet_AsString(PyC_FlagSet *item) int PyC_FlagSet_ValueFromID_int(PyC_FlagSet *item, const char *identifier, int *value) { for ( ; item->identifier; item++) { - if (strcmp(item->identifier, identifier) == 0) { + if (STREQ(item->identifier, identifier)) { *value = item->value; return 1; } diff --git a/source/blender/python/intern/bpy.c b/source/blender/python/intern/bpy.c index 1f8385288bd..01567a87fdf 100644 --- a/source/blender/python/intern/bpy.c +++ b/source/blender/python/intern/bpy.c @@ -32,13 +32,17 @@ #include <Python.h> -#include "RNA_types.h" -#include "RNA_access.h" - +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "BLI_string.h" + +#include "BKE_main.h" +#include "BKE_global.h" /* XXX, G.main only */ +#include "BKE_blender.h" #include "BKE_bpath.h" -#include "BLI_utildefines.h" + +#include "RNA_types.h" +#include "RNA_access.h" #include "bpy.h" #include "bpy_util.h" @@ -48,10 +52,6 @@ #include "bpy_library.h" #include "bpy_operator.h" -#include "BKE_main.h" -#include "BKE_global.h" /* XXX, G.main only */ -#include "BKE_blender.h" - #include "MEM_guardedalloc.h" /* external util modules */ @@ -78,7 +78,7 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self)) { PyObject *ret = PyTuple_New(2); PyObject *item; - char *path; + const char *path; path = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, NULL); item = PyUnicode_DecodeFSDefault(path ? path : ""); @@ -151,16 +151,16 @@ static PyObject *bpy_user_resource(PyObject *UNUSED(self), PyObject *args, PyObj int folder_id; static const char *kwlist[] = {"type", "subdir", NULL}; - char *path; + const char *path; if (!PyArg_ParseTupleAndKeywords(args, kw, "s|s:user_resource", (char **)kwlist, &type, &subdir)) return NULL; /* stupid string compare */ - if (!strcmp(type, "DATAFILES")) folder_id = BLENDER_USER_DATAFILES; - else if (!strcmp(type, "CONFIG")) folder_id = BLENDER_USER_CONFIG; - else if (!strcmp(type, "SCRIPTS")) folder_id = BLENDER_USER_SCRIPTS; - else if (!strcmp(type, "AUTOSAVE")) folder_id = BLENDER_USER_AUTOSAVE; + if (STREQ(type, "DATAFILES")) folder_id = BLENDER_USER_DATAFILES; + else if (STREQ(type, "CONFIG")) folder_id = BLENDER_USER_CONFIG; + else if (STREQ(type, "SCRIPTS")) folder_id = BLENDER_USER_SCRIPTS; + else if (STREQ(type, "AUTOSAVE")) folder_id = BLENDER_USER_AUTOSAVE; else { PyErr_SetString(PyExc_ValueError, "invalid resource argument"); return NULL; @@ -195,15 +195,15 @@ static PyObject *bpy_resource_path(PyObject *UNUSED(self), PyObject *args, PyObj int major = BLENDER_VERSION / 100, minor = BLENDER_VERSION % 100; static const char *kwlist[] = {"type", "major", "minor", NULL}; int folder_id; - char *path; + const char *path; if (!PyArg_ParseTupleAndKeywords(args, kw, "s|ii:resource_path", (char **)kwlist, &type, &major, &minor)) return NULL; /* stupid string compare */ - if (!strcmp(type, "USER")) folder_id = BLENDER_RESOURCE_PATH_USER; - else if (!strcmp(type, "LOCAL")) folder_id = BLENDER_RESOURCE_PATH_LOCAL; - else if (!strcmp(type, "SYSTEM")) folder_id = BLENDER_RESOURCE_PATH_SYSTEM; + if (STREQ(type, "USER")) folder_id = BLENDER_RESOURCE_PATH_USER; + else if (STREQ(type, "LOCAL")) folder_id = BLENDER_RESOURCE_PATH_LOCAL; + else if (STREQ(type, "SYSTEM")) folder_id = BLENDER_RESOURCE_PATH_SYSTEM; else { PyErr_SetString(PyExc_ValueError, "invalid resource argument"); return NULL; @@ -249,7 +249,7 @@ void BPy_init_modules(void) PyObject *mod; /* Needs to be first since this dir is needed for future modules */ - char *modpath = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules"); + const char * const modpath = BLI_get_folder(BLENDER_SYSTEM_SCRIPTS, "modules"); if (modpath) { // printf("bpy: found module path '%s'.\n", modpath); PyObject *sys_path = PySys_GetObject("path"); /* borrow */ diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 7889b9a7f0b..e5180c58d56 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -41,9 +41,8 @@ #include "bpy_app_handlers.h" #include "bpy_driver.h" -#include "BLI_path_util.h" #include "BLI_utildefines.h" - +#include "BLI_path_util.h" #include "BKE_blender.h" #include "BKE_global.h" diff --git a/source/blender/python/intern/bpy_app_translations.c b/source/blender/python/intern/bpy_app_translations.c index 7c89972b486..35c39814124 100644 --- a/source/blender/python/intern/bpy_app_translations.c +++ b/source/blender/python/intern/bpy_app_translations.c @@ -32,9 +32,9 @@ /* XXX Why bloody hell isn't that included in Python.h???? */ #include <structmember.h> +#include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_ghash.h" -#include "BLI_utildefines.h" #include "BPY_extern.h" #include "bpy_app_translations.h" diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index 90199a403dc..552df561bbd 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -39,13 +39,13 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_math_base.h" #include "BLI_string.h" #include "BLI_string_utf8.h" -#include "BLI_utildefines.h" #include "BLI_threads.h" #include "RNA_types.h" @@ -931,11 +931,7 @@ static void bpy_module_free(void *UNUSED(mod)) /* EVIL, define text.c functions here... */ -extern int text_check_identifier_unicode(const unsigned int ch); -extern int text_check_identifier_nodigit_unicode(const unsigned int ch); -extern int text_check_identifier(const char ch); -extern int text_check_identifier_nodigit(const char ch); - +/* BKE_text.h */ int text_check_identifier_unicode(const unsigned int ch) { return (ch < 255 && text_check_identifier((char)ch)) || Py_UNICODE_ISALNUM(ch); diff --git a/source/blender/python/intern/bpy_library.c b/source/blender/python/intern/bpy_library.c index ec6322a1a11..3f66fb7b337 100644 --- a/source/blender/python/intern/bpy_library.c +++ b/source/blender/python/intern/bpy_library.c @@ -411,7 +411,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { - BKE_library_make_local(bmain, lib, 1); + BKE_library_make_local(bmain, lib, true); } } diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index ee885684e03..26c043f796f 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -369,7 +369,7 @@ static PyObject *pyop_dir(PyObject *UNUSED(self)) GHashIterator *iter = WM_operatortype_iter(); PyObject *list = PyList_New(0), *name; - for ( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for ( ; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { wmOperatorType *ot = BLI_ghashIterator_getValue(iter); name = PyUnicode_FromString(ot->idname); diff --git a/source/blender/python/intern/bpy_operator_wrap.c b/source/blender/python/intern/bpy_operator_wrap.c index 9d92ff51213..1c722243424 100644 --- a/source/blender/python/intern/bpy_operator_wrap.c +++ b/source/blender/python/intern/bpy_operator_wrap.c @@ -127,6 +127,11 @@ void operator_wrapper(wmOperatorType *ot, void *userdata) *ot = *((wmOperatorType *)userdata); ot->srna = srna; /* restore */ + /* Use i18n context from ext.srna if possible (py operators). */ + if (ot->ext.srna) { + RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); + } + operator_properties_init(ot); } @@ -143,6 +148,11 @@ void macro_wrapper(wmOperatorType *ot, void *userdata) ot->ui = data->ui; ot->ext = data->ext; + /* Use i18n context from ext.srna if possible (py operators). */ + if (ot->ext.srna) { + RNA_def_struct_translation_context(ot->srna, RNA_struct_translation_context(ot->ext.srna)); + } + operator_properties_init(ot); } diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 830c2c8de3a..c330eb1549d 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -1265,9 +1265,11 @@ static int icon_id_from_name(const char *name) int id; if (name[0]) { - for (item = icon_items, id = 0; item->identifier; item++, id++) - if (strcmp(item->name, name) == 0) + for (item = icon_items, id = 0; item->identifier; item++, id++) { + if (STREQ(item->name, name)) { return item->value; + } + } } return 0; @@ -1353,7 +1355,7 @@ static EnumPropertyItem *enum_items_from_py(PyObject *seq_fast, PyObject *def, i tmp.value = i; } - if (def && def_used == 0 && strcmp(def_cmp, tmp.identifier) == 0) { + if (def && def_used == 0 && STREQ(def_cmp, tmp.identifier)) { *defvalue = tmp.value; def_used++; /* only ever 1 */ } diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index cef4e23242d..0adb5e2e90e 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -250,7 +250,7 @@ static void id_release_weakref_list(struct ID *id, GHash *weakinfo_hash) fprintf(stdout, "id_release_weakref: '%s', %d items\n", id->name, BLI_ghash_size(weakinfo_hash)); #endif - while (!BLI_ghashIterator_isDone(&weakinfo_hash_iter)) { + while (BLI_ghashIterator_notDone(&weakinfo_hash_iter)) { PyObject *weakref = (PyObject *)BLI_ghashIterator_getKey(&weakinfo_hash_iter); PyObject *item = PyWeakref_GET_OBJECT(weakref); if (item != Py_None) { @@ -1427,7 +1427,9 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha { arg_name = RNA_property_identifier(prop); - if (strcmp(arg_name, "rna_type") == 0) continue; + if (STREQ(arg_name, "rna_type")) { + continue; + } if (kw == NULL) { PyErr_Format(PyExc_TypeError, @@ -2223,7 +2225,7 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel RNA_PROP_BEGIN (&self->ptr, itemptr, self->prop) { ID *id = itemptr.data; /* always an ID */ - if (id->lib == lib && (strncmp(keyname, id->name + 2, sizeof(id->name) - 2) == 0)) { + if (id->lib == lib && (STREQLEN(keyname, id->name + 2, sizeof(id->name) - 2))) { found = true; if (r_ptr) { *r_ptr = itemptr; @@ -3463,7 +3465,7 @@ static PyObject *pyrna_struct_getattro(BPy_StructRNA *self, PyObject *pyname) } else if (name[0] == '_') { /* rna can't start with a "_", so for __dict__ and similar we can skip using rna lookups */ /* annoying exception, maybe we need to have different types for this... */ - if ((strcmp(name, "__getitem__") == 0 || strcmp(name, "__setitem__") == 0) && !RNA_struct_idprops_check(self->ptr.type)) { + if ((STREQ(name, "__getitem__") || STREQ(name, "__setitem__")) && !RNA_struct_idprops_check(self->ptr.type)) { PyErr_SetString(PyExc_AttributeError, "bpy_struct: no __getitem__ support for this type"); ret = NULL; } @@ -4939,7 +4941,7 @@ static PyObject *small_dict_get_item_string(PyObject *dict, const char *key_look while (PyDict_Next(dict, &pos, &key, &value)) { if (PyUnicode_Check(key)) { - if (strcmp(key_lookup, _PyUnicode_AsString(key)) == 0) { + if (STREQ(key_lookup, _PyUnicode_AsString(key))) { return value; } } @@ -5139,7 +5141,7 @@ static PyObject *pyrna_func_call(BPy_FunctionRNA *self, PyObject *args, PyObject RNA_parameter_list_begin(&parms, &iter); for (; iter.valid; RNA_parameter_list_next(&iter)) { parm = iter.parm; - if (strcmp(arg_name, RNA_property_identifier(parm)) == 0) { + if (STREQ(arg_name, RNA_property_identifier(parm))) { found = true; break; } @@ -6937,7 +6939,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v /* Sneaky workaround to use the class name as the bl_idname */ #define BPY_REPLACEMENT_STRING(rna_attr, py_attr) \ - (strcmp(identifier, rna_attr) == 0) { \ + (STREQ(identifier, rna_attr)) { \ item = PyObject_GetAttr(py_class, py_attr); \ if (item && item != Py_None) { \ if (pyrna_py_to_prop(dummyptr, prop, NULL, \ @@ -6948,7 +6950,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v } \ } \ Py_XDECREF(item); \ - } /* intendionally allow else here */ + } /* intentionally allow else here */ if BPY_REPLACEMENT_STRING("bl_idname", bpy_intern_str___name__) else if BPY_REPLACEMENT_STRING("bl_description", bpy_intern_str___doc__) diff --git a/source/blender/python/intern/bpy_traceback.c b/source/blender/python/intern/bpy_traceback.c index 48bf65a841b..81d12e9d9a6 100644 --- a/source/blender/python/intern/bpy_traceback.c +++ b/source/blender/python/intern/bpy_traceback.c @@ -29,6 +29,7 @@ #include <Python.h> #include <frameobject.h> +#include "BLI_utildefines.h" #include "BLI_path_util.h" #include "BLI_string.h" diff --git a/source/blender/python/mathutils/mathutils_Matrix.c b/source/blender/python/mathutils/mathutils_Matrix.c index da2888045d0..1fcebf29f28 100644 --- a/source/blender/python/mathutils/mathutils_Matrix.c +++ b/source/blender/python/mathutils/mathutils_Matrix.c @@ -829,10 +829,10 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) mat[0] = 1.0f; mat[3] = 1.0f; - if (strcmp(plane, "X") == 0) { + if (STREQ(plane, "X")) { mat[2] = factor; } - else if (strcmp(plane, "Y") == 0) { + else if (STREQ(plane, "Y")) { mat[1] = factor; } else { @@ -855,15 +855,15 @@ static PyObject *C_Matrix_Shear(PyObject *cls, PyObject *args) mat[4] = 1.0f; mat[8] = 1.0f; - if (strcmp(plane, "XY") == 0) { + if (STREQ(plane, "XY")) { mat[6] = factor[0]; mat[7] = factor[1]; } - else if (strcmp(plane, "XZ") == 0) { + else if (STREQ(plane, "XZ")) { mat[3] = factor[0]; mat[5] = factor[1]; } - else if (strcmp(plane, "YZ") == 0) { + else if (STREQ(plane, "YZ")) { mat[1] = factor[0]; mat[2] = factor[1]; } diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m index 2e910e38871..974c2555ee5 100644 --- a/source/blender/quicktime/apple/qtkit_import.m +++ b/source/blender/quicktime/apple/qtkit_import.m @@ -32,6 +32,7 @@ #include "BLO_sys_types.h" #include "BKE_global.h" +#include "BLI_utildefines.h" #include "BLI_dynstr.h" #include "BLI_path_util.h" diff --git a/source/blender/quicktime/apple/quicktime_export.c b/source/blender/quicktime/apple/quicktime_export.c index c85df29de92..5e114bf7379 100644 --- a/source/blender/quicktime/apple/quicktime_export.c +++ b/source/blender/quicktime/apple/quicktime_export.c @@ -559,7 +559,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R #ifdef __APPLE__ EnterMoviesOnThread(0); - sprintf(theFullPath, "%s", name); + strcpy(theFullPath, name); /* hack: create an empty file to make FSPathMakeRef() happy */ myFile = open(theFullPath, O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRUSR | S_IWUSR); @@ -575,7 +575,7 @@ int start_qt(struct Scene *scene, struct RenderData *rd, int rectx, int recty, R #endif #ifdef _WIN32 qtname = get_valid_qtname(name); - sprintf(theFullPath, "%s", qtname); + strcpy(theFullPath, qtname); strcpy(name, qtname); MEM_freeN(qtname); diff --git a/source/blender/quicktime/apple/quicktime_import.c b/source/blender/quicktime/apple/quicktime_import.c index e44eba2bfe0..9481a37e3c7 100644 --- a/source/blender/quicktime/apple/quicktime_import.c +++ b/source/blender/quicktime/apple/quicktime_import.c @@ -210,13 +210,13 @@ int anim_is_quicktime(const char *name) if (QTIME_DEBUG) printf("qt: checking as movie: %s\n", name); #ifdef __APPLE__ - sprintf(theFullPath, "%s", name); + strcpy(theFullPath, name); err = FSPathMakeRef(theFullPath, &myRef, 0); err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL); #else qtname = get_valid_qtname(name); - sprintf(theFullPath, "%s", qtname); + strcpy(theFullPath, qtname); MEM_freeN(qtname); CopyCStringToPascal(theFullPath, dst); @@ -461,13 +461,13 @@ int startquicktime(struct anim *anim) if (QTIME_DEBUG) printf("qt: attempting to load as movie %s\n", anim->name); #ifdef __APPLE__ - sprintf(theFullPath, "%s", anim->name); + strcpy(theFullPath, anim->name); err = FSPathMakeRef(theFullPath, &myRef, 0); err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL); #else qtname = get_valid_qtname(anim->name); - sprintf(theFullPath, "%s", qtname); + strcpy(theFullPath, qtname); MEM_freeN(qtname); CopyCStringToPascal(theFullPath, dst); @@ -592,7 +592,7 @@ int imb_is_a_quicktime(char *name) return 0; } - sprintf(theFullPath, "%s", name); + strcpy(theFullPath, name); #ifdef __APPLE__ err = FSPathMakeRef(theFullPath, &myRef, 0); err = FSGetCatalogInfo(&myRef, kFSCatInfoNone, NULL, NULL, &theFSSpec, NULL); diff --git a/source/blender/render/CMakeLists.txt b/source/blender/render/CMakeLists.txt index 12d36ccfdd2..f284f80df96 100644 --- a/source/blender/render/CMakeLists.txt +++ b/source/blender/render/CMakeLists.txt @@ -165,6 +165,10 @@ if(WITH_GAMEENGINE) add_definitions(-DWITH_GAMEENGINE) endif() +if(WITH_INTERNATIONAL) + add_definitions(-DWITH_INTERNATIONAL) +endif() + if(APPLE) # SSE math is enabled by default on x86_64 if(CMAKE_OSX_ARCHITECTURES MATCHES "i386") diff --git a/source/blender/render/SConscript b/source/blender/render/SConscript index c4309577ae9..9606c2c0f9c 100644 --- a/source/blender/render/SConscript +++ b/source/blender/render/SConscript @@ -90,6 +90,9 @@ if env['WITH_BF_FREESTYLE']: if env['WITH_BF_GAMEENGINE']: defs.append('WITH_GAMEENGINE') +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index b687acae1f7..5df860750fc 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -33,12 +33,14 @@ #define __RE_ENGINE_H__ #include "DNA_listBase.h" +#include "DNA_scene_types.h" #include "RNA_types.h" struct bNode; struct bNodeTree; struct Object; struct Render; +struct RenderData; struct RenderEngine; struct RenderEngineType; struct RenderLayer; @@ -134,6 +136,7 @@ void RE_engines_exit(void); RenderEngineType *RE_engines_find(const char *idname); void RE_engine_get_current_tiles(struct Render *re, int *total_tiles_r, rcti **tiles_r); +struct RenderData *RE_engine_get_render_data(struct Render *re); #endif /* __RE_ENGINE_H__ */ diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index b31aff82777..9e639501fdd 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -87,7 +87,7 @@ MALWAYS_INLINE void rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, RayObject *RE_rayface_from_vlak(RayFace *rayface, ObjectInstanceRen *obi, VlakRen *vlr) { - return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : 0); + return rayface_from_coords(rayface, obi, vlr, vlr->v1->co, vlr->v2->co, vlr->v3->co, vlr->v4 ? vlr->v4->co : NULL); } RayObject *RE_rayface_from_coords(RayFace *rayface, void *ob, void *face, float *v1, float *v2, float *v3, float *v4) diff --git a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp index 4195b103811..1d67a8c4f44 100644 --- a/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp +++ b/source/blender/render/intern/raytrace/rayobject_rtbuild.cpp @@ -50,15 +50,15 @@ static bool selected_node(RTBuilder::Object *node) static void rtbuild_init(RTBuilder *b) { b->split_axis = -1; - b->primitives.begin = 0; - b->primitives.end = 0; + b->primitives.begin = NULL; + b->primitives.end = NULL; b->primitives.maxsize = 0; for (int i = 0; i < RTBUILD_MAX_CHILDS; i++) b->child_offset[i] = 0; for (int i = 0; i < 3; i++) - b->sorted_begin[i] = b->sorted_end[i] = 0; + b->sorted_begin[i] = b->sorted_end[i] = NULL; INIT_MINMAX(b->bb, b->bb + 3); } @@ -178,8 +178,8 @@ RTBuilder *rtbuild_get_child(RTBuilder *b, int child, RTBuilder *tmp) tmp->sorted_end[i] = b->sorted_begin[i] + b->child_offset[child + 1]; } else { - tmp->sorted_begin[i] = 0; - tmp->sorted_end[i] = 0; + tmp->sorted_begin[i] = NULL; + tmp->sorted_end[i] = NULL; } return tmp; diff --git a/source/blender/render/intern/source/bake.c b/source/blender/render/intern/source/bake.c index 7c5d6038e0a..c20b0c6da16 100644 --- a/source/blender/render/intern/source/bake.c +++ b/source/blender/render/intern/source/bake.c @@ -622,7 +622,7 @@ static int get_next_bake_face(BakeShade *bs) continue; if (*origindex >= me->totpoly) { /* Small hack for Array modifier, which gives false - original indices - z0r */ + * original indices - z0r */ continue; } #if 0 diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index cbc357b3d60..2ff612e7c0f 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -46,6 +46,8 @@ # include "BLI_edgehash.h" #endif +#include "BLF_translation.h" + #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_material_types.h" @@ -3554,9 +3556,9 @@ static void init_render_mesh(Render *re, ObjectRen *obr, int timeoffset) if (need_origindex) { /* Find original index of mpoly for this tessface. Options: - - Modified mesh; two-step look up from tessface -> modified mpoly -> original mpoly - - OR Tesselated mesh; look up from tessface -> mpoly - - OR Failsafe; tessface == mpoly. Could probably assert(false) in this case? */ + * - Modified mesh; two-step look up from tessface -> modified mpoly -> original mpoly + * - OR Tesselated mesh; look up from tessface -> mpoly + * - OR Failsafe; tessface == mpoly. Could probably assert(false) in this case? */ int *origindex; origindex = RE_vlakren_get_origindex(obr, vlr, 1); if (index_mf_to_mpoly && index_mp_to_orig) @@ -5214,7 +5216,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l tothalo= re->tothalo; if (!re->test_break(re->tbh)) { if (re->wrld.mode & WO_STARS) { - re->i.infostr= "Creating Starfield"; + re->i.infostr = IFACE_("Creating Starfield"); re->stats_draw(re->sdh, &re->i); RE_make_stars(re, NULL, NULL, NULL, NULL); } @@ -5223,7 +5225,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l init_camera_inside_volumes(re); - re->i.infostr= "Creating Shadowbuffers"; + re->i.infostr = IFACE_("Creating Shadowbuffers"); re->stats_draw(re->sdh, &re->i); /* SHADOW BUFFER */ @@ -5273,7 +5275,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l else re->i.convertdone = TRUE; - re->i.infostr= NULL; + re->i.infostr = NULL; re->stats_draw(re->sdh, &re->i); } @@ -5686,7 +5688,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned ListBase strandsurface; int step; - re->i.infostr= "Calculating previous frame vectors"; + re->i.infostr = IFACE_("Calculating previous frame vectors"); re->r.mode |= R_SPEED; speedvector_project(re, NULL, NULL, NULL); /* initializes projection code */ @@ -5705,7 +5707,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned if (!re->test_break(re->tbh)) { /* creates entire dbase */ - re->i.infostr= "Calculating next frame vectors"; + re->i.infostr = IFACE_("Calculating next frame vectors"); database_fromscene_vectors(re, sce, lay, +1); } @@ -5791,7 +5793,7 @@ void RE_Database_FromScene_Vectors(Render *re, Main *bmain, Scene *sce, unsigned } } - re->i.infostr= NULL; + re->i.infostr = NULL; re->stats_draw(re->sdh, &re->i); } diff --git a/source/blender/render/intern/source/envmap.c b/source/blender/render/intern/source/envmap.c index 9adae6f49ba..c5872c52e0f 100644 --- a/source/blender/render/intern/source/envmap.c +++ b/source/blender/render/intern/source/envmap.c @@ -38,6 +38,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" /* for rectcpy */ @@ -512,7 +514,7 @@ void make_envmaps(Render *re) trace = (re->r.mode & R_RAYTRACE); re->r.mode &= ~R_RAYTRACE; - re->i.infostr = "Creating Environment maps"; + re->i.infostr = IFACE_("Creating Environment maps"); re->stats_draw(re->sdh, &re->i); /* 5 = hardcoded max recursion level */ diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 22a49bcbbc3..4a48b6cc5f4 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -385,6 +385,11 @@ void RE_engine_get_current_tiles(Render *re, int *total_tiles_r, rcti **tiles_r) *tiles_r = tiles; } +RenderData *RE_engine_get_render_data(Render *re) +{ + return &re->r; +} + /* Render */ int RE_engine_render(Render *re, int do_all) diff --git a/source/blender/render/intern/source/imagetexture.c b/source/blender/render/intern/source/imagetexture.c index 12286fc9999..756fb098882 100644 --- a/source/blender/render/intern/source/imagetexture.c +++ b/source/blender/render/intern/source/imagetexture.c @@ -224,7 +224,7 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul } /* keep this before interpolation [#29761] */ - if (tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) { + if ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { texres->talpha = TRUE; } @@ -274,14 +274,18 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul ibuf_get_color(col, ibuf, x+1, y); val2= (col[0]+col[1]+col[2]); } - else val2= val1; + else { + val2= val1; + } if (y<ibuf->y-1) { float col[4]; ibuf_get_color(col, ibuf, x, y+1); - val3= (col[0]+col[1]+col[2]); + val3 = (col[0]+col[1]+col[2]); + } + else { + val3 = val1; } - else val3= val1; /* do not mix up x and y here! */ texres->nor[0]= (val1-val2); @@ -289,13 +293,19 @@ int imagewrap(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], TexResul } } - if (texres->talpha) texres->tin= texres->ta; + if (texres->talpha) { + texres->tin = texres->ta; + } else if (tex->imaflag & TEX_CALCALPHA) { texres->ta = texres->tin = max_fff(texres->tr, texres->tg, texres->tb); } - else texres->ta= texres->tin= 1.0; + else { + texres->ta = texres->tin = 1.0; + } - if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; + if (tex->flag & TEX_NEGALPHA) { + texres->ta = 1.0f - texres->ta; + } /* de-premul, this is being premulled in shade_input_do_shade() */ if (texres->ta!=1.0f && texres->ta>1e-4f) { @@ -829,7 +839,7 @@ static float EWA_WTS[EWA_MAXIDX + 1] = { #endif //static int ISNAN(float x) { return (x != x); } -static void radangle2imp(float a2, float b2, float th, float* A, float* B, float* C, float* F) +static void radangle2imp(float a2, float b2, float th, float *A, float *B, float *C, float *F) { float ct2 = cosf(th); const float st2 = 1.0f - ct2 * ct2; /* <- sin(th)^2 */ @@ -841,7 +851,7 @@ static void radangle2imp(float a2, float b2, float th, float* A, float* B, float } /* all tests here are done to make sure possible overflows are hopefully minimized */ -static void imp2radangle(float A, float B, float C, float F, float* a, float* b, float* th, float* ecc) +static void imp2radangle(float A, float B, float C, float F, float *a, float *b, float *th, float *ecc) { if (F <= 1e-5f) { /* use arbitrary major radius, zero minor, infinite eccentricity */ *a = sqrtf(A > C ? A : C); @@ -1098,7 +1108,7 @@ static int imagewraposa_aniso(Tex *tex, Image *ima, ImBuf *ibuf, const float tex /* mipmap test */ image_mipmap_test(tex, ibuf); - if (tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) { + if ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) { if ((tex->imaflag & TEX_CALCALPHA) == 0) texres->talpha = 1; } @@ -1514,7 +1524,7 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const /* mipmap test */ image_mipmap_test(tex, ibuf); - if (tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) { + if ((tex->imaflag & TEX_USEALPHA) && tex->ima && (tex->ima->flag & IMA_IGNORE_ALPHA) == 0) { if ((tex->imaflag & TEX_CALCALPHA) == 0) { texres->talpha = TRUE; } @@ -1838,7 +1848,9 @@ int imagewraposa(Tex *tex, Image *ima, ImBuf *ibuf, const float texvec[3], const if (tex->imaflag & TEX_CALCALPHA) { texres->ta = texres->tin = texres->ta * max_fff(texres->tr, texres->tg, texres->tb); } - else texres->tin= texres->ta; + else { + texres->tin = texres->ta; + } if (tex->flag & TEX_NEGALPHA) texres->ta= 1.0f-texres->ta; diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index 1c594ef7db2..50f9d6caff6 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -44,6 +44,8 @@ #include "BLI_threads.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_global.h" #include "BKE_scene.h" @@ -1257,7 +1259,7 @@ void make_occ_tree(Render *re) /* ugly, needed for occ_face */ R = *re; - re->i.infostr = "Occlusion preprocessing"; + re->i.infostr = IFACE_("Occlusion preprocessing"); re->stats_draw(re->sdh, &re->i); re->occlusiontree = tree = occ_tree_build(re); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index ce18723b8c0..753eab4c6ab 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -55,6 +55,8 @@ #include "BLI_rand.h" #include "BLI_callbacks.h" +#include "BLF_translation.h" + #include "BKE_animsys.h" /* <------ should this be here?, needed for sequencer update */ #include "BKE_camera.h" #include "BKE_global.h" @@ -160,22 +162,23 @@ static void stats_background(void *UNUSED(arg), RenderStats *rs) mmap_used_memory = (mmap_in_use) / (1024.0 * 1024.0); megs_peak_memory = (peak_memory) / (1024.0 * 1024.0); - fprintf(stdout, "Fra:%d Mem:%.2fM (%.2fM, peak %.2fM) ", rs->cfra, + fprintf(stdout, IFACE_("Fra:%d Mem:%.2fM (%.2fM, Peak %.2fM) "), rs->cfra, megs_used_memory, mmap_used_memory, megs_peak_memory); if (rs->curfield) - fprintf(stdout, "Field %d ", rs->curfield); + fprintf(stdout, IFACE_("Field %d "), rs->curfield); if (rs->curblur) - fprintf(stdout, "Blur %d ", rs->curblur); + fprintf(stdout, IFACE_("Blur %d "), rs->curblur); if (rs->infostr) { fprintf(stdout, "| %s", rs->infostr); } else { if (rs->tothalo) - fprintf(stdout, "Sce: %s Ve:%d Fa:%d Ha:%d La:%d", rs->scene_name, rs->totvert, rs->totface, rs->tothalo, rs->totlamp); + fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d Ha:%d La:%d"), + rs->scene_name, rs->totvert, rs->totface, rs->tothalo, rs->totlamp); else - fprintf(stdout, "Sce: %s Ve:%d Fa:%d La:%d", rs->scene_name, rs->totvert, rs->totface, rs->totlamp); + fprintf(stdout, IFACE_("Sce: %s Ve:%d Fa:%d La:%d"), rs->scene_name, rs->totvert, rs->totface, rs->totlamp); } BLI_callback_exec(G.main, NULL, BLI_CB_EVT_RENDER_STATS); @@ -458,13 +461,43 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * re->i.starttime = PIL_check_seconds_timer(); re->r = *rd; /* hardcopy */ - + + if (source) { + /* reuse border flags from source renderer */ + re->r.mode &= ~(R_BORDER | R_CROP); + re->r.mode |= source->r.mode & (R_BORDER | R_CROP); + + /* dimensions shall be shared between all renderers */ + re->r.xsch = source->r.xsch; + re->r.ysch = source->r.ysch; + re->r.size = source->r.size; + } + re->winx = winx; re->winy = winy; - if (disprect) { + if (source && (source->r.mode & R_BORDER)) { + /* eeh, doesn't seem original bordered disprect is storing anywhere + * after insertion on black happening in do_render_fields_blur_3d(), + * so for now simply re-calculate disprect using border from source + * renderer (sergey) + */ + + re->disprect.xmin = source->r.border.xmin * winx; + re->disprect.xmax = source->r.border.xmax * winx; + + re->disprect.ymin = source->r.border.ymin * winy; + re->disprect.ymax = source->r.border.ymax * winy; + + re->rectx = BLI_rcti_size_x(&re->disprect); + re->recty = BLI_rcti_size_y(&re->disprect); + + /* copy border itself, since it could be used by external engines */ + re->r.border = source->r.border; + } + else if (disprect) { re->disprect = *disprect; - re->rectx = BLI_rcti_size_x(disprect); - re->recty = BLI_rcti_size_y(disprect); + re->rectx = BLI_rcti_size_x(&re->disprect); + re->recty = BLI_rcti_size_y(&re->disprect); } else { re->disprect.xmin = re->disprect.ymin = 0; @@ -826,7 +859,7 @@ static void print_part_stats(Render *re, RenderPart *pa) { char str[64]; - BLI_snprintf(str, sizeof(str), "%s, Part %d-%d", re->scene->id.name + 2, pa->nr, re->i.totpart); + BLI_snprintf(str, sizeof(str), IFACE_("%s, Part %d-%d"), re->scene->id.name + 2, pa->nr, re->i.totpart); re->i.infostr = str; re->stats_draw(re->sdh, &re->i); re->i.infostr = NULL; @@ -972,7 +1005,20 @@ static void threaded_tile_processor(Render *re) if ((g_break=re->test_break(re->tbh))) break; } - + + if (g_break) { + /* review the done queue and handle all the render parts, + * so no unfreed render result are lurking around + */ + BLI_thread_queue_nowait(donequeue); + while ((pa = BLI_thread_queue_pop(donequeue))) { + if (pa->result) { + render_result_free_list(&pa->fullresult, pa->result); + pa->result = NULL; + } + } + } + BLI_thread_queue_free(donequeue); BLI_thread_queue_free(workqueue); @@ -2091,7 +2137,7 @@ int RE_is_rendering_allowed(Scene *scene, Object *camera_override, ReportList *r render_result_exr_file_path(scene, "", 0, str); - if (BLI_file_is_writable(str) == 0) { + if (!BLI_file_is_writable(str)) { BKE_report(reports, RPT_ERROR, "Cannot save render buffers, check the temp default path"); return 0; } @@ -2532,7 +2578,7 @@ void RE_BlenderAnim(Render *re, Main *bmain, Scene *scene, Object *camera_overri /* remove touched file */ if (BKE_imtype_is_movie(scene->r.im_format.imtype) == 0) { if (scene->r.mode & R_TOUCH && BLI_exists(name) && BLI_file_size(name) == 0) { - BLI_delete(name, 0, 0); + BLI_delete(name, false, false); } } diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index 3ca4015ff7b..d740780ec30 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -40,6 +40,8 @@ #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_lattice.h" @@ -299,7 +301,7 @@ void make_pointdensities(Render *re) if (re->scene->r.scemode & R_PREVIEWBUTS) return; - re->i.infostr= "Caching Point Densities"; + re->i.infostr = IFACE_("Caching Point Densities"); re->stats_draw(re->sdh, &re->i); for (tex= re->main->tex.first; tex; tex= tex->id.next) { @@ -308,7 +310,7 @@ void make_pointdensities(Render *re) } } - re->i.infostr= NULL; + re->i.infostr = NULL; re->stats_draw(re->sdh, &re->i); } diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index fe23f31c6d7..88c0719fa59 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -47,6 +47,8 @@ #include "BLI_rand.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "BKE_global.h" #include "BKE_node.h" @@ -400,7 +402,7 @@ static void makeraytree_single(Render *re) } if (!test_break(re)) { - re->i.infostr= "Raytree.. building"; + re->i.infostr = IFACE_("Raytree.. building"); re->stats_draw(re->sdh, &re->i); RE_rayobject_done(raytree); @@ -412,7 +414,7 @@ void makeraytree(Render *re) float min[3], max[3], sub[3]; int i; - re->i.infostr= "Raytree.. preparing"; + re->i.infostr = IFACE_("Raytree.. preparing"); re->stats_draw(re->sdh, &re->i); /* disable options not yet supported by octree, @@ -425,7 +427,7 @@ void makeraytree(Render *re) if (test_break(re)) { freeraytree(re); - re->i.infostr= "Raytree building canceled"; + re->i.infostr = IFACE_("Raytree building canceled"); re->stats_draw(re->sdh, &re->i); } else { @@ -446,7 +448,7 @@ void makeraytree(Render *re) re->maxdist = len_v3(sub); - re->i.infostr= "Raytree finished"; + re->i.infostr = IFACE_("Raytree finished"); re->stats_draw(re->sdh, &re->i); } diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index be1a3806e43..21e7b698610 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -35,13 +35,13 @@ #include "MEM_guardedalloc.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_threads.h" -#include "BLI_utildefines.h" #include "BKE_image.h" #include "BKE_global.h" @@ -990,11 +990,9 @@ void render_result_exr_file_merge(RenderResult *rr, RenderResult *rrpart) /* path to temporary exr file */ void render_result_exr_file_path(Scene *scene, const char *layname, int sample, char *filepath) { - char di[FILE_MAX], name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE]; - - BLI_strncpy(di, G.main->name, FILE_MAX); - BLI_splitdirstring(di, fi); + char name[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100], fi[FILE_MAXFILE]; + BLI_split_file_part(G.main->name, fi, sizeof(fi)); if (sample == 0) BLI_snprintf(name, sizeof(name), "%s_%s_%s.exr", fi, scene->id.name + 2, layname); else diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 6d0e15ea46e..9d6391ccb59 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -55,6 +55,8 @@ #include "BLI_ghash.h" #include "BLI_memarena.h" +#include "BLF_translation.h" + #include "PIL_time.h" #include "DNA_material_types.h" @@ -994,7 +996,7 @@ void make_sss_tree(Render *re) re->sss_hash= BLI_ghash_ptr_new("make_sss_tree gh"); - re->i.infostr= "SSS preprocessing"; + re->i.infostr = IFACE_("SSS preprocessing"); re->stats_draw(re->sdh, &re->i); for (mat= re->main->mat.first; mat; mat= mat->id.next) @@ -1016,7 +1018,7 @@ void free_sss(Render *re) if (re->sss_hash) { GHashIterator *it= BLI_ghashIterator_new(re->sss_hash); - while (!BLI_ghashIterator_isDone(it)) { + while (BLI_ghashIterator_notDone(it)) { sss_free_tree(BLI_ghashIterator_getValue(it)); BLI_ghashIterator_step(it); } diff --git a/source/blender/render/intern/source/volume_precache.c b/source/blender/render/intern/source/volume_precache.c index a9db197ed48..028217b8609 100644 --- a/source/blender/render/intern/source/volume_precache.c +++ b/source/blender/render/intern/source/volume_precache.c @@ -43,6 +43,8 @@ #include "BLI_voxel.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "PIL_time.h" #include "RE_shader_ext.h" @@ -400,10 +402,11 @@ static void multiple_scattering_diffusion(Render *re, VolumePrecache *vp, Materi /* Displays progress every second */ if (time-lasttime>1.0) { char str[64]; - BLI_snprintf(str, sizeof(str), "Simulating multiple scattering: %d%%", (int)(100.0f * (c / total))); - re->i.infostr= str; + BLI_snprintf(str, sizeof(str), IFACE_("Simulating multiple scattering: %d%%"), + (int)(100.0f * (c / total))); + re->i.infostr = str; re->stats_draw(re->sdh, &re->i); - re->i.infostr= NULL; + re->i.infostr = NULL; lasttime= time; } } @@ -742,11 +745,12 @@ static void vol_precache_objectinstance_threads(Render *re, ObjectInstanceRen *o time= PIL_check_seconds_timer(); if (time-lasttime>1.0) { char str[64]; - BLI_snprintf(str, sizeof(str), "Precaching volume: %d%%", (int)(100.0f * ((float)counter / (float)totparts))); - re->i.infostr= str; + BLI_snprintf(str, sizeof(str), IFACE_("Precaching volume: %d%%"), + (int)(100.0f * ((float)counter / (float)totparts))); + re->i.infostr = str; re->stats_draw(re->sdh, &re->i); - re->i.infostr= NULL; - lasttime= time; + re->i.infostr = NULL; + lasttime = time; } } @@ -784,7 +788,7 @@ void volume_precache(Render *re) ObjectInstanceRen *obi; VolumeOb *vo; - re->i.infostr= "Volume preprocessing"; + re->i.infostr = IFACE_("Volume preprocessing"); re->stats_draw(re->sdh, &re->i); for (vo= re->volumes.first; vo; vo= vo->next) { @@ -803,7 +807,7 @@ void volume_precache(Render *re) } } - re->i.infostr= NULL; + re->i.infostr = NULL; re->stats_draw(re->sdh, &re->i); } diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index 92099060bf5..9990ad7e900 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -34,6 +34,10 @@ #include <stdlib.h> #include <stdio.h> +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + #include "MEM_guardedalloc.h" #include "BLI_math.h" @@ -41,6 +45,8 @@ #include "BLI_voxel.h" #include "BLI_utildefines.h" +#include "BLF_translation.h" + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -400,7 +406,7 @@ void make_voxeldata(struct Render *re) { Tex *tex; - re->i.infostr = "Loading voxel datasets"; + re->i.infostr = IFACE_("Loading voxel datasets"); re->stats_draw(re->sdh, &re->i); /* XXX: should be doing only textures used in this render */ diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 57fe518dd46..4cac73b4cf6 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -165,7 +165,7 @@ struct wmEventHandler *WM_event_add_dropbox_handler(ListBase *handlers, ListBase /* mouse */ void WM_event_add_mousemove(struct bContext *C); void WM_event_add_mousemove_window(struct wmWindow *window); -int WM_modal_tweak_exit(struct wmEvent *evt, int tweak_event); +int WM_modal_tweak_exit(const struct wmEvent *event, int tweak_event); /* notifiers */ void WM_event_add_notifier(const struct bContext *C, unsigned int type, void *reference); @@ -180,19 +180,19 @@ void WM_event_timer_sleep(struct wmWindowManager *wm, struct wmWindow *win, str /* operator api, default callbacks */ /* invoke callback, uses enum property named "type" */ -int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); -int WM_menu_invoke (struct bContext *C, struct wmOperator *op, struct wmEvent *event); -int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_menu_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_enum_search_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); /* invoke callback, confirm menu + exec */ -int WM_operator_confirm (struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_operator_confirm (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); /* invoke callback, file selector "filepath" unset + exec */ -int WM_operator_filesel (struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_operator_filesel (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_operator_filesel_ensure_ext_imtype(wmOperator *op, const struct ImageFormatData *im_format); /* poll callback, context checks */ int WM_operator_winactive (struct bContext *C); /* invoke callback, exec + redo popup */ -int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, struct wmEvent *event); -int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, struct wmEvent *event); +int WM_operator_props_popup_call(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_operator_props_popup (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_operator_props_dialog_popup (struct bContext *C, struct wmOperator *op, int width, int height); int WM_operator_redo_popup (struct bContext *C, struct wmOperator *op); int WM_operator_ui_popup (struct bContext *C, struct wmOperator *op, int width, int height); @@ -282,31 +282,31 @@ void WM_menutype_freelink(struct MenuType *mt); 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_invoke (struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_border_select_modal (struct bContext *C, struct wmOperator *op, const 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_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_gesture_circle_modal(struct bContext *C, struct wmOperator *op, const 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_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_gesture_lines_modal(struct bContext *C, struct wmOperator *op, const 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_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op); const int (*WM_gesture_lasso_path_to_array(struct bContext *C, struct wmOperator *op, int *mcords_tot))[2]; -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_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); +int WM_gesture_straightline_modal(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); int WM_gesture_straightline_cancel(struct bContext *C, struct wmOperator *op); /* Gesture manager API */ -struct wmGesture *WM_gesture_new(struct bContext *C, struct wmEvent *event, int type); +struct wmGesture *WM_gesture_new(struct bContext *C, const struct wmEvent *event, int type); void WM_gesture_end(struct bContext *C, struct wmGesture *gesture); void WM_gestures_remove(struct bContext *C); /* fileselecting support */ void WM_event_add_fileselect(struct bContext *C, struct wmOperator *op); -void WM_event_fileselect_event(struct bContext *C, void *ophandle, int eventval); +void WM_event_fileselect_event(struct wmWindowManager *wm, void *ophandle, int eventval); #ifndef NDEBUG void WM_event_print(const struct wmEvent *event); #endif @@ -317,7 +317,7 @@ void WM_operator_region_active_win_set(struct bContext *C); struct wmDrag *WM_event_start_drag(struct bContext *C, int icon, int type, void *poin, double value); void WM_event_drag_image(struct wmDrag *, struct ImBuf *, float scale, int sx, int sy); -struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, struct wmEvent *event), +struct wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(struct bContext *, struct wmDrag *, const struct wmEvent *event), void (*copy)(struct wmDrag *, struct wmDropBox *)); ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 881d4464ed6..a42e4438311 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -515,6 +515,7 @@ typedef struct wmTimer { typedef struct wmOperatorType { const char *name; /* text for ui, undo */ const char *idname; /* unique identifier */ + const char *translation_context; const char *description; /* tooltips and python docs */ /* this callback executes the operator without any interactive input, @@ -537,13 +538,13 @@ typedef struct wmOperatorType { * any further events are handled in modal. if the operation is * canceled due to some external reason, cancel is called * - see defines below for return values */ - int (*invoke)(struct bContext *, struct wmOperator *, struct wmEvent *) + int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) #ifdef __GNUC__ __attribute__((warn_unused_result)) #endif ; int (*cancel)(struct bContext *, struct wmOperator *); - int (*modal)(struct bContext *, struct wmOperator *, struct wmEvent *) + int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) #ifdef __GNUC__ __attribute__((warn_unused_result)) #endif @@ -648,7 +649,7 @@ typedef struct wmDropBox { struct wmDropBox *next, *prev; /* test if the dropbox is active, then can print optype name */ - int (*poll)(struct bContext *, struct wmDrag *, wmEvent *); + int (*poll)(struct bContext *, struct wmDrag *, const wmEvent *); /* before exec, this copies drag info to wmDrop properties */ void (*copy)(struct wmDrag *, struct wmDropBox *); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index a01f7301ec2..29e0fcf302f 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -218,7 +218,7 @@ void WM_uilisttype_free(void) { GHashIterator *iter = BLI_ghashIterator_new(uilisttypes_hash); - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { uiListType *ult = BLI_ghashIterator_getValue(iter); if (ult->ext.free) { ult->ext.free(ult->ext.data); @@ -271,7 +271,7 @@ void WM_menutype_free(void) { GHashIterator *iter = BLI_ghashIterator_new(menutypes_hash); - for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { + for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) { MenuType *mt = BLI_ghashIterator_getValue(iter); if (mt->ext.free) { mt->ext.free(mt->ext.data); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index 0581000e07c..ed066117b28 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -103,7 +103,7 @@ ListBase *WM_dropboxmap_find(const char *idname, int spaceid, int regionid) -wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, wmEvent *), +wmDropBox *WM_dropbox_add(ListBase *lb, const char *idname, int (*poll)(bContext *, wmDrag *, const wmEvent *), void (*copy)(wmDrag *, wmDropBox *)) { wmDropBox *drop = MEM_callocN(sizeof(wmDropBox), "wmDropBox"); @@ -323,7 +323,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy); else { glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */ - glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, drag->imb->rect, drag->scale, drag->scale); + glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale); } } else { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4e181ec930b..b2647626f3a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2244,12 +2244,12 @@ void wm_event_do_handlers(bContext *C) /* ********** filesector handling ************ */ -void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval) +void WM_event_fileselect_event(wmWindowManager *wm, void *ophandle, int eventval) { /* add to all windows! */ wmWindow *win; - for (win = CTX_wm_manager(C)->windows.first; win; win = win->next) { + for (win = wm->windows.first; win; win = win->next) { wmEvent event = *win->eventstate; event.type = EVT_FILESELECT; @@ -2271,6 +2271,7 @@ void WM_event_fileselect_event(bContext *C, void *ophandle, int eventval) void WM_event_add_fileselect(bContext *C, wmOperator *op) { wmEventHandler *handler, *handlernext; + wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win = CTX_wm_window(C); int full = 1; // XXX preset? @@ -2302,7 +2303,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) op->type->check(C, op); /* ignore return value */ } - WM_event_fileselect_event(C, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN); + WM_event_fileselect_event(wm, op, full ? EVT_FILESELECT_FULL_OPEN : EVT_FILESELECT_OPEN); } #if 0 @@ -2487,14 +2488,14 @@ void WM_event_add_mousemove_window(wmWindow *window) } /* for modal callbacks, check configuration for how to interpret exit with tweaks */ -int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) +int WM_modal_tweak_exit(const wmEvent *event, int tweak_event) { /* if the release-confirm userpref setting is enabled, * tweak events can be canceled when mouse is released */ if (U.flag & USER_RELEASECONFIRM) { /* option on, so can exit with km-release */ - if (evt->val == KM_RELEASE) { + if (event->val == KM_RELEASE) { switch (tweak_event) { case EVT_TWEAK_L: case EVT_TWEAK_M: @@ -2515,7 +2516,7 @@ int WM_modal_tweak_exit(wmEvent *evt, int tweak_event) * some items (i.e. markers) being tweaked may end up getting * dropped all over */ - if (evt->val != KM_RELEASE) + if (event->val != KM_RELEASE) return 1; } @@ -2745,9 +2746,9 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g } /* imperfect but probably usable... draw/enable drags to other windows */ -static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt) +static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event) { - int mx = evt->x, my = evt->y; + int mx = event->x, my = event->y; if (wm->windows.first == wm->windows.last) return NULL; @@ -2779,8 +2780,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi if (mx - posx >= 0 && owin->posy >= 0 && mx - posx <= WM_window_pixels_x(owin) && my - posy <= WM_window_pixels_y(owin)) { - evt->x = mx - (int)(U.pixelsize * owin->posx); - evt->y = my - (int)(U.pixelsize * owin->posy); + event->x = mx - (int)(U.pixelsize * owin->posx); + event->y = my - (int)(U.pixelsize * owin->posy); return owin; } diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index d1156f77e41..c682165eb69 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -509,7 +509,7 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory G.relbase_valid = 0; if (!from_memory) { - char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); + const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); if (cfgdir) { BLI_make_file_string(G.main->name, startstr, cfgdir, BLENDER_STARTUP_FILE); BLI_make_file_string(G.main->name, prefstr, cfgdir, BLENDER_USERPREF_FILE); @@ -533,7 +533,8 @@ int wm_homefile_read(bContext *C, ReportList *UNUSED(reports), short from_memory } if (U.themes.first == NULL) { - printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr); + if (G.debug & G_DEBUG) + printf("\nNote: No (valid) '%s' found, fall back to built-in default.\n\n", startstr); success = 0; } } @@ -621,7 +622,7 @@ void wm_read_history(void) struct RecentFile *recent; char *line; int num; - char *cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); + const char * const cfgdir = BLI_get_folder(BLENDER_USER_CONFIG, NULL); if (!cfgdir) return; @@ -650,7 +651,7 @@ static void write_history(void) { struct RecentFile *recent, *next_recent; char name[FILE_MAX]; - char *user_config_dir; + const char *user_config_dir; FILE *fp; int i; @@ -1051,7 +1052,7 @@ void wm_autosave_delete(void) BLI_make_file_string("/", str, BLI_temporary_dir(), BLENDER_QUIT_FILE); /* if global undo; remove tempsave, otherwise rename */ - if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, 0, 0); + if (U.uiflag & USER_GLOBALUNDO) BLI_delete(filename, false, false); else BLI_rename(filename, str); } } diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 302bf61756a..adf159bcfee 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -58,7 +58,7 @@ /* context checked on having screen, window and area */ -wmGesture *WM_gesture_new(bContext *C, wmEvent *event, int type) +wmGesture *WM_gesture_new(bContext *C, const wmEvent *event, int type) { wmGesture *gesture = MEM_callocN(sizeof(wmGesture), "new gesture"); wmWindow *window = CTX_wm_window(C); diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index da0c6dd2a63..6e557647d12 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -449,6 +449,7 @@ void WM_exit_ext(bContext *C, const short do_python) #ifdef WITH_INTERNATIONAL BLF_free_unifont(); + BLF_free_unifont_mono(); BLF_lang_free(); #endif diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index 3c3e2c0feaa..c637b77738e 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -363,7 +363,9 @@ void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job) if (G.debug & G_DEBUG_JOBS) wm_job->start_time = PIL_check_seconds_timer(); } - else printf("job fails, not initialized\n"); + else { + printf("job fails, not initialized\n"); + } } } diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 92a310ac34e..20e715c18d0 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -836,7 +836,7 @@ int WM_keymap_item_to_string(wmKeyMapItem *kmi, char *str, int len) } strcat(buf, WM_key_event_string(kmi->type)); - return BLI_snprintf(str, len, "%s", buf); + return BLI_strncpy_rlen(str, buf, len); } static wmKeyMapItem *wm_keymap_item_find_handlers( diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 678c77d0d88..8ea507f97e8 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -248,7 +248,7 @@ static int wm_macro_exec(bContext *C, wmOperator *op) return wm_macro_end(op, retval); } -static int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event, wmOperator *opm) +static int wm_macro_invoke_internal(bContext *C, wmOperator *op, const wmEvent *event, wmOperator *opm) { int retval = OPERATOR_FINISHED; @@ -275,13 +275,13 @@ static int wm_macro_invoke_internal(bContext *C, wmOperator *op, wmEvent *event, return wm_macro_end(op, retval); } -static int wm_macro_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int wm_macro_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wm_macro_start(op); return wm_macro_invoke_internal(C, op, event, op->macro.first); } -static int wm_macro_modal(bContext *C, wmOperator *op, wmEvent *event) +static int wm_macro_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmOperator *opm = op->opm; int retval = OPERATOR_FINISHED; @@ -381,7 +381,9 @@ wmOperatorType *WM_operatortype_append_macro(const char *idname, const char *nam RNA_def_struct_ui_text(ot->srna, ot->name, ot->description); RNA_def_struct_identifier(ot->srna, ot->idname); - RNA_def_struct_translation_context(ot->srna, BLF_I18NCONTEXT_OPERATOR_DEFAULT); + /* Use i18n context from ext.srna if possible (py operators). */ + RNA_def_struct_translation_context(ot->srna, ot->ext.srna ? RNA_struct_translation_context(ot->ext.srna) : + BLF_I18NCONTEXT_OPERATOR_DEFAULT); BLI_ghash_insert(global_ops_hash, (void *)ot->idname, ot); @@ -875,7 +877,7 @@ void WM_operator_properties_free(PointerRNA *ptr) /* ************ default op callbacks, exported *********** */ -int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, struct wmEvent *UNUSED(event)) +int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *UNUSED(event)) { Scene *scene = CTX_data_scene(C); View3D *v3d = CTX_wm_view3d(C); @@ -905,7 +907,7 @@ int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op } /* invoke callback, uses enum property named "type" */ -int WM_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { PropertyRNA *prop = op->type->prop; uiPopupMenu *pup; @@ -1024,7 +1026,7 @@ static uiBlock *wm_enum_search_menu(bContext *C, ARegion *ar, void *arg_op) } -int WM_enum_search_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +int WM_enum_search_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { uiPupBlock(C, wm_enum_search_menu, op); return OPERATOR_CANCELLED; @@ -1051,13 +1053,13 @@ int WM_operator_confirm_message(bContext *C, wmOperator *op, const char *message } -int WM_operator_confirm(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +int WM_operator_confirm(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return WM_operator_confirm_message(C, op, NULL); } /* op->invoke, opens fileselect if path property not set, otherwise executes */ -int WM_operator_filesel(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +int WM_operator_filesel(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (RNA_struct_property_is_set(op->ptr, "filepath")) { return WM_operator_call_notest(C, op); /* call exec direct */ @@ -1475,12 +1477,12 @@ static int wm_operator_props_popup_ex(bContext *C, wmOperator *op, const int do_ * This way - the button values correspond to the result of the operator. * Without this, first access to a button will make the result jump, * see [#32452] */ -int WM_operator_props_popup_call(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +int WM_operator_props_popup_call(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return wm_operator_props_popup_ex(C, op, TRUE); } -int WM_operator_props_popup(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +int WM_operator_props_popup(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { return wm_operator_props_popup_ex(C, op, FALSE); } @@ -1529,7 +1531,7 @@ static int wm_debug_menu_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int wm_debug_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_debug_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { RNA_int_set(op->ptr, "debug_value", G.debug_value); return WM_operator_props_dialog_popup(C, op, 9 * UI_UNIT_X, UI_UNIT_Y); @@ -1598,14 +1600,14 @@ static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_bl static int wm_resource_check_prev(void) { - char *res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, TRUE); + const char *res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION, true); // if (res) printf("USER: %s\n", res); #if 0 /* ignore the local folder */ if (res == NULL) { /* with a local dir, copying old files isn't useful since local dir get priority for config */ - res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, TRUE); + res = BLI_get_folder_version(BLENDER_RESOURCE_PATH_LOCAL, BLENDER_VERSION, true); } #endif @@ -1614,7 +1616,7 @@ static int wm_resource_check_prev(void) return FALSE; } else { - return (BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, TRUE) != NULL); + return (BLI_get_folder_version(BLENDER_RESOURCE_PATH_USER, BLENDER_VERSION - 1, true) != NULL); } } @@ -1704,7 +1706,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar uiItemStringO(col, IFACE_("Blender Website"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org"); uiItemStringO(col, IFACE_("User Community"), ICON_URL, "WM_OT_url_open", "url", "http://www.blender.org/community/user-community"); - if (strcmp(STRINGIFY(BLENDER_VERSION_CYCLE), "release") == 0) { + if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) { BLI_snprintf(url, sizeof(url), "http://www.blender.org/documentation/blender_python_api_%d_%d" STRINGIFY(BLENDER_VERSION_CHAR) "_release", BLENDER_VERSION / 100, BLENDER_VERSION % 100); @@ -1742,7 +1744,7 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *UNUSED(ar return block; } -static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *UNUSED(event)) +static int wm_splash_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) { uiPupBlock(C, wm_block_create_splash, NULL); @@ -1796,7 +1798,7 @@ static int wm_search_menu_exec(bContext *UNUSED(C), wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -static int wm_search_menu_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { uiPupBlock(C, wm_block_search_menu, op); @@ -1944,7 +1946,7 @@ static void open_set_use_scripts(wmOperator *op) } } -static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_open_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { const char *openname = G.main->name; @@ -2034,7 +2036,7 @@ static int wm_link_append_poll(bContext *C) return 0; } -static int wm_link_append_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_link_append_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { if (RNA_struct_property_is_set(op->ptr, "filepath")) { return WM_operator_call_notest(C, op); @@ -2168,7 +2170,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) /* append, rather than linking */ if ((flag & FILE_LINK) == 0) { Library *lib = BLI_findstring(&bmain->library, libname, offsetof(Library, filepath)); - if (lib) BKE_library_make_local(bmain, lib, 1); + if (lib) BKE_library_make_local(bmain, lib, true); else BLI_assert(!"cant find name of just added library!"); } @@ -2289,7 +2291,7 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_recover_auto_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { char filename[FILE_MAX]; @@ -2319,7 +2321,7 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot) static void untitled(char *filepath) { if (G.save_over == 0 && strlen(filepath) < FILE_MAX - 16) { - char *c = BLI_last_slash(filepath); + char *c = (char *)BLI_last_slash(filepath); if (c) strcpy(&c[1], "untitled.blend"); @@ -2338,7 +2340,7 @@ static void save_set_compress(wmOperator *op) } } -static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { char name[FILE_MAX]; @@ -2409,7 +2411,7 @@ static int blend_save_check(bContext *UNUSED(C), wmOperator *op) RNA_string_get(op->ptr, "filepath", filepath); if (!BLO_has_bfile_extension(filepath)) { /* some users would prefer BLI_replace_extension(), - * we keep getting knit-picking bug reports about this - campbell */ + * we keep getting nitpicking bug reports about this - campbell */ BLI_ensure_extension(filepath, FILE_MAX, ".blend"); RNA_string_set(op->ptr, "filepath", filepath); return TRUE; @@ -2444,7 +2446,7 @@ static void WM_OT_save_as_mainfile(wmOperatorType *ot) /* *************** save file directly ******** */ -static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event)) +static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { char name[FILE_MAX]; int ret; @@ -2650,7 +2652,7 @@ static void wm_gesture_end(bContext *C, wmOperator *op) WM_cursor_restore(CTX_wm_window(C)); } -int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) +int WM_border_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) { if (ISTWEAK(event->type)) op->customdata = WM_gesture_new(C, event, WM_GESTURE_RECT); @@ -2665,7 +2667,7 @@ int WM_border_select_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -int WM_border_select_modal(bContext *C, wmOperator *op, wmEvent *event) +int WM_border_select_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; rcti *rect = gesture->customdata; @@ -2734,7 +2736,7 @@ int WM_border_select_cancel(bContext *C, wmOperator *op) int circle_select_size = 25; /* XXX - need some operator memory thing! */ #endif -int WM_gesture_circle_invoke(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_circle_invoke(bContext *C, wmOperator *op, const wmEvent *event) { op->customdata = WM_gesture_new(C, event, WM_GESTURE_CIRCLE); @@ -2769,7 +2771,7 @@ static void gesture_circle_apply(bContext *C, wmOperator *op) #endif } -int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_circle_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; rcti *rect = gesture->customdata; @@ -2787,7 +2789,18 @@ int WM_gesture_circle_modal(bContext *C, wmOperator *op, wmEvent *event) gesture_circle_apply(C, op); } else if (event->type == EVT_MODAL_MAP) { + float fac; + switch (event->val) { + case GESTURE_MODAL_CIRCLE_SIZE: + fac = 0.3f * (event->y - event->prevy); + if (fac > 0) + rect->xmax += ceil(fac); + else + rect->xmax += floor(fac); + if (rect->xmax < 1) rect->xmax = 1; + wm_gesture_tag_redraw(C); + break; case GESTURE_MODAL_CIRCLE_ADD: rect->xmax += 2 + rect->xmax / 10; wm_gesture_tag_redraw(C); @@ -2854,7 +2867,7 @@ void WM_OT_circle_gesture(wmOperatorType *ot) /* **************** Tweak gesture *************** */ -static void tweak_gesture_modal(bContext *C, wmEvent *event) +static void tweak_gesture_modal(bContext *C, const wmEvent *event) { wmWindow *window = CTX_wm_window(C); wmGesture *gesture = window->tweak; @@ -2896,7 +2909,9 @@ static void tweak_gesture_modal(bContext *C, wmEvent *event) WM_gesture_end(C, gesture); /* when tweak fails we should give the other keymap entries a chance */ - event->val = KM_RELEASE; + + /* XXX, assigning to readonly, BAD JUJU! */ + ((wmEvent *)event)->val = KM_RELEASE; } break; default: @@ -2932,7 +2947,7 @@ void wm_tweakevent_test(bContext *C, wmEvent *event, int action) /* *********************** lasso gesture ****************** */ -int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, const wmEvent *event) { op->customdata = WM_gesture_new(C, event, WM_GESTURE_LASSO); @@ -2947,7 +2962,7 @@ int WM_gesture_lasso_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -int WM_gesture_lines_invoke(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_lines_invoke(bContext *C, wmOperator *op, const wmEvent *event) { op->customdata = WM_gesture_new(C, event, WM_GESTURE_LINES); @@ -2989,7 +3004,7 @@ static void gesture_lasso_apply(bContext *C, wmOperator *op) } } -int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_lasso_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; int sx, sy; @@ -3045,7 +3060,7 @@ int WM_gesture_lasso_modal(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -int WM_gesture_lines_modal(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_lines_modal(bContext *C, wmOperator *op, const wmEvent *event) { return WM_gesture_lasso_modal(C, op, event); } @@ -3164,7 +3179,7 @@ static int straightline_apply(bContext *C, wmOperator *op) } -int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, const wmEvent *event) { op->customdata = WM_gesture_new(C, event, WM_GESTURE_STRAIGHTLINE); @@ -3179,7 +3194,7 @@ int WM_gesture_straightline_invoke(bContext *C, wmOperator *op, wmEvent *event) return OPERATOR_RUNNING_MODAL; } -int WM_gesture_straightline_modal(bContext *C, wmOperator *op, wmEvent *event) +int WM_gesture_straightline_modal(bContext *C, wmOperator *op, const wmEvent *event) { wmGesture *gesture = op->customdata; rcti *rect = gesture->customdata; @@ -3271,7 +3286,7 @@ typedef struct { void *cursor; } RadialControl; -static void radial_control_set_initial_mouse(RadialControl *rc, wmEvent *event) +static void radial_control_set_initial_mouse(RadialControl *rc, const wmEvent *event) { float d[2] = {0, 0}; float zoom[2] = {1, 1}; @@ -3587,7 +3602,7 @@ static int radial_control_get_properties(bContext *C, wmOperator *op) return 1; } -static int radial_control_invoke(bContext *C, wmOperator *op, wmEvent *event) +static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *event) { wmWindowManager *wm; RadialControl *rc; @@ -3684,7 +3699,7 @@ static int radial_control_cancel(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } -static int radial_control_modal(bContext *C, wmOperator *op, wmEvent *event) +static int radial_control_modal(bContext *C, wmOperator *op, const wmEvent *event) { RadialControl *rc = op->customdata; float new_value, dist, zoom[2]; @@ -4062,6 +4077,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) {GESTURE_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, {GESTURE_MODAL_CIRCLE_ADD, "ADD", 0, "Add", ""}, {GESTURE_MODAL_CIRCLE_SUB, "SUBTRACT", 0, "Subtract", ""}, + {GESTURE_MODAL_CIRCLE_SIZE, "SIZE", 0, "Size", ""}, {GESTURE_MODAL_SELECT, "SELECT", 0, "Select", ""}, {GESTURE_MODAL_DESELECT, "DESELECT", 0, "DeSelect", ""}, @@ -4100,6 +4116,7 @@ static void gesture_circle_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, PADMINUS, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_SUB); WM_modalkeymap_add_item(keymap, WHEELDOWNMOUSE, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_ADD); WM_modalkeymap_add_item(keymap, PADPLUSKEY, KM_PRESS, 0, 0, GESTURE_MODAL_CIRCLE_ADD); + WM_modalkeymap_add_item(keymap, MOUSEPAN, 0, 0, 0, GESTURE_MODAL_CIRCLE_SIZE); /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_select_circle"); @@ -4184,6 +4201,7 @@ static void gesture_border_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_assign(keymap, "MARKER_OT_select_border"); WM_modalkeymap_assign(keymap, "NLA_OT_select_border"); WM_modalkeymap_assign(keymap, "NODE_OT_select_border"); + WM_modalkeymap_assign(keymap, "NODE_OT_viewer_border"); WM_modalkeymap_assign(keymap, "PAINT_OT_hide_show"); WM_modalkeymap_assign(keymap, "OUTLINER_OT_select_border"); // WM_modalkeymap_assign(keymap, "SCREEN_OT_border_select"); // template diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index b510956dbc1..a289d182f1c 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -49,12 +49,12 @@ #include "PIL_time.h" +#include "BLI_utildefines.h" #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_rect.h" #include "BLI_string.h" -#include "BLI_utildefines.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -76,10 +76,16 @@ #include "WM_api.h" /* only for WM_main_playanim */ struct PlayState; -static void playanim_window_zoom(const struct PlayState *ps, const float zoom_offset); +static void playanim_window_zoom(struct PlayState *ps, const float zoom_offset); typedef struct PlayState { + /* window and viewport size */ + int win_x, win_y; + + /* current zoom level */ + float zoom; + /* playback state */ short direction; short next_frame; @@ -91,7 +97,7 @@ typedef struct PlayState { short wait2; short stopped; short go; - + int fstep; /* current picture */ @@ -103,6 +109,9 @@ typedef struct PlayState { /* saves passing args */ struct ImBuf *curframe_ibuf; + + /* restarts player for file drop */ + char dropped_file[FILE_MAX]; } PlayState; /* for debugging */ @@ -204,7 +213,6 @@ typedef struct PlayAnimPict { static struct ListBase picsbase = {NULL, NULL}; static int fromdisk = FALSE; -static float zoomx = 1.0, zoomy = 1.0; static double ptottime = 0.0, swaptime = 0.04; static PlayAnimPict *playanim_step(PlayAnimPict *playanim, int step) @@ -234,8 +242,9 @@ static int pupdate_time(void) return (ptottime < 0); } -static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep) +static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep) { + float offsx, offsy; if (ibuf == NULL) { printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>"); @@ -250,17 +259,29 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); - glRasterPos2f(0.0f, 0.0f); + /* offset within window */ + offsx = 0.5f * (((float)ps->win_x - ps->zoom * ibuf->x) / (float)ps->win_x); + offsy = 0.5f * (((float)ps->win_y - ps->zoom * ibuf->y) / (float)ps->win_y); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + CLAMP(offsx, 0.0f, 1.0f); + CLAMP(offsy, 0.0f, 1.0f); + glRasterPos2f(offsx, offsy); - fdrawcheckerboard(0.0f, 0.0f, ibuf->x, ibuf->y); + glClearColor(0.1, 0.1, 0.1, 0.0); + glClear(GL_COLOR_BUFFER_BIT); + + /* checkerboard for case alpha */ + if (ibuf->planes == 32) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + fdrawcheckerboard(offsx, offsy, offsx + (ps->zoom * ibuf->x) / (float)ps->win_x, offsy + (ps->zoom * ibuf->y) / (float)ps->win_y); + } + glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect); glDisable(GL_BLEND); - + pupdate_time(); if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) { @@ -283,7 +304,7 @@ static void playanim_toscreen(PlayAnimPict *picture, struct ImBuf *ibuf, int fon GHOST_SwapWindowBuffers(g_WS.ghost_window); } -static void build_pict_list(char *first, int totframes, int fstep, int fontid) +static void build_pict_list(PlayState *ps, char *first, int totframes, int fstep, int fontid) { char *mem, filepath[FILE_MAX]; // short val; @@ -299,7 +320,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) int pic; ibuf = IMB_anim_absolute(anim, 0, IMB_TC_NONE, IMB_PROXY_NONE); if (ibuf) { - playanim_toscreen(NULL, ibuf, fontid, fstep); + playanim_toscreen(ps, NULL, ibuf, fontid, fstep); IMB_freeImBuf(ibuf); } @@ -402,7 +423,7 @@ static void build_pict_list(char *first, int totframes, int fstep, int fontid) ibuf = IMB_loadiffname(picture->name, picture->IB_flags, NULL); } if (ibuf) { - playanim_toscreen(picture, ibuf, fontid, fstep); + playanim_toscreen(ps, picture, ibuf, fontid, fstep); IMB_freeImBuf(ibuf); } pupdate_time(); @@ -587,7 +608,9 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) case GHOST_kKeyPeriod: case GHOST_kKeyNumpadPeriod: if (val) { - if (ps->sstep) ps->wait2 = FALSE; + if (ps->sstep) { + ps->wait2 = FALSE; + } else { ps->sstep = TRUE; ps->wait2 = !ps->wait2; @@ -704,28 +727,33 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) case GHOST_kEventWindowSize: case GHOST_kEventWindowMove: { - int sizex, sizey; - - playanim_window_get_size(&sizex, &sizey); + float zoomx, zoomy; + + playanim_window_get_size(&ps->win_x, &ps->win_y); GHOST_ActivateWindowDrawingContext(g_WS.ghost_window); - glViewport(0, 0, sizex, sizey); - glScissor(0, 0, sizex, sizey); - - zoomx = (float) sizex / ps->ibufx; - zoomy = (float) sizey / ps->ibufy; - zoomx = floor(zoomx + 0.5f); - zoomy = floor(zoomy + 0.5f); - if (zoomx < 1.0f) zoomx = 1.0f; - if (zoomy < 1.0f) zoomy = 1.0f; - - sizex = zoomx * ps->ibufx; - sizey = zoomy * ps->ibufy; + zoomx = (float) ps->win_x / ps->ibufx; + zoomy = (float) ps->win_y / ps->ibufy; + + /* zoom always show entire image */ + ps->zoom = MIN2(zoomx, zoomy); + + /* zoom steps of 2 for speed */ + ps->zoom = floor(ps->zoom + 0.5f); + if (ps->zoom < 1.0f) ps->zoom = 1.0f; + + glViewport(0, 0, ps->win_x, ps->win_y); + glScissor(0, 0, ps->win_x, ps->win_y); + + /* unified matrix, note it affects offset for drawing */ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); + glMatrixMode(GL_MODELVIEW); - glPixelZoom(zoomx, zoomy); - glEnable(GL_DITHER); + glPixelZoom(ps->zoom, ps->zoom); ptottime = 0.0; - playanim_toscreen(ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); + playanim_toscreen(ps, ps->picture, ps->curframe_ibuf, ps->fontid, ps->fstep); break; } @@ -735,6 +763,23 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr ps_void) ps->go = FALSE; break; } + case GHOST_kEventDraggingDropDone: + { + GHOST_TEventDragnDropData *ddd = GHOST_GetEventData(evt); + + if (ddd->dataType == GHOST_kDragnDropTypeFilenames) { + GHOST_TStringArray *stra = ddd->data; + int a; + + for (a = 0; a < stra->count; a++) { + BLI_strncpy(ps->dropped_file, (char *)stra->strings[a], sizeof(ps->dropped_file)); + ps->go = FALSE; + printf("drop file %s\n", stra->strings[a]); + break; /* only one drop element supported now */ + } + } + break; + } default: /* quiet warnings */ break; @@ -765,32 +810,31 @@ static void playanim_window_open(const char *title, int posx, int posy, int size FALSE /* no stereo */, FALSE); } -static void playanim_window_zoom(const PlayState *ps, const float zoom_offset) +static void playanim_window_zoom(PlayState *ps, const float zoom_offset) { int sizex, sizey; /* int ofsx, ofsy; */ /* UNUSED */ - if (zoomx + zoom_offset > 0.0f) zoomx += zoom_offset; - if (zoomy + zoom_offset > 0.0f) zoomy += zoom_offset; + if (ps->zoom + zoom_offset > 0.0f) ps->zoom += zoom_offset; // playanim_window_get_position(&ofsx, &ofsy); playanim_window_get_size(&sizex, &sizey); /* ofsx += sizex / 2; */ /* UNUSED */ /* ofsy += sizey / 2; */ /* UNUSED */ - sizex = zoomx * ps->ibufx; - sizey = zoomy * ps->ibufy; + sizex = ps->zoom * ps->ibufx; + sizey = ps->zoom * ps->ibufy; /* ofsx -= sizex / 2; */ /* UNUSED */ /* ofsy -= sizey / 2; */ /* UNUSED */ // window_set_position(g_WS.ghost_window,sizex,sizey); GHOST_SetClientSize(g_WS.ghost_window, sizex, sizey); } -void WM_main_playanim(int argc, const char **argv) +/* return path for restart */ +static char *wm_main_playanim_intern(int argc, const char **argv) { struct ImBuf *ibuf = NULL; - char filepath[FILE_MAX]; + static char filepath[FILE_MAX]; /* abused to return dropped file path */ GHOST_TUns32 maxwinx, maxwiny; - /* short c233 = FALSE, yuvx = FALSE; */ /* UNUSED */ int i; /* This was done to disambiguate the name for use under c++. */ struct anim *anim = NULL; @@ -798,7 +842,7 @@ void WM_main_playanim(int argc, const char **argv) int sfra = -1; int efra = -1; int totblock; - + PlayState ps = {0}; /* ps.doubleb = TRUE;*/ /* UNUSED */ @@ -813,6 +857,8 @@ void WM_main_playanim(int argc, const char **argv) ps.wait2 = FALSE; ps.stopped = FALSE; ps.picture = NULL; + ps.dropped_file[0] = 0; + ps.zoom = 1.0f; /* resetmap = FALSE */ ps.fstep = 1; @@ -918,20 +964,16 @@ void WM_main_playanim(int argc, const char **argv) #endif #endif //XXX25 - /* XXX, fixme zr */ { -// extern void add_to_mainqueue(wmWindow *win, void *user_data, short evt, short val, char ascii); GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, &ps); g_WS.ghost_system = GHOST_CreateSystem(); GHOST_AddEventConsumer(g_WS.ghost_system, consumer); - - playanim_window_open("Blender:Anim", start_x, start_y, ibuf->x, ibuf->y, 0); -//XXX25 window_set_handler(g_WS.ghost_window, add_to_mainqueue, NULL); + /* unified matrix, note it affects offset for drawing */ glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f); @@ -949,11 +991,15 @@ void WM_main_playanim(int argc, const char **argv) ps.ibufx = ibuf->x; ps.ibufy = ibuf->y; + + ps.win_x = ps.ibufx; + ps.win_y = ps.ibufy; if (maxwinx % ibuf->x) maxwinx = ibuf->x * (1 + (maxwinx / ibuf->x)); if (maxwiny % ibuf->y) maxwiny = ibuf->y * (1 + (maxwiny / ibuf->y)); - glClearColor(0.0, 0.0, 0.0, 0.0); + + glClearColor(0.1, 0.1, 0.1, 0.0); glClear(GL_COLOR_BUFFER_BIT); GHOST_SwapWindowBuffers(g_WS.ghost_window); @@ -964,11 +1010,11 @@ void WM_main_playanim(int argc, const char **argv) efra = MAXFRAME; } - build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); + build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); for (i = 2; i < argc; i++) { BLI_strncpy(filepath, argv[i], sizeof(filepath)); - build_pict_list(filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); + build_pict_list(&ps, filepath, (efra - sfra) + 1, ps.fstep, ps.fontid); } IMB_freeImBuf(ibuf); @@ -1041,8 +1087,8 @@ void WM_main_playanim(int argc, const char **argv) while (pupdate_time()) PIL_sleep_ms(1); ptottime -= swaptime; - playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep); - } /* else deleten */ + playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep); + } /* else delete */ else { printf("error: can't play this image type\n"); exit(0); @@ -1060,16 +1106,17 @@ void WM_main_playanim(int argc, const char **argv) ps.next_frame = ps.direction; - while ((hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0) || ps.wait2 != 0)) { + while ( (hasevent = GHOST_ProcessEvents(g_WS.ghost_system, 0)) || ps.wait2 != 0) { if (hasevent) { GHOST_DispatchEvents(g_WS.ghost_system); } + /* Note, this still draws for mousemoves on pause */ if (ps.wait2) { if (hasevent) { if (ibuf) { while (pupdate_time()) PIL_sleep_ms(1); ptottime -= swaptime; - playanim_toscreen(ps.picture, ibuf, ps.fontid, ps.fstep); + playanim_toscreen(&ps, ps.picture, ibuf, ps.fontid, ps.fstep); } } } @@ -1142,12 +1189,20 @@ void WM_main_playanim(int argc, const char **argv) #else /* we still miss freeing a lot!, * but many areas could skip initialization too for anim play */ - IMB_exit(); - BKE_images_exit(); + BLF_exit(); #endif GHOST_DisposeWindow(g_WS.ghost_system, g_WS.ghost_window); + /* early exit, IMB and BKE should be exited only in end */ + if (ps.dropped_file) { + BLI_strncpy(filepath, ps.dropped_file, sizeof(filepath)); + return filepath; + } + + IMB_exit(); + BKE_images_exit(); + totblock = MEM_get_memory_blocks_in_use(); if (totblock != 0) { /* prints many bAKey, bArgument's which are tricky to fix */ @@ -1156,4 +1211,25 @@ void WM_main_playanim(int argc, const char **argv) MEM_printmemlist(); #endif } + + return NULL; +} + + +void WM_main_playanim(int argc, const char **argv) +{ + bool looping = true; + + while (looping) { + char *filepath = wm_main_playanim_intern(argc, argv); + + if (filepath) { /* use simple args */ + argv[1] = "-a"; + argv[2] = filepath; + argc = 3; + } + else { + looping = false; + } + } } diff --git a/source/blender/windowmanager/intern/wm_subwindow.c b/source/blender/windowmanager/intern/wm_subwindow.c index 20406ac463d..01bebe8a1b8 100644 --- a/source/blender/windowmanager/intern/wm_subwindow.c +++ b/source/blender/windowmanager/intern/wm_subwindow.c @@ -257,9 +257,9 @@ void wmSubWindowScissorSet(wmWindow *win, int swinid, rcti *srct) glViewport(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height); if (srct) { - int width = BLI_rcti_size_x(srct) + 1; /* only here */ - int height = BLI_rcti_size_y(srct) + 1; - glScissor(srct->xmin, srct->ymin, width, height); + int scissor_width = BLI_rcti_size_x(srct) + 1; /* only here */ + int scissor_height = BLI_rcti_size_y(srct) + 1; + glScissor(srct->xmin, srct->ymin, scissor_width, scissor_height); } else glScissor(_curswin->winrct.xmin, _curswin->winrct.ymin, width, height); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index a1ab0de49cf..53698ca7e9e 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -28,7 +28,6 @@ * \ingroup wm */ - #include <math.h> #include <stdlib.h> #include <stdio.h> @@ -37,7 +36,6 @@ #include "DNA_listBase.h" #include "DNA_screen_types.h" #include "DNA_windowmanager_types.h" -#include "RNA_access.h" #include "MEM_guardedalloc.h" @@ -55,9 +53,10 @@ #include "BKE_global.h" #include "BKE_main.h" - #include "BIF_gl.h" +#include "RNA_access.h" + #include "WM_api.h" #include "WM_types.h" #include "wm.h" @@ -445,11 +444,15 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) #endif #if !defined(__APPLE__) && !defined(WIN32) /* X11 */ - /* X11, start maximized but use default same size */ + /* X11, start maximized but use default sane size */ wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X); wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y); + /* pad */ + wm_init_state.start_x = WM_WIN_INIT_PAD; + wm_init_state.start_y = WM_WIN_INIT_PAD; + wm_init_state.size_x -= WM_WIN_INIT_PAD * 2; + wm_init_state.size_y -= WM_WIN_INIT_PAD * 2; #endif - } for (win = wm->windows.first; win; win = win->next) { @@ -460,19 +463,7 @@ void wm_window_add_ghostwindows(wmWindowManager *wm) win->sizex = wm_init_state.size_x; win->sizey = wm_init_state.size_y; -#if !defined(__APPLE__) && !defined(WIN32) /* X11 */ - if (wm_init_state.override_flag & WIN_OVERRIDE_GEOM) { - /* we can't properly resize a maximized window */ - win->windowstate = GHOST_kWindowStateNormal; - } - else { - /* loading without userpref, default to maximized */ - win->windowstate = GHOST_kWindowStateMaximized; - } -#else win->windowstate = GHOST_kWindowStateNormal; -#endif - wm_init_state.override_flag &= ~WIN_OVERRIDE_GEOM; } @@ -1253,7 +1244,9 @@ void WM_clipboard_text_set(char *buf, int selection) if (*p == '\n') { *(p2++) = '\r'; *p2 = '\n'; } - else *p2 = *p; + else { + *p2 = *p; + } } *p2 = '\0'; diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index bc7e7efdcfd..338ef8bc65b 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -384,6 +384,8 @@ enum { #define GESTURE_MODAL_IN 9 #define GESTURE_MODAL_OUT 10 +#define GESTURE_MODAL_CIRCLE_SIZE 11 /* circle sel: size brush (for trackpad event) */ + #endif /* __WM_EVENT_TYPES_H__ */ diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index c4c64ed429f..a0546c88b78 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -74,6 +74,7 @@ int wm_window_fullscreen_toggle_exec(bContext *C, struct wmOperator *op); * Clamped by real desktop limits */ #define WM_WIN_INIT_SIZE_X 1800 #define WM_WIN_INIT_SIZE_Y 1000 +#define WM_WIN_INIT_PAD 40 #endif /* __WM_WINDOW_H__ */ diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 5e65324d893..c775f7d3279 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -150,6 +150,7 @@ endif() bf_intern_opencolorio bf_intern_opennl extern_rangetree + extern_wcwidth ) if(WITH_MOD_CLOTH_ELTOPO) diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 5e8a0b2a06b..c76992677d5 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -71,6 +71,7 @@ struct Mask; struct Material; struct MenuType; struct Mesh; +struct MetaBall; struct ModifierData; struct MovieClip; struct MultiresModifierData; @@ -116,6 +117,7 @@ struct bNodeSocket; struct bNodeTree; struct bPoseChannel; struct bPythonConstraint; +struct bTheme; struct uiLayout; struct wmEvent; struct wmKeyConfig; @@ -201,7 +203,7 @@ void WM_menutype_free(void) {} void WM_menutype_freelink(struct MenuType *mt) {} int WM_menutype_add(struct MenuType *mt) {return 0;} int WM_operator_props_dialog_popup(struct bContext *C, struct wmOperator *op, int width, int height) {return 0;} -int WM_operator_confirm(struct bContext *C, struct wmOperator *op, struct wmEvent *event) {return 0;} +int WM_operator_confirm(struct bContext *C, struct wmOperator *op, const struct wmEvent *event) {return 0;} struct MenuType *WM_menutype_find(const char *idname, int quiet) {return (struct MenuType *) NULL;} void WM_operator_stack_clear(struct bContext *C) {} void WM_operator_handlers_clear(struct bContext *C, struct wmOperatorType *ot) {} @@ -420,6 +422,7 @@ void uiLayoutSetContextPointer(struct uiLayout *layout, char *name, struct Point char *uiLayoutIntrospect(struct uiLayout *layout) {return (char *)NULL;} void UI_reinit_font(void) {} int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big) {return 0;} +struct bTheme *UI_GetTheme(void) {return (struct bTheme *) NULL;}; /* rna template */ void uiTemplateAnyID(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, char *text) {} @@ -466,6 +469,7 @@ struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, struct RenderResult *RE_AcquireResultRead(struct Render *re) {return (struct RenderResult *) NULL;} struct RenderResult *RE_AcquireResultWrite(struct Render *re) {return (struct RenderResult *) NULL;} struct RenderStats *RE_GetStats(struct Render *re) {return (struct RenderStats *) NULL;} +struct RenderData *RE_engine_get_render_data(struct Render *re) {return (struct RenderData *) NULL;} void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result) {} void RE_engine_update_progress(struct RenderEngine *engine, float progress) {} void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result) {} @@ -524,7 +528,6 @@ float sculpt_get_brush_alpha(struct Brush *brush) {return 0.0f;} void sculpt_set_brush_alpha(struct Brush *brush, float alpha) {} void ED_sculpt_modifiers_changed(struct Object *ob) {} void ED_mesh_calc_tessface(struct Mesh *mesh) {} -void BKE_brush_gen_texture_cache(struct Brush *br, int half_side) {} /* bpy/python internal api */ void operator_wrapper(struct wmOperatorType *ot, void *userdata) {} diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index d858f7ac62d..551579dcf65 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -927,6 +927,7 @@ endif() bf_intern_raskter bf_intern_opencolorio extern_rangetree + extern_wcwidth ) if(WITH_COMPOSITOR) diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index 3a9a10dd0cc..f24392352b0 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -166,7 +166,7 @@ void BL_draw_gamedebug_box(int xco, int yco, int width, int height, float percen } /* Print 3D text */ -void BL_print_game_line(int fontid, const char* text, int size, int dpi, float* color, double* mat, float aspect) +void BL_print_game_line(int fontid, const char *text, int size, int dpi, float *color, double *mat, float aspect) { /* gl prepping */ DisableForText(); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h index 2a96d4c5216..0ce479cad6f 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderInputDevice.h @@ -64,7 +64,7 @@ public: } KX_EnumInputs ToNative(unsigned short incode) { - return ConvertKeyCode(incode); + return ConvertKeyCode(incode); } virtual bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode)=0; diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index c4af3255f4a..580691d88c4 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -253,9 +253,9 @@ public: // Increase global reference count, used to see at the end of the program // if all CValue-derived classes have been dereferenced to 0 //debug(gRefCountValue++); - #ifdef _DEBUG +#ifdef _DEBUG //gRefCountValue++; - #endif +#endif m_refcount++; return this; } @@ -266,9 +266,9 @@ public: // Decrease global reference count, used to see at the end of the program // if all CValue-derived classes have been dereferenced to 0 //debug(gRefCountValue--); - #ifdef _DEBUG +#ifdef _DEBUG //gRefCountValue--; - #endif +#endif // Decrease local reference count, if it reaches 0 the object should be freed if (--m_refcount > 0) { diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 090df1e75e2..aed49bc1822 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -131,7 +131,7 @@ public: virtual void ProcessReplica(); /** - * Return true iff all the current events + * Return true if all the current events * are negative. The definition of negative event is * not immediately clear. But usually refers to key-up events * or events where no action is required. diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index 00c5911a8b4..07f96166ec2 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -36,8 +36,8 @@ #include "RAS_Rect.h" #ifdef WIN32 - #pragma warning (disable:4786) // suppress stl-MSVC debug info warning - #include <windows.h> +# pragma warning (disable:4786) // suppress stl-MSVC debug info warning +# include <windows.h> #endif /* WIN32 */ #include "GL/glew.h" diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index c1f43306eba..5d843cccf85 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -1055,6 +1055,7 @@ int main(int argc, char** argv) #ifdef WITH_INTERNATIONAL BLF_free_unifont(); + BLF_free_unifont_mono(); BLF_lang_free(); #endif diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 4a5a1704979..ece6abc9447 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -68,8 +68,8 @@ extern "C"{ #include "KX_BulletPhysicsController.h" #include "btBulletDynamicsCommon.h" - #ifdef WIN32 -#if _MSC_VER >= 1310 +#ifdef WIN32 +#if defined(_MSC_VER) && (_MSC_VER >= 1310) //only use SIMD Hull code under Win32 //#define TEST_HULL 1 #ifdef TEST_HULL diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 3a60ccc85e9..ae5758b8597 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -2742,11 +2742,11 @@ PyObject *KX_GameObject::PyGetReactionForce() // only can get the velocity if we have a physics object connected to us... // XXX - Currently not working with bullet intergration, see KX_BulletPhysicsController.cpp's getReactionForce - /* +#if 0 if (GetPhysicsController()) return PyObjectFrom(GetPhysicsController()->getReactionForce()); return PyObjectFrom(dummy_point); - */ +#endif return Py_BuildValue("fff", 0.0, 0.0, 0.0); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index a54d4909db9..22715214324 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -1888,7 +1888,7 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur * somehow it remembers the sys.path - Campbell */ static bool first_time = true; - char *py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL); + const char * const py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL); #if 0 // TODO - py3 STR_String pname = progname; diff --git a/source/gameengine/Network/NG_NetworkScene.h b/source/gameengine/Network/NG_NetworkScene.h index 10dad210128..e6233852ee2 100644 --- a/source/gameengine/Network/NG_NetworkScene.h +++ b/source/gameengine/Network/NG_NetworkScene.h @@ -42,7 +42,7 @@ //MSVC defines SendMessage as a win api function, even though we aren't using it #ifdef SendMessage - #undef SendMessage +# undef SendMessage #endif using namespace std; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 702452bc77e..9fb86dec569 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -1206,7 +1206,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac { // soft body using different face numbering because of randomization // hopefully we have stored the original face number in m_tag - btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject); + const btSoftBody* softBody = static_cast<const btSoftBody*>(rayCallback.m_collisionObject); if (softBody->m_faces[hitTriangleIndex].m_tag != 0) { rayCallback.m_hitTriangleIndex = (int)((uintptr_t)(softBody->m_faces[hitTriangleIndex].m_tag)-1); @@ -1226,7 +1226,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac if (shape->isSoftBody()) { // soft body give points directly in world coordinate - btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject); + const btSoftBody* softBody = static_cast<const btSoftBody*>(rayCallback.m_collisionObject); v1 = softBody->m_faces[hitTriangleIndex].m_n[0]->m_x; v2 = softBody->m_faces[hitTriangleIndex].m_n[1]->m_x; v3 = softBody->m_faces[hitTriangleIndex].m_n[2]->m_x; @@ -1274,7 +1274,7 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallbac if (shape->isSoftBody()) { // we can get the real normal directly from the body - btSoftBody* softBody = static_cast<btSoftBody*>(rayCallback.m_collisionObject); + const btSoftBody* softBody = static_cast<const btSoftBody*>(rayCallback.m_collisionObject); rayCallback.m_hitNormalWorld = softBody->m_faces[hitTriangleIndex].m_normal; } else { @@ -2211,8 +2211,8 @@ void CcdPhysicsEnvironment::CallbackTriggers() int numContacts = manifold->getNumContacts(); if (numContacts) { - btRigidBody* rb0 = static_cast<btRigidBody*>(manifold->getBody0()); - btRigidBody* rb1 = static_cast<btRigidBody*>(manifold->getBody1()); + const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0()); + const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1()); if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)) { for (int j=0;j<numContacts;j++) @@ -2223,8 +2223,8 @@ void CcdPhysicsEnvironment::CallbackTriggers() m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); } } - btRigidBody* obj0 = rb0; - btRigidBody* obj1 = rb1; + const btRigidBody* obj0 = rb0; + const btRigidBody* obj1 = rb1; //m_internalOwner is set in 'addPhysicsController' CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer()); diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index ab0f62c84c7..e093b7cd722 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -435,6 +435,9 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // if the last rendered face had alpha add it would messes with the color of the plane we apply 2DFilter to glDisable(GL_BLEND); + // fix for [#34523] alpha buffer is now available for all OSs + glDisable(GL_ALPHA_TEST); + glPushMatrix(); //GL_MODELVIEW glLoadIdentity(); // GL_MODELVIEW glMatrixMode(GL_TEXTURE); @@ -465,7 +468,8 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) } glEnable(GL_DEPTH_TEST); - canvas->SetViewPort(viewport[0],viewport[1],viewport[2],viewport[3]); + //We can't pass the results of canvas->GetViewPort() directly because canvas->SetViewPort() does some extra math [#34517] + canvas->SetViewPort(0, 0, viewport[2]-1, viewport[3]-1); EndShaderProgram(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); diff --git a/source/tests/bl_pyapi_mathutils.py b/source/tests/bl_pyapi_mathutils.py index a37f74463ee..1754644e813 100644 --- a/source/tests/bl_pyapi_mathutils.py +++ b/source/tests/bl_pyapi_mathutils.py @@ -89,7 +89,7 @@ class MatrixTesting(unittest.TestCase): (19, 26, 33), (29, 40, 51))) - self.assertEqual(mat1*mat2, prod_mat1) + self.assertEqual(mat1 * mat2, prod_mat1) self.assertEqual(mat2 * mat1, prod_mat2) def test_mat4x4_vec3D_mult(self): diff --git a/source/tests/bl_run_operators.py b/source/tests/bl_run_operators.py index 0202f7c64fb..e6f1cc56eb0 100644 --- a/source/tests/bl_run_operators.py +++ b/source/tests/bl_run_operators.py @@ -139,7 +139,9 @@ if USE_ATTRSET: if subvalue == parent: continue - + # grr, recursive! + if prop == "point_caches": + continue subvalue_type = type(subvalue) yield value, prop, subvalue_type subvalue_id = getattr(subvalue, "id_data", Ellipsis) |