diff options
author | Sergej Reich <sergej.reich@googlemail.com> | 2013-09-06 12:35:00 +0400 |
---|---|---|
committer | Sergej Reich <sergej.reich@googlemail.com> | 2013-09-06 12:35:00 +0400 |
commit | 36e6bddb5c155b4ae27a9cd17b4af26bbcdc8dae (patch) | |
tree | 025a56b2e71adc77d53a4a33ac17a6cf55d360c2 /source/blender | |
parent | df3974b6d1c6469ca1a0b8a1c505b09385198780 (diff) | |
parent | 63ade11564798e68943ad5d8c82d45771df67677 (diff) |
svn merge -r59229:59868 ^/trunk/blender
Diffstat (limited to 'source/blender')
653 files changed, 16336 insertions, 13688 deletions
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 15098d50531..d46df829295 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -50,6 +50,7 @@ #include "BLI_string_utf8.h" #include "BLI_threads.h" #include "BLI_linklist.h" /* linknode */ +#include "BLI_strict_flags.h" #include "BIF_gl.h" #include "BLF_api.h" @@ -59,10 +60,6 @@ #include "blf_internal_types.h" #include "blf_internal.h" -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -#endif - /* freetype2 handle ONLY for this file!. */ static FT_Library ft_lib; static SpinLock ft_lib_mutex; @@ -163,7 +160,7 @@ static void blf_font_ensure_ascii_table(FontBLF *font) _kern_mode, \ &(_delta)) == 0) \ { \ - _pen_x += _delta.x >> 6; \ + _pen_x += (int)_delta.x >> 6; \ } \ } \ } (void)0 @@ -194,7 +191,7 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len) /* do not return this loop if clipped, we want every character tested */ blf_glyph_render(font, g, (float)pen_x, (float)pen_y); - pen_x += g->advance; + pen_x += (int)g->advance; g_prev = g; } } @@ -221,7 +218,7 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len) /* do not return this loop if clipped, we want every character tested */ blf_glyph_render(font, g, (float)pen_x, (float)pen_y); - pen_x += g->advance; + pen_x += (int)g->advance; g_prev = g; } } @@ -273,10 +270,11 @@ void blf_font_buffer(FontBLF *font, const char *str) /* buffer specific vars */ FontBufInfoBLF *buf_info = &font->buf_info; float b_col_float[4]; - const unsigned char b_col_char[4] = {buf_info->col[0] * 255, - buf_info->col[1] * 255, - buf_info->col[2] * 255, - buf_info->col[3] * 255}; + const unsigned char b_col_char[4] = { + (unsigned char)(buf_info->col[0] * 255), + (unsigned char)(buf_info->col[1] * 255), + (unsigned char)(buf_info->col[2] * 255), + (unsigned char)(buf_info->col[3] * 255)}; unsigned char *cbuf; int chx, chy; @@ -378,14 +376,27 @@ void blf_font_buffer(FontBLF *font, const char *str) cbuf[0] = b_col_char[0]; cbuf[1] = b_col_char[1]; cbuf[2] = b_col_char[2]; - cbuf[3] = (alphatest = ((int)cbuf[3] + (int)b_col_char[3])) < 255 ? alphatest : 255; + + alphatest = (int)cbuf[3] + (int)b_col_char[3]; + if (alphatest < 255) { + cbuf[3] = (unsigned char)(alphatest); + } + else { + cbuf[3] = 255; + } } else { - cbuf[0] = (b_col_char[0] * a) + (cbuf[0] * (1.0f - a)); - cbuf[1] = (b_col_char[1] * a) + (cbuf[1] * (1.0f - a)); - cbuf[2] = (b_col_char[2] * a) + (cbuf[2] * (1.0f - a)); - cbuf[3] = (alphatest = ((int)cbuf[3] + (int)((b_col_float[3] * a) * 255.0f))) < - 255 ? alphatest : 255; + cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a))); + cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a))); + cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a))); + + alphatest = ((int)cbuf[3] + (int)((b_col_float[3] * a) * 255.0f)); + if (alphatest < 255) { + cbuf[3] = (unsigned char)(alphatest); + } + else { + cbuf[3] = 255; + } } } } @@ -398,7 +409,7 @@ void blf_font_buffer(FontBLF *font, const char *str) } } - pen_x += g->advance; + pen_x += (int)g->advance; g_prev = g; } } @@ -433,10 +444,10 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box) if (has_kerning) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); - gbox.xmin = pen_x; - gbox.xmax = pen_x + g->advance; - gbox.ymin = g->box.ymin + pen_y; - gbox.ymax = g->box.ymax + pen_y; + gbox.xmin = (float)pen_x; + gbox.xmax = (float)pen_x + g->advance; + gbox.ymin = g->box.ymin + (float)pen_y; + gbox.ymax = g->box.ymax + (float)pen_y; if (gbox.xmin < box->xmin) box->xmin = gbox.xmin; if (gbox.ymin < box->ymin) box->ymin = gbox.ymin; @@ -444,7 +455,7 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box) if (gbox.xmax > box->xmax) box->xmax = gbox.xmax; if (gbox.ymax > box->ymax) box->ymax = gbox.ymax; - pen_x += g->advance; + pen_x += (int)g->advance; g_prev = g; } @@ -524,9 +535,7 @@ void blf_font_free(FontBLF *font) GlyphCacheBLF *gc; font->glyph_cache = NULL; - while (font->cache.first) { - gc = font->cache.first; - BLI_remlink(&font->cache, gc); + while ((gc = BLI_pophead(&font->cache))) { blf_glyph_cache_free(gc); } diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index 37e874fa396..2a8e91299b4 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -56,9 +56,7 @@ #include "blf_internal_types.h" #include "blf_internal.h" -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -#endif +#include "BLI_strict_flags.h" GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi) { @@ -89,28 +87,28 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) gc->textures = (GLuint *)MEM_mallocN(sizeof(GLuint) * 256, __func__); gc->ntex = 256; - gc->cur_tex = -1; + gc->cur_tex = BLF_CURTEX_UNSET; gc->x_offs = 0; gc->y_offs = 0; gc->pad = 3; - gc->num_glyphs = font->face->num_glyphs; - gc->rem_glyphs = font->face->num_glyphs; + gc->num_glyphs = (int)font->face->num_glyphs; + gc->rem_glyphs = (int)font->face->num_glyphs; gc->ascender = ((float)font->face->size->metrics.ascender) / 64.0f; gc->descender = ((float)font->face->size->metrics.descender) / 64.0f; if (FT_IS_SCALABLE(font->face)) { - gc->max_glyph_width = (float)((font->face->bbox.xMax - font->face->bbox.xMin) * - (((float)font->face->size->metrics.x_ppem) / - ((float)font->face->units_per_EM))); + gc->max_glyph_width = (int)((float)(font->face->bbox.xMax - font->face->bbox.xMin) * + (((float)font->face->size->metrics.x_ppem) / + ((float)font->face->units_per_EM))); - gc->max_glyph_height = (float)((font->face->bbox.yMax - font->face->bbox.yMin) * - (((float)font->face->size->metrics.y_ppem) / - ((float)font->face->units_per_EM))); + gc->max_glyph_height = (int)((float)(font->face->bbox.yMax - font->face->bbox.yMin) * + (((float)font->face->size->metrics.y_ppem) / + ((float)font->face->units_per_EM))); } else { - gc->max_glyph_width = ((float)font->face->size->metrics.max_advance) / 64.0f; - gc->max_glyph_height = ((float)font->face->size->metrics.height) / 64.0f; + gc->max_glyph_width = (int)(((float)font->face->size->metrics.max_advance) / 64.0f); + gc->max_glyph_height = (int)(((float)font->face->size->metrics.height) / 64.0f); } gc->p2_width = 0; @@ -128,9 +126,7 @@ void blf_glyph_cache_clear(FontBLF *font) for (gc = font->cache.first; gc; gc = gc->next) { for (i = 0; i < 257; i++) { - while (gc->bucket[i].first) { - g = gc->bucket[i].first; - BLI_remlink(&(gc->bucket[i]), g); + while ((g = BLI_pophead(&gc->bucket[i]))) { blf_glyph_free(g); } } @@ -145,15 +141,13 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc) int i; for (i = 0; i < 257; i++) { - while (gc->bucket[i].first) { - g = gc->bucket[i].first; - BLI_remlink(&(gc->bucket[i]), g); + while ((g = BLI_pophead(&gc->bucket[i]))) { blf_glyph_free(g); } } - if (gc->cur_tex > -1) - glDeleteTextures(gc->cur_tex + 1, gc->textures); + if (gc->cur_tex != BLF_CURTEX_UNSET) + glDeleteTextures((int)gc->cur_tex + 1, gc->textures); MEM_freeN((void *)gc->textures); MEM_freeN(gc); } @@ -287,7 +281,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ int i; for (i = 0; i < (g->width * g->height); i++) { - bitmap.buffer[i] = 255 * bitmap.buffer[i]; + bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0; } } @@ -296,8 +290,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) } g->advance = ((float)slot->advance.x) / 64.0f; - g->pos_x = slot->bitmap_left; - g->pos_y = slot->bitmap_top; + g->pos_x = (float)slot->bitmap_left; + g->pos_y = (float)slot->bitmap_top; g->pitch = slot->bitmap.pitch; FT_Outline_Get_CBox(&(slot->outline), &bbox); @@ -351,7 +345,7 @@ static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x const float *fp = soft; float color[4]; - int dx, dy; + float dx, dy; color[0] = shadow_col[0]; color[1] = shadow_col[1]; @@ -376,7 +370,7 @@ static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x const float *fp = soft; float color[4]; - int dx, dy; + float dx, dy; color[0] = shadow_col[0]; color[1] = shadow_col[1]; @@ -395,10 +389,10 @@ static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y) { - rect->xmin = floor(x + g->pos_x); - rect->xmax = rect->xmin + g->width; + rect->xmin = (float)floor(x + g->pos_x); + rect->xmax = rect->xmin + (float)g->width; rect->ymin = y + g->pos_y; - rect->ymax = y + g->pos_y - g->height; + rect->ymax = y + g->pos_y - (float)g->height; } void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) @@ -414,7 +408,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) if (font->max_tex_size == -1) glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size); - if (gc->cur_tex == -1) { + if (gc->cur_tex == BLF_CURTEX_UNSET) { blf_glyph_cache_texture(font, gc); gc->x_offs = gc->pad; gc->y_offs = 0; @@ -462,7 +456,7 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) g->uv[1][1] = ((float)(g->yoff + g->height)) / ((float)gc->p2_height); /* update the x offset for the next glyph. */ - gc->x_offs += (int)(BLI_rctf_size_x(&g->box) + gc->pad); + gc->x_offs += (int)BLI_rctf_size_x(&g->box) + gc->pad; gc->rem_glyphs--; g->build_tex = 1; @@ -486,7 +480,9 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) if (font->flags & BLF_SHADOW) { rctf rect_ofs; - blf_glyph_calc_rect(&rect_ofs, g, x + font->shadow_x, y + font->shadow_y); + blf_glyph_calc_rect(&rect_ofs, g, + x + (float)font->shadow_x, + y + (float)font->shadow_y); switch (font->shadow) { case 3: diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 096ff50a3ca..c64b7e974e7 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -54,7 +54,7 @@ typedef struct GlyphCacheBLF { unsigned int ntex; /* and the last texture, aka. the current texture. */ - int cur_tex; + unsigned int cur_tex; /* like bftgl, we draw every glyph in a big texture, so this is the * current position inside the texture. @@ -235,4 +235,6 @@ typedef struct DirBLF { char *path; } DirBLF; +#define BLF_CURTEX_UNSET ((unsigned int)-1) + #endif /* __BLF_INTERNAL_TYPES_H__ */ diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 8396380fd06..d8af90b4ae7 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -72,6 +72,8 @@ #include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" +#include "BLI_compiler_attrs.h" + #include "BKE_customdata.h" #include "BKE_bvhutils.h" @@ -733,14 +735,12 @@ void DM_init_origspace(DerivedMesh *dm); char *DM_debug_info(DerivedMesh *dm); void DM_debug_print(DerivedMesh *dm); void DM_debug_print_cdlayers(CustomData *cdata); -#endif -#ifdef __GNUC__ -BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) - __attribute__((nonnull(1))) -; +bool DM_is_valid(DerivedMesh *dm); #endif +BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) ATTR_NONNULL(1); + BLI_INLINE int DM_origindex_mface_mpoly(const int *index_mf_to_mpoly, const int *index_mp_to_orig, const int i) { const int j = index_mf_to_mpoly[i]; diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 539c5780cd5..7de7a745ed6 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -59,7 +59,7 @@ void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets); /* Curve Paths */ void free_path(struct Path *path); -void calc_curvepath(struct Object *ob); +void calc_curvepath(struct Object *ob, struct ListBase *nurbs); int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius, float *weight); /* ---------------------------------------------------- */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 9bdc5b0fc8f..60e03af5077 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -124,11 +124,13 @@ void BKE_pchan_to_pose_mat(struct bPoseChannel *pchan, float rotscale_mat[4][4], void BKE_rotMode_change_values(float quat[4], float eul[3], float axis[3], float *angle, short oldMode, short newMode); /* B-Bone support */ +#define MAX_BBONE_SUBDIV 32 + typedef struct Mat4 { float mat[4][4]; } Mat4; -Mat4 *b_bone_spline_setup(struct bPoseChannel *pchan, int rest); +void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]); /* like EBONE_VISIBLE */ #define PBONE_VISIBLE(arm, bone) ( \ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 84e24df43e5..13fd4b2bab7 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 268 -#define BLENDER_SUBVERSION 2 +#define BLENDER_SUBVERSION 3 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index edf710ef7c9..b4c5f47cf25 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -76,10 +76,10 @@ float BKE_brush_sample_masktex(const Scene *scene, struct Brush *br, const float const int thread, struct ImagePool *pool); /* texture */ -unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side); +unsigned int *BKE_brush_gen_texture_cache(struct Brush *br, int half_side, bool use_secondary); /* radial control */ -struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br); +struct ImBuf *BKE_brush_gen_radial_control_imbuf(struct Brush *br, bool secondary); /* unified strength and size */ diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 947e680d119..1b61d0a5443 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -80,7 +80,7 @@ typedef struct Cloth { struct MFace *mfaces; struct Implicit_Data *implicit; /* our implicit solver connects to this pointer */ struct Implicit_Data *implicitEM; /* our implicit solver connects to this pointer */ - struct EdgeHash *edgehash; /* used for selfcollisions */ + struct EdgeHash *edgehash; /* used for selfcollisions (currently used as a 'set', value is ignored) */ int last_frame, pad4; } Cloth; diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index baa90e7a856..609b7e4ae4b 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -42,6 +42,13 @@ struct Main; struct Nurb; struct Object; struct Scene; +struct Path; + +typedef struct CurveCache { + ListBase disp; + ListBase bev; + struct Path *path; +} CurveCache; #define KNOTSU(nu) ( (nu)->orderu + (nu)->pntsu + (((nu)->flagu & CU_NURB_CYCLIC) ? ((nu)->orderu - 1) : 0) ) #define KNOTSV(nu) ( (nu)->orderv + (nu)->pntsv + (((nu)->flagv & CU_NURB_CYCLIC) ? ((nu)->orderv - 1) : 0) ) @@ -63,7 +70,11 @@ void BKE_curve_make_local(struct Curve *cu); short BKE_curve_type_get(struct Curve *cu); void BKE_curve_type_test(struct Object *ob); void BKE_curve_curve_dimension_update(struct Curve *cu); + +void BKE_curve_boundbox_calc(struct Curve *cu, float r_loc[3], float r_size[3]); +struct BoundBox *BKE_curve_boundbox_get(struct Object *ob); void BKE_curve_texspace_calc(struct Curve *cu); +void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], float r_size[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]); @@ -74,11 +85,11 @@ void BKE_curve_material_index_clear(struct Curve *cu); ListBase *BKE_curve_nurbs_get(struct Curve *cu); -float (*BKE_curve_vertexCos_get(struct Curve *cu, struct ListBase *lb, int *numVerts_r))[3]; -void BK_curve_vertexCos_apply(struct Curve *cu, struct ListBase *lb, float (*vertexCos)[3]); +float (*BKE_curve_nurbs_vertexCos_get(struct ListBase *lb, int *numVerts_r))[3]; +void BK_curve_nurbs_vertexCos_apply(struct ListBase *lb, float (*vertexCos)[3]); -float (*BKE_curve_keyVertexCos_get(struct Curve *cu, struct ListBase *lb, float *key))[3]; -void BKE_curve_keyVertexTilts_apply(struct Curve *cu, struct ListBase *lb, float *key); +float (*BKE_curve_nurbs_keyVertexCos_get(struct ListBase *lb, float *key))[3]; +void BKE_curve_nurbs_keyVertexTilts_apply(struct ListBase *lb, float *key); void BKE_curve_editNurb_keyIndex_free(struct EditNurb *editnurb); void BKE_curve_editNurb_free(struct Curve *cu); @@ -87,7 +98,7 @@ struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu); float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts); float *BKE_curve_surf_make_orco(struct Object *ob); -void BKE_curve_bevelList_make(struct Object *ob); +void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render); void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBase *disp, int forRender, int renderResolution); void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); @@ -139,6 +150,7 @@ void BKE_nurb_bezt_calc_normal(struct Nurb *nu, struct BezTriple *bezt, float r_ void BKE_nurb_bezt_calc_plane(struct Nurb *nu, struct BezTriple *bezt, float r_plane[3]); void BKE_nurb_handle_calc(struct BezTriple *bezt, struct BezTriple *prev, struct BezTriple *next, int mode); +void BKE_nurb_handle_calc_simple(struct Nurb *nu, struct BezTriple *bezt); void BKE_nurb_handles_calc(struct Nurb *nu); void BKE_nurb_handles_autocalc(struct Nurb *nu, int flag); diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 1cf77c68345..2178f860825 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -102,4 +102,6 @@ float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int /* add Orco layer to the displist object which has got derived mesh and return orco */ float *BKE_displist_make_orco(struct Scene *scene, struct Object *ob, struct DerivedMesh *derivedFinal, int forRender, int renderResolution); +void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]); + #endif diff --git a/source/blender/blenkernel/BKE_editmesh_bvh.h b/source/blender/blenkernel/BKE_editmesh_bvh.h index 6750ee1ff3e..7b4ad4284c6 100644 --- a/source/blender/blenkernel/BKE_editmesh_bvh.h +++ b/source/blender/blenkernel/BKE_editmesh_bvh.h @@ -44,7 +44,7 @@ typedef struct BMBVHTree BMBVHTree; BMBVHTree *BKE_bmbvh_new(struct BMEditMesh *em, int flag, const float (*cos_cage)[3], const bool cos_cage_free); void BKE_bmbvh_free(BMBVHTree *tree); struct BVHTree *BKE_bmbvh_tree_get(BMBVHTree *tree); -struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], +struct BMFace *BKE_bmbvh_ray_cast(BMBVHTree *tree, const float co[3], const float dir[3], const float radius, float *r_dist, float r_hitout[3], float r_cagehit[3]); /* find a face intersecting a segment (but not apart of the segment) */ struct BMFace *BKE_bmbvh_find_face_segment(BMBVHTree *tree, const float co_a[3], const float co_b[3], diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 133a0690dc6..71fd163a8ee 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -30,6 +30,8 @@ #include "DNA_ID.h" +#include "BLI_compiler_attrs.h" + struct IDProperty; struct ID; @@ -55,32 +57,14 @@ typedef union IDPropertyTemplate { /* ----------- Property Array Type ---------- */ -IDProperty *IDP_NewIDPArray(const char *name) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -IDProperty *IDP_CopyIDPArray(IDProperty *array) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +IDProperty *IDP_NewIDPArray(const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +IDProperty *IDP_CopyIDPArray(IDProperty *array) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void IDP_FreeIDPArray(IDProperty *prop); /* shallow copies item */ -void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item); -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +void IDP_SetIndexArray(struct IDProperty *prop, int index, struct IDProperty *item) ATTR_NONNULL(); +struct IDProperty *IDP_GetIndexArray(struct IDProperty *prop, int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void IDP_AppendArray(struct IDProperty *prop, struct IDProperty *item); void IDP_ResizeIDPArray(struct IDProperty *prop, int len); @@ -90,33 +74,11 @@ void IDP_ResizeArray(struct IDProperty *prop, int newlen); void IDP_FreeArray(struct IDProperty *prop); /* ---------- String Type ------------ */ -IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) /* maxlen excludes '\0' */ -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull (2))) /* 'name' arg */ -#endif -; - -void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen) /* maxlen excludes '\0' */ -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; -void IDP_ConcatStringC(struct IDProperty *prop, const char *st) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; -void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; -void IDP_FreeString(struct IDProperty *prop) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2 /* 'name 'arg */); /* maxlen excludes '\0' */ +void IDP_AssignString(struct IDProperty *prop, const char *st, int maxlen) ATTR_NONNULL(); /* maxlen excludes '\0' */ +void IDP_ConcatStringC(struct IDProperty *prop, const char *st) ATTR_NONNULL(); +void IDP_ConcatString(struct IDProperty *str1, struct IDProperty *append) ATTR_NONNULL(); +void IDP_FreeString(struct IDProperty *prop) ATTR_NONNULL(); /*-------- ID Type -------*/ void IDP_LinkID(struct IDProperty *prop, ID *id); @@ -125,107 +87,30 @@ void IDP_UnlinkID(struct IDProperty *prop); /*-------- Group Functions -------*/ /** Sync values from one group to another, only where they match */ -void IDP_SyncGroupValues(struct IDProperty *dest, struct IDProperty *src) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; - -void IDP_ReplaceGroupInGroup(struct IDProperty *dest, struct IDProperty *src) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; -void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; - -void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; - -int IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +void IDP_SyncGroupValues(struct IDProperty *dest, struct IDProperty *src) ATTR_NONNULL(); +void IDP_ReplaceGroupInGroup(struct IDProperty *dest, struct IDProperty *src) ATTR_NONNULL(); +void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); +void IDP_MergeGroup(IDProperty *dest, IDProperty *src, const int do_overwrite) ATTR_NONNULL(); +int IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); int IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous, - struct IDProperty *pnew) -#ifdef __GNUC__ -__attribute__((nonnull (1, 3))) /* 'group', 'pnew' */ -#endif -; -void IDP_RemFromGroup(struct IDProperty *group, struct IDProperty *prop) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; + struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */); +void IDP_RemFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); -IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -void *IDP_GetGroupIterator(struct IDProperty *prop) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -#endif -; -IDProperty *IDP_GroupIterNext(void *vself) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -void IDP_FreeIterBeforeEnd(void *vself) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void *IDP_GetGroupIterator(struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT; +IDProperty *IDP_GroupIterNext(void *vself) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void IDP_FreeIterBeforeEnd(void *vself) ATTR_NONNULL(); /*-------- Main Functions --------*/ -struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -struct IDProperty *IDP_CopyProperty(struct IDProperty *prop) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +struct IDProperty *IDP_GetProperties(struct ID *id, int create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +struct IDProperty *IDP_CopyProperty(struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -#endif -; +int IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const int is_strict) ATTR_WARN_UNUSED_RESULT; -int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -#endif -; +int IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT; -struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void IDP_FreeProperty(struct IDProperty *prop); diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index de60d316426..19264feaf48 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -41,6 +41,7 @@ struct Object; struct Scene; struct Lattice; struct Mesh; +struct WeightsArrayCache; /* Kernel prototypes */ #ifdef __cplusplus @@ -73,8 +74,17 @@ struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index); struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]); void BKE_keyblock_copy_settings(struct KeyBlock *kb_dst, const struct KeyBlock *kb_src); char *BKE_keyblock_curval_rnapath_get(struct Key *key, struct KeyBlock *kb); + // needed for the GE -void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, const int mode); +typedef struct WeightsArrayCache { + int num_defgroup_weights; + float **defgroup_weights; +} WeightsArrayCache; + +float **BKE_keyblock_get_per_block_weights(struct Object *ob, struct Key *key, struct WeightsArrayCache *cache); +void BKE_keyblock_free_per_block_weights(struct Key *key, float **per_keyblock_weights, struct WeightsArrayCache *cache); +void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, struct Key *key, struct KeyBlock *actkb, + float **per_keyblock_weights, const int mode); /* conversion functions */ void BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 205c7c7d1e6..fb2c4da91ea 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -36,13 +36,15 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct Lamp; struct Main; struct Scene; -struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) WARN_UNUSED; -struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED; -struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED; +struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT; +struct Lamp *BKE_lamp_copy(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; +struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; void BKE_lamp_make_local(struct Lamp *la); void BKE_lamp_free(struct Lamp *la); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 9b29412675b..ba33da7729c 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -49,9 +49,14 @@ void BKE_lattice_free(struct Lattice *lt); void BKE_lattice_make_local(struct Lattice *lt); void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du); -void init_latt_deform(struct Object *oblatt, struct Object *ob); -void calc_latt_deform(struct Object *, float co[3], float weight); -void end_latt_deform(struct Object *); +struct LatticeDeformData; +struct LatticeDeformData *init_latt_deform(struct Object *oblatt, struct Object *ob) +#ifdef __GNUC__ +__attribute__((warn_unused_result)) +#endif +; +void calc_latt_deform(struct LatticeDeformData *lattice_deform_data, float co[3], float weight); +void end_latt_deform(struct LatticeDeformData *lattice_deform_data); int object_deform_mball(struct Object *ob, struct ListBase *dispbase); void outside_lattice(struct Lattice *lt); diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 3c5406c4a77..b8da5002d84 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -36,6 +36,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct ListBase; struct ID; struct Main; @@ -45,24 +47,9 @@ struct bContext; struct PointerRNA; struct PropertyRNA; -void *BKE_libblock_alloc(struct ListBase *lb, short type, const char *name) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -void *BKE_libblock_copy(struct ID *id) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +void *BKE_libblock_alloc(struct ListBase *lb, short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void *BKE_libblock_copy_ex(struct Main *bmain, struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void *BKE_libblock_copy(struct ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); 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); @@ -99,12 +86,7 @@ void rename_id(struct ID *id, const char *name); void name_uiprefix_id(char *name, const struct ID *id); void test_idbutton(char *name); 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)) -__attribute__((nonnull)) -#endif -; +struct ID *BKE_libblock_find_name(const short type, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void clear_id_newpoins(void); #if 0 diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 44459300c56..7665e1b54dc 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -47,7 +47,7 @@ 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); +void BKE_mball_polygonize(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, bool for_render); 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); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index e582af77d61..3d443cbe38c 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -108,7 +108,7 @@ void BKE_mesh_calc_poly_angles(struct MPoly *mpoly, struct MLoop *loopstart, int *BKE_mesh_calc_smoothgroups(const struct MEdge *medge, const int totedge, const struct MPoly *mpoly, const int totpoly, const struct MLoop *mloop, const int totloop, - int *r_totgroup); + int *r_totgroup, const bool use_bitflags); void BKE_mesh_calc_relative_deform( const struct MPoly *mpoly, const int totpoly, @@ -332,16 +332,16 @@ void BKE_mesh_edge_poly_map_create(MeshElemMap **r_map, int **r_mem, /* vertex level transformations & checks (no derived mesh) */ -int BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]); -int BKE_mesh_center_median(struct Mesh *me, float cent[3]); -int BKE_mesh_center_bounds(struct Mesh *me, float cent[3]); -int BKE_mesh_center_centroid(struct Mesh *me, float cent[3]); +bool BKE_mesh_minmax(struct Mesh *me, float r_min[3], float r_max[3]); +bool BKE_mesh_center_median(struct Mesh *me, float cent[3]); +bool BKE_mesh_center_bounds(struct Mesh *me, float cent[3]); +bool BKE_mesh_center_centroid(struct Mesh *me, float cent[3]); void BKE_mesh_translate(struct Mesh *me, const float offset[3], const bool do_keys); /* mesh_validate.c */ /* XXX Loop v/e are unsigned, so using max uint_32 value as invalid marker... */ #define INVALID_LOOP_EDGE_MARKER 4294967295u -int BKE_mesh_validate_arrays( +bool BKE_mesh_validate_arrays( struct Mesh *me, struct MVert *mverts, unsigned int totvert, struct MEdge *medges, unsigned int totedge, @@ -349,9 +349,17 @@ int BKE_mesh_validate_arrays( struct MLoop *mloops, unsigned int totloop, struct MPoly *mpolys, unsigned int totpoly, struct MDeformVert *dverts, /* assume totvert length */ - const bool do_verbose, const bool do_fixes); + const bool do_verbose, const bool do_fixes, + bool *r_change); + +bool BKE_mesh_validate_all_customdata( + struct CustomData *vdata, struct CustomData *edata, + struct CustomData *ldata, struct CustomData *pdata, + const bool check_meshmask, + const bool do_verbose, const bool do_fixes, + bool *r_change); + int BKE_mesh_validate(struct Mesh *me, const int do_verbose); -int BKE_mesh_validate_dm(struct DerivedMesh *dm); void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select); diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 0727e11f397..f42e131394b 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -29,6 +29,7 @@ */ #include "DNA_modifier_types.h" /* needed for all enum typdefs */ +#include "BLI_compiler_attrs.h" #include "BKE_customdata.h" struct ID; @@ -304,6 +305,9 @@ typedef struct ModifierTypeInfo { TexWalkFunc walk, void *userData); } ModifierTypeInfo; +/* Initialize modifier's global data (type info and some common global storages). */ +void BKE_modifier_init(void); + ModifierTypeInfo *modifierType_getInfo(ModifierType type); /* Modifier utility calls, do call through type pointer and return @@ -322,11 +326,7 @@ bool modifier_isCorrectableDeformed(struct ModifierData *md); bool modifier_isSameTopology(ModifierData *md); bool modifier_isNonGeometrical(ModifierData *md); bool modifier_isEnabled(struct Scene *scene, struct ModifierData *md, int required_mode); -void modifier_setError(struct ModifierData *md, const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 2, 3))) -#endif -; +void modifier_setError(struct ModifierData *md, const char *format, ...) ATTR_PRINTF_FORMAT(2, 3); bool modifier_isPreview(struct ModifierData *md); void modifiers_foreachObjectLink(struct Object *ob, @@ -377,7 +377,15 @@ struct CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, struct ModifierData *modifiers_getLastPreview(struct Scene *scene, struct ModifierData *md, int required_mode); -struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob); + +typedef struct VirtualModifierData { + ArmatureModifierData amd; + CurveModifierData cmd; + LatticeModifierData lmd; + ShapeKeyModifierData smd; +} VirtualModifierData; + +struct ModifierData *modifiers_getVirtualModifierList(struct Object *ob, struct VirtualModifierData *data); /* ensure modifier correctness when changing ob->data */ void test_object_modifiers(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 27192437c89..a9d06ad6512 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -32,8 +32,8 @@ * \ingroup bke */ -#include "BLI_ghash.h" #include "BLI_utildefines.h" +#include "BLI_ghash.h" #include "DNA_listBase.h" diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 992792dcb99..8007aba2a53 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -60,6 +60,7 @@ void BKE_object_copy_softbody(struct Object *obn, struct Object *ob); void BKE_object_free_particlesystems(struct Object *ob); void BKE_object_free_softbody(struct Object *ob); void BKE_object_free_bulletsoftbody(struct Object *ob); +void BKE_object_free_curve_cache(struct Object *ob); void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob); void BKE_object_free(struct Object *ob); @@ -193,6 +194,8 @@ struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet struct LinkNode *BKE_object_groups(struct Object *ob); void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object); +struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 56b550a6f5d..d4965cf55fe 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -54,6 +54,7 @@ struct MCol; struct MFace; struct MVert; struct IpoCurve; +struct LatticeDeformData; struct LinkNode; struct KDTree; struct RNG; @@ -258,7 +259,7 @@ void psys_set_current_num(Object *ob, int index); /* UNUSED */ // struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); -struct Object *psys_get_lattice(struct ParticleSimulationData *sim); +struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim); int psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); int psys_check_enabled(struct Object *ob, struct ParticleSystem *psys); diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 7d3d8d7dcbd..9e21831dba0 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -172,8 +172,8 @@ int BKE_pbvh_node_planes_contain_AABB(PBVHNode *node, void *data); /* test if AABB is at least partially outside the planes' volume */ int BKE_pbvh_node_planes_exclude_AABB(PBVHNode *node, void *data); -struct GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node); -struct GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node); +struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node); +struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node); void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node); void BKE_pbvh_bmesh_after_stroke(PBVH *bvh); @@ -235,9 +235,10 @@ typedef struct PBVHVertexIter { float *vmask; /* bmesh */ - struct GHashIterator bm_unique_verts; - struct GHashIterator bm_other_verts; + struct GSetIterator bm_unique_verts; + struct GSetIterator bm_other_verts; struct CustomData *bm_vdata; + int cd_vert_mask_offset; /* result: these are all computed in the macro, but we assume * that compiler optimization's will skip the ones we don't use */ @@ -294,22 +295,20 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, vi.mask = &vi.vmask[vi.vert_indices[vi.gx]]; \ } \ else { \ - if (!BLI_ghashIterator_done(&vi.bm_unique_verts)) {\ - vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_unique_verts); \ - BLI_ghashIterator_step(&vi.bm_unique_verts); \ + if (!BLI_gsetIterator_done(&vi.bm_unique_verts)) {\ + vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_unique_verts); \ + BLI_gsetIterator_step(&vi.bm_unique_verts); \ } \ else { \ - vi.bm_vert = BLI_ghashIterator_getKey(&vi.bm_other_verts); \ - BLI_ghashIterator_step(&vi.bm_other_verts); \ + vi.bm_vert = BLI_gsetIterator_getKey(&vi.bm_other_verts); \ + BLI_gsetIterator_step(&vi.bm_other_verts); \ } \ if (mode == PBVH_ITER_UNIQUE && \ BM_elem_flag_test(vi.bm_vert, BM_ELEM_HIDDEN)) \ continue; \ vi.co = vi.bm_vert->co; \ vi.fno = vi.bm_vert->no; \ - vi.mask = CustomData_bmesh_get(vi.bm_vdata, \ - vi.bm_vert->head.data, \ - CD_PAINT_MASK); \ + vi.mask = BM_ELEM_CD_GET_VOID_P(vi.bm_vert, vi.cd_vert_mask_offset); \ } #define BKE_pbvh_vertex_iter_end \ diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index 1cb50425c40..d5131fcd19e 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -156,6 +156,8 @@ typedef struct PTCacheID { /* total number of simulated points (the cfra parameter is just for using same function pointer with totwrite) */ int (*totpoint)(void *calldata, int cfra); + /* report error if number of points does not match */ + void (*error)(void *calldata, const char *message); /* number of points written for current cache frame */ int (*totwrite)(void *calldata, int cfra); diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index ae457cf4f47..101fc463375 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -34,6 +34,7 @@ extern "C" { #include <stdio.h> #include "DNA_windowmanager_types.h" +#include "BLI_compiler_attrs.h" #include "BLI_utildefines.h" /* Reporting Information and Errors @@ -47,18 +48,10 @@ void BKE_reports_init(ReportList *reports, int flag); void BKE_reports_clear(ReportList *reports); void BKE_report(ReportList *reports, ReportType type, const char *message); -void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 3, 4))) -#endif -; +void BKE_reportf(ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4); void BKE_reports_prepend(ReportList *reports, const char *prepend); -void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 2, 3))) -#endif -; +void BKE_reports_prependf(ReportList *reports, const char *prepend, ...) ATTR_PRINTF_FORMAT(2, 3); ReportType BKE_report_print_level(ReportList *reports); void BKE_report_print_level_set(ReportList *reports, ReportType level); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index c883bdf74e0..3c0928d38a0 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -189,9 +189,15 @@ typedef struct PanelType { /* uilist types */ -/* draw an item in the uiList */ +/* Draw an item in the uiList */ typedef void (*uiListDrawItemFunc)(struct uiList *, struct bContext *, struct uiLayout *, struct PointerRNA *, - struct PointerRNA *, int, struct PointerRNA *, const char *, int); + struct PointerRNA *, int, struct PointerRNA *, const char *, int, int); + +/* Draw the filtering part of an uiList */ +typedef void (*uiListDrawFilterFunc)(struct uiList *, struct bContext *, struct uiLayout *); + +/* Filter items of an uiList */ +typedef void (*uiListFilterItemsFunc)(struct uiList *, struct bContext *, struct PointerRNA *, const char *); typedef struct uiListType { struct uiListType *next, *prev; @@ -199,6 +205,8 @@ typedef struct uiListType { char idname[BKE_ST_MAXNAME]; /* unique name */ uiListDrawItemFunc draw_item; + uiListDrawFilterFunc draw_filter; + uiListFilterItemsFunc filter_items; /* RNA integration */ ExtensionRNA ext; diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 78018f04458..12b6d18ab7c 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -194,6 +194,7 @@ void BKE_sequencer_editing_free(struct Scene *scene); void BKE_sequencer_sort(struct Scene *scene); +struct Sequence *BKE_sequencer_from_elem(ListBase *seqbase, struct StripElem *se); struct Sequence *BKE_sequencer_active_get(struct Scene *scene); int BKE_sequencer_active_get_pair(struct Scene *scene, struct Sequence **seq_act, struct Sequence **seq_other); void BKE_sequencer_active_set(struct Scene *scene, struct Sequence *seq); @@ -318,6 +319,8 @@ void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq void BKE_sequencer_update_muting(struct Editing *ed); void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound); +void BKE_sequencer_refresh_sound_length(struct Scene *scene); + 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); bool BKE_sequence_is_valid_check(struct Sequence *seq); diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 24fd763d078..bba209334d4 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -58,7 +58,7 @@ void BKE_text_write (struct Text *text, const char *str); char *txt_to_buf (struct Text *text); void txt_clean_text (struct Text *text); -void txt_order_cursors (struct Text *text); +void txt_order_cursors (struct Text *text, const bool reverse); int txt_find_string (struct Text *text, const char *findstr, int wrap, int match_case); int txt_has_sel (struct Text *text); int txt_get_span (struct TextLine *from, struct TextLine *to); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 0d148e55753..51946da3857 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -68,7 +68,7 @@ void BKE_tracking_get_projection_matrix(struct MovieTracking *tracking, struct M /* **** Clipboard **** */ void BKE_tracking_clipboard_free(void); void BKE_tracking_clipboard_copy_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); -int BKE_tracking_clipboard_has_tracks(void); +bool BKE_tracking_clipboard_has_tracks(void); void BKE_tracking_clipboard_paste_tracks(struct MovieTracking *tracking, struct MovieTrackingObject *object); /* **** Track **** */ @@ -80,8 +80,8 @@ void BKE_tracking_track_free(struct MovieTrackingTrack *track); void BKE_tracking_track_flag_set(struct MovieTrackingTrack *track, int area, int flag); void BKE_tracking_track_flag_clear(struct MovieTrackingTrack *track, int area, int flag); -int BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr); -int BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr); +bool BKE_tracking_track_has_marker_at_frame(struct MovieTrackingTrack *track, int framenr); +bool BKE_tracking_track_has_enabled_marker_at_frame(struct MovieTrackingTrack *track, int framenr); void BKE_tracking_track_path_clear(struct MovieTrackingTrack *track, int ref_frame, int action); void BKE_tracking_tracks_join(struct MovieTracking *tracking, struct MovieTrackingTrack *dst_track, struct MovieTrackingTrack *src_track); @@ -98,7 +98,7 @@ float *BKE_tracking_track_get_mask(int frame_width, int frame_height, struct Mov struct MovieTrackingMarker *marker); /* selection */ -void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, int extend); +void BKE_tracking_track_select(struct ListBase *tracksbase, struct MovieTrackingTrack *track, int area, bool extend); void BKE_tracking_track_deselect(struct MovieTrackingTrack *track, int area); void BKE_tracking_tracks_deselect_all(struct ListBase *tracksbase); @@ -145,7 +145,7 @@ struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTr /* **** Object **** */ struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name); -int BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object); +bool BKE_tracking_object_delete(struct MovieTracking *tracking, struct MovieTrackingObject *object); void BKE_tracking_object_unique_name(struct MovieTracking *tracking, struct MovieTrackingObject *object); @@ -178,7 +178,7 @@ void BKE_tracking_distortion_update(struct MovieDistortion *distortion, struct M 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); + struct ImBuf *ibuf, int width, int height, float overscan, bool undistort); void BKE_tracking_distortion_free(struct MovieDistortion *distortion); void BKE_tracking_distort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); @@ -194,15 +194,15 @@ 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 from_anchor, int use_mask, + struct MovieTrackingMarker *marker, bool from_anchor, bool 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); + struct MovieTrackingMarker *marker, bool anchored, bool disable_channels); struct ImBuf *BKE_tracking_get_search_imbuf(struct ImBuf *ibuf, struct MovieTrackingTrack *track, - struct MovieTrackingMarker *marker, int anchored, int disable_channels); + struct MovieTrackingMarker *marker, bool anchored, bool disable_channels); -void BKE_tracking_disable_channels(struct ImBuf *ibuf, int disable_red, int disable_green, - int disable_blue, int grayscale); +void BKE_tracking_disable_channels(struct ImBuf *ibuf, bool disable_red, bool disable_green, + bool disable_blue, bool grayscale); /* **** 2D tracking **** */ struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user, @@ -210,8 +210,8 @@ struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, st void BKE_tracking_context_free(struct MovieTrackingContext *context); void BKE_tracking_context_sync(struct MovieTrackingContext *context); void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context, struct MovieClipUser *user); -int BKE_tracking_context_step(struct MovieTrackingContext *context); -void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, int backwards); +bool BKE_tracking_context_step(struct MovieTrackingContext *context); +void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards); /* **** Plane tracking **** */ @@ -219,8 +219,8 @@ void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrac void BKE_tracking_homography_between_two_quads(/*const*/ float reference_corners[4][2], /*const*/ float corners[4][2], float H[3][3]); /* **** Camera solving **** */ -int BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object, - char *error_msg, int error_size); +bool BKE_tracking_reconstruction_check(struct MovieTracking *tracking, struct MovieTrackingObject *object, + char *error_msg, int error_size); struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(struct MovieTracking *tracking, struct MovieTrackingObject *object, @@ -229,14 +229,14 @@ struct MovieReconstructContext *BKE_tracking_reconstruction_context_new(struct M void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *context); void BKE_tracking_reconstruction_solve(struct MovieReconstructContext *context, short *stop, short *do_update, float *progress, char *stats_message, int message_size); -int BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context, struct MovieTracking *tracking); +bool BKE_tracking_reconstruction_finish(struct MovieReconstructContext *context, struct MovieTracking *tracking); void BKE_tracking_reconstruction_scale(struct MovieTracking *tracking, float scale[3]); /* **** Feature detection **** */ void BKE_tracking_detect_fast(struct MovieTracking *tracking, struct ListBase *tracksbase, struct ImBuf *imbuf, int framenr, int margin, int min_trackness, int min_distance, struct bGPDlayer *layer, - int place_outside_layer); + bool place_outside_layer); /* **** 2D stabilization **** */ void BKE_tracking_stabilization_data_get(struct MovieTracking *tracking, int framenr, int width, int height, diff --git a/source/blender/blenkernel/BKE_treehash.h b/source/blender/blenkernel/BKE_treehash.h new file mode 100644 index 00000000000..54deef1ce2f --- /dev/null +++ b/source/blender/blenkernel/BKE_treehash.h @@ -0,0 +1,52 @@ +/* + * ***** 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): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_TREEHASH_H__ +#define __BKE_TREEHASH_H__ + +/** \file BKE_treehash.h + * \ingroup bke + */ + +struct ID; +struct GHash; +struct BLI_mempool; +struct TreeStoreElem; + +/* create and fill hashtable with treestore elements */ +void *BKE_treehash_create_from_treestore(struct BLI_mempool *treestore); + +/* full rebuild for already allocated hashtable */ +void *BKE_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore); + +/* full rebuild for already allocated hashtable */ +void BKE_treehash_add_element(void *treehash, struct TreeStoreElem *elem); + +/* find first unused element with specific type, nr and id */ +struct TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id); + +/* find user or unused element with specific type, nr and id */ +struct TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id); + +/* free treehash structure */ +void BKE_treehash_free(void *treehash); + +#endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 655e0d65133..e9142ef1abd 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -45,6 +45,7 @@ set(INC ../../../intern/raskter ../../../intern/smoke/extern ../../../extern/libmv + ../../../intern/atomic # XXX - BAD LEVEL CALL WM_api.h ../windowmanager @@ -152,6 +153,7 @@ set(SRC intern/text.c intern/texture.c intern/tracking.c + intern/treehash.c intern/unit.c intern/world.c intern/writeavi.c @@ -243,6 +245,7 @@ set(SRC BKE_text.h BKE_texture.h BKE_tracking.h + BKE_treehash.h BKE_unit.h BKE_utildefines.h BKE_world.h diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 6d080fea031..3c3ac61a3cb 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -52,6 +52,7 @@ incs = [ '#/intern/iksolver/extern', '#/intern/opennl/extern', '#/intern/smoke/extern', + '#/intern/atomic', '../avi', '../blenfont', '../blenlib', diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 2ece90183bd..8f4c2973104 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -82,11 +82,20 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); #include "GPU_extensions.h" #include "GPU_material.h" +/* very slow! enable for testing only! */ +// #define USE_MODIFIER_VALIDATE + +#ifdef USE_MODIFIER_VALIDATE +# define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true))) +#else +# define ASSERT_IS_VALID_DM(dm) +#endif + static void add_shapekey_layers(DerivedMesh *dm, Mesh *me, Object *ob); static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape_uid); -/////////////////////////////////// -/////////////////////////////////// + +/* -------------------------------------------------------------------- */ static MVert *dm_getVertArray(DerivedMesh *dm) { @@ -879,6 +888,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, add_shapekey_layers(tdm, me, ob); dm = modwrap_applyModifier(md, ob, tdm, 0); + ASSERT_IS_VALID_DM(dm); if (tdm != dm) tdm->release(tdm); } @@ -1440,6 +1450,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* XXX Same as above... For now, only weights preview in WPaint mode. */ const int do_mod_wmcol = do_init_wmcol; + VirtualModifierData virtualModifierData; + ModifierApplyFlag app_flags = useRenderParams ? MOD_APPLY_RENDER : 0; ModifierApplyFlag deform_app_flags = app_flags; if (useCache) @@ -1451,7 +1463,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos has_multires = 0; if (!skipVirtualArmature) { - firstmd = modifiers_getVirtualModifierList(ob); + firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); } else { /* game engine exception */ @@ -1648,6 +1660,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } else { dm = CDDM_from_mesh(me, ob); + ASSERT_IS_VALID_DM(dm); if (build_shapekey_layers) add_shapekey_layers(dm, me, ob); @@ -1705,6 +1718,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos } ndm = modwrap_applyModifier(md, ob, dm, app_flags); + ASSERT_IS_VALID_DM(ndm); if (ndm) { /* if the modifier returned a new dm, release the old one */ @@ -1731,6 +1745,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos mti->requiredDataMask(ob, md) : 0)); ndm = modwrap_applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO); + ASSERT_IS_VALID_DM(ndm); if (ndm) { /* if the modifier returned a new dm, release the old one */ @@ -1748,6 +1763,7 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX); ndm = modwrap_applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO); + ASSERT_IS_VALID_DM(ndm); if (ndm) { /* if the modifier returned a new dm, release the old one */ @@ -1961,6 +1977,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D int do_init_wmcol = ((((Mesh *)ob->data)->drawflag & ME_DRAWEIGHT) && !do_final_wmcol); int do_init_statvis = ((((Mesh *)ob->data)->drawflag & ME_DRAW_STATVIS) && !do_init_wmcol); const int do_mod_wmcol = do_init_wmcol; + VirtualModifierData virtualModifierData; modifiers_clearErrors(ob); @@ -1969,7 +1986,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } dm = NULL; - md = modifiers_getVirtualModifierList(ob); + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); /* copied from mesh_calc_modifiers */ if (do_mod_wmcol) { @@ -2049,6 +2066,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D } else { dm = CDDM_from_editbmesh(em, FALSE, FALSE); + ASSERT_IS_VALID_DM(dm); if (deformedVerts) { CDDM_apply_vert_coords(dm, deformedVerts); @@ -2072,6 +2090,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO); else ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO); + ASSERT_IS_VALID_DM(ndm); if (ndm) { /* if the modifier returned a new dm, release the old one */ @@ -2097,6 +2116,7 @@ static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, D ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE); else ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE); + ASSERT_IS_VALID_DM(ndm); if (ndm) { if (dm && dm != ndm) @@ -2738,11 +2758,9 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm) int offs = 0; /* initial triangulation is 0,1,2 and 0, 2, 3 */ if (nr_verts == 4) { float pos_len_diag0, pos_len_diag1; - float vtmp[3]; - sub_v3_v3v3(vtmp, verts[2], verts[0]); - pos_len_diag0 = dot_v3v3(vtmp, vtmp); - sub_v3_v3v3(vtmp, verts[3], verts[1]); - pos_len_diag1 = dot_v3v3(vtmp, vtmp); + + pos_len_diag0 = len_squared_v3v3(verts[2], verts[0]); + pos_len_diag1 = len_squared_v3v3(verts[3], verts[1]); if (pos_len_diag1 < pos_len_diag0) { offs = 1; // alter split @@ -2750,10 +2768,8 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm) else if (pos_len_diag0 == pos_len_diag1) { /* do UV check instead */ float tex_len_diag0, tex_len_diag1; - sub_v2_v2v2(vtmp, tex_coords[2], tex_coords[0]); - tex_len_diag0 = dot_v2v2(vtmp, vtmp); - sub_v2_v2v2(vtmp, tex_coords[3], tex_coords[1]); - tex_len_diag1 = dot_v2v2(vtmp, vtmp); + tex_len_diag0 = len_squared_v2v2(tex_coords[2], tex_coords[0]); + tex_len_diag1 = len_squared_v2v2(tex_coords[3], tex_coords[1]); if (tex_len_diag1 < tex_len_diag0) { offs = 1; /* alter split */ @@ -2762,7 +2778,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm) } nr_tris_to_pile = nr_verts - 2; if (nr_tris_to_pile == 1 || nr_tris_to_pile == 2) { - const int indices[] = {offs + 0, offs + 1, offs + 2, offs + 0, offs + 2, (offs + 3) & 0x3 }; + const int indices[6] = {offs + 0, offs + 1, offs + 2, offs + 0, offs + 2, (offs + 3) & 0x3 }; int t; for (t = 0; t < nr_tris_to_pile; t++) { float f2x_area_uv; @@ -2782,7 +2798,7 @@ void DM_calc_auto_bump_scale(DerivedMesh *dm) cross_v3_v3v3(norm, v0, v1); f2x_surf_area = len_v3(norm); - fsurf_ratio = f2x_surf_area / f2x_area_uv; // tri area divided by texture area + fsurf_ratio = f2x_surf_area / f2x_area_uv; /* tri area divided by texture area */ nr_accumulated++; dsum += (double)(fsurf_ratio); @@ -3262,4 +3278,35 @@ void DM_debug_print_cdlayers(CustomData *data) printf("}\n"); } +bool DM_is_valid(DerivedMesh *dm) +{ + const bool do_verbose = true; + const bool do_fixes = false; + + bool is_valid = true; + bool is_change = true; + + is_valid &= BKE_mesh_validate_all_customdata( + dm->getVertDataLayout(dm), + dm->getEdgeDataLayout(dm), + dm->getLoopDataLayout(dm), + dm->getPolyDataLayout(dm), + 0, /* setting mask here isn't useful, gives false positives */ + do_verbose, do_fixes, &is_change); + + is_valid &= BKE_mesh_validate_arrays( + NULL, + dm->getVertArray(dm), dm->getNumVerts(dm), + dm->getEdgeArray(dm), dm->getNumEdges(dm), + dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), + dm->getLoopArray(dm), dm->getNumLoops(dm), + dm->getPolyArray(dm), dm->getNumPolys(dm), + dm->getVertDataArray(dm, CD_MDEFORMVERT), + do_verbose, do_fixes, &is_change); + + BLI_assert(is_change == false); + + return is_valid; +} + #endif /* NDEBUG */ diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index ba680147201..49c9a8e9083 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -488,18 +488,16 @@ void free_path(Path *path) /* calculate a curve-deform path for a curve * - only called from displist.c -> do_makeDispListCurveTypes */ -void calc_curvepath(Object *ob) +void calc_curvepath(Object *ob, ListBase *nurbs) { BevList *bl; BevPoint *bevp, *bevpn, *bevpfirst, *bevplast; PathPoint *pp; - Curve *cu; Nurb *nu; Path *path; float *fp, *dist, *maxdist, xyz[3]; float fac, d = 0, fac1, fac2; int a, tot, cycl = 0; - ListBase *nurbs; /* in a path vertices are with equal differences: path->len = number of verts */ /* NOW WITH BEVELCURVE!!! */ @@ -507,21 +505,19 @@ void calc_curvepath(Object *ob) if (ob == NULL || ob->type != OB_CURVE) { return; } - cu = ob->data; - if (cu->path) free_path(cu->path); - cu->path = NULL; + if (ob->curve_cache->path) free_path(ob->curve_cache->path); + ob->curve_cache->path = NULL; /* weak! can only use first curve */ - bl = cu->bev.first; + bl = ob->curve_cache->bev.first; if (bl == NULL || !bl->nr) { return; } - nurbs = BKE_curve_nurbs_get(cu); nu = nurbs->first; - cu->path = path = MEM_callocN(sizeof(Path), "calc_curvepath"); + ob->curve_cache->path = path = MEM_callocN(sizeof(Path), "calc_curvepath"); /* if POLY: last vertice != first vertice */ cycl = (bl->poly != -1); @@ -598,8 +594,7 @@ void calc_curvepath(Object *ob) static int interval_test(const int min, const int max, int p1, const int cycl) { if (cycl) { - if (p1 < min) p1 = ((p1 - min) % (max - min + 1)) + max + 1; - else if (p1 > max) p1 = ((p1 - min) % (max - min + 1)) + min; + p1 = mod_i(p1 - min, (max - min + 1)) + min; } else { if (p1 < min) p1 = min; @@ -630,15 +625,15 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua if (ob == NULL || ob->type != OB_CURVE) return 0; cu = ob->data; - if (cu->path == NULL || cu->path->data == NULL) { + if (ob->curve_cache == NULL || ob->curve_cache->path == NULL || ob->curve_cache->path->data == NULL) { printf("no path!\n"); return 0; } - path = cu->path; + path = ob->curve_cache->path; pp = path->data; /* test for cyclic */ - bl = cu->bev.first; + bl = ob->curve_cache->bev.first; if (!bl) return 0; if (!bl->nr) return 0; if (bl->poly > -1) cycl = 1; @@ -1332,7 +1327,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p psys_check_group_weights(part); - psys->lattice = psys_get_lattice(&sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* gather list of objects or single object */ if (part->ren_as == PART_DRAW_GR) { @@ -1569,9 +1564,9 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (obcopylist) MEM_freeN(obcopylist); - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice = NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index f006710dc21..6b2b782717d 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -381,8 +381,6 @@ int bone_autoside_name(char name[MAXBONENAME], int UNUSED(strip_number), short a /* ************* B-Bone support ******************* */ -#define MAX_BBONE_SUBDIV 32 - /* data has MAX_BBONE_SUBDIV+1 interpolated points, will become desired amount with equal distances */ static void equalize_bezier(float *data, int desired) { @@ -426,11 +424,8 @@ static void equalize_bezier(float *data, int desired) /* returns pointer to static array, filled with desired amount of bone->segments elements */ /* this calculation is done within unit bone space */ -Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) +void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BBONE_SUBDIV]) { - static Mat4 bbone_array[MAX_BBONE_SUBDIV]; - static Mat4 bbone_rest_array[MAX_BBONE_SUBDIV]; - Mat4 *result_array = (rest) ? bbone_rest_array : bbone_array; bPoseChannel *next, *prev; Bone *bone = pchan->bone; float h1[3], h2[3], scale[3], length, hlength1, hlength2, roll1 = 0.0f, roll2; @@ -587,8 +582,6 @@ Mat4 *b_bone_spline_setup(bPoseChannel *pchan, int rest) mul_serie_m4(result_array[a].mat, iscalemat, result_array[a].mat, scalemat, NULL, NULL, NULL, NULL, NULL); } } - - return result_array; } /* ************ Armature Deform ******************* */ @@ -602,13 +595,15 @@ typedef struct bPoseChanDeform { static void pchan_b_bone_defmats(bPoseChannel *pchan, bPoseChanDeform *pdef_info, int use_quaternion) { Bone *bone = pchan->bone; - Mat4 *b_bone = b_bone_spline_setup(pchan, 0); - Mat4 *b_bone_rest = b_bone_spline_setup(pchan, 1); + Mat4 b_bone[MAX_BBONE_SUBDIV], b_bone_rest[MAX_BBONE_SUBDIV]; Mat4 *b_bone_mats; DualQuat *b_bone_dual_quats = NULL; float tmat[4][4] = MAT4_UNITY; int a; + b_bone_spline_setup(pchan, 0, b_bone); + b_bone_spline_setup(pchan, 1, b_bone_rest); + /* allocate b_bone matrices and dual quats */ b_bone_mats = MEM_mallocN((1 + bone->segments) * sizeof(Mat4), "BBone defmats"); pdef_info->b_bone_mats = b_bone_mats; @@ -1826,18 +1821,16 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos * - this is a workaround for a depsgraph bug... */ if (ikData->tar) { - Curve *cu = ikData->tar->data; - /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, * currently for paths to work it needs to go through the bevlist/displist system (ton) */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (ELEM(NULL, cu->path, cu->path->data)) { + if (ELEM3(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { BKE_displist_make_curveTypes(scene, ikData->tar, 0); /* path building may fail in EditMode after removing verts [#33268]*/ - if (ELEM(NULL, cu->path, cu->path->data)) { + if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { /* BLI_assert(cu->path != NULL); */ return; } @@ -1901,7 +1894,6 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos * since it's easier to determine the positions of all the joints beforehand this way */ if ((ikData->flag & CONSTRAINT_SPLINEIK_SCALE_LIMITED) && (totLength != 0.0f)) { - Curve *cu = (Curve *)ikData->tar->data; float splineLen, maxScale; int i; @@ -1914,7 +1906,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos /* get the current length of the curve */ /* NOTE: this is assumed to be correct even after the curve was resized */ - splineLen = cu->path->totdist; + splineLen = ikData->tar->curve_cache->path->totdist; /* calculate the scale factor to multiply all the path values by so that the * bone chain retains its current length, such that diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 26f481e5341..3fbdba351b0 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -924,9 +924,7 @@ int BKE_copybuffer_save(const char *filename, ReportList *reports) ID *id; ListBase *lb1 = lbarray[a], *lb2 = fromarray[a]; - while (lb2->first) { - id = lb2->first; - BLI_remlink(lb2, id); + while ((id = BLI_pophead(lb2))) { BLI_addtail(lb1, id); id_sort_by_name(lb1, id); } diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index cf761bf3dab..8ce84609c15 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -253,7 +253,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * //check boids in own system if (acbr->options & BRULE_ACOLL_WITH_BOIDS) { - neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, acbr->look_ahead * len_v3(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); + neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, pa->prev_state.co, pa->prev_state.ave, + &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel)); if (neighbors > 1) for (n=1; n<neighbors; n++) { copy_v3_v3(co1, pa->prev_state.co); copy_v3_v3(vel1, pa->prev_state.vel); @@ -299,7 +300,8 @@ static int rule_avoid_collision(BoidRule *rule, BoidBrainData *bbd, BoidValues * ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if (epsys) { - neighbors = BLI_kdtree_range_search(epsys->tree, acbr->look_ahead * len_v3(pa->prev_state.vel), pa->prev_state.co, pa->prev_state.ave, &ptn); + neighbors = BLI_kdtree_range_search(epsys->tree, pa->prev_state.co, pa->prev_state.ave, + &ptn, acbr->look_ahead * len_v3(pa->prev_state.vel)); if (neighbors > 0) for (n=0; n<neighbors; n++) { copy_v3_v3(co1, pa->prev_state.co); copy_v3_v3(vel1, pa->prev_state.vel); @@ -354,7 +356,8 @@ static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues ParticleTarget *pt; float len = 2.0f * val->personal_space * pa->size + 1.0f; float vec[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, pa->prev_state.co, NULL, + &ptn, 2.0f * val->personal_space * pa->size); int ret = 0; if (neighbors > 1 && ptn[1].dist!=0.0f) { @@ -372,7 +375,8 @@ static int rule_separate(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues ParticleSystem *epsys = psys_get_target_system(bbd->sim->ob, pt); if (epsys) { - neighbors = BLI_kdtree_range_search(epsys->tree, 2.0f * val->personal_space * pa->size, pa->prev_state.co, NULL, &ptn); + neighbors = BLI_kdtree_range_search(epsys->tree, pa->prev_state.co, NULL, + &ptn, 2.0f * val->personal_space * pa->size); if (neighbors > 0 && ptn[0].dist < len) { sub_v3_v3v3(vec, pa->prev_state.co, ptn[0].co); @@ -392,7 +396,7 @@ static int rule_flock(BoidRule *UNUSED(rule), BoidBrainData *bbd, BoidValues *UN { KDTreeNearest ptn[11]; float vec[3] = {0.0f, 0.0f, 0.0f}, loc[3] = {0.0f, 0.0f, 0.0f}; - int neighbors = BLI_kdtree_find_n_nearest(bbd->sim->psys->tree, 11, pa->state.co, pa->prev_state.ave, ptn); + int neighbors = BLI_kdtree_find_nearest_n(bbd->sim->psys->tree, pa->state.co, pa->prev_state.ave, ptn, 11); int n; int ret = 0; @@ -619,7 +623,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti int n, ret = 0; /* calculate own group strength */ - int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); + int neighbors = BLI_kdtree_range_search(bbd->sim->psys->tree, pa->prev_state.co, NULL, + &ptn, fbr->distance); for (n=0; n<neighbors; n++) { bpa = bbd->sim->psys->particles[ptn[n].index].boid; health += bpa->data.health; @@ -635,7 +640,8 @@ static int rule_fight(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, Parti if (epsys) { epars = epsys->particles; - neighbors = BLI_kdtree_range_search(epsys->tree, fbr->distance, pa->prev_state.co, NULL, &ptn); + neighbors = BLI_kdtree_range_search(epsys->tree, pa->prev_state.co, NULL, + &ptn, fbr->distance); health = 0.0f; diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index 4018b757559..30dc7514eaf 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -76,7 +76,7 @@ #include "BKE_node.h" #include "BKE_report.h" #include "BKE_sequencer.h" -#include "BKE_image.h" /* so we can check the image's type */ +#include "BKE_image.h" #include "BKE_bpath.h" /* own include */ @@ -297,7 +297,14 @@ static bool findMissingFiles_visit_cb(void *userdata, char *path_dst, const char return false; } else { + bool was_relative = BLI_path_is_rel(path_dst); + BLI_strncpy(path_dst, filename_new, FILE_MAX); + + /* keep path relative if the previous one was relative */ + if (was_relative) + BLI_path_rel(path_dst, data->basedir); + return true; } } @@ -307,6 +314,7 @@ void BKE_bpath_missing_files_find(Main *bmain, const char *searchpath, ReportLis { struct BPathFind_Data data = {NULL}; + data.basedir = bmain->name; data.reports = reports; data.searchdir = searchpath; data.find_all = find_all; @@ -330,6 +338,9 @@ static bool rewrite_path_fixed(char *path, BPathVisitor visit_cb, const char *ab path_src = path; } + /* so functions can check old value */ + BLI_strncpy(path_dst, path, FILE_MAX); + if (visit_cb(userdata, path_dst, path_src)) { BLI_strncpy(path, path_dst, FILE_MAX); return true; @@ -388,6 +399,13 @@ static bool rewrite_path_alloc(char **path, BPathVisitor visit_cb, const char *a } } +/* fix the image user "ok" tag after updating paths, so ImBufs get loaded */ +static void bpath_traverse_image_user_cb(Image *ima, ImageUser *iuser, void *customdata) +{ + if (ima == customdata) + iuser->ok = 1; +} + /* Run visitor function 'visit' on all paths contained in 'id'. */ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int flag, void *bpath_user_data) { @@ -405,6 +423,8 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int if (ima->packedfile == NULL || (flag & BKE_BPATH_TRAVERSE_SKIP_PACKED) == 0) { if (ELEM3(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { rewrite_path_fixed(ima->name, visit_cb, absbase, bpath_user_data); + BKE_image_signal(ima, NULL, IMA_SIGNAL_RELOAD); + BKE_image_walk_all_users(bmain, ima, bpath_traverse_image_user_cb); } } break; diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 70b5d90120d..790c1f09ff0 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -951,7 +951,6 @@ float BKE_brush_curve_strength_clamp(Brush *br, float p, const float len) if (p >= len) return 0; else p = p / len; - curvemapping_initialize(br->curve); strength = curvemapping_evaluateF(br->curve, 0, p); CLAMP(strength, 0.0f, 1.0f); @@ -967,15 +966,14 @@ float BKE_brush_curve_strength(Brush *br, float p, const float len) else p = p / len; - curvemapping_initialize(br->curve); 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 *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_secondary) { unsigned int *texcache = NULL; - MTex *mtex = &br->mtex; + MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex; TexResult texres = {0}; int hasrgb, ix, iy; int side = half_side * 2; @@ -1016,7 +1014,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side) /**** Radial Control ****/ -struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br) +struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary) { ImBuf *im = MEM_callocN(sizeof(ImBuf), "radial control texture"); unsigned int *texcache; @@ -1024,7 +1022,8 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br) int half = side / 2; int i, j; - texcache = BKE_brush_gen_texture_cache(br, half); + curvemapping_initialize(br->curve); + texcache = BKE_brush_gen_texture_cache(br, half, secondary); im->rect_float = MEM_callocN(sizeof(float) * side * side, "radial control rect"); im->x = im->y = side; diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index f9444ca2cf9..536ec95e3d1 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -456,9 +456,10 @@ void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3]) typedef struct CameraViewFrameData { + float plane_tx[4][4]; /* 4 planes (not 4x4 matrix)*/ float frame_tx[4][3]; float normal_tx[4][3]; - float dist_vals[4]; + float dist_vals_sq[4]; /* distance squared (signed) */ unsigned int tot; } CameraViewFrameData; @@ -468,9 +469,9 @@ static void camera_to_frame_view_cb(const float co[3], void *user_data) unsigned int i; for (i = 0; i < 4; i++) { - float nd = dist_to_plane_v3(co, data->frame_tx[i], data->normal_tx[i]); - if (nd < data->dist_vals[i]) { - data->dist_vals[i] = nd; + float nd = dist_squared_to_plane_v3(co, data->plane_tx[i]); + if (nd < data->dist_vals_sq[i]) { + data->dist_vals_sq[i] = nd; } } @@ -514,15 +515,12 @@ int BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object } for (i = 0; i < 4; i++) { - normal_tri_v3(data_cb.normal_tx[i], - zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]); + normal_tri_v3(data_cb.normal_tx[i], zero, data_cb.frame_tx[i], data_cb.frame_tx[(i + 1) % 4]); + plane_from_point_normal_v3(data_cb.plane_tx[i], data_cb.frame_tx[i], data_cb.normal_tx[i]); } /* initialize callback data */ - data_cb.dist_vals[0] = - data_cb.dist_vals[1] = - data_cb.dist_vals[2] = - data_cb.dist_vals[3] = FLT_MAX; + copy_v4_fl(data_cb.dist_vals_sq, FLT_MAX); data_cb.tot = 0; /* run callback on all visible points */ BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, @@ -537,11 +535,16 @@ int BKE_camera_view_frame_fit_to_scene(Scene *scene, struct View3D *v3d, Object float plane_isect_pt_1[3], plane_isect_pt_2[3]; + /* could make a generic macro */ +#define SQRT_SIGNED(f) copysign(sqrtf(fabsf(f)), f) + /* apply the dist-from-plane's to the transformed plane points */ for (i = 0; i < 4; i++) { - mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], data_cb.dist_vals[i]); + mul_v3_v3fl(plane_tx[i], data_cb.normal_tx[i], SQRT_SIGNED(data_cb.dist_vals_sq[i])); } +#undef SQRT_SIGNED + isect_plane_plane_v3(plane_isect_1, plane_isect_1_no, plane_tx[0], data_cb.normal_tx[0], plane_tx[2], data_cb.normal_tx[2]); diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 6205c8016b6..1bc12cffe7b 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1814,7 +1814,13 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh, Object *UNUSED(ob)) DerivedMesh *CDDM_from_curve(Object *ob) { - return CDDM_from_curve_displist(ob, &ob->disp); + ListBase disp = {NULL, NULL}; + + if (ob->curve_cache) { + disp = ob->curve_cache->disp; + } + + return CDDM_from_curve_displist(ob, &disp); } DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase) @@ -2399,7 +2405,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int STACK_DECLARE(mpoly); STACK_DECLARE(oldp); - EdgeHash *ehash = BLI_edgehash_new(); + EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge); int i, j, c; @@ -2601,10 +2607,12 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm) EdgeHashIterator *ehi; MFace *mf = cddm->mface; MEdge *med; - EdgeHash *eh = BLI_edgehash_new(); - int i, *index, numEdges, maxFaces = dm->numTessFaceData; + EdgeHash *eh; + int i, *index, numEdges, numFaces = dm->numTessFaceData; + + eh = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(numFaces)); - for (i = 0; i < maxFaces; i++, mf++) { + for (i = 0; i < numFaces; 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)) @@ -2634,7 +2642,7 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm) for (ehi = BLI_edgehashIterator_new(eh), i = 0; BLI_edgehashIterator_isDone(ehi) == FALSE; - BLI_edgehashIterator_step(ehi), ++i, ++med, ++index) + BLI_edgehashIterator_step(ehi), i++, med++, index++) { BLI_edgehashIterator_getKey(ehi, &med->v1, &med->v2); @@ -2662,21 +2670,27 @@ void CDDM_calc_edges(DerivedMesh *dm) MPoly *mp = cddm->mpoly; MLoop *ml; MEdge *med, *origmed; - EdgeHash *eh = BLI_edgehash_new(); + EdgeHash *eh; + unsigned int eh_reserve; int v1, v2; int *eindex; - int i, j, *index, numEdges = cddm->dm.numEdgeData, maxFaces = dm->numPolyData; + int i, j, *index; + const int numFaces = dm->numPolyData; + const int numLoops = dm->numLoopData; + int numEdges = dm->numEdgeData; eindex = DM_get_edge_data_layer(dm, CD_ORIGINDEX); - med = cddm->medge; + + eh_reserve = max_ii(med ? numEdges : 0, BLI_EDGEHASH_SIZE_GUESS_FROM_LOOPS(numLoops)); + eh = BLI_edgehash_new_ex(__func__, eh_reserve); if (med) { for (i = 0; i < numEdges; i++, med++) { BLI_edgehash_insert(eh, med->v1, med->v2, SET_INT_IN_POINTER(i + 1)); } } - for (i = 0; i < maxFaces; i++, mp++) { + for (i = 0; i < numFaces; i++, mp++) { ml = cddm->mloop + mp->loopstart; for (j = 0; j < mp->totloop; j++, ml++) { v1 = ml->v; @@ -2726,7 +2740,7 @@ void CDDM_calc_edges(DerivedMesh *dm) cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE); mp = cddm->mpoly; - for (i = 0; i < maxFaces; i++, mp++) { + for (i = 0; i < numFaces; i++, mp++) { ml = cddm->mloop + mp->loopstart; for (j = 0; j < mp->totloop; j++, ml++) { v1 = ml->v; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 05ffd4a6265..e4c6f7790d7 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -332,11 +332,13 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul if (clmd->clothObject == NULL) { if (!cloth_from_object(ob, clmd, result, framenr, 1)) { BKE_ptcache_invalidate(cache); + modifier_setError(&(clmd->modifier), "Can't initialize cloth"); return 0; } if (clmd->clothObject == NULL) { BKE_ptcache_invalidate(cache); + modifier_setError(&(clmd->modifier), "Null cloth object"); return 0; } @@ -973,6 +975,18 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) * SPRING NETWORK BUILDING IMPLEMENTATION BEGIN ***************************************************************************************/ +BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) +{ + if (v0 < v1) { + spring->ij = v0; + spring->kl = v1; + } + else { + spring->ij = v1; + spring->kl = v0; + } +} + // be careful: implicit solver has to be resettet when using this one! // --> only for implicit handling of this spring! int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int indexB, float restlength, int spring_type) @@ -1004,10 +1018,20 @@ int cloth_add_spring(ClothModifierData *clmd, unsigned int indexA, unsigned int return 0; } -static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *UNUSED(edgehash), LinkNode **edgelist) +static void cloth_free_edgelist(LinkNode **edgelist, unsigned int numverts) +{ + if (edgelist) { + unsigned int i; + for (i = 0; i < numverts; i++) { + BLI_linklist_free(edgelist[i], NULL); + } + + MEM_freeN(edgelist); + } +} + +static void cloth_free_errorsprings(Cloth *cloth, LinkNode **edgelist) { - unsigned int i = 0; - if ( cloth->springs != NULL ) { LinkNode *search = cloth->springs; while (search) { @@ -1020,17 +1044,13 @@ static void cloth_free_errorsprings(Cloth *cloth, EdgeHash *UNUSED(edgehash), Li cloth->springs = NULL; } - - if (edgelist) { - for ( i = 0; i < cloth->numverts; i++ ) { - BLI_linklist_free ( edgelist[i], NULL ); - } - MEM_freeN ( edgelist ); - } + cloth_free_edgelist(edgelist, cloth->numverts); - if (cloth->edgehash) - BLI_edgehash_free ( cloth->edgehash, NULL ); + if (cloth->edgehash) { + BLI_edgehash_free(cloth->edgehash, NULL); + cloth->edgehash = NULL; + } } /* update stiffness if vertex group values are changing from frame to frame */ @@ -1094,30 +1114,25 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) if ( numedges==0 ) return 0; + /* NOTE: handling ownership of sptings and edgehash is quite sloppy + * currenlty they are never initialized but assert just to be sure */ + BLI_assert(cloth->springs == NULL); + BLI_assert(cloth->edgehash == NULL); + cloth->springs = NULL; + cloth->edgehash = NULL; edgelist = MEM_callocN ( sizeof (LinkNode *) * numverts, "cloth_edgelist_alloc" ); if (!edgelist) return 0; - - for ( i = 0; i < numverts; i++ ) { - edgelist[i] = NULL; - } - - if ( cloth->springs ) - MEM_freeN ( cloth->springs ); - - // create spring network hash - edgehash = BLI_edgehash_new(); // structural springs for ( i = 0; i < numedges; i++ ) { spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if ( spring ) { - spring->ij = MIN2(medge[i].v1, medge[i].v2); - spring->kl = MAX2(medge[i].v2, medge[i].v1); + spring_verts_ordered_set(spring, medge[i].v1, medge[i].v2); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); clmd->sim_parms->avg_spring_len += spring->restlen; cloth->verts[spring->ij].avg_spring_len += spring->restlen; @@ -1132,11 +1147,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_prepend ( &cloth->springs, spring ); } else { - cloth_free_errorsprings(cloth, edgehash, edgelist); + cloth_free_errorsprings(cloth, edgelist); return 0; } } - + if (struct_springs > 0) clmd->sim_parms->avg_spring_len /= struct_springs; @@ -1153,12 +1168,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring = (ClothSpring *)MEM_callocN(sizeof(ClothSpring), "cloth spring"); if (!spring) { - cloth_free_errorsprings(cloth, edgehash, edgelist); + cloth_free_errorsprings(cloth, edgelist); return 0; } - spring->ij = MIN2(mface[i].v1, mface[i].v3); - spring->kl = MAX2(mface[i].v3, mface[i].v1); + spring_verts_ordered_set(spring, mface[i].v1, mface[i].v3); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; @@ -1174,12 +1188,11 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if (!spring) { - cloth_free_errorsprings(cloth, edgehash, edgelist); + cloth_free_errorsprings(cloth, edgelist); return 0; } - spring->ij = MIN2(mface[i].v2, mface[i].v4); - spring->kl = MAX2(mface[i].v4, mface[i].v2); + spring_verts_ordered_set(spring, mface[i].v2, mface[i].v4); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_SHEAR; spring->stiffness = (cloth->verts[spring->kl].shear_stiff + cloth->verts[spring->ij].shear_stiff) / 2.0f; @@ -1191,6 +1204,9 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) BLI_linklist_prepend ( &cloth->springs, spring ); } + edgehash = BLI_edgehash_new_ex(__func__, numedges); + cloth->edgehash = edgehash; + if (numfaces) { // bending springs search2 = cloth->springs; @@ -1206,18 +1222,17 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) // check for existing spring // check also if startpoint is equal to endpoint - if (!BLI_edgehash_haskey(edgehash, MIN2(tspring2->ij, index2), MAX2(tspring2->ij, index2)) && - (index2 != tspring2->ij)) + if ((index2 != tspring2->ij) && + !BLI_edgehash_haskey(edgehash, tspring2->ij, index2)) { spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if (!spring) { - cloth_free_errorsprings(cloth, edgehash, edgelist); + cloth_free_errorsprings(cloth, edgelist); return 0; } - spring->ij = MIN2(tspring2->ij, index2); - spring->kl = MAX2(tspring2->ij, index2); + spring_verts_ordered_set(spring, tspring2->ij, index2); spring->restlen = len_v3v3(cloth->verts[spring->kl].xrest, cloth->verts[spring->ij].xrest); spring->type = CLOTH_SPRING_TYPE_BENDING; spring->stiffness = (cloth->verts[spring->kl].bend_stiff + cloth->verts[spring->ij].bend_stiff) / 2.0f; @@ -1249,7 +1264,7 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) spring = (ClothSpring *)MEM_callocN ( sizeof ( ClothSpring ), "cloth spring" ); if (!spring) { - cloth_free_errorsprings(cloth, edgehash, edgelist); + cloth_free_errorsprings(cloth, edgelist); return 0; } @@ -1268,34 +1283,30 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) } } + /* note: the edges may already exist so run reinsert */ + /* insert other near springs in edgehash AFTER bending springs are calculated (for selfcolls) */ for (i = 0; i < numedges; i++) { /* struct springs */ - BLI_edgehash_insert(edgehash, MIN2(medge[i].v1, medge[i].v2), MAX2(medge[i].v2, medge[i].v1), NULL); + BLI_edgehash_reinsert(edgehash, medge[i].v1, medge[i].v2, NULL); } for (i = 0; i < numfaces; i++) { /* edge springs */ if (mface[i].v4) { - BLI_edgehash_insert(edgehash, MIN2(mface[i].v1, mface[i].v3), MAX2(mface[i].v3, mface[i].v1), NULL); + BLI_edgehash_reinsert(edgehash, mface[i].v1, mface[i].v3, NULL); - BLI_edgehash_insert(edgehash, MIN2(mface[i].v2, mface[i].v4), MAX2(mface[i].v2, mface[i].v4), NULL); + BLI_edgehash_reinsert(edgehash, mface[i].v2, mface[i].v4, NULL); } } cloth->numsprings = struct_springs + shear_springs + bend_springs; - if ( edgelist ) { - for ( i = 0; i < numverts; i++ ) { - BLI_linklist_free ( edgelist[i], NULL ); - } - - MEM_freeN ( edgelist ); - } - - cloth->edgehash = edgehash; - + cloth_free_edgelist(edgelist, numverts); + +#if 0 if (G.debug_value > 0) printf("avg_len: %f\n", clmd->sim_parms->avg_spring_len); +#endif return 1; diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 91a09bb8554..e3081b9e670 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -281,7 +281,7 @@ static int cloth_collision_response_static ( ClothModifierData *clmd, CollisionM /* Decrease in magnitude of relative tangential velocity due to coulomb friction * in original formula "magrelVel" should be the "change of relative velocity in normal direction" */ - magtangent = min_ff(clmd->coll_parms->friction * 0.01f * magrelVel, sqrtf(dot_v3v3(vrel_t_pre, vrel_t_pre))); + magtangent = min_ff(clmd->coll_parms->friction * 0.01f * magrelVel, len_v3(vrel_t_pre)); /* Apply friction impulse. */ if ( magtangent > ALMOST_ZERO ) { @@ -865,8 +865,7 @@ int cloth_bvh_objcollision(Object *ob, ClothModifierData *clmd, float step, floa if ( ( ABS ( temp[0] ) > mindistance ) || ( ABS ( temp[1] ) > mindistance ) || ( ABS ( temp[2] ) > mindistance ) ) continue; - // check for adjacent points (i must be smaller j) - if ( BLI_edgehash_haskey ( cloth->edgehash, MIN2(i, j), MAX2(i, j) ) ) { + if (BLI_edgehash_haskey(cloth->edgehash, i, j)) { continue; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index eda770ddf30..7b7d20a54e0 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -69,6 +69,7 @@ #include "BKE_bvhutils.h" #include "BKE_camera.h" #include "BKE_constraint.h" +#include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" /* for geometry targets */ @@ -448,7 +449,7 @@ static void contarget_get_lattice_mat(Object *ob, const char *substring, float m { Lattice *lt = (Lattice *)ob->data; - DispList *dl = BKE_displist_find(&ob->disp, DL_VERTS); + DispList *dl = ob->curve_cache ? BKE_displist_find(&ob->curve_cache->disp, DL_VERTS) : NULL; float *co = dl ? dl->verts : NULL; BPoint *bp = lt->def; @@ -1163,10 +1164,10 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (cu->path == NULL || cu->path->data == NULL) + if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) BKE_displist_make_curveTypes(cob->scene, ct->tar, 0); - if (cu->path && cu->path->data) { + if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) { float quat[4]; if ((data->followflag & FOLLOWPATH_STATIC) == 0) { /* animated position along curve depending on time */ @@ -1933,10 +1934,8 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa if (VALID_CONS_TARGET(ct)) { /* special exception for curves - depsgraph issues */ if (ct->tar->type == OB_CURVE) { - Curve *cu = ct->tar->data; - /* this check is to make sure curve objects get updated on file load correctly.*/ - if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */ + if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */ BKE_displist_make_curveTypes(cob->scene, ct->tar, 0); } @@ -3009,14 +3008,12 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, short nocopy) static void clampto_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) { - Curve *cu = ct->tar->data; - /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, * currently for paths to work it needs to go through the bevlist/displist system (ton) */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (cu->path == NULL || cu->path->data == NULL) + if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) BKE_displist_make_curveTypes(cob->scene, ct->tar, 0); } @@ -3034,7 +3031,6 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar /* only evaluate if there is a target and it is a curve */ if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_CURVE)) { - Curve *cu = data->tar->data; float obmat[4][4], ownLoc[3]; float curveMin[3], curveMax[3]; float targetMatrix[4][4] = MAT4_UNITY; @@ -3047,7 +3043,7 @@ static void clampto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar BKE_object_minmax(ct->tar, curveMin, curveMax, TRUE); /* get targetmatrix */ - if (cu->path && cu->path->data) { + if (data->tar->curve_cache && data->tar->curve_cache->path && data->tar->curve_cache->path->data) { float vec[4], dir[3], totmat[4][4]; float curvetime; short clamp_axis; @@ -3396,13 +3392,11 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f; if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f; - if (dot_v3v3(no, no) < FLT_EPSILON) { + if (normalize_v3(no) < FLT_EPSILON) { fail = TRUE; break; } - normalize_v3(no); - bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6); if (treeData.tree == NULL) { @@ -3650,14 +3644,12 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, short nocopy) static void splineik_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) { - Curve *cu = ct->tar->data; - /* note: when creating constraints that follow path, the curve gets the CU_PATH set now, * currently for paths to work it needs to go through the bevlist/displist system (ton) */ /* only happens on reload file, but violates depsgraph still... fix! */ - if (cu->path == NULL || cu->path->data == NULL) + if (ct->tar->curve_cache == NULL || ct->tar->curve_cache->path == NULL || ct->tar->curve_cache->path->data == NULL) BKE_displist_make_curveTypes(cob->scene, ct->tar, 0); } diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 622b4f6df5a..2eb763831e4 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -198,8 +198,7 @@ void CTX_store_free_list(ListBase *contexts) { bContextStore *ctx; - while ((ctx = contexts->first)) { - BLI_remlink(contexts, ctx); + while ((ctx = BLI_pophead(contexts))) { CTX_store_free(ctx); } } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 801ed4f00a5..4e381669bb9 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -145,7 +145,6 @@ void BKE_curve_editNurb_free(Curve *cu) void BKE_curve_free(Curve *cu) { BKE_nurbList_free(&cu->nurb); - BLI_freelistN(&cu->bev); BKE_displist_free(&cu->disp); BKE_curve_editfont_free(cu); @@ -161,8 +160,6 @@ void BKE_curve_free(Curve *cu) MEM_freeN(cu->strinfo); if (cu->bb) MEM_freeN(cu->bb); - if (cu->path) - free_path(cu->path); if (cu->tb) MEM_freeN(cu->tb); } @@ -229,8 +226,6 @@ Curve *BKE_curve_copy(Curve *cu) if (cun->key) cun->key->from = (ID *)cun; cun->disp.first = cun->disp.last = NULL; - cun->bev.first = cun->bev.last = NULL; - cun->path = NULL; cun->editnurb = NULL; cun->editfont = NULL; @@ -372,60 +367,74 @@ void BKE_curve_type_test(Object *ob) BKE_curve_curve_dimension_update((Curve *)ob->data); } -void BKE_curve_texspace_calc(Curve *cu) +void BKE_curve_boundbox_calc(Curve *cu, float r_loc[3], float r_size[3]) { - DispList *dl; BoundBox *bb; - float *fp, min[3], max[3]; - int tot, do_it = FALSE; + float min[3], max[3]; + float mloc[3], msize[3]; - if (cu->bb == NULL) - cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); + if (cu->bb == NULL) cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); bb = cu->bb; + if (!r_loc) r_loc = mloc; + if (!r_size) r_size = msize; + INIT_MINMAX(min, max); + BKE_displist_minmax(&cu->disp, min, max); + mid_v3_v3v3(r_loc, min, max); - dl = cu->disp.first; - while (dl) { - tot = ELEM(dl->type, DL_INDEX3, DL_INDEX4) ? dl->nr : dl->nr * dl->parts; + r_size[0] = (max[0] - min[0]) / 2.0f; + r_size[1] = (max[1] - min[1]) / 2.0f; + r_size[2] = (max[2] - min[2]) / 2.0f; - if (tot) do_it = TRUE; - fp = dl->verts; - while (tot--) { - minmax_v3v3_v3(min, max, fp); - fp += 3; - } - dl = dl->next; - } + BKE_boundbox_init_from_minmax(bb, min, max); - if (do_it == FALSE) { - min[0] = min[1] = min[2] = -1.0f; - max[0] = max[1] = max[2] = 1.0f; - } + bb->flag &= ~BOUNDBOX_DIRTY; +} - BKE_boundbox_init_from_minmax(bb, min, max); +BoundBox *BKE_curve_boundbox_get(Object *ob) +{ + Curve *cu = ob->data; - if (cu->texflag & CU_AUTOSPACE) { - mid_v3_v3v3(cu->loc, min, max); - cu->size[0] = (max[0] - min[0]) / 2.0f; - cu->size[1] = (max[1] - min[1]) / 2.0f; - cu->size[2] = (max[2] - min[2]) / 2.0f; + if (ob->bb) + return ob->bb; - zero_v3(cu->rot); + if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) { + BKE_curve_texspace_calc(cu); + } - if (cu->size[0] == 0.0f) cu->size[0] = 1.0f; - else if (cu->size[0] > 0.0f && cu->size[0] < 0.00001f) cu->size[0] = 0.00001f; - else if (cu->size[0] < 0.0f && cu->size[0] > -0.00001f) cu->size[0] = -0.00001f; + return cu->bb; +} - if (cu->size[1] == 0.0f) cu->size[1] = 1.0f; - else if (cu->size[1] > 0.0f && cu->size[1] < 0.00001f) cu->size[1] = 0.00001f; - else if (cu->size[1] < 0.0f && cu->size[1] > -0.00001f) cu->size[1] = -0.00001f; +void BKE_curve_texspace_calc(Curve *cu) +{ + float loc[3], size[3]; + int a; + + BKE_curve_boundbox_calc(cu, loc, size); - if (cu->size[2] == 0.0f) cu->size[2] = 1.0f; - else if (cu->size[2] > 0.0f && cu->size[2] < 0.00001f) cu->size[2] = 0.00001f; - else if (cu->size[2] < 0.0f && cu->size[2] > -0.00001f) cu->size[2] = -0.00001f; + if (cu->texflag & CU_AUTOSPACE) { + for (a = 0; a < 3; a++) { + if (size[a] == 0.0f) size[a] = 1.0f; + else if (size[a] > 0.0f && size[a] < 0.00001f) size[a] = 0.00001f; + else if (size[a] < 0.0f && size[a] > -0.00001f) size[a] = -0.00001f; + } + + copy_v3_v3(cu->loc, loc); + copy_v3_v3(cu->size, size); + zero_v3(cu->rot); + } +} +void BKE_curve_texspace_get(Curve *cu, float r_loc[3], float r_rot[3], float r_size[3]) +{ + if (cu->bb == NULL || (cu->bb->flag & BOUNDBOX_DIRTY)) { + BKE_curve_texspace_calc(cu); } + + if (r_loc) copy_v3_v3(r_loc, cu->loc); + if (r_rot) copy_v3_v3(r_rot, cu->rot); + if (r_size) copy_v3_v3(r_size, cu->size); } int BKE_nurbList_index_get_co(ListBase *nurb, const int index, float r_co[3]) @@ -1586,10 +1595,10 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, int forRende dl = bevdisp.first; } else { - dl = cu->bevobj->disp.first; + dl = cu->bevobj->curve_cache ? cu->bevobj->curve_cache->disp.first : NULL; if (dl == NULL) { BKE_displist_make_curveTypes(scene, cu->bevobj, 0); - dl = cu->bevobj->disp.first; + dl = cu->bevobj->curve_cache->disp.first; } } @@ -1845,15 +1854,15 @@ static bool bevelinside(BevList *bl1, BevList *bl2) } -struct bevelsort { - float left; +struct BevelSort { BevList *bl; + float left; int dir; }; static int vergxcobev(const void *a1, const void *a2) { - const struct bevelsort *x1 = a1, *x2 = a2; + const struct BevelSort *x1 = a1, *x2 = a2; if (x1->left > x2->left) return 1; @@ -2447,7 +2456,7 @@ static void bevlist_firstlast_direction_calc_from_bpoint(Nurb *nu, BevList *bl) } } -void BKE_curve_bevelList_make(Object *ob) +void BKE_curve_bevelList_make(Object *ob, ListBase *nurbs, bool for_render) { /* * - convert all curves to polys, with indication of resol and flags for double-vertices @@ -2462,28 +2471,27 @@ void BKE_curve_bevelList_make(Object *ob) BevList *bl, *blnew, *blnext; BevPoint *bevp, *bevp2, *bevp1 = NULL, *bevp0; float min, inp; - struct bevelsort *sortdata, *sd, *sd1; + struct BevelSort *sortdata, *sd, *sd1; int a, b, nr, poly, resolu = 0, len = 0; int do_tilt, do_radius, do_weight; int is_editmode = 0; + ListBase *bev; /* this function needs an object, because of tflag and upflag */ cu = ob->data; + bev = &ob->curve_cache->bev; + /* do we need to calculate the radius for each point? */ /* do_radius = (cu->bevobj || cu->taperobj || (cu->flag & CU_FRONT) || (cu->flag & CU_BACK)) ? 0 : 1; */ /* STEP 1: MAKE POLYS */ - BLI_freelistN(&(cu->bev)); + BLI_freelistN(&(ob->curve_cache->bev)); + nu = nurbs->first; if (cu->editnurb && ob->type != OB_FONT) { - ListBase *nurbs = BKE_curve_editNurbs_get(cu); - nu = nurbs->first; is_editmode = 1; } - else { - nu = cu->nurb.first; - } for (; nu; nu = nu->next) { @@ -2499,12 +2507,12 @@ void BKE_curve_bevelList_make(Object *ob) * enforced in the UI but can go wrong possibly */ if (!BKE_nurb_check_valid_u(nu)) { bl = MEM_callocN(sizeof(BevList) + 1 * sizeof(BevPoint), "makeBevelList1"); - BLI_addtail(&(cu->bev), bl); + BLI_addtail(bev, bl); bl->nr = 0; bl->charidx = nu->charidx; } else { - if (G.is_rendering && cu->resolu_ren != 0) + if (for_render && cu->resolu_ren != 0) resolu = cu->resolu_ren; else resolu = nu->resolu; @@ -2512,7 +2520,7 @@ void BKE_curve_bevelList_make(Object *ob) if (nu->type == CU_POLY) { len = nu->pntsu; bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList2"); - BLI_addtail(&(cu->bev), bl); + BLI_addtail(bev, bl); bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->nr = len; @@ -2539,7 +2547,7 @@ void BKE_curve_bevelList_make(Object *ob) /* in case last point is not cyclic */ len = resolu * (nu->pntsu + (nu->flagu & CU_NURB_CYCLIC) - 1) + 1; bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelBPoints"); - BLI_addtail(&(cu->bev), bl); + BLI_addtail(bev, bl); bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; bl->charidx = nu->charidx; @@ -2632,7 +2640,7 @@ void BKE_curve_bevelList_make(Object *ob) len = (resolu * SEGMENTSU(nu)); bl = MEM_callocN(sizeof(BevList) + len * sizeof(BevPoint), "makeBevelList3"); - BLI_addtail(&(cu->bev), bl); + BLI_addtail(bev, bl); bl->nr = len; bl->dupe_nr = 0; bl->poly = (nu->flagu & CU_NURB_CYCLIC) ? 0 : -1; @@ -2654,7 +2662,7 @@ void BKE_curve_bevelList_make(Object *ob) } /* STEP 2: DOUBLE POINTS AND AUTOMATIC RESOLUTION, REDUCE DATABLOCKS */ - bl = cu->bev.first; + bl = bev->first; while (bl) { if (bl->nr) { /* null bevel items come from single points */ nr = bl->nr; @@ -2676,7 +2684,7 @@ void BKE_curve_bevelList_make(Object *ob) } bl = bl->next; } - bl = cu->bev.first; + bl = bev->first; while (bl) { blnext = bl->next; if (bl->nr && bl->dupe_nr) { @@ -2684,8 +2692,8 @@ void BKE_curve_bevelList_make(Object *ob) blnew = MEM_mallocN(sizeof(BevList) + nr * sizeof(BevPoint), "makeBevelList4"); memcpy(blnew, bl, sizeof(BevList)); blnew->nr = 0; - BLI_remlink(&(cu->bev), bl); - BLI_insertlinkbefore(&(cu->bev), blnext, blnew); /* to make sure bevlijst is tuned with nurblist */ + BLI_remlink(bev, bl); + BLI_insertlinkbefore(bev, blnext, blnew); /* to make sure bevlijst is tuned with nurblist */ bevp0 = (BevPoint *)(bl + 1); bevp1 = (BevPoint *)(blnew + 1); nr = bl->nr; @@ -2704,7 +2712,7 @@ void BKE_curve_bevelList_make(Object *ob) } /* STEP 3: POLYS COUNT AND AUTOHOLE */ - bl = cu->bev.first; + bl = bev->first; poly = 0; while (bl) { if (bl->nr && bl->poly >= 0) { @@ -2717,8 +2725,8 @@ void BKE_curve_bevelList_make(Object *ob) /* find extreme left points, also test (turning) direction */ if (poly > 0) { - sd = sortdata = MEM_mallocN(sizeof(struct bevelsort) * poly, "makeBevelList5"); - bl = cu->bev.first; + sd = sortdata = MEM_mallocN(sizeof(struct BevelSort) * poly, "makeBevelList5"); + bl = bev->first; while (bl) { if (bl->poly > 0) { @@ -2759,7 +2767,7 @@ void BKE_curve_bevelList_make(Object *ob) bl = bl->next; } - qsort(sortdata, poly, sizeof(struct bevelsort), vergxcobev); + qsort(sortdata, poly, sizeof(struct BevelSort), vergxcobev); sd = sortdata + 1; for (a = 1; a < poly; a++, sd++) { @@ -2798,7 +2806,7 @@ void BKE_curve_bevelList_make(Object *ob) /* STEP 4: 2D-COSINES or 3D ORIENTATION */ if ((cu->flag & CU_3D) == 0) { /* 2D Curves */ - for (bl = cu->bev.first; bl; bl = bl->next) { + for (bl = bev->first; bl; bl = bl->next) { if (bl->nr < 2) { /* do nothing */ } @@ -2812,7 +2820,7 @@ void BKE_curve_bevelList_make(Object *ob) } else { /* 3D Curves */ - for (bl = cu->bev.first; bl; bl = bl->next) { + for (bl = bev->first; bl; bl = bl->next) { if (bl->nr < 2) { /* do nothing */ } @@ -3076,6 +3084,14 @@ void BKE_nurb_handles_calc(Nurb *nu) /* first, if needed, set handle flags */ calchandlesNurb_intern(nu, FALSE); } +/* similar to BKE_nurb_handle_calc but for curves and + * figures out the previous and next for us */ +void BKE_nurb_handle_calc_simple(Nurb *nu, BezTriple *bezt) +{ + BezTriple *prev = BKE_nurb_bezt_get_prev(nu, bezt); + BezTriple *next = BKE_nurb_bezt_get_next(nu, bezt); + BKE_nurb_handle_calc(bezt, prev, next, 0); +} void BKE_nurb_handles_test(Nurb *nu) { @@ -3401,7 +3417,7 @@ void BKE_nurb_direction_switch(Nurb *nu) } -float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r))[3] +float (*BKE_curve_nurbs_vertexCos_get(ListBase *lb, int *numVerts_r))[3] { int i, numVerts = *numVerts_r = BKE_nurbList_verts_count(lb); float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos"); @@ -3430,7 +3446,7 @@ float (*BKE_curve_vertexCos_get(Curve *UNUSED(cu), ListBase *lb, int *numVerts_r return cos; } -void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos)[3]) +void BK_curve_nurbs_vertexCos_apply(ListBase *lb, float (*vertexCos)[3]) { float *co = vertexCos[0]; Nurb *nu; @@ -3458,7 +3474,7 @@ void BK_curve_vertexCos_apply(Curve *UNUSED(cu), ListBase *lb, float (*vertexCos } } -float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key))[3] +float (*BKE_curve_nurbs_keyVertexCos_get(ListBase *lb, float *key))[3] { int i, numVerts = BKE_nurbList_verts_count(lb); float *co, (*cos)[3] = MEM_mallocN(sizeof(*cos) * numVerts, "cu_vcos"); @@ -3489,7 +3505,7 @@ float (*BKE_curve_keyVertexCos_get(Curve *UNUSED(cu), ListBase *lb, float *key)) return cos; } -void BKE_curve_keyVertexTilts_apply(Curve *UNUSED(cu), ListBase *lb, float *key) +void BKE_curve_nurbs_keyVertexTilts_apply(ListBase *lb, float *key) { Nurb *nu; int i; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 4ce06623bae..f786f842be3 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -29,6 +29,7 @@ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <math.h> diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 38a0b848339..6a89ca2cb84 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -43,6 +43,7 @@ #include "DNA_material_types.h" #include "BLI_blenlib.h" +#include "BLI_memarena.h" #include "BLI_math.h" #include "BLI_scanfill.h" #include "BLI_utildefines.h" @@ -62,8 +63,7 @@ #include "BLI_sys_types.h" // for intptr_t support -static void boundbox_displist(Object *ob); -static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase); +static void boundbox_displist_object(Object *ob); void BKE_displist_elem_free(DispList *dl) { @@ -82,11 +82,8 @@ void BKE_displist_free(ListBase *lb) { DispList *dl; - dl = lb->first; - while (dl) { - BLI_remlink(lb, dl); + while ((dl = BLI_pophead(lb))) { BKE_displist_elem_free(dl); - dl = lb->first; } } @@ -454,6 +451,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj ScanFillContext sf_ctx; ScanFillVert *sf_vert, *sf_vert_new, *sf_vert_last; ScanFillFace *sf_tri; + MemArena *sf_arena; DispList *dlnew = NULL, *dl; float *f1; int colnr = 0, charidx = 0, cont = 1, tot, a, *index, nextcol = 0; @@ -464,12 +462,14 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj if (dispbase->first == NULL) return; + sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); + while (cont) { cont = 0; totvert = 0; nextcol = 0; - BLI_scanfill_begin(&sf_ctx); + BLI_scanfill_begin_arena(&sf_ctx, sf_arena); dl = dispbase->first; while (dl) { @@ -557,7 +557,7 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj BLI_addhead(to, dlnew); } - BLI_scanfill_end(&sf_ctx); + BLI_scanfill_end_arena(&sf_ctx, sf_arena); if (nextcol) { /* stay at current char but fill polys with next material */ @@ -570,6 +570,8 @@ void BKE_displist_fill(ListBase *dispbase, ListBase *to, const float normal_proj } } + BLI_memarena_free(sf_arena); + /* do not free polys, needed for wireframe display */ } @@ -667,10 +669,10 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) if (taperobj == NULL || taperobj->type != OB_CURVE) return 1.0; - dl = taperobj->disp.first; + dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL; if (dl == NULL) { BKE_displist_make_curveTypes(scene, taperobj, 0); - dl = taperobj->disp.first; + dl = taperobj->curve_cache->disp.first; } if (dl) { float minx, dx, *fp; @@ -712,29 +714,28 @@ void BKE_displist_make_mball(Scene *scene, Object *ob) if (!ob || ob->type != OB_MBALL) return; - /* XXX: mball stuff uses plenty of global variables - * while this is unchanged updating during render is unsafe - */ - if (G.is_rendering) - return; - - BKE_displist_free(&(ob->disp)); + if (ob->curve_cache) { + BKE_displist_free(&(ob->curve_cache->disp)); + } + else { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + } if (ob->type == OB_MBALL) { if (ob == BKE_mball_basis_find(scene, ob)) { - BKE_mball_polygonize(scene, ob, &ob->disp); + BKE_mball_polygonize(scene, ob, &ob->curve_cache->disp, false); BKE_mball_texspace_calc(ob); - object_deform_mball(ob, &ob->disp); + object_deform_mball(ob, &ob->curve_cache->disp); } - } - boundbox_displist(ob); + boundbox_displist_object(ob); + } } void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispbase) { - BKE_mball_polygonize(scene, ob, dispbase); + BKE_mball_polygonize(scene, ob, dispbase, true); BKE_mball_texspace_calc(ob); object_deform_mball(ob, dispbase); @@ -742,7 +743,8 @@ void BKE_displist_make_mball_forRender(Scene *scene, Object *ob, ListBase *dispb static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int renderResolution, int editmode) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); ModifierData *pretessellatePoint; int required_mode; @@ -780,18 +782,16 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, int re return pretessellatePoint; } -static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, int renderResolution, - float (**originalVerts_r)[3], - float (**deformedVerts_r)[3], int *numVerts_r) +static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb, + int forRender, int renderResolution) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; - ListBase *nurb = BKE_curve_nurbs_get(cu); int numVerts = 0; const int editmode = (!forRender && (cu->editnurb || cu->editfont)); ModifierApplyFlag app_flag = 0; - float (*originalVerts)[3] = NULL; float (*deformedVerts)[3] = NULL; float *keyVerts = NULL; int required_mode; @@ -818,8 +818,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in * tilts, which is passed through in the modifier stack. * this is also the reason curves do not use a virtual * shape key modifier yet. */ - deformedVerts = BKE_curve_keyVertexCos_get(cu, nurb, keyVerts); - originalVerts = MEM_dupallocN(deformedVerts); + deformedVerts = BKE_curve_nurbs_keyVertexCos_get(nurb, keyVerts); BLI_assert(BKE_nurbList_verts_count(nurb) == numVerts); } } @@ -836,8 +835,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in continue; if (!deformedVerts) { - deformedVerts = BKE_curve_vertexCos_get(cu, nurb, &numVerts); - originalVerts = MEM_dupallocN(deformedVerts); + deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts); } mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag); @@ -847,17 +845,15 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, int forRender, in } } - if (deformedVerts) - BK_curve_vertexCos_apply(cu, nurb, deformedVerts); + if (deformedVerts) { + BK_curve_nurbs_vertexCos_apply(nurb, deformedVerts); + MEM_freeN(deformedVerts); + } if (keyVerts) /* these are not passed through modifier stack */ - BKE_curve_keyVertexTilts_apply(cu, nurb, keyVerts); + BKE_curve_nurbs_keyVertexTilts_apply(nurb, keyVerts); if (keyVerts) MEM_freeN(keyVerts); - - *originalVerts_r = originalVerts; - *deformedVerts_r = deformedVerts; - *numVerts_r = numVerts; } static float (*displist_get_allverts(ListBase *dispbase, int *totvert))[3] @@ -894,14 +890,14 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3]) } } -static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal, - int forRender, int renderResolution, - float (*originalVerts)[3], float (*deformedVerts)[3]) +static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, + ListBase *dispbase, DerivedMesh **derivedFinal, + int forRender, int renderResolution) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; - ListBase *nurb = BKE_curve_nurbs_get(cu); int required_mode = 0, totvert = 0; int editmode = (!forRender && (cu->editnurb || cu->editfont)); DerivedMesh *dm = NULL, *ndm; @@ -1046,12 +1042,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *dispba } (*derivedFinal) = dm; } - - if (deformedVerts) { - BK_curve_vertexCos_apply(ob->data, nurb, originalVerts); - MEM_freeN(originalVerts); - MEM_freeN(deformedVerts); - } } static void displist_surf_indices(DispList *dl) @@ -1142,8 +1132,8 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina /* this function represents logic of mesh's orcodm calculation * for displist-based objects */ - - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; int required_mode; @@ -1201,25 +1191,24 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *derivedFina void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal, int forRender, int forOrco, int renderResolution) { - ListBase *nubase; + ListBase nubase = {NULL, NULL}; Nurb *nu; Curve *cu = ob->data; DispList *dl; float *data; int len; - int numVerts; - float (*originalVerts)[3]; - float (*deformedVerts)[3]; - if (!forRender && cu->editnurb) - nubase = BKE_curve_editNurbs_get(cu); - else - nubase = &cu->nurb; + if (!forRender && cu->editnurb) { + BKE_nurbList_duplicate(&nubase, BKE_curve_editNurbs_get(cu)); + } + else { + BKE_nurbList_duplicate(&nubase, &cu->nurb); + } if (!forOrco) - curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts); + curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution); - for (nu = nubase->first; nu; nu = nu->next) { + for (nu = nubase.first; nu; nu = nu->next) { if (forRender || nu->hide == 0) { int resolu = nu->resolu, resolv = nu->resolv; @@ -1287,15 +1276,12 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, * already applied, thats how it worked for years, so keep for compatibility (sergey) */ BKE_displist_copy(&cu->disp, dispbase); - if (!forRender) { - BKE_curve_texspace_calc(cu); - } - if (!forOrco) { - curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, - forRender, renderResolution, - originalVerts, deformedVerts); + curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal, + forRender, renderResolution); } + + BKE_nurbList_free(&nubase); } static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r) @@ -1389,37 +1375,34 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; - ListBase *nubase; - float (*originalVerts)[3]; - float (*deformedVerts)[3]; - int numVerts; + ListBase nubase = {NULL, NULL}; - nubase = BKE_curve_nurbs_get(cu); + BLI_freelistN(&(ob->curve_cache->bev)); - BLI_freelistN(&(cu->bev)); - - if (cu->path) free_path(cu->path); - cu->path = NULL; + if (ob->curve_cache->path) free_path(ob->curve_cache->path); + ob->curve_cache->path = NULL; if (ob->type == OB_FONT) BKE_vfont_to_curve(G.main, scene, ob, 0); + BKE_nurbList_duplicate(&nubase, BKE_curve_nurbs_get(cu)); + if (!forOrco) - curve_calc_modifiers_pre(scene, ob, forRender, renderResolution, &originalVerts, &deformedVerts, &numVerts); + curve_calc_modifiers_pre(scene, ob, &nubase, forRender, renderResolution); - BKE_curve_bevelList_make(ob); + BKE_curve_bevelList_make(ob, &nubase, forRender != FALSE); /* If curve has no bevel will return nothing */ BKE_curve_bevel_make(scene, ob, &dlbev, forRender, renderResolution); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width == 1.0f) { - curve_to_displist(cu, nubase, dispbase, forRender, renderResolution); + curve_to_displist(cu, &nubase, dispbase, forRender, renderResolution); } else { float widfac = cu->width - 1.0f; - BevList *bl = cu->bev.first; - Nurb *nu = nubase->first; + BevList *bl = ob->curve_cache->bev.first; + Nurb *nu = nubase.first; for (; bl && nu; bl = bl->next, nu = nu->next) { DispList *dl; @@ -1586,27 +1569,25 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } if (!(cu->flag & CU_DEFORM_FILL)) { - curve_to_filledpoly(cu, nubase, dispbase); + curve_to_filledpoly(cu, &nubase, dispbase); } if ((cu->flag & CU_PATH) && !forOrco) - calc_curvepath(ob); + calc_curvepath(ob, &nubase); /* make copy of 'undeformed" displist for texture space calculation * actually, it's not totally undeformed -- pre-tessellation modifiers are * already applied, thats how it worked for years, so keep for compatibility (sergey) */ BKE_displist_copy(&cu->disp, dispbase); - if (!forRender) { - BKE_curve_texspace_calc(cu); - } - if (!forOrco) - curve_calc_modifiers_post(scene, ob, dispbase, derivedFinal, forRender, renderResolution, originalVerts, deformedVerts); + curve_calc_modifiers_post(scene, ob, &nubase, dispbase, derivedFinal, forRender, renderResolution); if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) { - curve_to_filledpoly(cu, nubase, dispbase); + curve_to_filledpoly(cu, &nubase, dispbase); } + + BKE_nurbList_free(&nubase); } } @@ -1621,37 +1602,36 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, int forOrco) if (!ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; - BKE_displist_free(&(ob->disp)); - dispbase = &(ob->disp); - BKE_displist_free(dispbase); - - /* free displist used for textspace */ BKE_displist_free(&cu->disp); + BKE_object_free_derived_caches(ob); - do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0); + if (!ob->curve_cache) { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for curve types"); + } - if (ob->derivedFinal) { - DM_set_object_boundbox(ob, ob->derivedFinal); + dispbase = &(ob->curve_cache->disp); - /* always keep curve's BB in sync with non-deformed displist */ - if (cu->bb == NULL) - cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); + do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, forOrco, 0); - boundbox_dispbase(cu->bb, &cu->disp); - } - else { - boundbox_displist(ob); - } + boundbox_displist_object(ob); } void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase, DerivedMesh **derivedFinal, int forOrco, int renderResolution) { + if (ob->curve_cache == NULL) { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + } + do_makeDispListCurveTypes(scene, ob, dispbase, derivedFinal, 1, forOrco, renderResolution); } void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase) { + if (ob->curve_cache == NULL) { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); + } + do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1); } @@ -1676,16 +1656,13 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *derivedFina return orco; } -static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase) +void BKE_displist_minmax(ListBase *dispbase, float min[3], float max[3]) { - float min[3], max[3]; DispList *dl; float *vert; int a, tot = 0; int doit = 0; - INIT_MINMAX(min, max); - for (dl = dispbase->first; dl; dl = dl->next) { tot = (dl->type == DL_INDEX3) ? dl->nr : dl->nr * dl->parts; vert = dl->verts; @@ -1700,26 +1677,29 @@ static void boundbox_dispbase(BoundBox *bb, ListBase *dispbase) zero_v3(min); zero_v3(max); } - - BKE_boundbox_init_from_minmax(bb, min, max); } /* this is confusing, there's also min_max_object, appplying the obmat... */ -static void boundbox_displist(Object *ob) +static void boundbox_displist_object(Object *ob) { if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - Curve *cu = ob->data; - - /* calculate curve's BB based on non-deformed displist */ - if (cu->bb == NULL) - cu->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); - - boundbox_dispbase(cu->bb, &cu->disp); + /* Curver's BB is already calculated as a part of modifier stack, + * here we only calculate object BB based on final display list. + */ /* object's BB is calculated from final displist */ if (ob->bb == NULL) ob->bb = MEM_callocN(sizeof(BoundBox), "boundbox"); - boundbox_dispbase(ob->bb, &ob->disp); + if (ob->derivedFinal) { + DM_set_object_boundbox(ob, ob->derivedFinal); + } + else { + float min[3], max[3]; + + INIT_MINMAX(min, max); + BKE_displist_minmax(&ob->curve_cache->disp, min, max); + BKE_boundbox_init_from_minmax(ob->bb, min, max); + } } } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index a62ca530bf9..a6cff9f20fb 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -3802,14 +3802,15 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface, */ KDTreeNearest *nearest; - int n, particles = 0; + int n, particles; float smooth_range = smooth * (1.0f - strength), dist; /* calculate max range that can have particles with higher influence than the nearest one */ float max_range = smooth - strength * smooth + solidradius; /* Make gcc happy! */ dist = max_range; - particles = BLI_kdtree_range_search(tree, max_range, bData->realCoord[bData->s_pos[index]].v, NULL, &nearest); + particles = BLI_kdtree_range_search(tree, bData->realCoord[bData->s_pos[index]].v, NULL, + &nearest, max_range); /* Find particle that produces highest influence */ for (n = 0; n < particles; n++) { diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index e8e56c6f17b..caa5bf90584 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -1872,7 +1872,7 @@ static void statvis_calc_thickness( normal_tri_v3(ray_no, cos[2], cos[1], cos[0]); #define FACE_RAY_TEST_ANGLE \ - f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, \ + f_hit = BKE_bmbvh_ray_cast(bmtree, ray_co, ray_no, 0.0f, \ &dist, NULL, NULL); \ if (f_hit && dist < face_dists[index]) { \ float angle_fac = fabsf(dot_v3v3(ltri[0]->f->no, f_hit->no)); \ diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index 74cd8834d5d..6a89d16d7bf 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -36,6 +36,7 @@ #include "DNA_mesh_types.h" #include "BLI_math.h" +#include "BLI_memarena.h" #include "BLI_scanfill.h" #include "BKE_editmesh.h" @@ -123,6 +124,7 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) int i = 0; ScanFillContext sf_ctx; + MemArena *sf_arena = NULL; #if 0 /* note, we could be clever and re-use this array but would need to ensure @@ -217,7 +219,11 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) ScanFillFace *sf_tri; int totfilltri; - BLI_scanfill_begin(&sf_ctx); + if (UNLIKELY(sf_arena == NULL)) { + sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); + } + + BLI_scanfill_begin_arena(&sf_ctx, sf_arena); /* scanfill time */ j = 0; @@ -262,10 +268,15 @@ static void editmesh_tessface_calc_intern(BMEditMesh *em) l_ptr[2] = l3; } - BLI_scanfill_end(&sf_ctx); + BLI_scanfill_end_arena(&sf_ctx, sf_arena); } } + if (sf_arena) { + BLI_memarena_free(sf_arena); + sf_arena = NULL; + } + em->tottri = i; em->looptris = looptris; diff --git a/source/blender/blenkernel/intern/editmesh_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index fced3472566..5b00e5a83ac 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -193,12 +193,17 @@ static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, const BMLoop **ltri = bmcb_data->looptris[index]; float dist, uv[2]; const float *tri_cos[3]; + bool isect; bmbvh_tri_from_face(tri_cos, ltri, bmcb_data->cos_cage); - if (isect_ray_tri_v3(ray->origin, ray->direction, tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv) && - (dist < hit->dist)) - { + isect = (ray->radius > 0.0f ? + isect_ray_tri_epsilon_v3(ray->origin, ray->direction, + tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv, ray->radius) : + isect_ray_tri_v3(ray->origin, ray->direction, + tri_cos[0], tri_cos[1], tri_cos[2], &dist, uv)); + + if (isect && dist < hit->dist) { hit->dist = dist; hit->index = index; @@ -213,7 +218,7 @@ static void bmbvh_ray_cast_cb(void *userdata, int index, const BVHTreeRay *ray, } } -BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir[3], +BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir[3], const float radius, float *r_dist, float r_hitout[3], float r_cagehit[3]) { BVHTreeRayHit hit; @@ -229,7 +234,7 @@ BMFace *BKE_bmbvh_ray_cast(BMBVHTree *bmtree, const float co[3], const float dir bmcb_data.looptris = (const BMLoop *(*)[3])bmtree->em->looptris; bmcb_data.cos_cage = (const float (*)[3])bmtree->cos_cage; - BLI_bvhtree_ray_cast(bmtree->tree, co, dir, 0.0f, &hit, bmbvh_ray_cast_cb, &bmcb_data); + BLI_bvhtree_ray_cast(bmtree->tree, co, dir, radius, &hit, bmbvh_ray_cast_cb, &bmcb_data); if (hit.index != -1 && hit.dist != dist) { if (r_hitout) { if (bmtree->flag & BMBVH_RETURN_ORIG) { diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 0df8684044a..81b0de9fd32 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -67,6 +67,7 @@ #include "BKE_blender.h" #include "BKE_collision.h" #include "BKE_constraint.h" +#include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_depsgraph.h" #include "BKE_displist.h" @@ -176,10 +177,10 @@ static void precalculate_effector(EffectorCache *eff) if (eff->pd->forcefield == PFIELD_GUIDE && eff->ob->type==OB_CURVE) { Curve *cu= eff->ob->data; if (cu->flag & CU_PATH) { - if (cu->path==NULL || cu->path->data==NULL) + if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL) BKE_displist_make_curveTypes(eff->scene, eff->ob, 0); - if (cu->path && cu->path->data) { + if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) { where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); mul_m4_v3(eff->ob->obmat, eff->guide_loc); mul_mat3_m4_v3(eff->ob->obmat, eff->guide_dir); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 7c23438f93d..f24d84df2e8 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -41,6 +41,7 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_threads.h" #include "BLI_vfontdata.h" #include "BLI_utildefines.h" @@ -59,6 +60,7 @@ #include "BKE_curve.h" #include "BKE_displist.h" +static ThreadMutex vfont_mutex = BLI_MUTEX_INITIALIZER; /* The vfont code */ void BKE_vfont_free_data(struct VFont *vfont) @@ -138,6 +140,18 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont) if (!vfont->data) { PackedFile *pf; + BLI_mutex_lock(&vfont_mutex); + + if (vfont->data) { + /* Check data again, since it might have been already + * initialized from other thread (previous check is + * not accurate or threading, just prevents unneeded + * lock if all the data is here for sure). + */ + BLI_mutex_unlock(&vfont_mutex); + return vfont->data; + } + if (BKE_vfont_is_builtin(vfont)) { pf = get_builtin_packedfile(); } @@ -175,8 +189,10 @@ static VFontData *vfont_get_data(Main *bmain, VFont *vfont) freePackedFile(pf); } } + + BLI_mutex_unlock(&vfont_mutex); } - + return vfont->data; } @@ -819,8 +835,10 @@ makebreak: cucu->flag |= (CU_PATH + CU_FOLLOW); - if (cucu->path == NULL) BKE_displist_make_curveTypes(scene, cu->textoncurve, 0); - if (cucu->path) { + if (cu->textoncurve->curve_cache == NULL || cu->textoncurve->curve_cache->path == NULL) { + BKE_displist_make_curveTypes(scene, cu->textoncurve, 0); + } + if (cu->textoncurve->curve_cache->path) { float distfac, imat[4][4], imat3[3][3], cmat[3][3]; float minx, maxx, miny, maxy; float timeofs, sizefac; @@ -845,7 +863,7 @@ makebreak: /* we put the x-coordinaat exact at the curve, the y is rotated */ /* length correction */ - distfac = sizefac * cucu->path->totdist / (maxx - minx); + distfac = sizefac * cu->textoncurve->curve_cache->path->totdist / (maxx - minx); timeofs = 0.0f; if (distfac > 1.0f) { diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index ad0aed4691a..a5cbf064bc2 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -65,9 +65,7 @@ void BKE_group_free(Group *group) /* don't free group itself */ GroupObject *go; - while (group->gobject.first) { - go = group->gobject.first; - BLI_remlink(&group->gobject, go); + while ((go = BLI_pophead(&group->gobject))) { free_group_object(go); } } diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index f20506af967..2e32c18b264 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -133,11 +133,10 @@ void IDP_AppendArray(IDProperty *prop, IDProperty *item) void IDP_ResizeIDPArray(IDProperty *prop, int newlen) { - void *newarr; - int newsize = newlen; + int newsize; - /*first check if the array buffer size has room*/ - /*if newlen is 200 chars less then totallen, reallocate anyway*/ + /* first check if the array buffer size has room */ + /* if newlen is 200 items less then totallen, reallocate anyway */ if (newlen <= prop->totallen) { if (newlen < prop->len && prop->totallen - newlen < 200) { int i; @@ -154,6 +153,15 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) } } + /* free trailing items */ + if (newlen < prop->len) { + /* newlen is smaller */ + int i; + for (i = newlen; i < prop->len; i++) { + IDP_FreeProperty(GETPROP(prop, i)); + } + } + /* - Note: This code comes from python, here's the corresponding comment. - */ /* This over-allocates proportional to the list size, making room * for additional growth. The over-allocation is mild, but is @@ -162,25 +170,9 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) * system realloc(). * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... */ + newsize = newlen; newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; - - newarr = MEM_callocN(sizeof(IDProperty) * newsize, "idproperty array resized"); - if (newlen >= prop->len) { - /* newlen is bigger */ - memcpy(newarr, prop->data.pointer, prop->len * sizeof(IDProperty)); - } - else { - int i; - /* newlen is smaller */ - for (i = newlen; i < prop->len; i++) { - IDP_FreeProperty(GETPROP(prop, i)); - } - memcpy(newarr, prop->data.pointer, newlen * sizeof(IDProperty)); - } - - if (prop->data.pointer) - MEM_freeN(prop->data.pointer); - prop->data.pointer = newarr; + prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * newsize); prop->len = newlen; prop->totallen = newsize; } @@ -217,11 +209,11 @@ static void idp_resize_group_array(IDProperty *prop, int newlen, void *newarr) /*this function works for strings too!*/ void IDP_ResizeArray(IDProperty *prop, int newlen) { - void *newarr; - int newsize = newlen; + int newsize; + const bool is_grow = newlen >= prop->len; - /*first check if the array buffer size has room*/ - /*if newlen is 200 chars less then totallen, reallocate anyway*/ + /* first check if the array buffer size has room */ + /* if newlen is 200 chars less then totallen, reallocate anyway */ if (newlen <= prop->totallen && prop->totallen - newlen < 200) { idp_resize_group_array(prop, newlen, prop->data.pointer); prop->len = newlen; @@ -236,22 +228,17 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) * system realloc(). * The growth pattern is: 0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ... */ - newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; + newsize = newlen; + newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize;\ - newarr = MEM_callocN(idp_size_table[(int)prop->subtype] * newsize, "idproperty array resized"); - if (newlen >= prop->len) { - /* newlen is bigger */ - memcpy(newarr, prop->data.pointer, prop->len * idp_size_table[(int)prop->subtype]); - idp_resize_group_array(prop, newlen, newarr); - } - else { - /* newlen is smaller */ - idp_resize_group_array(prop, newlen, newarr); - memcpy(newarr, prop->data.pointer, newlen * idp_size_table[(int)prop->subtype]); - } + if (is_grow == false) + idp_resize_group_array(prop, newlen, prop->data.pointer); + + prop->data.pointer = MEM_recallocN(prop->data.pointer, idp_size_table[(int)prop->subtype] * newsize); + + if (is_grow == true) + idp_resize_group_array(prop, newlen, prop->data.pointer); - MEM_freeN(prop->data.pointer); - prop->data.pointer = newarr; prop->len = newlen; prop->totallen = newsize; } @@ -301,14 +288,23 @@ static IDProperty *IDP_CopyArray(IDProperty *prop) } /* ---------- String Type ------------ */ + +/** + * + * \param st The string to assign. + * \param name The property name. + * \param maxlen The size of the new string (including the \0 terminator) + * \return + */ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) { IDProperty *prop = MEM_callocN(sizeof(IDProperty), "IDProperty string"); if (st == NULL) { - prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); + prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); + *IDP_String(prop) = '\0'; prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; - prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/ + prop->len = 1; /* NULL string, has len of 1 to account for null byte. */ } else { int stlen = strlen(st); @@ -318,7 +314,7 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) stlen++; /* null terminator '\0' */ - prop->data.pointer = MEM_callocN(stlen, "id property string 2"); + prop->data.pointer = MEM_mallocN(stlen, "id property string 2"); prop->len = prop->totallen = stlen; BLI_strncpy(prop->data.pointer, st, stlen); } @@ -354,7 +350,7 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) memcpy(prop->data.pointer, st, stlen); } else { - stlen++; /* make room for null byte */ + stlen++; IDP_ResizeArray(prop, stlen); BLI_strncpy(prop->data.pointer, st, stlen); } @@ -822,7 +818,8 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n if (val->string.subtype == IDP_STRING_SUB_BYTE) { /* note, intentionally not null terminated */ if (st == NULL) { - prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); + prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); + *IDP_String(prop) = '\0'; prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; prop->len = 0; } @@ -835,7 +832,8 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n } else { if (st == NULL) { - prop->data.pointer = MEM_callocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); + prop->data.pointer = MEM_mallocN(DEFAULT_ALLOC_FOR_NULL_STRINGS, "id property string 1"); + *IDP_String(prop) = '\0'; prop->totallen = DEFAULT_ALLOC_FOR_NULL_STRINGS; prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/ } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 86382c64ed3..8c0c16402da 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -195,9 +195,7 @@ static void image_free_buffers(Image *ima) { ImBuf *ibuf; - while ((ibuf = ima->ibufs.first)) { - BLI_remlink(&ima->ibufs, ibuf); - + while ((ibuf = BLI_pophead(&ima->ibufs))) { if (ibuf->userdata) { MEM_freeN(ibuf->userdata); ibuf->userdata = NULL; @@ -524,8 +522,7 @@ void BKE_image_merge(Image *dest, Image *source) /* sanity check */ if (dest && source && dest != source) { - while ((ibuf = source->ibufs.first)) { - BLI_remlink(&source->ibufs, ibuf); + while ((ibuf = BLI_pophead(&source->ibufs))) { image_assign_ibuf(dest, ibuf, IMA_INDEX_PASS(ibuf->index), IMA_INDEX_FRAME(ibuf->index)); } @@ -2152,9 +2149,7 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata, /* texture users */ for (tex = mainp->tex.first; tex; tex = tex->id.next) { if (tex->type == TEX_IMAGE && tex->ima) { - if (ELEM(tex->ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { - callback(tex->ima, &tex->iuser, customdata); - } + callback(tex->ima, &tex->iuser, customdata); } } @@ -2196,7 +2191,7 @@ static void image_tag_frame_recalc(Image *ima, ImageUser *iuser, void *customdat { Image *changed_image = customdata; - if (ima == changed_image) { + if (ima == changed_image && ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE)) { iuser->flag |= IMA_NEED_FRAME_RECALC; } } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index d2d2cb1c2d0..7b73dee73fc 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -85,29 +85,23 @@ void BKE_key_free(Key *key) KeyBlock *kb; BKE_free_animdata((ID *)key); - - while ( (kb = key->block.first) ) { - - if (kb->data) MEM_freeN(kb->data); - - BLI_remlink(&key->block, kb); + + while ((kb = BLI_pophead(&key->block))) { + if (kb->data) + MEM_freeN(kb->data); MEM_freeN(kb); } - } void BKE_key_free_nolib(Key *key) { KeyBlock *kb; - - while ( (kb = key->block.first) ) { - - if (kb->data) MEM_freeN(kb->data); - - BLI_remlink(&key->block, kb); + + while ((kb = BLI_pophead(&key->block))) { + if (kb->data) + MEM_freeN(kb->data); MEM_freeN(kb); } - } Key *BKE_key_add(ID *id) /* common function */ @@ -734,12 +728,13 @@ static void cp_cu_key(Curve *cu, Key *key, KeyBlock *actkb, KeyBlock *kb, const } } -void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, const int mode) +void BKE_key_evaluate_relative(const int start, int end, const int tot, char *basispoin, Key *key, KeyBlock *actkb, + float **per_keyblock_weights, const int mode) { KeyBlock *kb; int *ofsp, ofs[3], elemsize, b; char *cp, *poin, *reffrom, *from, elemstr[8]; - int poinsize; + int poinsize, keyblock_index; /* currently always 0, in future key_pointer_size may assign */ ofs[1] = 0; @@ -763,14 +758,14 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba /* step 2: do it */ - for (kb = key->block.first; kb; kb = kb->next) { + for (kb = key->block.first, keyblock_index = 0; kb; kb = kb->next, keyblock_index++) { if (kb != key->refkey) { float icuval = kb->curval; /* only with value, and no difference allowed */ if (!(kb->flag & KEYBLOCK_MUTE) && icuval != 0.0f && kb->totelem == tot) { KeyBlock *refb; - float weight, *weights = kb->weights; + float weight, *weights = per_keyblock_weights ? per_keyblock_weights[keyblock_index] : NULL; char *freefrom = NULL, *freereffrom = NULL; /* reference now can be any block */ @@ -1058,7 +1053,7 @@ static void do_key(const int start, int end, const int tot, char *poin, Key *key if (freek4) MEM_freeN(freek4); } -static float *get_weights_array(Object *ob, char *vgroup) +static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cache) { MDeformVert *dvert = NULL; BMEditMesh *em = NULL; @@ -1091,7 +1086,21 @@ static float *get_weights_array(Object *ob, char *vgroup) if (defgrp_index != -1) { float *weights; int i; - + + if (cache) { + if (cache->defgroup_weights == NULL) { + int num_defgroup = BLI_countlist(&ob->defbase); + cache->defgroup_weights = + MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup, + "cached defgroup weights"); + cache->num_defgroup_weights = num_defgroup; + } + + if (cache->defgroup_weights[defgrp_index]) { + return cache->defgroup_weights[defgrp_index]; + } + } + weights = MEM_mallocN(totvert * sizeof(float), "weights"); if (em) { @@ -1107,11 +1116,61 @@ static float *get_weights_array(Object *ob, char *vgroup) } } + if (cache) { + cache->defgroup_weights[defgrp_index] = weights; + } + return weights; } return NULL; } +float **BKE_keyblock_get_per_block_weights(Object *ob, Key *key, WeightsArrayCache *cache) +{ + KeyBlock *keyblock; + float **per_keyblock_weights; + int keyblock_index; + + per_keyblock_weights = + MEM_mallocN(sizeof(*per_keyblock_weights) * key->totkey, + "per keyblock weights"); + + for (keyblock = key->block.first, keyblock_index = 0; + keyblock; + keyblock = keyblock->next, keyblock_index++) + { + per_keyblock_weights[keyblock_index] = get_weights_array(ob, keyblock->vgroup, cache); + } + + return per_keyblock_weights; +} + +void BKE_keyblock_free_per_block_weights(Key *key, float **per_keyblock_weights, WeightsArrayCache *cache) +{ + int a; + + if (cache) { + if (cache->num_defgroup_weights) { + for (a = 0; a < cache->num_defgroup_weights; a++) { + if (cache->defgroup_weights[a]) { + MEM_freeN(cache->defgroup_weights[a]); + } + } + MEM_freeN(cache->defgroup_weights); + } + cache->defgroup_weights = NULL; + } + else { + for (a = 0; a < key->totkey; a++) { + if (per_keyblock_weights[a]) { + MEM_freeN(per_keyblock_weights[a]); + } + } + } + + MEM_freeN(per_keyblock_weights); +} + static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int tot) { KeyBlock *k[4], *actkb = BKE_keyblock_from_object(ob); @@ -1144,17 +1203,11 @@ static void do_mesh_key(Scene *scene, Object *ob, Key *key, char *out, const int } else { if (key->type == KEY_RELATIVE) { - KeyBlock *kb; - for (kb = key->block.first; kb; kb = kb->next) { - kb->weights = get_weights_array(ob, kb->vgroup); - } - - BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, KEY_MODE_DUMMY); - - for (kb = key->block.first; kb; kb = kb->next) { - if (kb->weights) MEM_freeN(kb->weights); - kb->weights = NULL; - } + WeightsArrayCache cache = {0, NULL}; + float **per_keyblock_weights; + per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, &cache); + BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY); + BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, &cache); } else { const float ctime_scaled = key->ctime / 100.0f; @@ -1197,11 +1250,11 @@ static void do_rel_cu_key(Curve *cu, Key *key, KeyBlock *actkb, char *out, const for (a = 0, nu = cu->nurb.first; nu; nu = nu->next, a += step) { if (nu->bp) { step = nu->pntsu * nu->pntsv; - BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BPOINT); + BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, NULL, KEY_MODE_BPOINT); } else if (nu->bezt) { step = 3 * nu->pntsu; - BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, KEY_MODE_BEZTRIPLE); + BKE_key_evaluate_relative(a, a + step, tot, out, key, actkb, NULL, KEY_MODE_BEZTRIPLE); } else { step = 0; @@ -1315,17 +1368,10 @@ static void do_latt_key(Scene *scene, Object *ob, Key *key, char *out, const int } else { if (key->type == KEY_RELATIVE) { - KeyBlock *kb; - - for (kb = key->block.first; kb; kb = kb->next) - kb->weights = get_weights_array(ob, kb->vgroup); - - BKE_key_evaluate_relative(0, tot, tot, out, key, actkb, KEY_MODE_DUMMY); - - for (kb = key->block.first; kb; kb = kb->next) { - if (kb->weights) MEM_freeN(kb->weights); - kb->weights = NULL; - } + float **per_keyblock_weights; + per_keyblock_weights = BKE_keyblock_get_per_block_weights(ob, key, NULL); + BKE_key_evaluate_relative(0, tot, tot, (char *)out, key, actkb, per_keyblock_weights, KEY_MODE_DUMMY); + BKE_keyblock_free_per_block_weights(key, per_keyblock_weights, NULL); } else { const float ctime_scaled = key->ctime / 100.0f; @@ -1415,7 +1461,7 @@ float *BKE_key_evaluate_object_ex(Scene *scene, Object *ob, int *r_totelem, } if (OB_TYPE_SUPPORT_VGROUP(ob->type)) { - float *weights = get_weights_array(ob, kb->vgroup); + float *weights = get_weights_array(ob, kb->vgroup, NULL); cp_key(0, tot, tot, out, key, actkb, kb, weights, 0); diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index a4892253c63..60b4db6aa9b 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -51,6 +51,7 @@ #include "BKE_animsys.h" #include "BKE_anim.h" #include "BKE_cdderivedmesh.h" +#include "BKE_curve.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_key.h" @@ -164,7 +165,7 @@ void BKE_lattice_resize(Lattice *lt, int uNew, int vNew, int wNew, Object *ltOb) lt->typeu = lt->typev = lt->typew = KEY_LINEAR; /* prevent using deformed locations */ - BKE_displist_free(<Ob->disp); + BKE_displist_free(<Ob->curve_cache->disp); copy_m4_m4(mat, ltOb->obmat); unit_m4(ltOb->obmat); @@ -306,37 +307,46 @@ void BKE_lattice_make_local(Lattice *lt) } } -void init_latt_deform(Object *oblatt, Object *ob) +typedef struct LatticeDeformData { + Object *object; + float *latticedata; + float latmat[4][4]; +} LatticeDeformData; + +LatticeDeformData *init_latt_deform(Object *oblatt, Object *ob) { /* we make an array with all differences */ Lattice *lt = oblatt->data; BPoint *bp; - DispList *dl = BKE_displist_find(&oblatt->disp, DL_VERTS); + DispList *dl = oblatt->curve_cache ? BKE_displist_find(&oblatt->curve_cache->disp, DL_VERTS) : NULL; float *co = dl ? dl->verts : NULL; float *fp, imat[4][4]; float fu, fv, fw; int u, v, w; + float *latticedata; + float latmat[4][4]; + LatticeDeformData *lattice_deform_data; if (lt->editlatt) lt = lt->editlatt->latt; bp = lt->def; - fp = lt->latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw, "latticedata"); + fp = latticedata = MEM_mallocN(sizeof(float) * 3 * lt->pntsu * lt->pntsv * lt->pntsw, "latticedata"); /* for example with a particle system: (ob == NULL) */ if (ob == NULL) { /* in deformspace, calc matrix */ - invert_m4_m4(lt->latmat, oblatt->obmat); + invert_m4_m4(latmat, oblatt->obmat); /* back: put in deform array */ - invert_m4_m4(imat, lt->latmat); + invert_m4_m4(imat, latmat); } else { /* in deformspace, calc matrix */ invert_m4_m4(imat, oblatt->obmat); - mul_m4_m4m4(lt->latmat, imat, ob->obmat); + mul_m4_m4m4(latmat, imat, ob->obmat); /* back: put in deform array */ - invert_m4_m4(imat, lt->latmat); + invert_m4_m4(imat, latmat); } for (w = 0, fw = lt->fw; w < lt->pntsw; w++, fw += lt->dw) { @@ -357,10 +367,18 @@ void init_latt_deform(Object *oblatt, Object *ob) } } } + + lattice_deform_data = MEM_mallocN(sizeof(LatticeDeformData), "Lattice Deform Data"); + lattice_deform_data->latticedata = latticedata; + lattice_deform_data->object = oblatt; + copy_m4_m4(lattice_deform_data->latmat, latmat); + + return lattice_deform_data; } -void calc_latt_deform(Object *ob, float co[3], float weight) +void calc_latt_deform(LatticeDeformData *lattice_deform_data, float co[3], float weight) { + Object *ob = lattice_deform_data->object; Lattice *lt = ob->data; float u, v, w, tu[4], tv[4], tw[4]; float vec[3]; @@ -374,7 +392,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight) if (lt->editlatt) lt = lt->editlatt->latt; - if (lt->latticedata == NULL) return; + if (lattice_deform_data->latticedata == NULL) return; if (lt->vgroup[0] && dvert) { defgrp_index = defgroup_name_index(ob, lt->vgroup); @@ -382,7 +400,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight) } /* co is in local coords, treat with latmat */ - mul_v3_m4v3(vec, lt->latmat, co); + mul_v3_m4v3(vec, lattice_deform_data->latmat, co); /* u v w coords */ @@ -455,7 +473,7 @@ void calc_latt_deform(Object *ob, float co[3], float weight) idx_u = idx_v; } - madd_v3_v3fl(co, <->latticedata[idx_u * 3], u); + madd_v3_v3fl(co, &lattice_deform_data->latticedata[idx_u * 3], u); if (defgrp_index != -1) weight_blend += (u * defvert_find_weight(dvert + idx_u, defgrp_index)); @@ -471,15 +489,12 @@ void calc_latt_deform(Object *ob, float co[3], float weight) } -void end_latt_deform(Object *ob) +void end_latt_deform(LatticeDeformData *lattice_deform_data) { - Lattice *lt = ob->data; - - if (lt->editlatt) lt = lt->editlatt->latt; - - if (lt->latticedata) - MEM_freeN(lt->latticedata); - lt->latticedata = NULL; + if (lattice_deform_data->latticedata) + MEM_freeN(lattice_deform_data->latticedata); + + MEM_freeN(lattice_deform_data); } /* calculations is in local space of deformed object @@ -506,13 +521,12 @@ static void init_curve_deform(Object *par, Object *ob, CurveDeform *cd) */ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir[3], float quat[4], float *radius) { - Curve *cu = ob->data; BevList *bl; float ctime1; int cycl = 0; /* test for cyclic */ - bl = cu->bev.first; + bl = ob->curve_cache->bev.first; if (!bl->nr) return 0; if (bl->poly > -1) cycl = 1; @@ -527,7 +541,7 @@ static int where_on_path_deform(Object *ob, float ctime, float vec[4], float dir if (where_on_path(ob, ctime1, vec, dir, quat, radius, NULL)) { if (cycl == 0) { - Path *path = cu->path; + Path *path = ob->curve_cache->path; float dvec[3]; if (ctime < 0.0f) { @@ -565,9 +579,9 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3], const int is_neg_axis = (axis > 2); /* to be sure, mostly after file load */ - if (cu->path == NULL) { + if (ELEM(NULL, par->curve_cache, par->curve_cache->path)) { BKE_displist_make_curveTypes(scene, par, 0); - if (cu->path == NULL) return 0; // happens on append... + if (par->curve_cache->path == NULL) return 0; // happens on append... } /* options */ @@ -576,14 +590,14 @@ static int calc_curve_deform(Scene *scene, Object *par, float co[3], if (cu->flag & CU_STRETCH) fac = (-co[index] - cd->dmax[index]) / (cd->dmax[index] - cd->dmin[index]); else - fac = -(co[index] - cd->dmax[index]) / (cu->path->totdist); + fac = -(co[index] - cd->dmax[index]) / (par->curve_cache->path->totdist); } else { index = axis; if (cu->flag & CU_STRETCH) fac = (co[index] - cd->dmin[index]) / (cd->dmax[index] - cd->dmin[index]); else - fac = +(co[index] - cd->dmin[index]) / (cu->path->totdist); + fac = +(co[index] - cd->dmin[index]) / (par->curve_cache->path->totdist); } if (where_on_path_deform(par, fac, loc, dir, new_quat, &radius)) { /* returns OK */ @@ -815,13 +829,14 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, const char *vgroup, float fac) { + LatticeDeformData *lattice_deform_data; int a; int use_vgroups; if (laOb->type != OB_LATTICE) return; - init_latt_deform(laOb, target); + lattice_deform_data = init_latt_deform(laOb, target); /* check whether to use vertex groups (only possible if target is a Mesh) * we want either a Mesh with no derived data, or derived data with @@ -855,16 +870,16 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, weight = defvert_find_weight(dvert, defgrp_index); if (weight > 0.0f) - calc_latt_deform(laOb, vertexCos[a], weight * fac); + calc_latt_deform(lattice_deform_data, vertexCos[a], weight * fac); } } } else { for (a = 0; a < numVerts; a++) { - calc_latt_deform(laOb, vertexCos[a], fac); + calc_latt_deform(lattice_deform_data, vertexCos[a], fac); } } - end_latt_deform(laOb); + end_latt_deform(lattice_deform_data); } int object_deform_mball(Object *ob, ListBase *dispbase) @@ -991,11 +1006,17 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]) void BKE_lattice_modifiers_calc(Scene *scene, Object *ob) { Lattice *lt = ob->data; - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); float (*vertexCos)[3] = NULL; int numVerts, editmode = (lt->editlatt != NULL); - BKE_displist_free(&ob->disp); + if (ob->curve_cache) { + BKE_displist_free(&ob->curve_cache->disp); + } + else { + ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for lattice"); + } for (; md; md = md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1021,7 +1042,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob) dl->nr = numVerts; dl->verts = (float *) vertexCos; - BLI_addtail(&ob->disp, dl); + BLI_addtail(&ob->curve_cache->disp, dl); } } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index a7bfb15c99d..afd725f55fe 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -1402,7 +1402,7 @@ void BKE_mask_update_deform(Mask *mask) int j; for (j = 0; j <= 2; j += 2) { /* (0, 2) */ - printf("--- %d %d, %d, %d\n", i, j, i_prev, i_next); + // printf("--- %d %d, %d, %d\n", i, j, i_prev, i_next); barycentric_weights_v2(bezt_prev->vec[1], bezt->vec[1], bezt_next->vec[1], bezt->vec[j], w_src); interp_v3_v3v3v3(bezt_def->vec[j], diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index ac48eaa3185..874e60936d1 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -82,17 +82,10 @@ #include "BLI_rect.h" #include "BLI_listbase.h" #include "BLI_linklist.h" +#include "BLI_strict_flags.h" #include "BKE_mask.h" -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif - /* this is rather and annoying hack, use define to isolate it. * problem is caused by scanfill removing edges on us. */ #define USE_SCANFILL_EDGE_WORKAROUND @@ -575,11 +568,14 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas const float zvec[3] = {0.0f, 0.0f, 1.0f}; MaskLayer *masklay; unsigned int masklay_index; + MemArena *sf_arena; mr_handle->layers_tot = (unsigned int)BLI_countlist(&mask->masklayers); mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, "MaskRasterLayer"); BLI_rctf_init_minmax(&mr_handle->bounds); + sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); + for (masklay = mask->masklayers.first, masklay_index = 0; masklay; masklay = masklay->next, masklay_index++) { /* we need to store vertex ranges for open splines for filling */ @@ -613,7 +609,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas tot_splines = (unsigned int)BLI_countlist(&masklay->splines); open_spline_ranges = MEM_callocN(sizeof(*open_spline_ranges) * tot_splines, __func__); - BLI_scanfill_begin(&sf_ctx); + BLI_scanfill_begin_arena(&sf_ctx, sf_arena); for (spline = masklay->splines.first; spline; spline = spline->next) { const unsigned int is_cyclic = (spline->flag & MASK_SPLINE_CYCLIC) != 0; @@ -1148,8 +1144,10 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas } /* add trianges */ - BLI_scanfill_end(&sf_ctx); + BLI_scanfill_end_arena(&sf_ctx, sf_arena); } + + BLI_memarena_free(sf_arena); } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index c23b4ac4408..f3dc64a7279 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -1291,7 +1291,9 @@ int object_remove_material_slot(Object *ob) /* check indices from mesh */ if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { material_data_index_remove_id((ID *)ob->data, actcol - 1); - BKE_displist_free(&ob->disp); + if (ob->curve_cache) { + BKE_displist_free(&ob->curve_cache->disp); + } } return TRUE; diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 173b193b752..a4b59153e2b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -56,6 +56,7 @@ /* #include "BKE_object.h" */ #include "BKE_animsys.h" +#include "BKE_curve.h" #include "BKE_scene.h" #include "BKE_library.h" #include "BKE_displist.h" @@ -199,7 +200,6 @@ void BKE_mball_free(MetaBall *mb) mb->adt = NULL; } if (mb->mat) MEM_freeN(mb->mat); - if (mb->bb) MEM_freeN(mb->bb); BLI_freelistN(&mb->elems); if (mb->disp.first) BKE_displist_free(&mb->disp); } @@ -233,7 +233,6 @@ MetaBall *BKE_mball_copy(MetaBall *mb) for (a = 0; a < mbn->totcol; a++) { id_us_plus((ID *)mbn->mat[a]); } - mbn->bb = MEM_dupallocN(mb->bb); mbn->editelems = NULL; mbn->lastelem = NULL; @@ -366,7 +365,7 @@ void BKE_mball_texspace_calc(Object *ob) (min)[0] = (min)[1] = (min)[2] = 1.0e30f; (max)[0] = (max)[1] = (max)[2] = -1.0e30f; - dl = ob->disp.first; + dl = ob->curve_cache->disp.first; while (dl) { tot = dl->nr; if (tot) do_it = TRUE; @@ -2281,7 +2280,7 @@ static void mball_count(PROCESS *process, Scene *scene, Object *basis) } } -void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) +void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase, bool for_render) { MetaBall *mb; DispList *dl; @@ -2294,7 +2293,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) mball_count(&process, scene, ob); if (process.totelem == 0) return; - if ((G.is_rendering == FALSE) && (mb->flag == MB_UPDATE_NEVER)) return; + if ((for_render == false) && (mb->flag == MB_UPDATE_NEVER)) return; if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; process.thresh = mb->thresh; @@ -2332,7 +2331,7 @@ void BKE_mball_polygonize(Scene *scene, Object *ob, ListBase *dispbase) } /* width is size per polygonize cube */ - if (G.is_rendering) { + if (for_render) { width = mb->rendersize; } else { diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 0db1f92f70f..459f7216d00 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -46,6 +46,7 @@ #include "BLI_utildefines.h" #include "BLI_blenlib.h" +#include "BLI_memarena.h" #include "BLI_math.h" #include "BLI_edgehash.h" #include "BLI_bitmap.h" @@ -177,8 +178,8 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 if (l1->type == CD_MEDGE) { MEdge *e1 = l1->data; MEdge *e2 = l2->data; - EdgeHash *eh = BLI_edgehash_new(); int etot = m1->totedge; + EdgeHash *eh = BLI_edgehash_new_ex(__func__, etot); for (j = 0; j < etot; j++, e1++) { BLI_edgehash_insert(eh, e1->v1, e1->v2, e1); @@ -657,6 +658,8 @@ void BKE_mesh_boundbox_calc(Mesh *me, float r_loc[3], float r_size[3]) r_size[2] = (max[2] - min[2]) / 2.0f; BKE_boundbox_init_from_minmax(bb, min, max); + + bb->flag &= ~BOUNDBOX_DIRTY; } void BKE_mesh_texspace_calc(Mesh *me) @@ -686,15 +689,16 @@ BoundBox *BKE_mesh_boundbox_get(Object *ob) if (ob->bb) return ob->bb; - if (!me->bb) + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(me); + } return me->bb; } void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]) { - if (!me->bb) { + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(me); } @@ -908,7 +912,7 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *alll MPoly *mpoly; MFace *mface; MEdge *medge, *med; - EdgeHash *hash = BLI_edgehash_new(); + EdgeHash *hash; struct EdgeSort *edsort, *ed; int a, totedge = 0; unsigned int totedge_final = 0; @@ -985,6 +989,7 @@ static void make_edges_mdata(MVert *UNUSED(allvert), MFace *allface, MLoop *alll MEM_freeN(edsort); /* set edge members of mloops */ + hash = BLI_edgehash_new_ex(__func__, totedge_final); for (edge_index = 0, med = medge; edge_index < totedge_final; edge_index++, med++) { BLI_edgehash_insert(hash, med->v1, med->v2, SET_UINT_IN_POINTER(edge_index)); } @@ -1237,10 +1242,12 @@ static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge, int totedge = *r_totedge; int totedge_new; EdgeHash *eh; + unsigned int eh_reserve; const MPoly *mp; int i; - eh = BLI_edgehash_new(); + eh_reserve = max_ii(totedge, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly)); + eh = BLI_edgehash_new_ex(__func__, eh_reserve); for (i = 0, mp = mpoly; i < totpoly; i++, mp++) { BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart); @@ -1307,7 +1314,13 @@ int BKE_mesh_nurbs_to_mdata(Object *ob, MVert **allvert, int *totvert, MEdge **alledge, int *totedge, MLoop **allloop, MPoly **allpoly, int *totloop, int *totpoly) { - return BKE_mesh_nurbs_displist_to_mdata(ob, &ob->disp, + ListBase disp = {NULL, NULL}; + + if (ob->curve_cache) { + disp = ob->curve_cache->disp; + } + + return BKE_mesh_nurbs_displist_to_mdata(ob, &disp, allvert, totvert, alledge, totedge, allloop, allpoly, NULL, @@ -1653,8 +1666,13 @@ void BKE_mesh_from_nurbs(Object *ob) { Curve *cu = (Curve *) ob->data; bool use_orco_uv = (cu->flag & CU_UV_ORCO) != 0; + ListBase disp = {NULL, NULL}; + + if (ob->curve_cache) { + disp = ob->curve_cache->disp; + } - BKE_mesh_from_nurbs_displist(ob, &ob->disp, use_orco_uv); + BKE_mesh_from_nurbs_displist(ob, &disp, use_orco_uv); } typedef struct EdgeLink { @@ -1914,6 +1932,21 @@ void BKE_mesh_smooth_flag_set(Object *meshOb, int enableSmooth) } } +/** + * Call when there are no polygons. + */ +static void mesh_calc_normals_vert_fallback(MVert *mverts, int numVerts) +{ + int i; + for (i = 0; i < numVerts; i++) { + MVert *mv = &mverts[i]; + float no[3]; + + normalize_v3_v3(no, mv->co); + normal_float_to_short_v3(mv->no, no); + } +} + void BKE_mesh_calc_normals_mapping(MVert *mverts, int numVerts, MLoop *mloop, MPoly *mpolys, int numLoops, int numPolys, float (*polyNors_r)[3], MFace *mfaces, int numFaces, int *origIndexFace, float (*faceNors_r)[3]) @@ -1935,6 +1968,9 @@ void BKE_mesh_calc_normals_mapping_ex(MVert *mverts, int numVerts, MPoly *mp; if (numPolys == 0) { + if (only_face_normals == FALSE) { + mesh_calc_normals_vert_fallback(mverts, numVerts); + } return; } @@ -2293,7 +2329,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData CustomData_external_read(fdata, id, CD_MASK_MDISPS, totface_i); } - eh = BLI_edgehash_new(); + eh = BLI_edgehash_new_ex(__func__, totedge_i); /* build edge hash */ me = medge; @@ -2698,6 +2734,7 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, ScanFillContext sf_ctx; ScanFillVert *sf_vert, *sf_vert_last, *sf_vert_first; ScanFillFace *sf_tri; + MemArena *sf_arena = NULL; int *mface_to_poly_map; int lindex[4]; /* only ever use 3 in this case */ int poly_index, j, mface_index; @@ -2780,7 +2817,11 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, #endif ml = mloop + mp->loopstart; - BLI_scanfill_begin(&sf_ctx); + if (UNLIKELY(sf_arena == NULL)) { + sf_arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); + } + + BLI_scanfill_begin_arena(&sf_ctx, sf_arena); sf_vert_first = NULL; sf_vert_last = NULL; for (j = 0; j < mp->totloop; j++, ml++) { @@ -2832,12 +2873,17 @@ int BKE_mesh_recalc_tessellation(CustomData *fdata, mface_index++; } - BLI_scanfill_end(&sf_ctx); + BLI_scanfill_end_arena(&sf_ctx, sf_arena); #undef USE_TESSFACE_CALCNORMAL } } + if (sf_arena) { + BLI_memarena_free(sf_arena); + sf_arena = NULL; + } + CustomData_free(fdata, totface); totface = mface_index; @@ -3266,19 +3312,21 @@ static float mesh_calc_poly_planar_area_centroid(MPoly *mpoly, MLoop *loopstart, * Calculate smooth groups from sharp edges. * * \param r_totgroup The total number of groups, 1 or more. - * \return Polygon aligned array of group index values (starting at 1) + * \return Polygon aligned array of group index values (bitflags if use_bitflags is true), starting at 1. */ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop, - int *r_totgroup) + int *r_totgroup, const bool use_bitflags) { int *poly_groups; int *poly_stack; - STACK_DECLARE(poly_stack); int poly_prev = 0; - int poly_group_id = 0; + const int temp_poly_group_id = 3; /* Placeholder value. */ + const int poly_group_id_overflowed = 5; /* Group we could not find any available bit, will be reset to 0 at end */ + int tot_group = 0; + bool group_id_overflow = false; /* map vars */ MeshElemMap *edge_poly_map; @@ -3297,10 +3345,11 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, poly_groups = MEM_callocN(sizeof(int) * totpoly, __func__); poly_stack = MEM_mallocN(sizeof(int) * totpoly, __func__); - STACK_INIT(poly_stack); - while (true) { int poly; + int bit_poly_group_mask = 0; + int poly_group_id; + int ps_curr_idx = 0, ps_end_idx = 0; /* stack indices */ for (poly = poly_prev; poly < totpoly; poly++) { if (poly_groups[poly] == 0) { @@ -3313,40 +3362,88 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, break; } + poly_group_id = use_bitflags ? temp_poly_group_id : ++tot_group; + /* start searching from here next time */ poly_prev = poly + 1; - /* group starts at 1 */ - poly_group_id++; - poly_groups[poly] = poly_group_id; - STACK_PUSH(poly_stack, poly); - - while ((poly = STACK_POP_ELSE(poly_stack, -1)) != -1) { + poly_stack[ps_end_idx++] = poly; - const MPoly *mp = &mpoly[poly]; + while (ps_curr_idx != ps_end_idx) { + const MPoly *mp; const MLoop *ml; - int j = mp->totloop; + int j; + poly = poly_stack[ps_curr_idx++]; BLI_assert(poly_groups[poly] == poly_group_id); - for (ml = &mloop[mp->loopstart]; j--; ml++) { + mp = &mpoly[poly]; + for (ml = &mloop[mp->loopstart], j = mp->totloop; j--; ml++) { + /* loop over poly users */ + const MeshElemMap *map_ele = &edge_poly_map[ml->e]; + int *p = map_ele->indices; + int i = map_ele->count; if (!(medge[ml->e].flag & ME_SHARP)) { - /* loop over poly users */ - const MeshElemMap *map_ele = &edge_poly_map[ml->e]; - int *p = map_ele->indices; - int i = map_ele->count; - for (; i--; p++) { /* if we meet other non initialized its a bug */ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); if (poly_groups[*p] == 0) { poly_groups[*p] = poly_group_id; - STACK_PUSH(poly_stack, *p); + poly_stack[ps_end_idx++] = *p; } } } + else if (use_bitflags) { + /* Find contiguous smooth groups already assigned, these are the values we can't reuse! */ + for (; i--; p++) { + int bit = poly_groups[*p]; + if (!ELEM3(bit, 0, poly_group_id, poly_group_id_overflowed) && + !(bit_poly_group_mask & bit)) + { + bit_poly_group_mask |= bit; + } + } + } + } + } + /* And now, we have all our poly from current group in poly_stack (from 0 to (ps_end_idx - 1)), as well as + * all smoothgroups bits we can't use in bit_poly_group_mask. + */ + if (use_bitflags) { + int i, *p, gid_bit = 0; + poly_group_id = 1; + + /* Find first bit available! */ + for (; (poly_group_id & bit_poly_group_mask) && (gid_bit < 32); gid_bit++) { + poly_group_id <<= 1; /* will 'overflow' on last possible iteration. */ + } + if (UNLIKELY(gid_bit > 31)) { + /* All bits used in contiguous smooth groups, we can't do much! + * Note: this is *very* unlikely - theoretically, four groups are enough, I don't think we can reach + * this goal with such a simple algo, but I don't think either we'll never need all 32 groups! + */ + printf("Warning, could not find an available id for current smooth group, faces will me marked " + "as out of any smooth group...\n"); + poly_group_id = poly_group_id_overflowed; /* Can't use 0, will have to set them to this value later. */ + group_id_overflow = true; + } + if (gid_bit > tot_group) { + tot_group = gid_bit; + } + /* And assign the final smooth group id to that poly group! */ + for (i = ps_end_idx, p = poly_stack; i--; p++) { + poly_groups[*p] = poly_group_id; + } + } + } + + if (UNLIKELY(group_id_overflow)) { + int i = totpoly, *gid = poly_groups; + for (; i--; gid++) { + if (*gid == poly_group_id_overflowed) { + *gid = 0; } } } @@ -3355,9 +3452,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, MEM_freeN(edge_poly_mem); MEM_freeN(poly_stack); - STACK_FREE(poly_stack); - - *r_totgroup = poly_group_id; + *r_totgroup = tot_group + 1; return poly_groups; } @@ -3653,7 +3748,7 @@ void BKE_mesh_flush_select_from_verts(Mesh *me) /* basic vertex data functions */ -int BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3]) +bool BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3]) { int i = me->totvert; MVert *mvert; @@ -3664,7 +3759,7 @@ int BKE_mesh_minmax(Mesh *me, float r_min[3], float r_max[3]) return (me->totvert != 0); } -int BKE_mesh_center_median(Mesh *me, float cent[3]) +bool BKE_mesh_center_median(Mesh *me, float cent[3]) { int i = me->totvert; MVert *mvert; @@ -3680,19 +3775,19 @@ int BKE_mesh_center_median(Mesh *me, float cent[3]) return (me->totvert != 0); } -int BKE_mesh_center_bounds(Mesh *me, float cent[3]) +bool BKE_mesh_center_bounds(Mesh *me, float cent[3]) { float min[3], max[3]; INIT_MINMAX(min, max); if (BKE_mesh_minmax(me, min, max)) { mid_v3_v3v3(cent, min, max); - return 1; + return true; } - return 0; + return false; } -int BKE_mesh_center_centroid(Mesh *me, float cent[3]) +bool BKE_mesh_center_centroid(Mesh *me, float cent[3]) { int i = me->totpoly; MPoly *mpoly; @@ -3714,6 +3809,11 @@ int BKE_mesh_center_centroid(Mesh *me, float cent[3]) mul_v3_fl(cent, 1.0f / total_area); } + /* zero area faces cause this, fallback to median */ + if (UNLIKELY(!is_finite_v3(cent))) { + return BKE_mesh_center_median(me, cent); + } + return (me->totpoly != 0); } @@ -3830,9 +3930,7 @@ void BKE_mesh_poly_edgehash_insert(EdgeHash *ehash, const MPoly *mp, const MLoop ml = &ml_next[i - 1]; /* last loop */ while (i-- != 0) { - if (!BLI_edgehash_haskey(ehash, ml->v, ml_next->v)) { - BLI_edgehash_insert(ehash, ml->v, ml_next->v, NULL); - } + BLI_edgehash_reinsert(ehash, ml->v, ml_next->v, NULL); ml = ml_next; ml_next++; diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 2eced15a147..b5056f75bf9 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -182,16 +182,28 @@ static int search_polyloop_cmp(const void *v1, const void *v2) return sp1->loopstart > sp2->loopstart ? 1 : sp1->loopstart < sp2->loopstart ? -1 : 0; } -#define PRINT if (do_verbose) printf - -int BKE_mesh_validate_arrays(Mesh *mesh, - MVert *mverts, unsigned int totvert, - MEdge *medges, unsigned int totedge, - MFace *mfaces, unsigned int totface, - MLoop *mloops, unsigned int totloop, - MPoly *mpolys, unsigned int totpoly, - MDeformVert *dverts, /* assume totvert length */ - const bool do_verbose, const bool do_fixes) +#define PRINT_MSG(...) (void) \ + ( \ + ((do_verbose) ? printf(__VA_ARGS__) : 0)) + +#define PRINT_ERR(...) (void) \ + (is_valid = false, \ + ((do_verbose) ? printf(__VA_ARGS__) : 0)) + +/** + * Validate the mesh, \a do_fixes requires \a mesh to be non-null. + * + * \return false if no changes needed to be made. + */ +bool BKE_mesh_validate_arrays(Mesh *mesh, + MVert *mverts, unsigned int totvert, + MEdge *medges, unsigned int totedge, + MFace *mfaces, unsigned int totface, + MLoop *mloops, unsigned int totloop, + MPoly *mpolys, unsigned int totpoly, + MDeformVert *dverts, /* assume totvert length */ + const bool do_verbose, const bool do_fixes, + bool *r_change) { # define REMOVE_EDGE_TAG(_me) { _me->v2 = _me->v1; do_edge_free = true; } (void)0 # define IS_REMOVED_EDGE(_me) (_me->v2 == _me->v1) @@ -206,6 +218,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh, unsigned int i, j; int *v; + bool is_valid = true; + bool do_edge_free = false; bool do_face_free = false; bool do_polyloop_free = false; /* This regroups loops and polys! */ @@ -216,15 +230,15 @@ int BKE_mesh_validate_arrays(Mesh *mesh, bool do_edge_recalc = false; - EdgeHash *edge_hash = BLI_edgehash_new(); + EdgeHash *edge_hash = BLI_edgehash_new_ex(__func__, totedge); BLI_assert(!(do_fixes && mesh == NULL)); - PRINT("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n", - __func__, totvert, totedge, totloop, totpoly); + PRINT_MSG("%s: verts(%u), edges(%u), loops(%u), polygons(%u)\n", + __func__, totvert, totedge, totloop, totpoly); if (totedge == 0 && totpoly != 0) { - PRINT("\tLogical error, %u polygons and 0 edges\n", totpoly); + PRINT_ERR("\tLogical error, %u polygons and 0 edges\n", totpoly); do_edge_recalc = do_fixes; } @@ -233,7 +247,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, for (j = 0; j < 3; j++) { if (!finite(mv->co[j])) { - PRINT("\tVertex %u: has invalid coordinate\n", i); + PRINT_ERR("\tVertex %u: has invalid coordinate\n", i); if (do_fixes) { zero_v3(mv->co); @@ -247,7 +261,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } if (fix_normal) { - PRINT("\tVertex %u: has zero normal, assuming Z-up normal\n", i); + PRINT_ERR("\tVertex %u: has zero normal, assuming Z-up normal\n", i); if (do_fixes) { mv->no[2] = SHRT_MAX; verts_fixed = TRUE; @@ -258,21 +272,21 @@ int BKE_mesh_validate_arrays(Mesh *mesh, for (i = 0, me = medges; i < totedge; i++, me++) { int remove = FALSE; if (me->v1 == me->v2) { - PRINT("\tEdge %u: has matching verts, both %u\n", i, me->v1); + PRINT_ERR("\tEdge %u: has matching verts, both %u\n", i, me->v1); remove = do_fixes; } if (me->v1 >= totvert) { - PRINT("\tEdge %u: v1 index out of range, %u\n", i, me->v1); + PRINT_ERR("\tEdge %u: v1 index out of range, %u\n", i, me->v1); remove = do_fixes; } if (me->v2 >= totvert) { - PRINT("\tEdge %u: v2 index out of range, %u\n", i, me->v2); + PRINT_ERR("\tEdge %u: v2 index out of range, %u\n", i, me->v2); remove = do_fixes; } if (BLI_edgehash_haskey(edge_hash, me->v1, me->v2)) { - PRINT("\tEdge %u: is a duplicate of %d\n", i, - GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2))); + PRINT_ERR("\tEdge %u: is a duplicate of %d\n", i, + GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, me->v1, me->v2))); remove = do_fixes; } @@ -288,13 +302,13 @@ int BKE_mesh_validate_arrays(Mesh *mesh, # define REMOVE_FACE_TAG(_mf) { _mf->v3 = 0; do_face_free = TRUE; } (void)0 # define CHECK_FACE_VERT_INDEX(a, b) \ if (mf->a == mf->b) { \ - PRINT(" face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \ + PRINT_ERR(" face %u: verts invalid, " STRINGIFY(a) "/" STRINGIFY(b) " both %u\n", i, mf->a); \ remove = do_fixes; \ } (void)0 # define CHECK_FACE_EDGE(a, b) \ if (!BLI_edgehash_haskey(edge_hash, mf->a, mf->b)) { \ - PRINT(" face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \ - " (%u,%u) is missing edge data\n", i, mf->a, mf->b); \ + PRINT_ERR(" face %u: edge " STRINGIFY(a) "/" STRINGIFY(b) \ + " (%u,%u) is missing edge data\n", i, mf->a, mf->b); \ do_edge_recalc = TRUE; \ } (void)0 @@ -306,7 +320,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, SortFace *sf_prev; unsigned int totsortface = 0; - PRINT("No Polys, only tesselated Faces\n"); + PRINT_ERR("No Polys, only tesselated Faces\n"); for (i = 0, mf = mfaces, sf = sort_faces; i < totface; i++, mf++) { int remove = FALSE; @@ -317,7 +331,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, do { fv[fidx] = *(&(mf->v1) + fidx); if (fv[fidx] >= totvert) { - PRINT("\tFace %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]); + PRINT_ERR("\tFace %u: 'v%d' index out of range, %u\n", i, fidx + 1, fv[fidx]); remove = do_fixes; } } while (fidx--); @@ -394,14 +408,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh, mf_prev = mfaces + sf_prev->index; if (mf->v4) { - PRINT("\tFace %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n", - sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4, - mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); + PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u,%u) (%u,%u,%u,%u)\n", + sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, mf->v4, + mf_prev->v1, mf_prev->v2, mf_prev->v3, mf_prev->v4); } else { - PRINT("\tFace %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n", - sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, - mf_prev->v1, mf_prev->v2, mf_prev->v3); + PRINT_ERR("\tFace %u & %u: are duplicates (%u,%u,%u) (%u,%u,%u)\n", + sf->index, sf_prev->index, mf->v1, mf->v2, mf->v3, + mf_prev->v1, mf_prev->v2, mf_prev->v3); } } @@ -446,13 +460,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh, if (mp->loopstart < 0 || mp->totloop < 3) { /* Invalid loop data. */ - PRINT("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n", sp->index, mp->loopstart, mp->totloop); + PRINT_ERR("\tPoly %u is invalid (loopstart: %u, totloop: %u)\n", + sp->index, mp->loopstart, mp->totloop); sp->invalid = TRUE; } else if (mp->loopstart + mp->totloop > totloop) { /* Invalid loop data. */ - PRINT("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n", - sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1); + PRINT_ERR("\tPoly %u uses loops out of range (loopstart: %u, loopend: %u, max nbr of loops: %u)\n", + sp->index, mp->loopstart, mp->loopstart + mp->totloop - 1, totloop - 1); sp->invalid = TRUE; } else { @@ -467,7 +482,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++, v++) { if (ml->v >= totvert) { /* Invalid vert idx. */ - PRINT("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v); + PRINT_ERR("\tLoop %u has invalid vert reference (%u)\n", sp->loopstart + j, ml->v); sp->invalid = TRUE; } @@ -480,7 +495,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, v = sp->verts; for (j = 0; j < mp->totloop; j++, v++) { if ((mverts[*v].flag & ME_VERT_TMP_TAG) == 0) { - PRINT("\tPoly %u has duplicate vert reference at corner (%u)\n", i, j); + PRINT_ERR("\tPoly %u has duplicate vert reference at corner (%u)\n", i, j); sp->invalid = TRUE; } mverts[*v].flag &= ~ME_VERT_TMP_TAG; @@ -496,7 +511,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, v2 = mloops[sp->loopstart + (j + 1) % mp->totloop].v; if (!BLI_edgehash_haskey(edge_hash, v1, v2)) { /* Edge not existing. */ - PRINT("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2); + PRINT_ERR("\tPoly %u needs missing edge (%u, %u)\n", sp->index, v1, v2); if (do_fixes) do_edge_recalc = TRUE; else @@ -508,11 +523,11 @@ int BKE_mesh_validate_arrays(Mesh *mesh, if (do_fixes) { int prev_e = ml->e; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2)); - PRINT("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n", - sp->loopstart + j, prev_e, ml->e); + PRINT_ERR("\tLoop %u has invalid edge reference (%u), fixed using edge %u\n", + sp->loopstart + j, prev_e, ml->e); } else { - PRINT("\tLoop %u has invalid edge reference (%u)\n", sp->loopstart + j, ml->e); + PRINT_ERR("\tLoop %u has invalid edge reference (%u)\n", sp->loopstart + j, ml->e); sp->invalid = TRUE; } } @@ -524,11 +539,11 @@ int BKE_mesh_validate_arrays(Mesh *mesh, if (do_fixes) { int prev_e = ml->e; ml->e = GET_INT_FROM_POINTER(BLI_edgehash_lookup(edge_hash, v1, v2)); - PRINT("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n", - sp->index, prev_e, ml->e); + PRINT_ERR("\tPoly %u has invalid edge reference (%u), fixed using edge %u\n", + sp->index, prev_e, ml->e); } else { - PRINT("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e); + PRINT_ERR("\tPoly %u has invalid edge reference (%u)\n", sp->index, ml->e); sp->invalid = TRUE; } } @@ -546,16 +561,16 @@ int BKE_mesh_validate_arrays(Mesh *mesh, if (*v != *prev_v) { int dlt = v - prev_v; if (dlt > 1) { - PRINT("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n", - sp->index, *prev_v, dlt); + PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n", + sp->index, *prev_v, dlt); sp->invalid = TRUE; } prev_v = v; } } if (v - prev_v > 1) { /* Don't forget final verts! */ - PRINT("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n", - sp->index, *prev_v, (int)(v - prev_v)); + PRINT_ERR("\tPoly %u is invalid, it multi-uses vertex %u (%u times)\n", + sp->index, *prev_v, (int)(v - prev_v)); sp->invalid = TRUE; } } @@ -633,11 +648,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } if ((p1_nv == p2_nv) && (memcmp(p1_v, p2_v, p1_nv * sizeof(*p1_v)) == 0)) { if (do_verbose) { - PRINT("\tPolys %u and %u use same vertices (%u", - prev_sp->index, sp->index, *p1_v); + PRINT_ERR("\tPolys %u and %u use same vertices (%u", + prev_sp->index, sp->index, *p1_v); for (j = 1; j < p1_nv; j++) - PRINT(", %u", p1_v[j]); - PRINT("), considering poly %u as invalid.\n", sp->index); + PRINT_ERR(", %u", p1_v[j]); + PRINT_ERR("), considering poly %u as invalid.\n", sp->index); + } + else { + is_valid = false; } sp->invalid = TRUE; } @@ -673,7 +691,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, /* Unused loops. */ if (prev_end < sp->loopstart) { for (j = prev_end, ml = &mloops[prev_end]; j < sp->loopstart; j++, ml++) { - PRINT("\tLoop %u is unused.\n", j); + PRINT_ERR("\tLoop %u is unused.\n", j); if (do_fixes) REMOVE_LOOP_TAG(ml); } @@ -682,8 +700,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } /* Multi-used loops. */ else if (prev_end > sp->loopstart) { - PRINT("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n", - prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index); + PRINT_ERR("\tPolys %u and %u share loops from %u to %u, considering poly %u as invalid.\n", + prev_sp->index, sp->index, sp->loopstart, prev_end, sp->index); if (do_fixes) { REMOVE_POLY_TAG((&mpolys[sp->index])); /* DO NOT REMOVE ITS LOOPS!!! @@ -701,7 +719,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, /* We may have some remaining unused loops to get rid of! */ if (prev_end < totloop) { for (j = prev_end, ml = &mloops[prev_end]; j < totloop; j++, ml++) { - PRINT("\tLoop %u is unused.\n", j); + PRINT_ERR("\tLoop %u is unused.\n", j); if (do_fixes) REMOVE_LOOP_TAG(ml); } @@ -721,14 +739,14 @@ int BKE_mesh_validate_arrays(Mesh *mesh, for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) { /* note, greater then max defgroups is accounted for in our code, but not < 0 */ if (!finite(dw->weight)) { - PRINT("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight); + PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight); if (do_fixes) { dw->weight = 0.0f; vert_weights_fixed = TRUE; } } else if (dw->weight < 0.0f || dw->weight > 1.0f) { - PRINT("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight); + PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight); if (do_fixes) { CLAMP(dw->weight, 0.0f, 1.0f); vert_weights_fixed = TRUE; @@ -736,7 +754,7 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } if (dw->def_nr < 0) { - PRINT("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr); + PRINT_ERR("\tVertex deform %u, has invalid group %d\n", i, dw->def_nr); if (do_fixes) { defvert_remove_group(dv, dw); if (dv->dw) { @@ -787,8 +805,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh, int tot_elem = 0; if (msel->index < 0) { - PRINT("\tMesh select element %d type %d index is negative, " - "resetting selection stack.\n", i, msel->type); + PRINT_ERR("\tMesh select element %d type %d index is negative, " + "resetting selection stack.\n", i, msel->type); free_msel = TRUE; break; } @@ -806,8 +824,8 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } if (msel->index > tot_elem) { - PRINT("\tMesh select element %d type %d index %d is larger than data array size %d, " - "resetting selection stack.\n", i, msel->type, msel->index, tot_elem); + PRINT_ERR("\tMesh select element %d type %d index %d is larger than data array size %d, " + "resetting selection stack.\n", i, msel->type, msel->index, tot_elem); free_msel = TRUE; break; @@ -821,29 +839,49 @@ int BKE_mesh_validate_arrays(Mesh *mesh, } } - PRINT("%s: finished\n\n", __func__); + PRINT_MSG("%s: finished\n\n", __func__); + + *r_change = (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed); - return (verts_fixed || vert_weights_fixed || do_polyloop_free || do_edge_free || do_edge_recalc || msel_fixed); + return is_valid; } -static int mesh_validate_customdata(CustomData *data, const bool do_verbose, const bool do_fixes) +static bool mesh_validate_customdata(CustomData *data, CustomDataMask mask, + const bool do_verbose, const bool do_fixes, + bool *r_change) { - int i = 0, has_fixes = 0; + bool is_valid = true; + bool has_fixes = false; + int i = 0; - PRINT("%s: Checking %d CD layers...\n", __func__, data->totlayer); + PRINT_MSG("%s: Checking %d CD layers...\n", __func__, data->totlayer); while (i < data->totlayer) { CustomDataLayer *layer = &data->layers[i]; - CustomDataMask mask = CD_TYPE_AS_MASK(layer->type); - int ok = 1; + bool ok = true; + + if (CustomData_layertype_is_singleton(layer->type)) { + const int layer_tot = CustomData_number_of_layers(data, layer->type); + if (layer_tot > 1) { + PRINT_ERR("\tCustomDataLayer type %d is a singleton, found %d in Mesh structure\n", + layer->type, layer_tot); + ok = false; + } + } - if ((mask & CD_MASK_MESH) == 0) { - PRINT("\tCustomDataLayer type %d which isn't in CD_MASK_MESH is stored in Mesh structure\n", layer->type); + if (mask != 0) { + CustomDataMask layer_typemask = CD_TYPE_AS_MASK(layer->type); + if ((layer_typemask & mask) == 0) { + PRINT_ERR("\tCustomDataLayer type %d which isn't in the mask\n", + layer->type); + ok = false; + } + } + if (ok == false) { if (do_fixes) { CustomData_free_layer(data, layer->type, 0, i); - ok = 0; - has_fixes = 1; + has_fixes = true; } } @@ -851,62 +889,76 @@ static int mesh_validate_customdata(CustomData *data, const bool do_verbose, con i++; } - PRINT("%s: Finished\n\n", __func__); + PRINT_MSG("%s: Finished (is_valid=%d)\n\n", __func__, (int)!has_fixes); - return has_fixes; + *r_change = has_fixes; + + return is_valid; } #undef PRINT -static int BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, - CustomData *ldata, CustomData *pdata, - const bool do_verbose, const short do_fixes) +/** + * \returns is_valid. + */ +bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, + CustomData *ldata, CustomData *pdata, + const bool check_meshmask, + const bool do_verbose, const bool do_fixes, + bool *r_change) { - int vfixed = 0, efixed = 0, lfixed = 0, pfixed = 0; + bool is_valid = true; + bool is_change_v, is_change_e, is_change_l, is_change_p; + CustomDataMask mask = check_meshmask ? CD_MASK_MESH : 0; + + is_valid &= mesh_validate_customdata(vdata, mask, do_verbose, do_fixes, &is_change_v); + is_valid &= mesh_validate_customdata(edata, mask, do_verbose, do_fixes, &is_change_e); + is_valid &= mesh_validate_customdata(ldata, mask, do_verbose, do_fixes, &is_change_l); + is_valid &= mesh_validate_customdata(pdata, mask, do_verbose, do_fixes, &is_change_p); - vfixed = mesh_validate_customdata(vdata, do_verbose, do_fixes); - efixed = mesh_validate_customdata(edata, do_verbose, do_fixes); - lfixed = mesh_validate_customdata(ldata, do_verbose, do_fixes); - pfixed = mesh_validate_customdata(pdata, do_verbose, do_fixes); + *r_change = (is_change_v || is_change_e || is_change_l || is_change_p); - return vfixed || efixed || lfixed || pfixed; + return is_valid; } +/** + * \see #DM_is_valid to call on derived meshes + * + * \returns true if a change is made. + */ int BKE_mesh_validate(Mesh *me, const int do_verbose) { - int layers_fixed = 0, arrays_fixed = 0; + bool is_valid = true; + bool is_change; if (do_verbose) { printf("MESH: %s\n", me->id.name + 2); } - layers_fixed = BKE_mesh_validate_all_customdata(&me->vdata, &me->edata, &me->ldata, &me->pdata, do_verbose, TRUE); - arrays_fixed = BKE_mesh_validate_arrays(me, - me->mvert, me->totvert, - me->medge, me->totedge, - me->mface, me->totface, - me->mloop, me->totloop, - me->mpoly, me->totpoly, - me->dvert, - do_verbose, true); - - if (layers_fixed || arrays_fixed) { + is_valid &= BKE_mesh_validate_all_customdata( + &me->vdata, &me->edata, &me->ldata, &me->pdata, + true, + do_verbose, true, + &is_change); + + is_valid &= BKE_mesh_validate_arrays( + me, + me->mvert, me->totvert, + me->medge, me->totedge, + me->mface, me->totface, + me->mloop, me->totloop, + me->mpoly, me->totpoly, + me->dvert, + do_verbose, true, + &is_change); + + if (is_change) { DAG_id_tag_update(&me->id, OB_RECALC_DATA); return true; } - return false; -} - -int BKE_mesh_validate_dm(DerivedMesh *dm) -{ - return BKE_mesh_validate_arrays(NULL, - dm->getVertArray(dm), dm->getNumVerts(dm), - dm->getEdgeArray(dm), dm->getNumEdges(dm), - dm->getTessFaceArray(dm), dm->getNumTessFaces(dm), - dm->getLoopArray(dm), dm->getNumLoops(dm), - dm->getPolyArray(dm), dm->getNumPolys(dm), - dm->getVertDataArray(dm, CD_MDEFORMVERT), - TRUE, FALSE); + else { + return false; + } } /** @@ -921,7 +973,8 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select) EdgeHashIterator *ehi; MPoly *mp; MEdge *med, *med_orig; - EdgeHash *eh = BLI_edgehash_new(); + EdgeHash *eh; + unsigned int eh_reserve; int i, totedge, totpoly = mesh->totpoly; int med_index; /* select for newly created meshes which are selected [#25595] */ @@ -930,6 +983,9 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select) if (mesh->totedge == 0) update = false; + eh_reserve = max_ii(update ? mesh->totedge : 0, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly)); + eh = BLI_edgehash_new_ex(__func__, eh_reserve); + if (update) { /* assume existing edges are valid * useful when adding more faces and generating edges from them */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 41e0acf9f7a..780bd9733f5 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -69,19 +69,44 @@ #include "MOD_modifiertypes.h" -ModifierTypeInfo *modifierType_getInfo(ModifierType type) +static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL}; +static VirtualModifierData virtualModifierCommonData; + +void BKE_modifier_init(void) { - static ModifierTypeInfo *types[NUM_MODIFIER_TYPES] = {NULL}; - static int types_init = 1; + ModifierData *md; - if (types_init) { - modifier_type_init(types); /* MOD_utils.c */ - types_init = 0; - } + /* Initialize modifier types */ + modifier_type_init(modifier_types); /* MOD_utils.c */ + + /* Initialize global cmmon storage used for virtual modifier list */ + md = modifier_new(eModifierType_Armature); + virtualModifierCommonData.amd = *((ArmatureModifierData *) md); + modifier_free(md); + + md = modifier_new(eModifierType_Curve); + virtualModifierCommonData.cmd = *((CurveModifierData *) md); + modifier_free(md); + md = modifier_new(eModifierType_Lattice); + virtualModifierCommonData.lmd = *((LatticeModifierData *) md); + modifier_free(md); + + md = modifier_new(eModifierType_ShapeKey); + virtualModifierCommonData.smd = *((ShapeKeyModifierData *) md); + modifier_free(md); + + virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual; + virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual; + virtualModifierCommonData.lmd.modifier.mode |= eModifierMode_Virtual; + virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual; +} + +ModifierTypeInfo *modifierType_getInfo(ModifierType type) +{ /* type unsigned, no need to check < 0 */ - if (type < NUM_MODIFIER_TYPES && types[type]->name[0] != '\0') { - return types[type]; + if (type < NUM_MODIFIER_TYPES && modifier_types[type]->name[0] != '\0') { + return modifier_types[type]; } else { return NULL; @@ -289,7 +314,8 @@ void modifier_setError(ModifierData *md, const char *_format, ...) */ int modifiers_getCageIndex(struct Scene *scene, Object *ob, int *lastPossibleCageIndex_r, int virtual_) { - ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob) : ob->modifiers.first; + VirtualModifierData virtualModifierData; + ModifierData *md = (virtual_) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : ob->modifiers.first; int i, cageIndex = -1; if (lastPossibleCageIndex_r) { @@ -435,74 +461,43 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in /* NOTE: This is to support old files from before Blender supported modifiers, * in some cases versioning code updates these so for new files this will * return an empty list. */ -ModifierData *modifiers_getVirtualModifierList(Object *ob) +ModifierData *modifiers_getVirtualModifierList(Object *ob, VirtualModifierData *virtualModifierData) { - /* Kinda hacky, but should be fine since we are never - * re-entrant and avoid free hassles. - */ - static ArmatureModifierData amd; - static CurveModifierData cmd; - static LatticeModifierData lmd; - static ShapeKeyModifierData smd; - static int init = 1; ModifierData *md; - if (init) { - md = modifier_new(eModifierType_Armature); - amd = *((ArmatureModifierData *) md); - modifier_free(md); - - md = modifier_new(eModifierType_Curve); - cmd = *((CurveModifierData *) md); - modifier_free(md); - - md = modifier_new(eModifierType_Lattice); - lmd = *((LatticeModifierData *) md); - modifier_free(md); - - md = modifier_new(eModifierType_ShapeKey); - smd = *((ShapeKeyModifierData *) md); - modifier_free(md); - - amd.modifier.mode |= eModifierMode_Virtual; - cmd.modifier.mode |= eModifierMode_Virtual; - lmd.modifier.mode |= eModifierMode_Virtual; - smd.modifier.mode |= eModifierMode_Virtual; - - init = 0; - } - md = ob->modifiers.first; + *virtualModifierData = virtualModifierCommonData; + if (ob->parent) { if (ob->parent->type == OB_ARMATURE && ob->partype == PARSKEL) { - amd.object = ob->parent; - amd.modifier.next = md; - amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag; - md = &amd.modifier; + virtualModifierData->amd.object = ob->parent; + virtualModifierData->amd.modifier.next = md; + virtualModifierData->amd.deformflag = ((bArmature *)(ob->parent->data))->deformflag; + md = &virtualModifierData->amd.modifier; } else if (ob->parent->type == OB_CURVE && ob->partype == PARSKEL) { - cmd.object = ob->parent; - cmd.defaxis = ob->trackflag + 1; - cmd.modifier.next = md; - md = &cmd.modifier; + virtualModifierData->cmd.object = ob->parent; + virtualModifierData->cmd.defaxis = ob->trackflag + 1; + virtualModifierData->cmd.modifier.next = md; + md = &virtualModifierData->cmd.modifier; } else if (ob->parent->type == OB_LATTICE && ob->partype == PARSKEL) { - lmd.object = ob->parent; - lmd.modifier.next = md; - md = &lmd.modifier; + virtualModifierData->lmd.object = ob->parent; + virtualModifierData->lmd.modifier.next = md; + md = &virtualModifierData->lmd.modifier; } } /* shape key modifier, not yet for curves */ if (ELEM(ob->type, OB_MESH, OB_LATTICE) && BKE_key_from_object(ob)) { if (ob->type == OB_MESH && (ob->shapeflag & OB_SHAPE_EDIT_MODE)) - smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage; + virtualModifierData->smd.modifier.mode |= eModifierMode_Editmode | eModifierMode_OnCage; else - smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage; + virtualModifierData->smd.modifier.mode &= ~eModifierMode_Editmode | eModifierMode_OnCage; - smd.modifier.next = md; - md = &smd.modifier; + virtualModifierData->smd.modifier.next = md; + md = &virtualModifierData->smd.modifier; } return md; @@ -513,7 +508,8 @@ ModifierData *modifiers_getVirtualModifierList(Object *ob) */ Object *modifiers_isDeformedByArmature(Object *ob) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); ArmatureModifierData *amd = NULL; /* return the first selected armature, this lets us use multiple armatures */ @@ -536,7 +532,8 @@ Object *modifiers_isDeformedByArmature(Object *ob) */ Object *modifiers_isDeformedByLattice(Object *ob) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); LatticeModifierData *lmd = NULL; /* return the first selected lattice, this lets us use multiple lattices */ @@ -559,7 +556,8 @@ Object *modifiers_isDeformedByLattice(Object *ob) */ Object *modifiers_isDeformedByCurve(Object *ob) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); CurveModifierData *cmd = NULL; /* return the first selected curve, this lets us use multiple curves */ @@ -579,7 +577,8 @@ Object *modifiers_isDeformedByCurve(Object *ob) bool modifiers_usesArmature(Object *ob, bArmature *arm) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { @@ -604,7 +603,8 @@ bool modifier_isCorrectableDeformed(ModifierData *md) bool modifiers_isCorrectableDeformed(Object *ob) { - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); for (; md; md = md->next) { if (ob->mode == OB_MODE_EDIT && (md->mode & eModifierMode_Editmode) == 0) { diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c index 290b0684e40..d1797810c86 100644 --- a/source/blender/blenkernel/intern/modifiers_bmesh.c +++ b/source/blender/blenkernel/intern/modifiers_bmesh.c @@ -52,7 +52,7 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, edges[j] = etable[ml->e]; } - return BM_face_create(bm, verts, edges, mp->totloop, BM_CREATE_SKIP_CD); + return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD); } /** diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c index 1d662ae3116..68564a1e298 100644 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ b/source/blender/blenkernel/intern/navmesh_conversion.c @@ -38,6 +38,7 @@ #include "BLI_utildefines.h" #include "BLI_math.h" +#include "BLI_sort.h" #include "BKE_navmesh_conversion.h" #include "BKE_cdderivedmesh.h" @@ -340,7 +341,7 @@ int buildNavMeshData(const int nverts, const float *verts, trisMapping[i] = i; context.recastData = recastData; context.trisToFacesMap = trisToFacesMap; - recast_qsort(trisMapping, ntris, sizeof(int), &context, compareByData); + BLI_qsort_r(trisMapping, ntris, sizeof(int), &context, compareByData); /* search first valid triangle - triangle of convex polygon */ validTriStart = -1; diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 1349c4dc8d4..ee5b11d3beb 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2666,7 +2666,7 @@ void BKE_node_instance_hash_clear(bNodeInstanceHash *hash, bNodeInstanceValueFP void *BKE_node_instance_hash_pop(bNodeInstanceHash *hash, bNodeInstanceKey key) { - return BLI_ghash_pop(hash->ghash, &key, NULL); + return BLI_ghash_popkey(hash->ghash, &key, NULL); } int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key) diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 962209bef87..6ffab678691 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -64,6 +64,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_linklist.h" +#include "BLI_kdtree.h" #include "BLF_translation.h" @@ -142,11 +143,9 @@ void BKE_object_update_base_layer(struct Scene *scene, Object *ob) void BKE_object_free_particlesystems(Object *ob) { - while (ob->particlesystem.first) { - ParticleSystem *psys = ob->particlesystem.first; - - BLI_remlink(&ob->particlesystem, psys); - + ParticleSystem *psys; + + while ((psys = BLI_pophead(&ob->particlesystem))) { psys_free(ob, psys); } } @@ -167,13 +166,24 @@ void BKE_object_free_bulletsoftbody(Object *ob) } } +void BKE_object_free_curve_cache(Object *ob) +{ + if (ob->curve_cache) { + BKE_displist_free(&ob->curve_cache->disp); + BLI_freelistN(&ob->curve_cache->bev); + if (ob->curve_cache->path) { + free_path(ob->curve_cache->path); + } + MEM_freeN(ob->curve_cache); + ob->curve_cache = NULL; + } +} + void BKE_object_free_modifiers(Object *ob) { - while (ob->modifiers.first) { - ModifierData *md = ob->modifiers.first; - - BLI_remlink(&ob->modifiers, md); - + ModifierData *md; + + while ((md = BLI_pophead(&ob->modifiers))) { modifier_free(md); } @@ -246,8 +256,14 @@ void BKE_object_free_derived_caches(Object *ob) Mesh *me = ob->data; if (me->bb) { - MEM_freeN(me->bb); - me->bb = NULL; + me->bb->flag |= BOUNDBOX_DIRTY; + } + } + else if (ELEM3(ob->type, OB_SURF, OB_CURVE, OB_FONT)) { + Curve *cu = ob->data; + + if (cu->bb) { + cu->bb->flag |= BOUNDBOX_DIRTY; } } @@ -267,7 +283,9 @@ void BKE_object_free_derived_caches(Object *ob) ob->derivedDeform = NULL; } - BKE_displist_free(&ob->disp); + if (ob->curve_cache) { + BKE_displist_free(&ob->curve_cache->disp); + } } /* do not free object itself */ @@ -337,6 +355,14 @@ void BKE_object_free(Object *ob) free_sculptsession(ob); if (ob->pc_ids.first) BLI_freelistN(&ob->pc_ids); + + /* Free runtime curves data. */ + if (ob->curve_cache) { + BLI_freelistN(&ob->curve_cache->bev); + if (ob->curve_cache->path) + free_path(ob->curve_cache->path); + MEM_freeN(ob->curve_cache); + } } static void unlink_object__unlinkModifierLinks(void *userData, Object *ob, Object **obpoin) @@ -1256,8 +1282,6 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches) for (a = 0; a < obn->totcol; a++) id_us_plus((ID *)obn->mat[a]); - obn->disp.first = obn->disp.last = NULL; - if (ob->pd) { obn->pd = MEM_dupallocN(ob->pd); if (obn->pd->tex) @@ -1279,7 +1303,10 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, int copy_caches) obn->pc_ids.first = obn->pc_ids.last = NULL; obn->mpath = NULL; - + + /* Copy runtime surve data. */ + obn->curve_cache = NULL; + return obn; } @@ -1772,9 +1799,9 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) unit_m4(mat); cu = par->data; - if (cu->path == NULL || cu->path->data == NULL) /* only happens on reload file, but violates depsgraph still... fix! */ + if (ELEM3(NULL, par->curve_cache, par->curve_cache->path, par->curve_cache->path->data)) /* only happens on reload file, but violates depsgraph still... fix! */ BKE_displist_make_curveTypes(scene, par, 0); - if (cu->path == NULL) return; + if (par->curve_cache->path == NULL) return; /* catch exceptions: feature for nla stride editing */ if (ob->ipoflag & OB_DISABLE_PATH) { @@ -1805,7 +1832,7 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) /* time calculus is correct, now apply distance offset */ if (cu->flag & CU_OFFS_PATHDIST) { - ctime += timeoffs / cu->path->totdist; + ctime += timeoffs / par->curve_cache->path->totdist; /* restore */ SWAP(float, sf_orig, ob->sf); @@ -1962,7 +1989,7 @@ static void give_parvert(Object *par, int nr, float vec[3]) } else if (par->type == OB_LATTICE) { Lattice *latt = par->data; - DispList *dl = BKE_displist_find(&par->disp, DL_VERTS); + DispList *dl = par->curve_cache ? BKE_displist_find(&par->curve_cache->disp, DL_VERTS) : NULL; float (*co)[3] = dl ? (float (*)[3])dl->verts : NULL; int tot; @@ -1986,29 +2013,23 @@ static void give_parvert(Object *par, int nr, float vec[3]) static void ob_parvert3(Object *ob, Object *par, float mat[4][4]) { - float cmat[3][3], v1[3], v2[3], v3[3], q[4]; /* in local ob space */ - unit_m4(mat); - - if (ELEM4(par->type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE)) { - + if (OB_TYPE_SUPPORT_PARVERT(par->type)) { + float cmat[3][3], v1[3], v2[3], v3[3], q[4]; + give_parvert(par, ob->par1, v1); give_parvert(par, ob->par2, v2); give_parvert(par, ob->par3, v3); - + tri_to_quat(q, v1, v2, v3); quat_to_mat3(cmat, q); copy_m4_m3(mat, cmat); - - if (ob->type == OB_CURVE) { - copy_v3_v3(mat[3], v1); - } - else { - add_v3_v3v3(mat[3], v1, v2); - add_v3_v3(mat[3], v3); - mul_v3_fl(mat[3], 1.0f / 3.0f); - } + + mid_v3_v3v3v3(mat[3], v1, v2, v3); + } + else { + unit_m4(mat); } } @@ -2291,7 +2312,7 @@ BoundBox *BKE_object_boundbox_get(Object *ob) bb = BKE_mesh_boundbox_get(ob); } else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - bb = ob->bb ? ob->bb : ((Curve *)ob->data)->bb; + bb = BKE_curve_boundbox_get(ob); } else if (ob->type == OB_MBALL) { bb = ob->bb; @@ -2360,18 +2381,7 @@ void BKE_object_minmax(Object *ob, float min_r[3], float max_r[3], const bool us case OB_FONT: case OB_SURF: { - Curve *cu = ob->data; - - /* Use the object bounding box so that modifier output - * gets taken into account */ - if (ob->bb) { - bb = *(ob->bb); - } - else { - if (cu->bb == NULL) - BKE_curve_texspace_calc(cu); - bb = *(cu->bb); - } + bb = *BKE_curve_boundbox_get(ob); for (a = 0; a < 8; a++) { mul_m4_v3(ob->obmat, bb.vec[a]); @@ -2519,10 +2529,10 @@ void BKE_object_foreach_display_point( func_cb(co, user_data); } } - else if (ob->disp.first) { + else if (ob->curve_cache && ob->curve_cache->disp.first) { DispList *dl; - for (dl = ob->disp.first; dl; dl = dl->next) { + for (dl = ob->curve_cache->disp.first; dl; dl = dl->next) { float *v3 = dl->verts; int totvert = dl->nr; int i; @@ -3158,8 +3168,9 @@ int BKE_object_is_modified(Scene *scene, Object *ob) } else { ModifierData *md; + VirtualModifierData virtualModifierData; /* cloth */ - for (md = modifiers_getVirtualModifierList(ob); + for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { @@ -3180,10 +3191,11 @@ int BKE_object_is_modified(Scene *scene, Object *ob) int BKE_object_is_deform_modified(Scene *scene, Object *ob) { ModifierData *md; + VirtualModifierData virtualModifierData; int flag = 0; /* cloth */ - for (md = modifiers_getVirtualModifierList(ob); + for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { @@ -3205,8 +3217,9 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) bool BKE_object_is_animated(Scene *scene, Object *ob) { ModifierData *md; + VirtualModifierData virtualModifierData; - for (md = modifiers_getVirtualModifierList(ob); md; md = md->next) + for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) if (modifier_dependsOnTime(md) && (modifier_isEnabled(scene, md, eModifierMode_Realtime) || modifier_isEnabled(scene, md, eModifierMode_Render))) @@ -3422,3 +3435,128 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) BKE_group_object_unlink(group, object, scene, base); } } + +/** + * Return a KDTree from the deformed object (in worldspace) + * + * \note Only mesh objects currently support deforming, others are TODO. + * + * \param ob + * \param r_tot + * \return The kdtree or NULL if it can't be created. + */ +KDTree *BKE_object_as_kdtree(Object *ob, int *r_tot) +{ + KDTree *tree = NULL; + unsigned int tot = 0; + float co[3]; + + switch (ob->type) { + case OB_MESH: + { + Mesh *me = ob->data; + unsigned int i; + + DerivedMesh *dm = ob->derivedDeform ? ob->derivedDeform : ob->derivedFinal; + int *index; + + if (dm && (index = CustomData_get_layer(&dm->vertData, CD_ORIGINDEX))) { + MVert *mvert = dm->getVertArray(dm); + unsigned int totvert = dm->getNumVerts(dm); + + /* tree over-allocs in case where some verts have ORIGINDEX_NONE */ + tot = 0; + tree = BLI_kdtree_new(totvert); + + /* we don't how how many verts from the DM we can use */ + for (i = 0; i < totvert; i++) { + if (index[i] != ORIGINDEX_NONE) { + mul_v3_m4v3(co, ob->obmat, mvert[i].co); + BLI_kdtree_insert(tree, index[i], co, NULL); + tot++; + } + } + } + else { + MVert *mvert = me->mvert; + + tot = me->totvert; + tree = BLI_kdtree_new(tot); + + for (i = 0; i < tot; i++) { + mul_v3_m4v3(co, ob->obmat, mvert[i].co); + BLI_kdtree_insert(tree, i, co, NULL); + } + } + + BLI_kdtree_balance(tree); + break; + } + case OB_CURVE: + case OB_SURF: + { + /* TODO: take deformation into account */ + Curve *cu = ob->data; + unsigned int i, a; + + Nurb *nu; + + tot = BKE_nurbList_verts_count_without_handles(&cu->nurb); + tree = BLI_kdtree_new(tot); + i = 0; + + nu = cu->nurb.first; + while (nu) { + if (nu->bezt) { + BezTriple *bezt; + + bezt = nu->bezt; + a = nu->pntsu; + while (a--) { + mul_v3_m4v3(co, ob->obmat, bezt->vec[1]); + BLI_kdtree_insert(tree, i++, co, NULL); + bezt++; + } + } + else { + BPoint *bp; + + bp = nu->bp; + a = nu->pntsu * nu->pntsv; + while (a--) { + mul_v3_m4v3(co, ob->obmat, bp->vec); + BLI_kdtree_insert(tree, i++, co, NULL); + bp++; + } + } + nu = nu->next; + } + + BLI_kdtree_balance(tree); + break; + } + case OB_LATTICE: + { + /* TODO: take deformation into account */ + Lattice *lt = ob->data; + BPoint *bp; + unsigned int i; + + tot = lt->pntsu * lt->pntsv * lt->pntsw; + tree = BLI_kdtree_new(tot); + i = 0; + + for (bp = lt->def; i < tot; bp++) { + float co[3]; + mul_v3_m4v3(co, ob->obmat, bp->vec); + BLI_kdtree_insert(tree, i++, co, NULL); + } + + BLI_kdtree_balance(tree); + break; + } + } + + *r_tot = tot; + return tree; +} diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index ca38aa42928..77c5e57f382 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -73,12 +73,13 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot) GHash *gh; int i, step1 = 1; //int defbase_tot = BLI_countlist(&ob->defbase); + VirtualModifierData virtualModifierData; if (ob->defbase.first == NULL) { return NULL; } - gh = BLI_ghash_str_new("BKE_objdef_validmap_get gh"); + gh = BLI_ghash_str_new_ex("BKE_objdef_validmap_get gh", defbase_tot); /* add all names to a hash table */ for (dg = ob->defbase.first; dg; dg = dg->next) { @@ -88,7 +89,7 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot) BLI_assert(BLI_ghash_size(gh) == defbase_tot); /* now loop through the armature modifiers and identify deform bones */ - for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob) : md->next) { + for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) { if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) continue; diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 6b754743c11..216bc94a058 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -221,12 +221,12 @@ Object *psys_find_object(Scene *scene, ParticleSystem *psys) } #endif -Object *psys_get_lattice(ParticleSimulationData *sim) +struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim) { - Object *lattice = NULL; - - if (psys_in_edit_mode(sim->scene, sim->psys) == 0) { + struct LatticeDeformData *lattice_deform_data = NULL; + if (psys_in_edit_mode(sim->scene, sim->psys) == 0) { + Object *lattice = NULL; ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys); for (; md; md = md->next) { @@ -237,10 +237,10 @@ Object *psys_get_lattice(ParticleSimulationData *sim) } } if (lattice) - init_latt_deform(lattice, NULL); + lattice_deform_data = init_latt_deform(lattice, NULL); } - return lattice; + return lattice_deform_data; } void psys_disable_all(Object *ob) { @@ -2513,7 +2513,7 @@ static int psys_threads_init_path(ParticleThread *threads, Scene *scene, float c ctx->cfra = cfra; ctx->editupdate = editupdate; - psys->lattice = psys_get_lattice(&ctx->sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim); /* cache all relevant vertex groups if they exist */ ctx->vg_length = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_LENGTH); @@ -2974,7 +2974,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) psys_free_path_cache(psys, psys->edit); cache = psys->pathcache = psys_alloc_path_cache_buffers(&psys->pathcachebufs, totpart, steps + 1); - psys->lattice = psys_get_lattice(sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(sim); ma = give_current_material(sim->ob, psys->part->omat); if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT)) copy_v3_v3(col, &ma->r); @@ -3079,9 +3079,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) } /* lattices have to be calculated separately to avoid mixups between effector calculations */ - if (psys->lattice) { + if (psys->lattice_deform_data) { for (k = 0, ca = cache[p]; k <= steps; k++, ca++) - calc_latt_deform(psys->lattice, ca->co, 1.0f); + calc_latt_deform(psys->lattice_deform_data, ca->co, 1.0f); } } @@ -3112,9 +3112,9 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra) psys->totcached = totpart; - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice = NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } if (vg_effector) @@ -4166,8 +4166,8 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * /* TODO: proper velocity handling */ } - if (psys->lattice && edit == 0) - calc_latt_deform(psys->lattice, state->co, 1.0f); + if (psys->lattice_deform_data && edit == 0) + calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f); } } } @@ -4402,8 +4402,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta unit_m4(mat); do_child_modifiers(sim, NULL, key1, key1->rot, cpa, cpa->fuv, mat, state, t); - if (psys->lattice) - calc_latt_deform(sim->psys->lattice, state->co, 1.0f); + if (psys->lattice_deform_data) + calc_latt_deform(psys->lattice_deform_data, state->co, 1.0f); } else { if (pa->state.time == cfra || ELEM(part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) @@ -4461,8 +4461,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta } } - if (sim->psys->lattice) - calc_latt_deform(sim->psys->lattice, state->co, 1.0f); + if (sim->psys->lattice_deform_data) + calc_latt_deform(sim->psys->lattice_deform_data, state->co, 1.0f); } return 1; @@ -4678,9 +4678,9 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) sim.psys = psys; sim.psmd = psys_get_modifier(ob, psys); - psys->lattice = psys_get_lattice(&sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - if (psys->lattice) { + if (psys->lattice_deform_data) { ParticleData *pa = psys->particles; HairKey *hkey; int p, h; @@ -4693,13 +4693,13 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) hkey = pa->hair; for (h = 0; h < pa->totkey; h++, hkey++) { mul_m4_v3(hairmat, hkey->co); - calc_latt_deform(psys->lattice, hkey->co, 1.0f); + calc_latt_deform(psys->lattice_deform_data, hkey->co, 1.0f); mul_m4_v3(imat, hkey->co); } } - end_latt_deform(psys->lattice); - psys->lattice = NULL; + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; /* protect the applied shape */ psys->flag |= PSYS_EDITED; diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 16ea71204cc..db22e030821 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -70,6 +70,7 @@ #include "BLI_blenlib.h" #include "BLI_kdtree.h" #include "BLI_kdopbvh.h" +#include "BLI_sort.h" #include "BLI_threads.h" #include "BLI_linklist.h" @@ -814,7 +815,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch psys_particle_on_dm(ctx->dm,from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co1,0,0,0,orco1,0); BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_find_n_nearest(ctx->tree,3,orco1,NULL,ptn); + maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,NULL,ptn,3); for (w=0; w<maxw; w++) { pa->verts[w]=ptn->num; @@ -939,7 +940,7 @@ static void distribute_threads_exec(ParticleThread *thread, ParticleData *pa, Ch psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL); BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1); - maxw = BLI_kdtree_find_n_nearest(ctx->tree,4,orco1,NULL,ptn); + maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,NULL,ptn,3); maxd=ptn[maxw-1].dist; /* mind=ptn[0].dist; */ /* UNUSED */ @@ -1010,12 +1011,11 @@ static void *distribute_threads_exec_cb(void *data) return 0; } -/* not thread safe, but qsort doesn't take userdata argument */ -static int *COMPARE_ORIG_INDEX = NULL; -static int distribute_compare_orig_index(const void *p1, const void *p2) +static int distribute_compare_orig_index(void *user_data, const void *p1, const void *p2) { - int index1 = COMPARE_ORIG_INDEX[*(const int *)p1]; - int index2 = COMPARE_ORIG_INDEX[*(const int *)p2]; + int *orig_index = (int *) user_data; + int index1 = orig_index[*(const int *)p1]; + int index2 = orig_index[*(const int *)p2]; if (index1 < index2) return -1; @@ -1332,20 +1332,19 @@ static int distribute_threads_init_data(ParticleThread *threads, Scene *scene, D /* For hair, sort by origindex (allows optimization's in rendering), */ /* however with virtual parents the children need to be in random order. */ if (part->type == PART_HAIR && !(part->childtype==PART_CHILD_FACES && part->parents!=0.0f)) { - COMPARE_ORIG_INDEX = NULL; + int *orig_index = NULL; if (from == PART_FROM_VERT) { if (dm->numVertData) - COMPARE_ORIG_INDEX= dm->getVertDataArray(dm, CD_ORIGINDEX); + orig_index = dm->getVertDataArray(dm, CD_ORIGINDEX); } else { if (dm->numTessFaceData) - COMPARE_ORIG_INDEX= dm->getTessFaceDataArray(dm, CD_ORIGINDEX); + orig_index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); } - if (COMPARE_ORIG_INDEX) { - qsort(particle_element, totpart, sizeof(int), distribute_compare_orig_index); - COMPARE_ORIG_INDEX = NULL; + if (orig_index) { + BLI_qsort_r(particle_element, totpart, sizeof(int), orig_index, distribute_compare_orig_index); } } @@ -1514,9 +1513,9 @@ void psys_threads_free(ParticleThread *threads) if (ctx->vg_roughe) MEM_freeN(ctx->vg_roughe); - if (ctx->sim.psys->lattice) { - end_latt_deform(ctx->sim.psys->lattice); - ctx->sim.psys->lattice= NULL; + if (ctx->sim.psys->lattice_deform_data) { + end_latt_deform(ctx->sim.psys->lattice_deform_data); + ctx->sim.psys->lattice_deform_data = NULL; } /* distribution */ @@ -2485,7 +2484,7 @@ static EdgeHash *sph_springhash_build(ParticleSystem *psys) ParticleSpring *spring; int i = 0; - springhash = BLI_edgehash_new(); + springhash = BLI_edgehash_new_ex(__func__, psys->tot_fluidsprings); for (i=0, spring=psys->fluid_springs; i<psys->tot_fluidsprings; i++, spring++) BLI_edgehash_insert(springhash, spring->particle_index[0], spring->particle_index[1], SET_INT_IN_POINTER(i+1)); @@ -4108,7 +4107,7 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) invert_m4_m4(ob->imat, ob->obmat); - psys->lattice= psys_get_lattice(sim); + psys->lattice_deform_data= psys_create_lattice_deform_data(sim); if (psys->totpart==0) return; @@ -4479,7 +4478,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) if (part->randsize > 0.0f) pa->size *= 1.0f - part->randsize * PSYS_FRAND(p + 1); - psys->lattice= psys_get_lattice(sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(sim); dietime = pa->dietime; @@ -4494,9 +4493,9 @@ static void cached_step(ParticleSimulationData *sim, float cfra) else pa->alive = PARS_ALIVE; - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice= NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } if (PSYS_FRAND(p) > disp) @@ -4777,9 +4776,9 @@ static void system_step(ParticleSimulationData *sim, float cfra) update_children(sim); /* cleanup */ - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice= NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 205159c94a1..45a29f6cc90 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -229,9 +229,10 @@ void pbvh_grow_nodes(PBVH *bvh, int totnode) bvh->node_mem_count *= 1.33; if (bvh->node_mem_count < totnode) bvh->node_mem_count = totnode; - bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count, + bvh->nodes = MEM_mallocN(sizeof(PBVHNode) * bvh->node_mem_count, "bvh nodes"); memcpy(bvh->nodes, prev, bvh->totnode * sizeof(PBVHNode)); + memset(bvh->nodes + bvh->totnode, 0, (bvh->node_mem_count - bvh->totnode) * sizeof(PBVHNode)); MEM_freeN(prev); } @@ -244,9 +245,13 @@ static int map_insert_vert(PBVH *bvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex) { - void *value, *key = SET_INT_IN_POINTER(vertex); + void *key, **value_p; - if (!BLI_ghash_haskey(map, key)) { + key = SET_INT_IN_POINTER(vertex); + value_p = BLI_ghash_lookup_p(map, key); + + if (value_p == NULL) { + void *value; if (BLI_BITMAP_GET(bvh->vert_bitmap, vertex)) { value = SET_INT_IN_POINTER(~(*face_verts)); ++(*face_verts); @@ -260,8 +265,9 @@ static int map_insert_vert(PBVH *bvh, GHash *map, BLI_ghash_insert(map, key, value); return GET_INT_FROM_POINTER(value); } - else - return GET_INT_FROM_POINTER(BLI_ghash_lookup(map, key)); + else { + return GET_INT_FROM_POINTER(*value_p); + } } /* Find vertices used by the faces in this node and update the draw buffers */ @@ -271,11 +277,12 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) GHash *map; int i, j, totface; - map = BLI_ghash_int_new("build_mesh_leaf_node gh"); - node->uniq_verts = node->face_verts = 0; totface = node->totprim; + /* reserve size is rough guess */ + map = BLI_ghash_int_new_ex("build_mesh_leaf_node gh", 2 * totface); + node->face_vert_indices = MEM_callocN(sizeof(int) * 4 * totface, "bvh node face vert indices"); @@ -607,9 +614,9 @@ void BKE_pbvh_free(PBVH *bvh) if (node->bm_faces) BLI_ghash_free(node->bm_faces, NULL, NULL); if (node->bm_unique_verts) - BLI_ghash_free(node->bm_unique_verts, NULL, NULL); + BLI_gset_free(node->bm_unique_verts, NULL); if (node->bm_other_verts) - BLI_ghash_free(node->bm_other_verts, NULL, NULL); + BLI_gset_free(node->bm_other_verts, NULL); } } @@ -1307,8 +1314,8 @@ void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *uniquevert, int *to if (uniquevert) *uniquevert = node->uniq_verts; break; case PBVH_BMESH: - tot = BLI_ghash_size(node->bm_unique_verts); - if (totvert) *totvert = tot + BLI_ghash_size(node->bm_other_verts); + tot = BLI_gset_size(node->bm_unique_verts); + if (totvert) *totvert = tot + BLI_gset_size(node->bm_other_verts); if (uniquevert) *uniquevert = tot; break; } @@ -1859,9 +1866,10 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, vi->mverts = verts; if (bvh->type == PBVH_BMESH) { - BLI_ghashIterator_init(&vi->bm_unique_verts, node->bm_unique_verts); - BLI_ghashIterator_init(&vi->bm_other_verts, node->bm_other_verts); + BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts); + BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts); vi->bm_vdata = &bvh->bm->vdata; + vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK); } vi->gh = NULL; diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c index 0e2e2bcfe19..29473fe64b7 100644 --- a/source/blender/blenkernel/intern/pbvh_bmesh.c +++ b/source/blender/blenkernel/intern/pbvh_bmesh.c @@ -48,8 +48,8 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) PBVHNode *n = &bvh->nodes[node_index]; /* Create vert hash sets */ - n->bm_unique_verts = BLI_ghash_ptr_new("bm_unique_verts"); - n->bm_other_verts = BLI_ghash_ptr_new("bm_other_verts"); + n->bm_unique_verts = BLI_gset_ptr_new("bm_unique_verts"); + n->bm_other_verts = BLI_gset_ptr_new("bm_other_verts"); BB_reset(&n->vb); @@ -67,13 +67,12 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) l_iter = l_first = BM_FACE_FIRST_LOOP(f); do { v = l_iter->v; - if (!BLI_ghash_haskey(n->bm_unique_verts, v)) { + if (!BLI_gset_haskey(n->bm_unique_verts, v)) { if (BLI_ghash_haskey(bvh->bm_vert_to_node, v)) { - if (!BLI_ghash_haskey(n->bm_other_verts, v)) - BLI_ghash_insert(n->bm_other_verts, v, NULL); + BLI_gset_reinsert(n->bm_other_verts, v, NULL); } else { - BLI_ghash_insert(n->bm_unique_verts, v, NULL); + BLI_gset_insert(n->bm_unique_verts, v); BLI_ghash_insert(bvh->bm_vert_to_node, v, node_val); } } @@ -92,7 +91,7 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh, int node_index) if (!G.background) { int smooth = bvh->flags & PBVH_DYNTOPO_SMOOTH_SHADING; n->draw_buffers = GPU_build_bmesh_buffers(smooth); - n->flag |= PBVH_UpdateDrawBuffers; + n->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals; } } @@ -101,6 +100,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) { GHash *empty, *other; GHashIterator gh_iter; + GSetIterator gs_iter; PBVHNode *n, *c1, *c2; BB cb; float mid; @@ -140,8 +140,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) c2 = &bvh->nodes[children + 1]; c1->flag |= PBVH_Leaf; c2->flag |= PBVH_Leaf; - c1->bm_faces = BLI_ghash_ptr_new("bm_faces"); - c2->bm_faces = BLI_ghash_ptr_new("bm_faces"); + c1->bm_faces = BLI_ghash_ptr_new_ex("bm_faces", BLI_ghash_size(n->bm_faces) / 2); + c2->bm_faces = BLI_ghash_ptr_new_ex("bm_faces", BLI_ghash_size(n->bm_faces) / 2); /* Partition the parent node's faces between the two children */ GHASH_ITER (gh_iter, n->bm_faces) { @@ -177,11 +177,11 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) /* Mark this node's unique verts as unclaimed */ if (n->bm_unique_verts) { - GHASH_ITER (gh_iter, n->bm_unique_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, n->bm_unique_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); } - BLI_ghash_free(n->bm_unique_verts, NULL, NULL); + BLI_gset_free(n->bm_unique_verts, NULL); } /* Unclaim faces */ @@ -192,7 +192,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) BLI_ghash_free(n->bm_faces, NULL, NULL); if (n->bm_other_verts) - BLI_ghash_free(n->bm_other_verts, NULL, NULL); + BLI_gset_free(n->bm_other_verts, NULL); if (n->layer_disp) MEM_freeN(n->layer_disp); @@ -227,19 +227,26 @@ static void pbvh_bmesh_node_split(PBVH *bvh, GHash *prim_bbc, int node_index) static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) { GHash *prim_bbc; + GHash *bm_faces; + int bm_faces_size; GHashIterator gh_iter; + BBC *bbc_array; + unsigned int i; - if (BLI_ghash_size(bvh->nodes[node_index].bm_faces) <= bvh->leaf_limit) { + bm_faces = bvh->nodes[node_index].bm_faces; + bm_faces_size = BLI_ghash_size(bm_faces); + if (bm_faces_size <= bvh->leaf_limit) { /* Node limit not exceeded */ return FALSE; } /* For each BMFace, store the AABB and AABB centroid */ - prim_bbc = BLI_ghash_ptr_new("prim_bbc"); + prim_bbc = BLI_ghash_ptr_new_ex("prim_bbc", bm_faces_size); + bbc_array = MEM_callocN(sizeof(BBC) * bm_faces_size, "BBC"); - GHASH_ITER (gh_iter, bvh->nodes[node_index].bm_faces) { + GHASH_ITER_INDEX (gh_iter, bm_faces, i) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); - BBC *bbc = MEM_callocN(sizeof(BBC), "BBC"); + BBC *bbc = &bbc_array[i]; BMLoop *l_iter; BMLoop *l_first; @@ -255,7 +262,8 @@ static int pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index) pbvh_bmesh_node_split(bvh, prim_bbc, node_index); - BLI_ghash_free(prim_bbc, NULL, MEM_freeN); + BLI_ghash_free(prim_bbc, NULL, NULL); + MEM_freeN(bbc_array); return TRUE; } @@ -278,12 +286,12 @@ static BMVert *pbvh_bmesh_vert_create(PBVH *bvh, int node_index, const float co[3], const BMVert *example) { - BMVert *v = BM_vert_create(bvh->bm, co, example, 0); + BMVert *v = BM_vert_create(bvh->bm, co, example, BM_CREATE_NOP); void *val = SET_INT_IN_POINTER(node_index); BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode); - BLI_ghash_insert(bvh->nodes[node_index].bm_unique_verts, v, NULL); + BLI_gset_insert(bvh->nodes[node_index].bm_unique_verts, v); BLI_ghash_insert(bvh->bm_vert_to_node, v, val); /* Log the new vertex */ @@ -302,9 +310,7 @@ static BMFace *pbvh_bmesh_face_create(PBVH *bvh, int node_index, /* ensure we never add existing face */ BLI_assert(BM_face_exists(v_tri, 3, NULL) == false); - f = BM_face_create(bvh->bm, v_tri, e_tri, 3, 0); - // BM_elem_attrs_copy(bvh->bm, bvh->bm, f_example, f); - f->mat_nr = f_example->mat_nr; + f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP); if (!BLI_ghash_haskey(bvh->bm_face_to_node, f)) { @@ -367,15 +373,14 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, BLI_assert(current_owner != new_owner); /* Remove current ownership */ - // BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); // assign handles below - BLI_ghash_remove(current_owner->bm_unique_verts, v, NULL, NULL); + BLI_gset_remove(current_owner->bm_unique_verts, v, NULL); /* Set new ownership */ - BLI_ghash_assign(bvh->bm_vert_to_node, v, - SET_INT_IN_POINTER(new_owner - bvh->nodes), NULL, NULL); - 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)); + BLI_ghash_reinsert(bvh->bm_vert_to_node, v, + SET_INT_IN_POINTER(new_owner - bvh->nodes), NULL, NULL); + BLI_gset_insert(new_owner->bm_unique_verts, v); + BLI_gset_remove(new_owner->bm_other_verts, v, NULL); + BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v)); } static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) @@ -386,18 +391,20 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v) BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); v_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_vert_to_node, v); - BLI_ghash_remove(v_node->bm_unique_verts, v, NULL, NULL); + BLI_gset_remove(v_node->bm_unique_verts, v, NULL); BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); /* Have to check each neighboring face's node */ BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) { PBVHNode *f_node = pbvh_bmesh_node_lookup(bvh, bvh->bm_face_to_node, f); - BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL); - BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL); + /* Remove current ownership */ + /* Should be handled above by vert_to_node removal, leaving just in case - psy-fi */ + //BLI_ghash_remove(f_node->bm_unique_verts, v, NULL, NULL); + BLI_gset_remove(f_node->bm_other_verts, v, NULL); - BLI_assert(!BLI_ghash_haskey(f_node->bm_unique_verts, v)); - BLI_assert(!BLI_ghash_haskey(f_node->bm_other_verts, v)); + BLI_assert(!BLI_gset_haskey(f_node->bm_unique_verts, v)); + BLI_assert(!BLI_gset_haskey(f_node->bm_other_verts, v)); } } @@ -417,7 +424,7 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) do { v = l_iter->v; if (pbvh_bmesh_node_vert_use_count(bvh, f_node, v) == 1) { - if (BLI_ghash_haskey(f_node->bm_unique_verts, v)) { + if (BLI_gset_haskey(f_node->bm_unique_verts, v)) { /* Find a different node that uses 'v' */ PBVHNode *new_node; @@ -427,10 +434,14 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f) if (new_node) { pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v); } + else { + BLI_gset_remove(f_node->bm_unique_verts, v, NULL); + BLI_ghash_remove(bvh->bm_vert_to_node, v, NULL, NULL); + } } else { /* Remove from other verts */ - BLI_ghash_remove(f_node->bm_other_verts, v, NULL, NULL); + BLI_gset_remove(f_node->bm_other_verts, v, NULL); } } } while ((l_iter = l_iter->next) != l_first); @@ -479,6 +490,13 @@ typedef struct { float limit_len_squared; } EdgeQueue; +typedef struct { + EdgeQueue *q; + BLI_mempool *pool; + BMesh *bm; + int cd_vert_mask_offset; +} EdgeQueueContext; + static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) { BMVert *v_tri[3]; @@ -495,16 +513,13 @@ static int edge_queue_tri_in_sphere(const EdgeQueue *q, BMFace *f) } /* Return true if the vertex mask is less than 0.5, false otherwise */ -static int check_mask_half(BMesh *bm, BMVert *v) +static bool check_mask_half(EdgeQueueContext *eq_ctx, BMVert *v) { - const float *mask; - - mask = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_PAINT_MASK); - return ((*mask) < 0.5f); + return (BM_ELEM_CD_GET_FLOAT(v, eq_ctx->cd_vert_mask_offset) < 0.5f); } -static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e, - float priority, BMesh *bm) +static void edge_queue_insert(EdgeQueueContext *eq_ctx, BMEdge *e, + float priority) { BMVert **pair; @@ -512,56 +527,56 @@ static void edge_queue_insert(EdgeQueue *q, BLI_mempool *pool, BMEdge *e, * 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); + if (check_mask_half(eq_ctx, e->v1) && check_mask_half(eq_ctx, e->v2)) { + pair = BLI_mempool_alloc(eq_ctx->pool); pair[0] = e->v1; pair[1] = e->v2; - BLI_heap_insert(q->heap, priority, pair); + BLI_heap_insert(eq_ctx->q->heap, priority, pair); } } -static void long_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, - BMEdge *e, BMesh *bm) +static void long_edge_queue_edge_add(EdgeQueueContext *eq_ctx, + BMEdge *e) { 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, bm); + if (len_sq > eq_ctx->q->limit_len_squared) + edge_queue_insert(eq_ctx, e, 1.0f / len_sq); } -static void short_edge_queue_edge_add(EdgeQueue *q, BLI_mempool *pool, - BMEdge *e, BMesh *bm) +static void short_edge_queue_edge_add(EdgeQueueContext *eq_ctx, + BMEdge *e) { 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, bm); + if (len_sq < eq_ctx->q->limit_len_squared) + edge_queue_insert(eq_ctx, e, len_sq); } -static void long_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f, BMesh *bm) +static void long_edge_queue_face_add(EdgeQueueContext *eq_ctx, + BMFace *f) { - if (edge_queue_tri_in_sphere(q, f)) { + if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; BMLoop *l_first; /* 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, bm); + long_edge_queue_edge_add(eq_ctx, l_iter->e); } while ((l_iter = l_iter->next) != l_first); } } -static void short_edge_queue_face_add(EdgeQueue *q, BLI_mempool *pool, - BMFace *f, BMesh *bm) +static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, + BMFace *f) { - if (edge_queue_tri_in_sphere(q, f)) { + if (edge_queue_tri_in_sphere(eq_ctx->q, f)) { BMLoop *l_iter; BMLoop *l_first; /* 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, bm); + short_edge_queue_edge_add(eq_ctx, l_iter->e); } while ((l_iter = l_iter->next) != l_first); } } @@ -575,16 +590,16 @@ 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, +static void long_edge_queue_create(EdgeQueueContext *eq_ctx, PBVH *bvh, const float center[3], float radius) { int n; - q->heap = BLI_heap_new(); - q->center = center; - q->radius_squared = radius * radius; - q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len; + eq_ctx->q->heap = BLI_heap_new(); + eq_ctx->q->center = center; + eq_ctx->q->radius_squared = radius * radius; + eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len; for (n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; @@ -599,7 +614,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, bvh->bm); + long_edge_queue_face_add(eq_ctx, f); } } } @@ -614,16 +629,16 @@ 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, +static void short_edge_queue_create(EdgeQueueContext *eq_ctx, PBVH *bvh, const float center[3], float radius) { int n; - q->heap = BLI_heap_new(); - q->center = center; - q->radius_squared = radius * radius; - q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; + eq_ctx->q->heap = BLI_heap_new(); + eq_ctx->q->center = center; + eq_ctx->q->radius_squared = radius * radius; + eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len; for (n = 0; n < bvh->totnode; n++) { PBVHNode *node = &bvh->nodes[n]; @@ -638,7 +653,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, bvh->bm); + short_edge_queue_face_add(eq_ctx, f); } } } @@ -653,7 +668,7 @@ static void bm_edges_from_tri(BMesh *bm, BMVert *v_tri[3], BMEdge *e_tri[3]) e_tri[2] = BM_edge_create(bm, v_tri[2], v_tri[0], NULL, BM_CREATE_NO_DOUBLE); } -static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, +static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx, PBVH *bvh, BMEdge *e, BLI_Buffer *edge_loops) { BMVert *v_new; @@ -686,7 +701,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, ni = GET_INT_FROM_POINTER(nip); /* Ensure node gets redrawn */ - bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers; + bvh->nodes[ni].flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals; /* Find the vertex not in the edge */ v_opp = l_adj->prev->v; @@ -706,7 +721,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, v_tri[2] = v_opp; bm_edges_from_tri(bvh->bm, v_tri, e_tri); f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj); - long_edge_queue_face_add(q, pool, f_new, bvh->bm); + long_edge_queue_face_add(eq_ctx, f_new); v_tri[0] = v_new; v_tri[1] = v2; @@ -715,17 +730,17 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, e_tri[2] = e_tri[1]; /* switched */ e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE); f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj); - long_edge_queue_face_add(q, pool, f_new, bvh->bm); + long_edge_queue_face_add(eq_ctx, f_new); /* Delete original */ pbvh_bmesh_face_remove(bvh, f_adj); BM_face_kill(bvh->bm, f_adj); /* Ensure new vertex is in the node */ - if (!BLI_ghash_haskey(bvh->nodes[ni].bm_unique_verts, v_new) && - !BLI_ghash_haskey(bvh->nodes[ni].bm_other_verts, v_new)) + if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new) && + !BLI_gset_haskey(bvh->nodes[ni].bm_other_verts, v_new)) { - BLI_ghash_insert(bvh->nodes[ni].bm_other_verts, v_new, NULL); + BLI_gset_insert(bvh->nodes[ni].bm_other_verts, v_new); } if (BM_vert_edge_count(v_opp) >= 9) { @@ -733,7 +748,7 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, BMEdge *e2; BM_ITER_ELEM (e2, &bm_iter, v_opp, BM_EDGES_OF_VERT) { - long_edge_queue_edge_add(q, pool, e2, bvh->bm); + long_edge_queue_edge_add(eq_ctx, e2); } } } @@ -741,23 +756,22 @@ static void pbvh_bmesh_split_edge(PBVH *bvh, EdgeQueue *q, BLI_mempool *pool, BM_edge_kill(bvh->bm, e); } -static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, - BLI_mempool *pool, +static int pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx, PBVH *bvh, BLI_Buffer *edge_loops) { int any_subdivided = FALSE; - while (!BLI_heap_is_empty(q->heap)) { - BMVert **pair = BLI_heap_popmin(q->heap); + while (!BLI_heap_is_empty(eq_ctx->q->heap)) { + BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap); BMEdge *e; /* Check that the edge still exists */ if (!(e = BM_edge_exists(pair[0], pair[1]))) { - BLI_mempool_free(pool, pair); + BLI_mempool_free(eq_ctx->pool, pair); continue; } - BLI_mempool_free(pool, pair); + BLI_mempool_free(eq_ctx->pool, pair); pair = NULL; /* Check that the edge's vertices are still in the PBVH. It's @@ -770,12 +784,12 @@ static int pbvh_bmesh_subdivide_long_edges(PBVH *bvh, EdgeQueue *q, continue; } - if (BM_edge_calc_length_squared(e) <= q->limit_len_squared) + if (BM_edge_calc_length_squared(e) <= eq_ctx->q->limit_len_squared) continue; any_subdivided = TRUE; - pbvh_bmesh_split_edge(bvh, q, pool, e, edge_loops); + pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops); } return any_subdivided; @@ -846,10 +860,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f); /* Ensure that v1 is in the new face's node */ - if (!BLI_ghash_haskey(n->bm_unique_verts, v1) && - !BLI_ghash_haskey(n->bm_other_verts, v1)) + if (!BLI_gset_haskey(n->bm_unique_verts, v1) && + !BLI_gset_haskey(n->bm_other_verts, v1)) { - BLI_ghash_insert(n->bm_other_verts, v1, NULL); + BLI_gset_insert(n->bm_other_verts, v1); } } @@ -917,8 +931,8 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh, BMEdge *e, BMVert *v1, BM_vert_kill(bvh->bm, v2); } -static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, - BLI_mempool *pool, +static int pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx, + PBVH *bvh, BLI_Buffer *edge_loops, BLI_Buffer *deleted_faces) { @@ -928,14 +942,14 @@ static int pbvh_bmesh_collapse_short_edges(PBVH *bvh, EdgeQueue *q, deleted_verts = BLI_ghash_ptr_new("deleted_verts"); - while (!BLI_heap_is_empty(q->heap)) { - BMVert **pair = BLI_heap_popmin(q->heap); + while (!BLI_heap_is_empty(eq_ctx->q->heap)) { + BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap); BMEdge *e; BMVert *v1, *v2; v1 = pair[0]; v2 = pair[1]; - BLI_mempool_free(pool, pair); + BLI_mempool_free(eq_ctx->pool, pair); pair = NULL; /* Check that the vertices/edge still exist */ @@ -1012,19 +1026,29 @@ int pbvh_bmesh_node_raycast(PBVHNode *node, const float ray_start[3], return hit; } + void pbvh_bmesh_normals_update(PBVHNode **nodes, int totnode) { int n; for (n = 0; n < totnode; n++) { PBVHNode *node = nodes[n]; - GHashIterator gh_iter; - GHASH_ITER (gh_iter, node->bm_faces) { - BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter)); - } - GHASH_ITER (gh_iter, node->bm_unique_verts) { - BM_vert_normal_update(BLI_ghashIterator_getKey(&gh_iter)); + if (node->flag & PBVH_UpdateNormals) { + GHashIterator gh_iter; + GSetIterator gs_iter; + + GHASH_ITER (gh_iter, node->bm_faces) { + BM_face_normal_update(BLI_ghashIterator_getKey(&gh_iter)); + } + GSET_ITER (gs_iter, node->bm_unique_verts) { + BM_vert_normal_update(BLI_gsetIterator_getKey(&gs_iter)); + } + /* This should be unneeded normally */ + GSET_ITER (gs_iter, node->bm_other_verts) { + BM_vert_normal_update(BLI_gsetIterator_getKey(&gs_iter)); + } + node->flag &= ~PBVH_UpdateNormals; } } } @@ -1059,7 +1083,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh, BMesh *bm, int smooth_shading, n = bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode"); bvh->totnode = 1; n->flag = PBVH_Leaf; - n->bm_faces = BLI_ghash_ptr_new("bm_faces"); + n->bm_faces = BLI_ghash_ptr_new_ex("bm_faces", bvh->bm->totface); BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) { BLI_ghash_insert(n->bm_faces, f, NULL); } @@ -1077,6 +1101,7 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, /* 2 is enough for edge faces - manifold edge */ BLI_buffer_declare_static(BMFace *, edge_loops, BLI_BUFFER_NOP, 2); BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32); + const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK); int modified = FALSE; int n; @@ -1085,8 +1110,10 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, 128, 128, 0); - short_edge_queue_create(&q, queue_pool, bvh, center, radius); - pbvh_bmesh_collapse_short_edges(bvh, &q, queue_pool, &edge_loops, + EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset}; + + short_edge_queue_create(&eq_ctx, bvh, center, radius); + pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &edge_loops, &deleted_faces); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); @@ -1096,8 +1123,10 @@ int BKE_pbvh_bmesh_update_topology(PBVH *bvh, PBVHTopologyUpdateMode mode, EdgeQueue q; BLI_mempool *queue_pool = BLI_mempool_create(sizeof(BMVert) * 2, 128, 128, 0); - long_edge_queue_create(&q, queue_pool, bvh, center, radius); - pbvh_bmesh_subdivide_long_edges(bvh, &q, queue_pool, &edge_loops); + EdgeQueueContext eq_ctx = {&q, queue_pool, bvh->bm, cd_vert_mask_offset}; + + long_edge_queue_create(&eq_ctx, bvh, center, radius); + pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops); BLI_heap_free(q.heap, NULL); BLI_mempool_destroy(queue_pool); } @@ -1136,14 +1165,15 @@ BLI_INLINE void bm_face_as_array_index_tri(BMFace *f, int r_index[3]) void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) { GHashIterator gh_iter; + GSetIterator gs_iter; int i, totvert, tottri; /* Skip if original coords/triangles are already saved */ if (node->bm_orco) return; - totvert = (BLI_ghash_size(node->bm_unique_verts) + - BLI_ghash_size(node->bm_other_verts)); + totvert = (BLI_gset_size(node->bm_unique_verts) + + BLI_gset_size(node->bm_other_verts)); tottri = BLI_ghash_size(node->bm_faces); @@ -1152,14 +1182,14 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node) /* Copy out the vertices and assign a temporary index */ i = 0; - GHASH_ITER (gh_iter, node->bm_unique_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, node->bm_unique_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); copy_v3_v3(node->bm_orco[i], v->co); BM_elem_index_set(v, i); /* set_dirty! */ i++; } - GHASH_ITER (gh_iter, node->bm_other_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, node->bm_other_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); copy_v3_v3(node->bm_orco[i], v->co); BM_elem_index_set(v, i); /* set_dirty! */ i++; @@ -1216,12 +1246,12 @@ void BKE_pbvh_node_mark_topology_update(PBVHNode *node) node->flag |= PBVH_UpdateTopology; } -GHash *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node) +GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node) { return node->bm_unique_verts; } -GHash *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node) +GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node) { return node->bm_other_verts; } @@ -1250,6 +1280,27 @@ void bli_ghash_duplicate_key_check(GHash *gh) } } +void bli_gset_duplicate_key_check(GSet *gs) +{ + GSetIterator gs_iter1, gs_iter2; + + GSET_ITER (gs_iter1, gs) { + void *key1 = BLI_gsetIterator_getKey(&gs_iter1); + int dup = -1; + + GSET_ITER (gs_iter2, gs) { + void *key2 = BLI_gsetIterator_getKey(&gs_iter2); + + if (key1 == key2) { + dup++; + if (dup > 0) { + BLI_assert(!"duplicate in hash"); + } + } + } + } +} + void bmesh_print(BMesh *bm) { BMIter iter, siter; @@ -1311,6 +1362,7 @@ void bmesh_print(BMesh *bm) void pbvh_bmesh_print(PBVH *bvh) { GHashIterator gh_iter; + GSetIterator gs_iter; int n; fprintf(stderr, "\npbvh=%p\n", bvh); @@ -1338,13 +1390,13 @@ void pbvh_bmesh_print(PBVH *bvh) fprintf(stderr, " %d\n", BM_elem_index_get((BMFace *)BLI_ghashIterator_getKey(&gh_iter))); fprintf(stderr, " unique verts:\n"); - GHASH_ITER (gh_iter, node->bm_unique_verts) + GSET_ITER (gs_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_gsetIterator_getKey(&gs_iter))); fprintf(stderr, " other verts:\n"); - GHASH_ITER (gh_iter, node->bm_other_verts) + GSET_ITER (gs_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_gsetIterator_getKey(&gs_iter))); } } @@ -1362,7 +1414,10 @@ void print_flag_factors(int flag) void pbvh_bmesh_verify(PBVH *bvh) { GHashIterator gh_iter; - int i; + GSetIterator gs_iter; + int i, vert_count = 0; + BMIter iter; + BMVert *vi; /* Check faces */ BLI_assert(bvh->bm->totface == BLI_ghash_size(bvh->bm_face_to_node)); @@ -1385,17 +1440,17 @@ void pbvh_bmesh_verify(PBVH *bvh) PBVHNode *nv; /* 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_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^ + BLI_gset_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); /* Check that the vertex's node knows it owns the vert */ - BLI_assert(BLI_ghash_haskey(nv->bm_unique_verts, v)); + BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v)); /* Check that the vertex isn't duplicated as an 'other' vert */ - BLI_assert(!BLI_ghash_haskey(nv->bm_other_verts, v)); + BLI_assert(!BLI_gset_haskey(nv->bm_other_verts, v)); } } @@ -1414,10 +1469,10 @@ void pbvh_bmesh_verify(PBVH *bvh) BLI_assert(n->flag & PBVH_Leaf); /* Check that the vert's node knows it owns the vert */ - BLI_assert(BLI_ghash_haskey(n->bm_unique_verts, v)); + BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v)); /* Check that the vertex isn't duplicated as an 'other' vert */ - BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v)); + BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v)); /* Check that the vert's node also contains one of the vert's * adjacent faces */ @@ -1428,8 +1483,37 @@ void pbvh_bmesh_verify(PBVH *bvh) } } BLI_assert(found); + + #if 1 + /* total freak stuff, check if node exists somewhere else */ + /* Slow */ + for (i = 0; i < bvh->totnode; i++) { + PBVHNode *n = &bvh->nodes[i]; + if (i != ni && n->bm_unique_verts) + BLI_assert(!BLI_gset_haskey(n->bm_unique_verts, v)); + } + + #endif } + #if 0 + /* check that every vert belongs somewhere */ + /* Slow */ + BM_ITER_MESH (vi, &iter, bvh->bm, BM_VERTS_OF_MESH) { + bool has_unique = false; + for (i = 0; i < bvh->totnode; i++) { + PBVHNode *n = &bvh->nodes[i]; + if ((n->bm_unique_verts != NULL) && BLI_gset_haskey(n->bm_unique_verts, vi)) + has_unique = true; + } + BLI_assert(has_unique); + vert_count++; + } + + /* if totvert differs from number of verts inside the hash. hash-totvert is checked above */ + BLI_assert(vert_count == bvh->bm->totvert); + #endif + /* Check that node elements are recorded in the top level */ for (i = 0; i < bvh->totnode; i++) { PBVHNode *n = &bvh->nodes[i]; @@ -1438,8 +1522,8 @@ void pbvh_bmesh_verify(PBVH *bvh) /* Slow */ #if 0 bli_ghash_duplicate_key_check(n->bm_faces); - bli_ghash_duplicate_key_check(n->bm_unique_verts); - bli_ghash_duplicate_key_check(n->bm_other_verts); + bli_gset_duplicate_key_check(n->bm_unique_verts); + bli_gset_duplicate_key_check(n->bm_other_verts); #endif GHASH_ITER (gh_iter, n->bm_faces) { @@ -1449,16 +1533,16 @@ void pbvh_bmesh_verify(PBVH *bvh) BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes)); } - GHASH_ITER (gh_iter, n->bm_unique_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, n->bm_unique_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); void *nip = BLI_ghash_lookup(bvh->bm_vert_to_node, v); BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); - BLI_assert(!BLI_ghash_haskey(n->bm_other_verts, v)); + BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v)); BLI_assert(GET_INT_FROM_POINTER(nip) == (n - bvh->nodes)); } - GHASH_ITER (gh_iter, n->bm_other_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, n->bm_other_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); BLI_assert(BLI_ghash_haskey(bvh->bm_vert_to_node, v)); BLI_assert(BM_vert_face_count(v) > 0); } diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h index 4154b8e4799..9af1c1decf5 100644 --- a/source/blender/blenkernel/intern/pbvh_intern.h +++ b/source/blender/blenkernel/intern/pbvh_intern.h @@ -101,8 +101,8 @@ struct PBVHNode { /* Dyntopo */ GHash *bm_faces; - GHash *bm_unique_verts; - GHash *bm_other_verts; + GSet *bm_unique_verts; + GSet *bm_other_verts; float (*bm_orco)[3]; int (*bm_ortri)[3]; int bm_tot_ortri; diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index b7aab87fc47..ff61dfc5266 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -66,6 +66,7 @@ #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcache.h" @@ -227,6 +228,11 @@ static int ptcache_softbody_totpoint(void *soft_v, int UNUSED(cfra)) SoftBody *soft= soft_v; return soft->totpoint; } +static void ptcache_softbody_error(void *UNUSED(soft_v), const char *UNUSED(message)) +{ + /* ignored for now */ +} + /* Particle functions */ void BKE_ptcache_make_particle_key(ParticleKey *key, int index, void **data, float time) { @@ -405,6 +411,12 @@ static int ptcache_particle_totpoint(void *psys_v, int UNUSED(cfra)) ParticleSystem *psys = psys_v; return psys->totpart; } + +static void ptcache_particle_error(void *UNUSED(psys_v), const char *UNUSED(message)) +{ + /* ignored for now */ +} + static int ptcache_particle_totwrite(void *psys_v, int cfra) { ParticleSystem *psys = psys_v; @@ -534,6 +546,12 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) return clmd->clothObject ? clmd->clothObject->numverts : 0; } +static void ptcache_cloth_error(void *cloth_v, const char *message) +{ + ClothModifierData *clmd= cloth_v; + modifier_setError(&clmd->modifier, "%s", message); +} + #ifdef WITH_SMOKE /* Smoke functions */ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) @@ -548,6 +566,12 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) return 0; } +static void ptcache_smoke_error(void *smoke_v, const char *message) +{ + SmokeModifierData *smd= (SmokeModifierData *)smoke_v; + modifier_setError(&smd->modifier, "%s", message); +} + #define SMOKE_CACHE_VERSION "1.04" static int ptcache_smoke_write(PTCacheFile *pf, void *smoke_v) @@ -865,8 +889,10 @@ static int ptcache_smoke_read(PTCacheFile *pf, void *smoke_v) return 1; } + #else // WITH_SMOKE static int ptcache_smoke_totpoint(void *UNUSED(smoke_v), int UNUSED(cfra)) { return 0; } +static void ptcache_smoke_error(void *UNUSED(smoke_v), const char *UNUSED(message)) { } static int ptcache_smoke_read(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; } static int ptcache_smoke_write(PTCacheFile *UNUSED(pf), void *UNUSED(smoke_v)) { return 0; } #endif // WITH_SMOKE @@ -879,6 +905,11 @@ static int ptcache_dynamicpaint_totpoint(void *sd, int UNUSED(cfra)) else return surface->data->total_points; } +static void ptcache_dynamicpaint_error(void *UNUSED(sd), const char *UNUSED(message)) +{ + /* ignored for now */ +} + #define DPAINT_CACHE_VERSION "1.01" static int ptcache_dynamicpaint_write(PTCacheFile *pf, void *dp_v) @@ -1059,6 +1090,11 @@ static int ptcache_rigidbody_totpoint(void *rb_v, int UNUSED(cfra)) return rbw->numbodies; } +static void ptcache_rigidbody_error(void *UNUSED(rb_v), const char *UNUSED(message)) +{ + /* ignored for now */ +} + /* Creating ID's */ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) { @@ -1071,6 +1107,7 @@ void BKE_ptcache_id_from_softbody(PTCacheID *pid, Object *ob, SoftBody *sb) pid->cache_ptr= &sb->pointcache; pid->ptcaches= &sb->ptcaches; pid->totpoint= pid->totwrite= ptcache_softbody_totpoint; + pid->error = ptcache_softbody_error; pid->write_point = ptcache_softbody_write; pid->read_point = ptcache_softbody_read; @@ -1111,6 +1148,7 @@ void BKE_ptcache_id_from_particles(PTCacheID *pid, Object *ob, ParticleSystem *p pid->totpoint = ptcache_particle_totpoint; pid->totwrite = ptcache_particle_totwrite; + pid->error = ptcache_particle_error; pid->write_point = ptcache_particle_write; pid->read_point = ptcache_particle_read; @@ -1163,6 +1201,7 @@ void BKE_ptcache_id_from_cloth(PTCacheID *pid, Object *ob, ClothModifierData *cl pid->cache_ptr= &clmd->point_cache; pid->ptcaches= &clmd->ptcaches; pid->totpoint= pid->totwrite= ptcache_cloth_totpoint; + pid->error = ptcache_cloth_error; pid->write_point = ptcache_cloth_write; pid->read_point = ptcache_cloth_read; @@ -1201,6 +1240,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo pid->ptcaches= &(sds->ptcaches[0]); pid->totpoint= pid->totwrite= ptcache_smoke_totpoint; + pid->error = ptcache_smoke_error; pid->write_point = NULL; pid->read_point = NULL; @@ -1240,6 +1280,7 @@ void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, Object *ob, DynamicPaintSu pid->cache_ptr= &surface->pointcache; pid->ptcaches= &surface->ptcaches; pid->totpoint= pid->totwrite= ptcache_dynamicpaint_totpoint; + pid->error = ptcache_dynamicpaint_error; pid->write_point = NULL; pid->read_point = NULL; @@ -1276,6 +1317,7 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r pid->cache_ptr= &rbw->pointcache; pid->ptcaches= &rbw->ptcaches; pid->totpoint= pid->totwrite= ptcache_rigidbody_totpoint; + pid->error = ptcache_rigidbody_error; pid->write_point = ptcache_rigidbody_write; pid->read_point = ptcache_rigidbody_read; @@ -2087,21 +2129,31 @@ static int ptcache_read_stream(PTCacheID *pid, int cfra) return 0; } - if (!ptcache_file_header_begin_read(pf)) + if (!ptcache_file_header_begin_read(pf)) { + pid->error(pid->calldata, "Failed to read point cache file"); error = 1; - - if (!error && (pf->type != pid->type || !pid->read_header(pf))) + } + else if (pf->type != pid->type) { + pid->error(pid->calldata, "Point cache file has wrong type"); error = 1; - - if (!error && pf->totpoint != pid->totpoint(pid->calldata, cfra)) + } + else if (!pid->read_header(pf)) { + pid->error(pid->calldata, "Failed to read point cache file header"); + error = 1; + } + else if (pf->totpoint != pid->totpoint(pid->calldata, cfra)) { + pid->error(pid->calldata, "Number of points in cache does not match mesh"); error = 1; + } if (!error) { ptcache_file_pointers_init(pf); // we have stream reading here - if (!pid->read_stream(pf, pid->calldata)) + if (!pid->read_stream(pf, pid->calldata)) { + pid->error(pid->calldata, "Failed to read point cache file data"); error = 1; + } } ptcache_file_close(pf); @@ -2129,8 +2181,14 @@ static int ptcache_read(PTCacheID *pid, int cfra) if (pm) { int totpoint = pm->totpoint; - if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, cfra)); + if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) { + int pid_totpoint = pid->totpoint(pid->calldata, cfra); + + if (totpoint != pid_totpoint) { + pid->error(pid->calldata, "Number of points in cache does not match mesh"); + totpoint = MIN2(totpoint, pid_totpoint); + } + } BKE_ptcache_mem_pointers_init(pm); @@ -2177,8 +2235,14 @@ static int ptcache_interpolate(PTCacheID *pid, float cfra, int cfra1, int cfra2) if (pm) { int totpoint = pm->totpoint; - if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) - totpoint = MIN2(totpoint, pid->totpoint(pid->calldata, (int)cfra)); + if ((pid->data_types & (1<<BPHYS_DATA_INDEX)) == 0) { + int pid_totpoint = pid->totpoint(pid->calldata, (int)cfra); + + if (totpoint != pid_totpoint) { + pid->error(pid->calldata, "Number of points in cache does not match mesh"); + totpoint = MIN2(totpoint, pid_totpoint); + } + } BKE_ptcache_mem_pointers_init(pm); @@ -2973,12 +3037,10 @@ void BKE_ptcache_free(PointCache *cache) } void BKE_ptcache_free_list(ListBase *ptcaches) { - PointCache *cache = ptcaches->first; + PointCache *cache; - while (cache) { - BLI_remlink(ptcaches, cache); + while ((cache = BLI_pophead(ptcaches))) { BKE_ptcache_free(cache); - cache = ptcaches->first; } } diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c index 73f2a864e32..bb04d548a44 100644 --- a/source/blender/blenkernel/intern/property.c +++ b/source/blender/blenkernel/intern/property.c @@ -59,9 +59,8 @@ void BKE_bproperty_free(bProperty *prop) void BKE_bproperty_free_list(ListBase *lb) { bProperty *prop; - - while ( (prop = lb->first) ) { - BLI_remlink(lb, prop); + + while ((prop = BLI_pophead(lb))) { BKE_bproperty_free(prop); } } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c index 92f57a54a01..7c374fd5d78 100644 --- a/source/blender/blenkernel/intern/sca.c +++ b/source/blender/blenkernel/intern/sca.c @@ -63,8 +63,7 @@ void free_sensors(ListBase *lb) { bSensor *sens; - while ((sens= lb->first)) { - BLI_remlink(lb, sens); + while ((sens = BLI_pophead(lb))) { free_sensor(sens); } } @@ -113,9 +112,6 @@ void init_sensor(bSensor *sens) case SENS_ALWAYS: sens->pulse = 0; break; - case SENS_TOUCH: - sens->data= MEM_callocN(sizeof(bTouchSensor), "touchsens"); - break; case SENS_NEAR: ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens"); ns->dist= 1.0; @@ -227,9 +223,9 @@ void free_controllers(ListBase *lb) { bController *cont; - while ((cont= lb->first)) { - BLI_remlink(lb, cont); - if (cont->slinks) MEM_freeN(cont->slinks); + while ((cont = BLI_pophead(lb))) { + if (cont->slinks) + MEM_freeN(cont->slinks); free_controller(cont); } } @@ -346,8 +342,7 @@ void free_actuators(ListBase *lb) { bActuator *act; - while ((act= lb->first)) { - BLI_remlink(lb, act); + while ((act = BLI_pophead(lb))) { free_actuator(act); } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 1874523dac9..5829ff4995e 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -44,6 +44,7 @@ #include "DNA_anim_types.h" #include "DNA_group_types.h" +#include "DNA_linestyle_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_rigidbody_types.h" @@ -1064,6 +1065,7 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra) */ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene) { + SceneRenderLayer *srl; float ctime = BKE_scene_frame_get(scene); /* scene itself */ @@ -1098,6 +1100,22 @@ static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene) if (adt && adt->drivers.first) BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS); } + + /* freestyle */ + for (srl = scene->r.layers.first; srl; srl = srl->next) { + FreestyleConfig *config = &srl->freestyleConfig; + FreestyleLineSet *lineset; + + for (lineset = config->linesets.first; lineset; lineset = lineset->next) { + if (lineset->linestyle) { + ID *lid = &lineset->linestyle->id; + AnimData *adt = BKE_animdata_from_id(lid); + + if (adt && adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS); + } + } + } } /* deps hack - do extra recalcs at end */ diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index fe2f52d79fd..efcbcacf974 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -47,6 +47,7 @@ #include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "BKE_idprop.h" #include "BKE_screen.h" /* ************ Spacetype/regiontype handling ************** */ @@ -267,6 +268,8 @@ void BKE_spacedata_draw_locks(int set) /* not region itself */ void BKE_area_region_free(SpaceType *st, ARegion *ar) { + uiList *uilst; + if (st) { ARegionType *art = BKE_regiontype_from_id(st, ar->regiontype); @@ -285,6 +288,23 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar) } BLI_freelistN(&ar->panels); + + for (uilst = ar->ui_lists.first; uilst; uilst = uilst->next) { + if (uilst->dyn_data) { + uiListDyn *dyn_data = uilst->dyn_data; + if (dyn_data->items_filter_flags) { + MEM_freeN(dyn_data->items_filter_flags); + } + if (dyn_data->items_filter_neworder) { + MEM_freeN(dyn_data->items_filter_neworder); + } + MEM_freeN(dyn_data); + } + if (uilst->properties) { + IDP_FreeProperty(uilst->properties); + MEM_freeN(uilst->properties); + } + } BLI_freelistN(&ar->ui_lists); } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 34b19e3f357..43845638754 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -417,33 +417,41 @@ void BKE_sequencer_editing_free(Scene *scene) static void sequencer_imbuf_assign_spaces(Scene *scene, ImBuf *ibuf) { - IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); + if (ibuf->rect_float) { + IMB_colormanagement_assign_float_colorspace(ibuf, scene->sequencer_colorspace_settings.name); + } } void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_float) { const char *from_colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); const char *to_colorspace = scene->sequencer_colorspace_settings.name; + const char *float_colorspace = IMB_colormanagement_get_float_colorspace(ibuf); if (!ibuf->rect_float) { - if (make_float && ibuf->rect) { - /* when converting byte buffer to float in sequencer we need to make float - * buffer be in sequencer's working space, which is currently only doable - * from linear space. - * - */ - - /* - * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's - */ - - IMB_float_from_rect(ibuf); + if (ibuf->rect) { + const char *byte_colorspace = IMB_colormanagement_get_rect_colorspace(ibuf); + if (make_float || !STREQ(to_colorspace, byte_colorspace)) { + /* If byte space is not in sequencer's working space, we deliver float color space, + * this is to to prevent data loss. + */ + + /* when converting byte buffer to float in sequencer we need to make float + * buffer be in sequencer's working space, which is currently only doable + * from linear space. + */ + + /* + * OCIO_TODO: would be nice to support direct single transform from byte to sequencer's + */ + + IMB_float_from_rect(ibuf); + } + else { + return; + } } else { - /* if there's only byte buffer in image it's already in compositor's working space, - * nothing to do here - */ - return; } } @@ -452,8 +460,10 @@ void BKE_sequencer_imbuf_to_sequencer_space(Scene *scene, ImBuf *ibuf, int make_ if (ibuf->rect) imb_freerectImBuf(ibuf); - IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, TRUE); + if (!STREQ(float_colorspace, to_colorspace)) { + IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, + from_colorspace, to_colorspace, true); + } } } @@ -467,7 +477,7 @@ void BKE_sequencer_imbuf_from_sequencer_space(Scene *scene, ImBuf *ibuf) if (to_colorspace && to_colorspace[0] != '\0') { IMB_colormanagement_transform_threaded(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, TRUE); + from_colorspace, to_colorspace, true); } } @@ -865,8 +875,7 @@ void BKE_sequencer_sort(Scene *scene) seqbase.first = seqbase.last = NULL; effbase.first = effbase.last = NULL; - while ( (seq = ed->seqbasep->first) ) { - BLI_remlink(ed->seqbasep, seq); + while ((seq = BLI_pophead(ed->seqbasep))) { if (seq->type & SEQ_TYPE_EFFECT) { seqt = effbase.first; @@ -2669,10 +2678,14 @@ static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, flo seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN, seq_rendersize_to_proxysize(context.preview_render_size)); - /* we don't need both (speed reasons)! */ - if (ibuf && ibuf->rect_float && ibuf->rect) - imb_freerectImBuf(ibuf); if (ibuf) { + BKE_sequencer_imbuf_to_sequencer_space(context.scene, ibuf, FALSE); + + /* we don't need both (speed reasons)! */ + if (ibuf->rect_float && ibuf->rect) { + imb_freerectImBuf(ibuf); + } + seq->strip->stripdata->orig_width = ibuf->x; seq->strip->stripdata->orig_height = ibuf->y; } @@ -3677,6 +3690,51 @@ bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, Scene *evil_scene) return offset ? false : true; } +/* Unlike _update_sound_ funcs, these ones take info from audaspace to update sequence length! */ +#ifdef WITH_AUDASPACE +static bool sequencer_refresh_sound_length_recursive(Scene *scene, ListBase *seqbase) +{ + Sequence *seq; + bool changed = false; + + for (seq = seqbase->first; seq; seq = seq->next) { + if (seq->type == SEQ_TYPE_META) { + if (sequencer_refresh_sound_length_recursive(scene, &seq->seqbase)) { + BKE_sequence_calc(scene, seq); + changed = true; + } + } + else if (seq->type == SEQ_TYPE_SOUND_RAM) { + AUD_SoundInfo info = AUD_getInfo(seq->sound->playback_handle); + int old = seq->len; + float fac; + + seq->len = (int)ceil((double)info.length * FPS); + fac = (float)seq->len / (float)old; + old = seq->startofs; + seq->startofs *= fac; + seq->endofs *= fac; + seq->start += (old - seq->startofs); /* So that visual/"real" start frame does not change! */ + + BKE_sequence_calc(scene, seq); + changed = true; + } + } + return changed; +} +#endif + +void BKE_sequencer_refresh_sound_length(Scene *scene) +{ +#ifdef WITH_AUDASPACE + if (scene->ed) { + sequencer_refresh_sound_length_recursive(scene, &scene->ed->seqbase); + } +#else + (void)scene; +#endif +} + void BKE_sequencer_update_sound_bounds_all(Scene *scene) { Editing *ed = scene->ed; @@ -3954,6 +4012,29 @@ Sequence *BKE_sequence_get_by_name(ListBase *seqbase, const char *name, int recu return NULL; } +/** + * Only use as last resort when the StripElem is available but no the Sequence. + * (needed for RNA) + */ +Sequence *BKE_sequencer_from_elem(ListBase *seqbase, StripElem *se) +{ + Sequence *iseq; + + for (iseq = seqbase->first; iseq; iseq = iseq->next) { + Sequence *seq_found; + if ((iseq->strip && iseq->strip->stripdata) && + (ARRAY_HAS_ITEM(se, iseq->strip->stripdata, iseq->len))) + { + break; + } + else if ((seq_found = BKE_sequencer_from_elem(&iseq->seqbase, se))) { + iseq = seq_found; + break; + } + } + + return iseq; +} Sequence *BKE_sequencer_active_get(Scene *scene) { diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index bb65955e3b5..189c1e967dd 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -1142,8 +1142,8 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult /* values */ output->influence[index_out] = em1.influence[index_in]; - if (output->velocity) { - output->velocity[index_out] = em1.velocity[index_in]; + if (output->velocity && em1.velocity) { + copy_v3_v3(&output->velocity[index_out * 3], &em1.velocity[index_in * 3]); } } @@ -1160,9 +1160,11 @@ static void em_combineMaps(EmissionMap *output, EmissionMap *em2, int hires_mult else { output->influence[index_out] = MAX2(em2->influence[index_in], output->influence[index_out]); } - if (output->velocity) { + if (output->velocity && em2->velocity) { /* last sample replaces the velocity */ - output->velocity[index_out] = ADD_IF_LOWER(output->velocity[index_out], em2->velocity[index_in]); + output->velocity[index_out * 3] = ADD_IF_LOWER(output->velocity[index_out * 3], em2->velocity[index_in * 3]); + output->velocity[index_out * 3 + 1] = ADD_IF_LOWER(output->velocity[index_out * 3 + 1], em2->velocity[index_in * 3 + 1]); + output->velocity[index_out * 3 + 2] = ADD_IF_LOWER(output->velocity[index_out * 3 + 2], em2->velocity[index_in * 3 + 2]); } } } // low res loop diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 2f8eb7d9931..3910ef5cb69 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -427,6 +427,8 @@ void sound_update_fps(struct Scene *scene) { if (scene->sound_scene) AUD_setSequencerFPS(scene->sound_scene, FPS); + + BKE_sequencer_refresh_sound_length(scene); } void sound_update_scene_listener(struct Scene *scene) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 35482d9553d..d5761fa918e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -298,7 +298,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, CCGVertHDL *fverts = NULL; BLI_array_declare(fverts); #endif - EdgeHash *ehash; + EdgeSet *eset; float creaseFactor = (float)ccgSubSurf_getSubdivisionLevels(ss); float uv[3] = {0.0f, 0.0f, 0.0f}; /* only first 2 values are written into */ @@ -334,7 +334,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, } /* create edges */ - ehash = BLI_edgehash_new(); + eset = BLI_edgeset_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totface)); for (i = 0; i < totface; i++) { MPoly *mp = &((MPoly *) mpoly)[i]; @@ -359,7 +359,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, MVert *mv0 = mvert + (ml[j_next].v); MVert *mv1 = mvert + (ml[j].v); - if (!BLI_edgehash_haskey(ehash, v0, v1)) { + if (BLI_edgeset_reinsert(eset, v0, v1)) { CCGEdge *e, *orige = ccgSubSurf_getFaceEdge(origf, j_next); CCGEdgeHDL ehdl = SET_INT_IN_POINTER(mp->loopstart + j_next); float crease; @@ -370,12 +370,11 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm, crease = ccgSubSurf_getEdgeCrease(orige); ccgSubSurf_syncEdge(ss, ehdl, fverts[j_next], fverts[j], crease, &e); - BLI_edgehash_insert(ehash, v0, v1, NULL); } } } - BLI_edgehash_free(ehash, NULL); + BLI_edgeset_free(eset); /* create faces */ for (i = 0; i < totface; i++) { @@ -1332,7 +1331,7 @@ static void ccgDM_copyFinalLoopArray(DerivedMesh *dm, MLoop *mloop) if (!ccgdm->ehash) { MEdge *medge; - ccgdm->ehash = BLI_edgehash_new(); + ccgdm->ehash = BLI_edgehash_new_ex(__func__, ccgdm->dm.numEdgeData); medge = ccgdm->dm.getEdgeArray((DerivedMesh *)ccgdm); for (i = 0; i < ccgdm->dm.numEdgeData; i++) { @@ -3190,8 +3189,10 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getVert = ccgDM_getFinalVert; ccgdm->dm.getEdge = ccgDM_getFinalEdge; ccgdm->dm.getTessFace = ccgDM_getFinalFace; + ccgdm->dm.getVertCo = ccgDM_getFinalVertCo; ccgdm->dm.getVertNo = ccgDM_getFinalVertNo; + ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray; @@ -3217,11 +3218,6 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, ccgdm->dm.getPolyMap = ccgDM_getPolyMap; ccgdm->dm.getPBVH = ccgDM_getPBVH; - ccgdm->dm.getTessFace = ccgDM_getFinalFace; - ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray; - ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray; - ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray; - ccgdm->dm.calcNormals = ccgDM_calcNormals; ccgdm->dm.recalcTessellation = ccgDM_recalcTessellation; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index f0c01e25598..be43aae1ed3 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -1151,17 +1151,26 @@ void txt_pop_sel(Text *text) text->selc = text->curc; } -void txt_order_cursors(Text *text) +void txt_order_cursors(Text *text, const bool reverse) { if (!text) return; if (!text->curl) return; if (!text->sell) return; - /* Flip so text->curl is before text->sell */ - if ((txt_get_span(text->curl, text->sell) < 0) || - (text->curl == text->sell && text->curc > text->selc)) - { - txt_curs_swap(text); + /* Flip so text->curl is before/after text->sell */ + if (reverse == false) { + if ((txt_get_span(text->curl, text->sell) < 0) || + (text->curl == text->sell && text->curc > text->selc)) + { + txt_curs_swap(text); + } + } + else { + if ((txt_get_span(text->curl, text->sell) > 0) || + (text->curl == text->sell && text->curc < text->selc)) + { + txt_curs_swap(text); + } } } @@ -1181,7 +1190,7 @@ static void txt_delete_sel(Text *text) if (!txt_has_sel(text)) return; - txt_order_cursors(text); + txt_order_cursors(text, false); if (!undoing) { buf = txt_sel_to_buf(text); @@ -1305,7 +1314,7 @@ int txt_find_string(Text *text, const char *findstr, int wrap, int match_case) if (!text || !text->curl || !text->sell) return 0; - txt_order_cursors(text); + txt_order_cursors(text, false); tl = startl = text->sell; @@ -1938,6 +1947,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s void txt_do_undo(Text *text) { int op = text->undo_buf[text->undo_pos]; + int prev_flags; unsigned int linep, i; unsigned int uchar; unsigned int curln, selln; @@ -2061,8 +2071,14 @@ void txt_do_undo(Text *text) txt_move_to(text, selln, selc, 1); if ((curln == selln) && (curc == selc)) { + /* disable tabs to spaces since moving right may involve skipping multiple spaces */ + prev_flags = text->flags; + text->flags &= ~TXT_TABSTOSPACES; + for (i = 0; i < linep; i++) txt_move_right(text, 1); + + text->flags = prev_flags; } txt_delete_selected(text); @@ -2833,7 +2849,7 @@ void txt_move_lines(struct Text *text, const int direction) if (!text || !text->curl || !text->sell) return; - txt_order_cursors(text); + txt_order_cursors(text, false); line_other = (direction == TXT_MOVE_LINE_DOWN) ? text->sell->next : text->curl->prev; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 54ba9ea56d7..19c1bf9b8a8 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -212,7 +212,7 @@ void BKE_tracking_settings_init(MovieTracking *tracking) tracking->settings.default_algorithm_flag |= TRACK_ALGORITHM_FLAG_USE_BRUTE; tracking->settings.dist = 1; tracking->settings.object_distance = 1; - tracking->settings.reconstruction_success_threshold = 1e-3; + tracking->settings.reconstruction_success_threshold = 1e-3f; tracking->stabilization.scaleinf = 1.0f; tracking->stabilization.locinf = 1.0f; @@ -501,7 +501,7 @@ void BKE_tracking_clipboard_copy_tracks(MovieTracking *tracking, MovieTrackingOb } /* Check whether there're any tracks in the clipboard. */ -int BKE_tracking_clipboard_has_tracks(void) +bool BKE_tracking_clipboard_has_tracks(void) { return tracking_clipboard.tracks.first != NULL; } @@ -678,7 +678,7 @@ void BKE_tracking_track_flag_clear(MovieTrackingTrack *track, int area, int flag * * NOTE: frame number should be in clip space, not scene space. */ -int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr) +bool BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framenr) { return BKE_tracking_marker_get_exact(track, framenr) != NULL; } @@ -687,7 +687,7 @@ int BKE_tracking_track_has_marker_at_frame(MovieTrackingTrack *track, int framen * * NOTE: frame number should be in clip space, not scene space. */ -int BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr) +bool BKE_tracking_track_has_enabled_marker_at_frame(MovieTrackingTrack *track, int framenr) { MovieTrackingMarker *marker = BKE_tracking_marker_get_exact(track, framenr); @@ -1022,7 +1022,7 @@ float *BKE_tracking_track_get_mask(int frame_width, int frame_height, } /* area - which part of marker should be selected. see TRACK_AREA_* constants */ -void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, int extend) +void BKE_tracking_track_select(ListBase *tracksbase, MovieTrackingTrack *track, int area, bool extend) { if (extend) { BKE_tracking_track_flag_set(track, area, SELECT); @@ -1303,6 +1303,25 @@ void BKE_tracking_marker_get_subframe_position(MovieTrackingTrack *track, float /*********************** Plane Track *************************/ +static void plane_tracks_replace_point_track(ListBase *plane_tracks, + MovieTrackingTrack *old_track, + MovieTrackingTrack *new_track) +{ + MovieTrackingPlaneTrack *plane_track; + + for (plane_track = plane_tracks->first; + plane_track; + plane_track = plane_track->next) + { + int i; + for (i = 0; i < plane_track->point_tracksnr; i++) { + if (plane_track->point_tracks[i] == old_track) { + plane_track->point_tracks[i] = new_track; + } + } + } +} + /* Creates new plane track out of selected point tracks */ MovieTrackingPlaneTrack *BKE_tracking_plane_track_add(MovieTracking *tracking, ListBase *plane_tracks_base, ListBase *tracks, int framenr) @@ -1622,17 +1641,17 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char return object; } -int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object) +bool BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *object) { MovieTrackingTrack *track; int index = BLI_findindex(&tracking->objects, object); if (index == -1) - return FALSE; + return false; if (object->flag & TRACKING_OBJECT_CAMERA) { /* object used for camera solving can't be deleted */ - return FALSE; + return false; } track = object->tracks.first; @@ -1655,7 +1674,7 @@ int BKE_tracking_object_delete(MovieTracking *tracking, MovieTrackingObject *obj BKE_tracking_dopesheet_tag_update(tracking); - return TRUE; + return true; } void BKE_tracking_object_unique_name(MovieTracking *tracking, MovieTrackingObject *object) @@ -1886,7 +1905,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 = (int) (calibration_height * aspy); } MovieDistortion *BKE_tracking_distortion_new(void) @@ -1928,7 +1947,7 @@ MovieDistortion *BKE_tracking_distortion_copy(MovieDistortion *distortion) } ImBuf *BKE_tracking_distortion_exec(MovieDistortion *distortion, MovieTracking *tracking, ImBuf *ibuf, - int calibration_width, int calibration_height, float overscan, int undistort) + int calibration_width, int calibration_height, float overscan, bool undistort) { ImBuf *resibuf; @@ -2020,7 +2039,7 @@ ImBuf *BKE_tracking_undistort_frame(MovieTracking *tracking, ImBuf *ibuf, int ca camera->intrinsics = BKE_tracking_distortion_new(); return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width, - calibration_height, overscan, TRUE); + calibration_height, overscan, true); } ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int calibration_width, @@ -2032,7 +2051,7 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, ImBuf *ibuf, int cali camera->intrinsics = BKE_tracking_distortion_new(); return BKE_tracking_distortion_exec(camera->intrinsics, tracking, ibuf, calibration_width, - calibration_height, overscan, FALSE); + calibration_height, overscan, false); } void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, rcti *rect, float delta[2]) @@ -2053,8 +2072,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r BKE_tracking_undistort_v2(tracking, pos, warped_pos); - delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); - delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); /* top edge */ pos[0] = a; @@ -2062,8 +2081,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r BKE_tracking_undistort_v2(tracking, pos, warped_pos); - delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); - delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); if (a >= rect->xmax) break; @@ -2079,8 +2098,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r BKE_tracking_undistort_v2(tracking, pos, warped_pos); - delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); - delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); /* right edge */ pos[0] = rect->xmax; @@ -2088,8 +2107,8 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r BKE_tracking_undistort_v2(tracking, pos, warped_pos); - delta[0] = max_ff(delta[0], fabs(pos[0] - warped_pos[0])); - delta[1] = max_ff(delta[1], fabs(pos[1] - warped_pos[1])); + delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); + delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); if (a >= rect->ymax) break; @@ -2098,7 +2117,7 @@ void BKE_tracking_max_undistortion_delta_across_bound(MovieTracking *tracking, r /*********************** Image sampling *************************/ -static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, int grayscale) +static void disable_imbuf_channels(ImBuf *ibuf, MovieTrackingTrack *track, bool grayscale) { BKE_tracking_disable_channels(ibuf, track->flag & TRACK_DISABLE_RED, track->flag & TRACK_DISABLE_GREEN, @@ -2107,7 +2126,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 from_anchor, int use_mask, int num_samples_x, int num_samples_y, + bool from_anchor, bool use_mask, int num_samples_x, int num_samples_y, float pos[2]) { ImBuf *pattern_ibuf; @@ -2170,7 +2189,7 @@ ImBuf *BKE_tracking_sample_pattern(int frame_width, int frame_height, ImBuf *sea } ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int anchored, int disable_channels) + bool anchored, bool disable_channels) { ImBuf *pattern_ibuf, *search_ibuf; float pat_min[2], pat_max[2]; @@ -2185,7 +2204,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, - anchored, FALSE, num_samples_x, num_samples_y, NULL); + anchored, false, num_samples_x, num_samples_y, NULL); IMB_freeImBuf(search_ibuf); } @@ -2197,7 +2216,7 @@ ImBuf *BKE_tracking_get_pattern_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mo } ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int anchored, int disable_channels) + bool anchored, bool disable_channels) { ImBuf *searchibuf; int x, y, w, h; @@ -2229,7 +2248,7 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov (track->flag & TRACK_DISABLE_GREEN) || (track->flag & TRACK_DISABLE_BLUE)) { - disable_imbuf_channels(searchibuf, track, TRUE); + disable_imbuf_channels(searchibuf, track, true); } } @@ -2240,8 +2259,8 @@ ImBuf *BKE_tracking_get_search_imbuf(ImBuf *ibuf, MovieTrackingTrack *track, Mov * better tracks sometimes. however, instead of simply zeroing the channels * out, do a partial grayscale conversion so the display is better. */ -void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_green, int disable_blue, - int grayscale) +void BKE_tracking_disable_channels(ImBuf *ibuf, bool disable_red, bool disable_green, bool disable_blue, + bool grayscale) { int x, y; float scale; @@ -2305,7 +2324,7 @@ void BKE_tracking_disable_channels(ImBuf *ibuf, int disable_red, int disable_gre typedef struct TracksMap { char object_name[MAX_NAME]; - int is_camera; + bool is_camera; int num_tracks; int customdata_size; @@ -2318,7 +2337,7 @@ typedef struct TracksMap { int ptr; } TracksMap; -static TracksMap *tracks_map_new(const char *object_name, int is_camera, int num_tracks, int customdata_size) +static TracksMap *tracks_map_new(const char *object_name, bool is_camera, int num_tracks, int customdata_size) { TracksMap *map = MEM_callocN(sizeof(TracksMap), "TrackingsMap"); @@ -2367,17 +2386,19 @@ static void tracks_map_insert(TracksMap *map, MovieTrackingTrack *track, void *c map->ptr++; } +/* TODO(sergey): Make it so tracks are not re-allocating here */ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) { MovieTrackingTrack *track; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); MovieTrackingTrack *rot_track = tracking->stabilization.rot_track; ListBase tracks = {NULL, NULL}, new_tracks = {NULL, NULL}; - ListBase *old_tracks; + ListBase *old_tracks, *plane_tracks; int a; if (map->is_camera) { old_tracks = &tracking->tracks; + plane_tracks = &tracking->plane_tracks; } else { MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, map->object_name); @@ -2388,6 +2409,7 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) } old_tracks = &object->tracks; + plane_tracks = &object->plane_tracks; } /* duplicate currently operating tracks to temporary list. @@ -2395,50 +2417,41 @@ static void tracks_map_merge(TracksMap *map, MovieTracking *tracking) * of currently operating tracks (if needed) */ for (a = 0; a < map->num_tracks; a++) { - int replace_sel = 0, replace_rot = 0; - MovieTrackingTrack *new_track, *old; + MovieTrackingTrack *new_track, *old_track; track = &map->tracks[a]; - /* find original of operating track in list of previously displayed tracks */ - old = BLI_ghash_lookup(map->hash, track); - if (old) { - MovieTrackingTrack *cur = old_tracks->first; + new_track = tracking_track_duplicate(track); - while (cur) { - if (cur == old) - break; + /* find original of operating track in list of previously displayed tracks */ + old_track = BLI_ghash_lookup(map->hash, track); + if (old_track) { + if (BLI_findindex(old_tracks, old_track) != -1) { + /* Update active track in movie clip. */ + if (old_track == act_track) { + tracking->act_track = new_track; + } - cur = cur->next; - } + /* Update track used for rotation stabilization. */ + if (old_track == rot_track) { + tracking->stabilization.rot_track = new_track; + } - /* original track was found, re-use flags and remove this track */ - if (cur) { - if (cur == act_track) - replace_sel = 1; - if (cur == rot_track) - replace_rot = 1; + new_track->flag = track->flag = old_track->flag; + new_track->pat_flag = track->pat_flag = old_track->pat_flag; + new_track->search_flag = track->search_flag = old_track->search_flag; - track->flag = cur->flag; - track->pat_flag = cur->pat_flag; - track->search_flag = cur->search_flag; + plane_tracks_replace_point_track(plane_tracks, old_track, new_track); - BKE_tracking_track_free(cur); - BLI_freelinkN(old_tracks, cur); + BKE_tracking_track_free(old_track); + BLI_freelinkN(old_tracks, old_track); } } - new_track = tracking_track_duplicate(track); - - BLI_ghash_remove(map->hash, track, NULL, NULL); /* XXX: are we actually need this */ + /* Update old-new track mapping */ + BLI_ghash_remove(map->hash, track, NULL, NULL); BLI_ghash_insert(map->hash, track, new_track); - if (replace_sel) /* update current selection in clip */ - tracking->act_track = new_track; - - if (replace_rot) /* update track used for rotation stabilization */ - tracking->stabilization.rot_track = new_track; - BLI_addtail(&tracks, new_track); } @@ -2518,7 +2531,7 @@ typedef struct MovieTrackingContext { MovieTrackingSettings settings; TracksMap *tracks_map; - short backwards, sequence; + bool backwards, sequence; int sync_frame; } MovieTrackingContext; @@ -2691,7 +2704,7 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, float *gray_pixels; int width, height; - searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, FALSE, TRUE); + searchibuf = BKE_tracking_get_search_imbuf(ibuf, track, marker, false, true); if (!searchibuf) { *width_r = 0; @@ -2887,19 +2900,24 @@ static void tracking_configure_tracker(const MovieTrackingTrack *track, float *m static bool tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker, int frame_width, int frame_height) { - float pat_min[2], pat_max[2], dim[2], margin[2]; + float pat_min[2], pat_max[2]; + float margin_left, margin_top, margin_right, margin_bottom; + float normalized_track_margin[2]; /* margin from frame boundaries */ BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - sub_v2_v2v2(dim, pat_max, pat_min); - margin[0] = margin[1] = max_ff(dim[0], dim[1]) / 2.0f; - margin[0] = max_ff(margin[0], (float)track->margin / frame_width); - margin[1] = max_ff(margin[1], (float)track->margin / frame_height); + normalized_track_margin[0] = (float)track->margin / frame_width; + normalized_track_margin[1] = (float)track->margin / frame_height; + + margin_left = max_ff(-pat_min[0], normalized_track_margin[0]); + margin_top = max_ff( pat_max[1], normalized_track_margin[1]); + margin_right = max_ff( pat_max[0], normalized_track_margin[0]); + margin_bottom = max_ff(-pat_min[1], normalized_track_margin[1]); /* do not track markers which are too close to boundary */ - if (marker->pos[0] < margin[0] || marker->pos[0] > 1.0f - margin[0] || - marker->pos[1] < margin[1] || marker->pos[1] > 1.0f - margin[1]) + if (marker->pos[0] < margin_left || marker->pos[0] > 1.0f - margin_right || + marker->pos[1] < margin_bottom || marker->pos[1] > 1.0f - margin_top) { return false; } @@ -3039,7 +3057,7 @@ static bool configure_and_run_tracker(ImBuf *destination_ibuf, MovieTrackingTrac /* Track all the tracks from context one more frame, * returns FALSe if nothing was tracked. */ -int BKE_tracking_context_step(MovieTrackingContext *context) +bool BKE_tracking_context_step(MovieTrackingContext *context) { ImBuf *destination_ibuf; int frame_delta = context->backwards ? -1 : 1; @@ -3053,7 +3071,7 @@ int BKE_tracking_context_step(MovieTrackingContext *context) /* Nothing to track, avoid unneeded frames reading to save time and memory. */ if (!map_size) - return FALSE; + return false; /* Get an image buffer for frame we're tracking to. */ context->user.framenr += frame_delta; @@ -3061,7 +3079,7 @@ int BKE_tracking_context_step(MovieTrackingContext *context) destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, context->clip_flag, MOVIECLIP_CACHE_SKIP); if (!destination_ibuf) - return FALSE; + return false; frame_width = destination_ibuf->x; frame_height = destination_ibuf->y; @@ -3128,7 +3146,7 @@ int BKE_tracking_context_step(MovieTrackingContext *context) * which means if backwards is false, previous keyframe will be as * reference. */ -void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, int backwards) +void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards) { MovieTrackingMarker *reference_marker = NULL; ImBuf *reference_ibuf, *destination_ibuf; @@ -3146,7 +3164,7 @@ void BKE_tracking_refine_marker(MovieClip *clip, MovieTrackingTrack *track, Movi BKE_movieclip_get_size(clip, &user, &frame_width, &frame_height); - /* Get an image buffer for reference frame, also gets referecnce marker. + /* Get an image buffer for reference frame, also gets reference marker. * * Usually tracking_context_get_reference_ibuf will return current frame * if marker is keyframed, which is correct for normal tracking. But here @@ -3346,12 +3364,12 @@ typedef struct MovieReconstructContext { struct libmv_Tracks *tracks; bool select_keyframes; int keyframe1, keyframe2; - short refine_flags; + int refine_flags; struct libmv_Reconstruction *reconstruction; char object_name[MAX_NAME]; - int is_camera; + bool is_camera; short motion_flag; float focal_length; @@ -3365,7 +3383,7 @@ typedef struct MovieReconstructContext { TracksMap *tracks_map; float success_threshold; - int use_fallback_reconstruction; + bool use_fallback_reconstruction; int sfra, efra; } MovieReconstructContext; @@ -3434,7 +3452,7 @@ static void reconstruct_retrieve_libmv_intrinsics(MovieReconstructContext *conte * Actually, this also copies reconstructed cameras * from libmv to movie clip datablock. */ -static int reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking) +static bool reconstruct_retrieve_libmv_tracks(MovieReconstructContext *context, MovieTracking *tracking) { struct libmv_Reconstruction *libmv_reconstruction = context->reconstruction; MovieTrackingReconstruction *reconstruction = NULL; @@ -3611,12 +3629,12 @@ static int reconstruct_count_tracks_on_both_keyframes(MovieTracking *tracking, M } /* Perform early check on whether everything is fine to start reconstruction. */ -int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, - char *error_msg, int error_size) +bool BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObject *object, + char *error_msg, int error_size) { if (tracking->settings.motion_flag & TRACKING_MOTION_MODAL) { /* TODO: check for number of tracks? */ - return TRUE; + return true; } else if ((tracking->settings.reconstruction_flag & TRACKING_USE_KEYFRAME_SELECTION) == 0) { /* automatic keyframe selection does not require any pre-process checks */ @@ -3625,16 +3643,16 @@ int BKE_tracking_reconstruction_check(MovieTracking *tracking, MovieTrackingObje N_("At least 8 common tracks on both of keyframes are needed for reconstruction"), error_size); - return FALSE; + return false; } } #ifndef WITH_LIBMV BLI_strncpy(error_msg, N_("Blender is compiled without motion tracking library"), error_size); - return FALSE; + return false; #endif - return TRUE; + return true; } /* Create context for camera/object motion reconstruction. @@ -3828,7 +3846,7 @@ void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, short * /* Finish reconstruction process by copying reconstructed data * to an actual movie clip datablock. */ -int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking) +bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTracking *tracking) { MovieTrackingReconstruction *reconstruction; MovieTrackingObject *object; @@ -3853,9 +3871,9 @@ int BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieTr reconstruction->flag |= TRACKING_RECONSTRUCTED; if (!reconstruct_retrieve_libmv(context, tracking)) - return FALSE; + return false; - return TRUE; + return true; } static void tracking_scale_reconstruction(ListBase *tracksbase, MovieTrackingReconstruction *reconstruction, @@ -4020,7 +4038,7 @@ static unsigned char *detect_get_frame_ucharbuf(ImBuf *ibuf) /* Detect features using FAST detector */ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImBuf *ibuf, int framenr, int margin, int min_trackness, int min_distance, bGPDlayer *layer, - int place_outside_layer) + bool place_outside_layer) { struct libmv_Features *features; unsigned char *pixels = detect_get_frame_ucharbuf(ibuf); @@ -4032,14 +4050,14 @@ void BKE_tracking_detect_fast(MovieTracking *tracking, ListBase *tracksbase, ImB detect_retrieve_libmv_features(tracking, tracksbase, features, framenr, ibuf->x, ibuf->y, layer, - place_outside_layer ? true : false); + place_outside_layer); libmv_featuresDestroy(features); } /*********************** 2D stabilization *************************/ -/* Claculate median point of markers of tracks marked as used for +/* Calculate median point of markers of tracks marked as used for * 2D stabilization. * * NOTE: frame number should be in clip space, not scene space @@ -4077,7 +4095,7 @@ static bool stabilization_median_point_get(MovieTracking *tracking, int framenr, * * NOTE: frame number should be in clip space, not scene space */ -static void stabilization_calculate_data(MovieTracking *tracking, int framenr, float width, float height, +static void stabilization_calculate_data(MovieTracking *tracking, int framenr, int width, int height, float firstmedian[2], float median[2], float translation[2], float *scale, float *angle) { @@ -4107,7 +4125,7 @@ static void stabilization_calculate_data(MovieTracking *tracking, int framenr, f b[0] *= width; b[1] *= height; - *angle = -atan2(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]); + *angle = -atan2f(a[0] * b[1] - a[1] * b[0], a[0] * b[0] + a[1] * b[1]); *angle *= stab->rotinf; /* convert to rotation around image center */ @@ -4167,8 +4185,8 @@ static float stabilization_calculate_autoscale_factor(MovieTracking *tracking, i BKE_tracking_stabilization_data_to_mat4(width, height, aspect, translation, 1.0f, angle, mat); - si = sin(angle); - co = cos(angle); + si = sinf(angle); + co = cosf(angle); for (i = 0; i < 4; i++) { int j; @@ -4307,7 +4325,7 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf float tloc[2], tscale, tangle; MovieTrackingStabilization *stab = &tracking->stabilization; ImBuf *tmpibuf; - float width = ibuf->x, height = ibuf->y; + int width = ibuf->x, height = ibuf->y; float aspect = tracking->camera.pixel_aspect; float mat[4][4]; int j, filter = tracking->stabilization.filter; @@ -4369,7 +4387,7 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf for (j = 0; j < tmpibuf->y; j++) { int i; for (i = 0; i < tmpibuf->x; i++) { - float vec[3] = {i, j, 0}; + float vec[3] = {i, j, 0.0f}; mul_v3_m4v3(vec, mat, vec); @@ -4396,7 +4414,7 @@ ImBuf *BKE_tracking_stabilize_frame(MovieTracking *tracking, int framenr, ImBuf * stabilization data and used for easy coordinate * transformation. * - * NOTE: The reaosn it is 4x4 matrix is because it's + * NOTE: The reason it is 4x4 matrix is because it's * used for OpenGL drawing directly. */ void BKE_tracking_stabilization_data_to_mat4(int width, int height, float aspect, @@ -4646,7 +4664,7 @@ static void tracking_dopesheet_channels_calc(MovieTracking *tracking) /* Sot dopesheet channels using given method (name, average error, total coverage, * longest tracked segment) and could also inverse the list if it's enabled. */ -static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_method, int inverse) +static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_method, bool inverse) { MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; @@ -4783,7 +4801,7 @@ void BKE_tracking_dopesheet_update(MovieTracking *tracking) MovieTrackingDopesheet *dopesheet = &tracking->dopesheet; short sort_method = dopesheet->sort_method; - short inverse = dopesheet->flag & TRACKING_DOPE_SORT_INVERSE; + bool inverse = (dopesheet->flag & TRACKING_DOPE_SORT_INVERSE) != 0; if (dopesheet->ok) return; diff --git a/source/blender/blenkernel/intern/treehash.c b/source/blender/blenkernel/intern/treehash.c new file mode 100644 index 00000000000..d1e9da72208 --- /dev/null +++ b/source/blender/blenkernel/intern/treehash.c @@ -0,0 +1,164 @@ +/* + * ***** 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): Blender Foundation 2013 + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file treehash.c + * \ingroup bke + * + * Tree hash for the outliner space. + */ + +#include <stdlib.h> + +#include "BKE_treehash.h" + +#include "BLI_utildefines.h" +#include "BLI_ghash.h" +#include "BLI_mempool.h" + +#include "DNA_outliner_types.h" + +#include "MEM_guardedalloc.h" + +typedef struct TseGroup +{ + TreeStoreElem **elems; + int size; + int allocated; +} TseGroup; + +/* Allocate structure for TreeStoreElements; + * Most of elements in treestore have no duplicates, + * so there is no need to preallocate memory for more than one pointer */ +static TseGroup *tse_group_create(void) +{ + TseGroup *tse_group = MEM_mallocN(sizeof(TseGroup), "TseGroup"); + tse_group->elems = MEM_mallocN(sizeof(TreeStoreElem *), "TseGroupElems"); + tse_group->size = 0; + tse_group->allocated = 1; + return tse_group; +} + +static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) +{ + if (tse_group->size == tse_group->allocated) { + tse_group->allocated *= 2; + tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated); + } + tse_group->elems[tse_group->size] = elem; + tse_group->size++; +} + +static void tse_group_free(TseGroup *tse_group) +{ + MEM_freeN(tse_group->elems); + MEM_freeN(tse_group); +} + +static unsigned int tse_hash(const void *ptr) +{ + const TreeStoreElem *tse = ptr; + unsigned int hash; + BLI_assert(tse->type || !tse->nr); + hash = BLI_ghashutil_inthash(SET_INT_IN_POINTER((tse->nr << 16) + tse->type)); + hash ^= BLI_ghashutil_inthash(tse->id); + return hash; +} + +static int tse_cmp(const void *a, const void *b) +{ + const TreeStoreElem *tse_a = a; + const TreeStoreElem *tse_b = b; + return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr || tse_a->id != tse_b->id; +} + +static void fill_treehash(void *treehash, BLI_mempool *treestore) +{ + TreeStoreElem *tselem; + BLI_mempool_iter iter; + BLI_mempool_iternew(treestore, &iter); + while ((tselem = BLI_mempool_iterstep(&iter))) { + BKE_treehash_add_element(treehash, tselem); + } +} + +void *BKE_treehash_create_from_treestore(BLI_mempool *treestore) +{ + GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore)); + fill_treehash(treehash, treestore); + return treehash; +} + +static void free_treehash_group(void *key) +{ + tse_group_free(key); +} + +void *BKE_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *treestore) +{ + BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore)); + fill_treehash(treehash, treestore); + return treehash; +} + +void BKE_treehash_add_element(void *treehash, TreeStoreElem *elem) +{ + TseGroup *group = BLI_ghash_lookup(treehash, elem); + if (!group) { + group = tse_group_create(); + BLI_ghash_insert(treehash, elem, group); + } + tse_group_add(group, elem); +} + +static TseGroup *BKE_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id) +{ + TreeStoreElem tse_template; + tse_template.type = type; + tse_template.nr = type ? nr : 0; // we're picky! :) + tse_template.id = id; + return BLI_ghash_lookup(th, &tse_template); +} + +TreeStoreElem *BKE_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id) +{ + TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id); + if (group) { + int i; + for (i = 0; i < group->size; i++) { + if (!group->elems[i]->used) { + return group->elems[i]; + } + } + } + return NULL; +} + +TreeStoreElem *BKE_treehash_lookup_any(void *treehash, short type, short nr, struct ID *id) +{ + TseGroup *group = BKE_treehash_lookup_group(treehash, type, nr, id); + return group ? group->elems[0] : NULL; +} + +void BKE_treehash_free(void *treehash) +{ + BLI_ghash_free(treehash, NULL, free_treehash_group); +} diff --git a/source/blender/blenlib/BLI_callbacks.h b/source/blender/blenlib/BLI_callbacks.h index 8a0442c8bc8..4f727773cd2 100644 --- a/source/blender/blenlib/BLI_callbacks.h +++ b/source/blender/blenlib/BLI_callbacks.h @@ -43,6 +43,8 @@ typedef enum { BLI_CB_EVT_SAVE_POST, BLI_CB_EVT_SCENE_UPDATE_PRE, BLI_CB_EVT_SCENE_UPDATE_POST, + BLI_CB_EVT_GAME_PRE, + BLI_CB_EVT_GAME_POST, BLI_CB_EVT_TOT } eCbEvent; @@ -61,8 +63,4 @@ void BLI_callback_add(bCallbackFuncStore *funcstore, eCbEvent evt); void BLI_callback_global_init(void); void BLI_callback_global_finalize(void); - -/* This is blenlib internal only, unrelated to above */ -void callLocalErrorCallBack(const char *msg); - #endif /* __BLI_CALLBACKS_H__ */ diff --git a/source/blender/blenlib/BLI_compiler_attrs.h b/source/blender/blenlib/BLI_compiler_attrs.h new file mode 100644 index 00000000000..fc16e7dbba6 --- /dev/null +++ b/source/blender/blenlib/BLI_compiler_attrs.h @@ -0,0 +1,88 @@ +/* + * ***** 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): Campbell Barton + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_COMPILER_ATTRS_H__ +#define __BLI_COMPILER_ATTRS_H__ + +/** \file BLI_compiler_attrs.h + * \ingroup bli + */ + +/* hint to make sure function result is actually used */ +#ifdef __GNUC__ +# define ATTR_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) +#else +# define ATTR_WARN_UNUSED_RESULT +#endif + +/* hint to mark function arguments expected to be non-null + * if no arguments are given to the macro, all of pointer + * arguments owuld be expected to be non-null + */ +#ifdef __GNUC__ +# define ATTR_NONNULL(args ...) __attribute__((nonnull(args))) +#else +# define ATTR_NONNULL(...) +#endif + +/* hint to mark function as it wouldn't return */ +#if defined(__GNUC__) || defined(__clang__) +# define ATTR_NORETURN __attribute__((noreturn)) +#else +# define ATTR_NORETURN +#endif + +/* hint to treat any non-null function return value cannot alias any other pointer */ +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) +# define ATTR_MALLOC __attribute__((malloc)) +#else +# define ATTR_MALLOC +#endif + +/* the function return value points to memory (2 args for 'size * tot') */ +#if (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) +# define ATTR_ALLOC_SIZE(args ...) __attribute__((alloc_size(args))) +#else +# define ATTR_ALLOC_SIZE(...) +#endif + +/* ensures a NULL terminating argument as the n'th last argument of a variadic function */ +#ifdef __GNUC__ +# define ATTR_SENTINEL(arg_pos) __attribute__((sentinel(arg_pos))) +#else +# define ATTR_SENTINEL(arg_pos) +#endif + +/* hint to compiler that function uses printf-style format string */ +#ifdef __GNUC__ +# define ATTR_PRINTF_FORMAT(format_param, dots_param) __attribute__((format(printf, format_param, dots_param))) +#else +# define ATTR_PRINTF_FORMAT(format_param, dots_param) +#endif + +#endif /* __BLI_COMPILER_ATTRS_H__ */ diff --git a/source/blender/blenlib/BLI_dynstr.h b/source/blender/blenlib/BLI_dynstr.h index 833c416c1c1..61bdf23cec1 100644 --- a/source/blender/blenlib/BLI_dynstr.h +++ b/source/blender/blenlib/BLI_dynstr.h @@ -40,6 +40,8 @@ #include <stdarg.h> +#include "BLI_compiler_attrs.h" + struct DynStr; /** The abstract DynStr type */ @@ -75,16 +77,8 @@ void BLI_dynstr_nappend(DynStr *ds, const char *cstr, int len); * \param ds The DynStr to append to. * \param format The printf format string to use. */ -void BLI_dynstr_appendf(DynStr *ds, const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 2, 3))) -#endif -; -void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) -#ifdef __GNUC__ -__attribute__ ((format(printf, 2, 0))) -#endif -; +void BLI_dynstr_appendf(DynStr *ds, const char *format, ...) ATTR_PRINTF_FORMAT(2, 3); +void BLI_dynstr_vappendf(DynStr *ds, const char *format, va_list args) ATTR_PRINTF_FORMAT(2, 0); /** * Find the length of a DynStr. diff --git a/source/blender/blenlib/BLI_edgehash.h b/source/blender/blenlib/BLI_edgehash.h index 1962201c8d2..2ca011871d8 100644 --- a/source/blender/blenlib/BLI_edgehash.h +++ b/source/blender/blenlib/BLI_edgehash.h @@ -29,6 +29,8 @@ * \brief A general unordered 2-int pair hash table ADT. */ +#include "BLI_compiler_attrs.h" + struct EdgeHash; struct EdgeHashIterator; typedef struct EdgeHash EdgeHash; @@ -40,24 +42,56 @@ enum { EDGEHASH_FLAG_ALLOW_DUPES = (1 << 0), /* only checked for in debug mode */ }; -EdgeHash *BLI_edgehash_new(void); +EdgeHash *BLI_edgehash_new_ex(const char *info, + const unsigned int nentries_reserve); +EdgeHash *BLI_edgehash_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp); void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); -void BLI_edgehash_assign(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); -void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1); -void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1); -bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1); -int BLI_edgehash_size(EdgeHash *eh); +bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val); +void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; +void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; +bool BLI_edgehash_haskey(EdgeHash *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; +int BLI_edgehash_size(EdgeHash *eh) ATTR_WARN_UNUSED_RESULT; +void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp, + const unsigned int nentries_reserve); void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp); -void BLI_edgehash_flag_set(EdgeHash *eh, unsigned short flag); -void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned short flag); +void BLI_edgehash_flag_set(EdgeHash *eh, unsigned int flag); +void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned int flag); -EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh); +EdgeHashIterator *BLI_edgehashIterator_new(EdgeHash *eh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; void BLI_edgehashIterator_free(EdgeHashIterator *ehi); void BLI_edgehashIterator_getKey(EdgeHashIterator *ehi, unsigned int *v0_r, unsigned int *v1_r); -void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi); +void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) ATTR_WARN_UNUSED_RESULT; +void **BLI_edgehashIterator_getValue_p(EdgeHashIterator *ehi) ATTR_WARN_UNUSED_RESULT; void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val); void BLI_edgehashIterator_step(EdgeHashIterator *ehi); -bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi); +bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) ATTR_WARN_UNUSED_RESULT; + +#define BLI_EDGEHASH_SIZE_GUESS_FROM_LOOPS(totloop) ((totloop) / 2) +#define BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(totpoly) ((totpoly) * 2) + +/* *** EdgeSet *** */ + +struct EdgeSet; +struct EdgeSetIterator; +typedef struct EdgeSet EdgeSet; +typedef struct EdgeSetIterator EdgeSetIterator; + +EdgeSet *BLI_edgeset_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +EdgeSet *BLI_edgeset_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +int BLI_edgeset_size(EdgeSet *es) ATTR_WARN_UNUSED_RESULT; +bool BLI_edgeset_reinsert(EdgeSet *es, unsigned int v0, unsigned int v1); +void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1); +bool BLI_edgeset_haskey(EdgeSet *eh, unsigned int v0, unsigned int v1) ATTR_WARN_UNUSED_RESULT; +void BLI_edgeset_free(EdgeSet *es); + +/* rely on inline api for now */ +BLI_INLINE EdgeSetIterator *BLI_edgesetIterator_new(EdgeSet *gs) { return (EdgeSetIterator *)BLI_edgehashIterator_new((EdgeHash *)gs); } +BLI_INLINE void BLI_edgesetIterator_free(EdgeSetIterator *esi) { BLI_edgehashIterator_free((EdgeHashIterator *)esi); } +BLI_INLINE void BLI_edgesetIterator_getKey(EdgeSetIterator *esi, unsigned int *v0_r, unsigned int *v1_r) { BLI_edgehashIterator_getKey((EdgeHashIterator *)esi, v0_r, v1_r); } +BLI_INLINE void BLI_edgesetIterator_step(EdgeSetIterator *esi) { BLI_edgehashIterator_step((EdgeHashIterator *)esi); } +BLI_INLINE bool BLI_edgesetIterator_isDone(EdgeSetIterator *esi) { return BLI_edgehashIterator_isDone((EdgeHashIterator *)esi); } + -#endif +#endif /* __BLI_EDGEHASH_H__ */ diff --git a/source/blender/blenlib/BLI_endian_switch.h b/source/blender/blenlib/BLI_endian_switch.h index f48b1b072c3..35242fecf4a 100644 --- a/source/blender/blenlib/BLI_endian_switch.h +++ b/source/blender/blenlib/BLI_endian_switch.h @@ -27,35 +27,28 @@ * \ingroup bli */ -#ifdef __GNUC__ -# define ATTR_ENDIAN_SWITCH \ - __attribute__((nonnull(1))) -#else -# define ATTR_ENDIAN_SWITCH -#endif +#include "BLI_compiler_attrs.h" /* BLI_endian_switch_inline.h */ -BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_float(float *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_ENDIAN_SWITCH; -BLI_INLINE void BLI_endian_switch_double(double *val) ATTR_ENDIAN_SWITCH; +BLI_INLINE void BLI_endian_switch_int16(short *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_uint16(unsigned short *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_int32(int *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_uint32(unsigned int *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_float(float *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_int64(int64_t *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_uint64(uint64_t *val) ATTR_NONNULL(1); +BLI_INLINE void BLI_endian_switch_double(double *val) ATTR_NONNULL(1); /* endian_switch.c */ -void BLI_endian_switch_int16_array(short *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_uint16_array(unsigned short *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_int32_array(int *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_float_array(float *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_int64_array(int64_t *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_uint64_array(uint64_t *val, const int size) ATTR_ENDIAN_SWITCH; -void BLI_endian_switch_double_array(double *val, const int size) ATTR_ENDIAN_SWITCH; +void BLI_endian_switch_int16_array(short *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_uint16_array(unsigned short *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_int32_array(int *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_uint32_array(unsigned int *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_float_array(float *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_int64_array(int64_t *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_uint64_array(uint64_t *val, const int size) ATTR_NONNULL(1); +void BLI_endian_switch_double_array(double *val, const int size) ATTR_NONNULL(1); #include "BLI_endian_switch_inline.h" -#undef ATTR_ENDIAN_SWITCH - #endif /* __BLI_ENDIAN_SWITCH_H__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 0a6d95df40a..ca82086b529 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -43,6 +43,12 @@ extern "C" { /* for size_t (needed on windows) */ #include <stddef.h> +#include <limits.h> /* for PATH_MAX */ + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + struct gzFile; /* Common */ diff --git a/source/blender/blenlib/BLI_fnmatch.h b/source/blender/blenlib/BLI_fnmatch.h index 6c466759010..f69f5b39869 100644 --- a/source/blender/blenlib/BLI_fnmatch.h +++ b/source/blender/blenlib/BLI_fnmatch.h @@ -28,6 +28,8 @@ extern "C" { #endif +#if defined WIN32 && !defined _LIBC || defined __sun + #if defined(__cplusplus) || (defined(__STDC__) && __STDC__) #undef __P #define __P(protos) protos @@ -65,6 +67,13 @@ extern "C" { extern int fnmatch __P((const char *__pattern, const char *__string, int __flags)); +#else +# ifndef _GNU_SOURCE +# define _GNU_SOURCE +# endif +# include <fnmatch.h> +#endif /* defined WIN32 && !defined _LIBC || defined __sun */ + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index 97dbcc051c4..e5a93691ad0 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -33,6 +33,9 @@ * \brief A general (pointer -> pointer) hash table ADT */ +#include "BLI_sys_types.h" /* for bool */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif @@ -56,77 +59,37 @@ enum { /* *** */ -GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info); +GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_insert(GHash *gh, void *key, void *val); -void BLI_ghash_assign(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); -void *BLI_ghash_lookup(GHash *gh, const void *key); -void **BLI_ghash_lookup_p(GHash *gh, const void *key); +bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); +void *BLI_ghash_lookup(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; +void **BLI_ghash_lookup_p(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp); -void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp); -bool BLI_ghash_haskey(GHash *gh, const void *key); -int BLI_ghash_size(GHash *gh); -void BLI_ghash_flag_set(GHash *gh, unsigned short flag); -void BLI_ghash_flag_clear(GHash *gh, unsigned short flag); +void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, + const unsigned int nentries_reserve); +void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT; +bool BLI_ghash_haskey(GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT; +int BLI_ghash_size(GHash *gh) ATTR_WARN_UNUSED_RESULT; +void BLI_ghash_flag_set(GHash *gh, unsigned int flag); +void BLI_ghash_flag_clear(GHash *gh, unsigned int flag); /* *** */ -/** - * Create a new GHashIterator. The hash table must not be mutated - * while the iterator is in use, and the iterator will step exactly - * BLI_ghash_size(gh) times before becoming done. - * - * \param gh The GHash to iterate over. - * \return Pointer to a new DynStr. - */ -GHashIterator *BLI_ghashIterator_new(GHash *gh); -/** - * Init an already allocated GHashIterator. The hash table must not - * be mutated while the iterator is in use, and the iterator will - * step exactly BLI_ghash_size(gh) times before becoming done. - * - * \param ghi The GHashIterator to initialize. - * \param gh The GHash to iterate over. - */ -void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh); -/** - * Free a GHashIterator. - * - * \param ghi The iterator to free. - */ -void BLI_ghashIterator_free(GHashIterator *ghi); +GHashIterator *BLI_ghashIterator_new(GHash *gh) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; -/** - * Retrieve the key from an iterator. - * - * \param ghi The iterator. - * \return The key at the current index, or NULL if the - * iterator is done. - */ -void *BLI_ghashIterator_getKey(GHashIterator *ghi); -/** - * Retrieve the value from an iterator. - * - * \param ghi The iterator. - * \return The value at the current index, or NULL if the - * iterator is done. - */ -void *BLI_ghashIterator_getValue(GHashIterator *ghi); -/** - * Steps the iterator to the next index. - * - * \param ghi The iterator. - */ -void BLI_ghashIterator_step(GHashIterator *ghi); -/** - * Determine if an iterator is done (has reached the end of - * the hash table). - * - * \param ghi The iterator. - * \return True if done, False otherwise. - */ -bool BLI_ghashIterator_done(GHashIterator *ghi); +void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh); +void BLI_ghashIterator_free(GHashIterator *ghi); + +void *BLI_ghashIterator_getKey(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT; +void *BLI_ghashIterator_getValue(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT; +void **BLI_ghashIterator_getValue_p(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT; + +void BLI_ghashIterator_step(GHashIterator *ghi); +bool BLI_ghashIterator_done(GHashIterator *ghi) ATTR_WARN_UNUSED_RESULT; #define GHASH_ITER(gh_iter_, ghash_) \ for (BLI_ghashIterator_init(&gh_iter_, ghash_); \ @@ -149,10 +112,18 @@ int BLI_ghashutil_strcmp(const void *a, const void *b); unsigned int BLI_ghashutil_inthash(const void *ptr); int BLI_ghashutil_intcmp(const void *a, const void *b); -GHash *BLI_ghash_ptr_new(const char *info); -GHash *BLI_ghash_str_new(const char *info); -GHash *BLI_ghash_int_new(const char *info); -GHash *BLI_ghash_pair_new(const char *info); +GHash *BLI_ghash_ptr_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_ptr_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_str_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_str_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_int_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_int_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_pair_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GHash *BLI_ghash_pair_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; typedef struct GHashPair { const void *first; @@ -164,6 +135,62 @@ unsigned int BLI_ghashutil_pairhash(const void *ptr); int BLI_ghashutil_paircmp(const void *a, const void *b); void BLI_ghashutil_pairfree(void *ptr); + +/* *** */ + +typedef struct GSet GSet; + +typedef GHashHashFP GSetHashFP; +typedef GHashCmpFP GSetCmpFP; +typedef GHashKeyFreeFP GSetKeyFreeFP; + +/* so we can cast but compiler sees as different */ +typedef struct GSetIterator { + GHashIterator _ghi +#ifdef __GNUC__ + __attribute__ ((deprecated)) +#endif + ; +} GSetIterator; + +GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +int BLI_gset_size(GSet *gs) ATTR_WARN_UNUSED_RESULT; +void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp); +void BLI_gset_insert(GSet *gh, void *key); +bool BLI_gset_reinsert(GSet *gh, void *key, GSetKeyFreeFP keyfreefp); +bool BLI_gset_haskey(GSet *gs, const void *key) ATTR_WARN_UNUSED_RESULT; +bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp); +void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, + const unsigned int nentries_reserve); +void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp); + +GSet *BLI_gset_ptr_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GSet *BLI_gset_ptr_new(const char *info); +GSet *BLI_gset_pair_new_ex(const char *info, + const unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +GSet *BLI_gset_pair_new(const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; + +/* rely on inline api for now */ +BLI_INLINE GSetIterator *BLI_gsetIterator_new(GSet *gs) { return (GSetIterator *)BLI_ghashIterator_new((GHash *)gs); } +BLI_INLINE void BLI_gsetIterator_init(GSetIterator *gsi, GSet *gs) { BLI_ghashIterator_init((GHashIterator *)gsi, (GHash *)gs); } +BLI_INLINE void BLI_gsetIterator_free(GSetIterator *gsi) { BLI_ghashIterator_free((GHashIterator *)gsi); } +BLI_INLINE void *BLI_gsetIterator_getKey(GSetIterator *gsi) { return BLI_ghashIterator_getKey((GHashIterator *)gsi); } +BLI_INLINE void BLI_gsetIterator_step(GSetIterator *gsi) { BLI_ghashIterator_step((GHashIterator *)gsi); } +BLI_INLINE bool BLI_gsetIterator_done(GSetIterator *gsi) { return BLI_ghashIterator_done((GHashIterator *)gsi); } + +#define GSET_ITER(gs_iter_, gset_) \ + for (BLI_gsetIterator_init(&gs_iter_, gset_); \ + BLI_gsetIterator_done(&gs_iter_) == false; \ + BLI_gsetIterator_step(&gs_iter_)) + +#define GSET_ITER_INDEX(gs_iter_, gset_, i_) \ + for (BLI_gsetIterator_init(&gs_iter_, gset_), i_ = 0; \ + BLI_gsetIterator_done(&gs_iter_) == false; \ + BLI_gsetIterator_step(&gs_iter_), i_++) + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_jitter.h b/source/blender/blenlib/BLI_jitter.h index 432bf73ad90..936a5260a68 100644 --- a/source/blender/blenlib/BLI_jitter.h +++ b/source/blender/blenlib/BLI_jitter.h @@ -33,8 +33,8 @@ */ void BLI_jitter_init(float *jitarr, int num); -void BLI_jitterate1(float *jit1, float *jit2, int num, float rad1); -void BLI_jitterate2(float *jit1, float *jit2, int num, float rad2); +void BLI_jitterate1(float *jit1, float *jit2, int num, float radius1); +void BLI_jitterate2(float *jit1, float *jit2, int num, float radius2); #endif diff --git a/source/blender/blenlib/BLI_kdopbvh.h b/source/blender/blenlib/BLI_kdopbvh.h index 8441413fba9..b55ab432a12 100644 --- a/source/blender/blenlib/BLI_kdopbvh.h +++ b/source/blender/blenlib/BLI_kdopbvh.h @@ -87,7 +87,7 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis); void BLI_bvhtree_free(BVHTree *tree); /* construct: first insert points, then call balance */ -int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints); +void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints); void BLI_bvhtree_balance(BVHTree *tree); /* update: first update points/nodes, then call update_tree to refit the bounding volumes */ diff --git a/source/blender/blenlib/BLI_kdtree.h b/source/blender/blenlib/BLI_kdtree.h index b687d98e6ad..e3c81021351 100644 --- a/source/blender/blenlib/BLI_kdtree.h +++ b/source/blender/blenlib/BLI_kdtree.h @@ -31,6 +31,8 @@ * \author Brecht van Lommel */ +#include "BLI_compiler_attrs.h" + struct KDTree; typedef struct KDTree KDTree; @@ -40,22 +42,19 @@ typedef struct KDTreeNearest { float co[3]; } KDTreeNearest; -/* Creates or free a kdtree */ -KDTree *BLI_kdtree_new(int maxsize); +KDTree *BLI_kdtree_new(unsigned int maxsize); void BLI_kdtree_free(KDTree *tree); -/* Construction: first insert points, then call balance. Normal is optional. */ -void BLI_kdtree_insert(KDTree *tree, int index, const float co[3], const float nor[3]); -void BLI_kdtree_balance(KDTree *tree); - -/* Find nearest returns index, and -1 if no node is found. - * Find n nearest returns number of points found, with results in nearest. - * Normal is optional, but if given will limit results to points in normal direction from co. */ -int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], KDTreeNearest *nearest); -int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const float nor[3], KDTreeNearest *nearest); - -/* Range search returns number of points found, with results in nearest */ -/* Normal is optional, but if given will limit results to points in normal direction from co. */ -/* Remember to free nearest after use! */ -int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const float nor[3], KDTreeNearest **nearest); -#endif +void BLI_kdtree_insert(KDTree *tree, int index, const float co[3], const float nor[3]) ATTR_NONNULL(1, 3); +void BLI_kdtree_balance(KDTree *tree) ATTR_NONNULL(1); + +int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], + KDTreeNearest *r_nearest) ATTR_NONNULL(1, 2); +int BLI_kdtree_find_nearest_n(KDTree *tree, const float co[3], const float nor[3], + KDTreeNearest *r_nearest, + unsigned int n) ATTR_NONNULL(1, 2, 4); +int BLI_kdtree_range_search(KDTree *tree, const float co[3], const float nor[3], + KDTreeNearest **r_nearest, + float range) ATTR_NONNULL(1, 2, 4) ATTR_WARN_UNUSED_RESULT; + +#endif /* __BLI_KDTREE_H__ */ diff --git a/source/blender/blenlib/BLI_lasso.h b/source/blender/blenlib/BLI_lasso.h index 0addd463a70..28f21e5bd85 100644 --- a/source/blender/blenlib/BLI_lasso.h +++ b/source/blender/blenlib/BLI_lasso.h @@ -34,8 +34,8 @@ struct rcti; -void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const short moves); -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); +void BLI_lasso_boundbox(struct rcti *rect, const int mcords[][2], const unsigned int moves); +bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves, const int sx, const int sy, const int error_value); +bool BLI_lasso_is_edge_inside(const int mcords[][2], const unsigned int moves, int x0, int y0, int x1, int y1, const int error_value); #endif diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h index 82ca986d9ca..e9cf820c6c8 100644 --- a/source/blender/blenlib/BLI_linklist_stack.h +++ b/source/blender/blenlib/BLI_linklist_stack.h @@ -81,7 +81,7 @@ BLI_mempool_destroy(_##var##_pool); \ _##var##_pool = NULL; (void)_##var##_pool; \ var = NULL; (void)var; \ - (void)_##var##_type; \ + (void)&(_##var##_type); \ } (void)0 #include "BLI_linklist.h" diff --git a/source/blender/blenlib/BLI_listbase.h b/source/blender/blenlib/BLI_listbase.h index 4c7ddf7ba66..0927620a2c6 100644 --- a/source/blender/blenlib/BLI_listbase.h +++ b/source/blender/blenlib/BLI_listbase.h @@ -60,6 +60,8 @@ void BLI_freelistN(struct ListBase *listbase); void BLI_addtail(struct ListBase *listbase, void *vlink); void BLI_remlink(struct ListBase *listbase, void *vlink); bool BLI_remlink_safe(struct ListBase *listbase, void *vlink); +void *BLI_pophead(ListBase *listbase); +void *BLI_poptail(ListBase *listbase); void BLI_addhead(struct ListBase *listbase, void *vlink); void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink); @@ -72,7 +74,8 @@ void BLI_freelinkN(struct ListBase *listbase, void *vlink); void BLI_movelisttolist(struct ListBase *dst, struct ListBase *src); void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src); void BLI_reverselist(struct ListBase *lb); -void BLI_rotatelist(struct ListBase *lb, void *vlink); +void BLI_rotatelist_first(struct ListBase *lb, void *vlink); +void BLI_rotatelist_last(struct ListBase *lb, void *vlink); /* create a generic list node containing link to provided data */ struct LinkData *BLI_genericNodeN(void *data); diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index 69dbd3253f0..1cb28d25b6c 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -222,6 +222,7 @@ MINLINE int power_of_2_max_i(int n); MINLINE int power_of_2_min_i(int n); MINLINE int divide_round_i(int a, int b); +MINLINE int mod_i(int i, int n); MINLINE float shell_angle_to_dist(const float angle); diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 6cb7103be9b..d3f6c7ef14b 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -34,6 +34,7 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" #include "BLI_math_inline.h" #if BLI_MATH_DO_INLINE @@ -61,6 +62,14 @@ float area_quad_v3(const float a[3], const float b[3], const float c[3], const f float area_poly_v3(int nr, float verts[][3], const float normal[3]); float area_poly_v2(int nr, float verts[][2]); +/********************************* Planes **********************************/ + +void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3]); +void plane_to_point_normal_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3]); +MINLINE float plane_point_side_v3(const float plane[4], const float co[3]); + +/********************************* Volume **********************************/ + float volume_tetrahedron_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]); int is_quad_convex_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]); @@ -73,15 +82,15 @@ float dist_squared_to_line_segment_v2(const float p[2], const float l1[2], const float dist_to_line_segment_v2(const float p[2], const float l1[2], const float l2[2]); void closest_to_line_segment_v2(float closest[2], const float p[2], const float l1[2], const float l2[2]); -float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3]); -float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]); +float dist_squared_to_plane_v3(const float p[3], const float plane[4]); +float dist_to_plane_v3(const float p[3], const float plane[4]); float dist_squared_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]); float dist_to_line_segment_v3(const float p[3], const float l1[3], const float l2[3]); float dist_to_line_v3(const float p[3], const float l1[3], const float l2[3]); float closest_to_line_v3(float r[3], const float p[3], const float l1[3], const float l2[3]); float closest_to_line_v2(float r[2], const float p[2], const float l1[2], const float l2[2]); void closest_to_line_segment_v3(float r[3], const float p[3], const float l1[3], const float l2[3]); -void closest_to_plane_v3(float r[3], const float plane_co[3], const float plane_no_unit[3], const float pt[3]); +void closest_to_plane_v3(float close_r[3], const float plane[4], const float pt[3]); /* Set 'r' to the point in triangle (t1, t2, t3) closest to point 'p' */ void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], const float t2[3], const float t3[3]); @@ -89,6 +98,10 @@ void closest_on_tri_to_point_v3(float r[3], const float p[3], const float t1[3], float line_point_factor_v3(const float p[3], const float l1[3], const float l2[3]); float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2]); + +float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], + const float l1[3], const float l2[3]); + void limit_dist_v3(float v1[3], float v2[3], const float dist); /******************************* Intersection ********************************/ @@ -120,8 +133,9 @@ bool isect_ray_plane_v3(const float p1[3], const float d[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, const int clip); +bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]); bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3], const bool no_flip); + const float plane_co[3], const float plane_no[3]); void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], const float plane_a_co[3], const float plane_a_no[3], @@ -130,6 +144,9 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], /* line/ray triangle */ bool isect_line_tri_v3(const float p1[3], const float p2[3], const float v0[3], const float v1[3], const float v2[3], float *r_lambda, float r_uv[2]); +bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float r_uv[2], const float epsilon); bool isect_ray_tri_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]); bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3], @@ -138,8 +155,8 @@ bool 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); +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned int nr); +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned 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]); @@ -277,11 +294,7 @@ float form_factor_hemi_poly(float p[3], float n[3], bool axis_dominant_v3_to_m3(float r_mat[3][3], const float normal[3]); void axis_dominant_v3(int *r_axis_a, int *r_axis_b, const float axis[3]); -float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -#endif -; +float axis_dominant_v3_max(int *r_axis_a, int *r_axis_b, const float axis[3]) ATTR_WARN_UNUSED_RESULT; MINLINE int max_axis_v3(const float vec[3]); MINLINE int min_axis_v3(const float vec[3]); diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h index 21975763779..543ff1bb38c 100644 --- a/source/blender/blenlib/BLI_math_interp.h +++ b/source/blender/blenlib/BLI_math_interp.h @@ -26,8 +26,8 @@ * */ -#ifndef BLI_MATH_INTERP -#define BLI_MATH_INTERP +#ifndef __BLI_MATH_INTERP__ +#define __BLI_MATH_INTERP__ void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, int components, float u, float v); @@ -41,4 +41,4 @@ void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, int components, float u, float v); -#endif +#endif /* __BLI_MATH_INTERP__ */ diff --git a/source/blender/blenlib/BLI_math_rotation.h b/source/blender/blenlib/BLI_math_rotation.h index b3702d10d87..87c065f3016 100644 --- a/source/blender/blenlib/BLI_math_rotation.h +++ b/source/blender/blenlib/BLI_math_rotation.h @@ -66,7 +66,7 @@ float normalize_qt(float q[4]); float normalize_qt_qt(float q1[4], const float q2[4]); /* comparison */ -int is_zero_qt(float q[4]); +bool is_zero_qt(const float q[4]); /* interpolation */ void interp_qt_qtqt(float q[4], const float a[4], const float b[4], const float t); @@ -163,13 +163,13 @@ typedef struct DualQuat { float scale_weight; } DualQuat; -void copy_dq_dq(DualQuat *r, DualQuat *dq); +void copy_dq_dq(DualQuat *r, const DualQuat *dq); void normalize_dq(DualQuat *dq, float totw); -void add_weighted_dq_dq(DualQuat *r, DualQuat *dq, float weight); +void add_weighted_dq_dq(DualQuat *r, const DualQuat *dq, float weight); void mul_v3m3_dq(float r[3], float R[3][3], DualQuat *dq); void mat4_to_dquat(DualQuat *r, float base[4][4], float M[4][4]); -void dquat_to_mat4(float R[4][4], DualQuat *dq); +void dquat_to_mat4(float R[4][4], const DualQuat *dq); void quat_apply_track(float quat[4], short axis, short upflag); void vec_apply_track(float vec[3], short axis); diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index e163c06440c..675ba88fc72 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -34,6 +34,7 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" #include "BLI_math_inline.h" /************************************* Init ***********************************/ @@ -43,11 +44,6 @@ extern "C" { # pragma GCC diagnostic ignored "-Wredundant-decls" #endif -#ifdef __GNUC__ -# define UNUSED_RESULT_ATTR __attribute__((warn_unused_result)) -#else -# define UNUSED_RESULT_ATTR -#endif MINLINE void zero_v2(float r[2]); MINLINE void zero_v3(float r[3]); @@ -117,10 +113,10 @@ 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]) UNUSED_RESULT_ATTR; -MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) UNUSED_RESULT_ATTR; -MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) UNUSED_RESULT_ATTR; -MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) UNUSED_RESULT_ATTR; +MINLINE float mul_project_m4_v3_zfac(float mat[4][4], const float co[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float dot_m3_v3_row_x(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float dot_m3_v3_row_y(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float dot_m3_v3_row_z(float M[3][3], const float a[3]) ATTR_WARN_UNUSED_RESULT; 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]); @@ -139,10 +135,10 @@ MINLINE void negate_v4_v4(float r[4], const float a[3]); MINLINE void negate_v3_short(short r[3]); -MINLINE float dot_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; -MINLINE float dot_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR; +MINLINE float dot_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE float cross_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; +MINLINE float cross_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; MINLINE void cross_v3_v3v3(float r[3], const float a[3], const float b[3]); MINLINE void add_newell_cross_v3_v3v3(float n[3], const float v_prev[3], const float v_curr[3]); @@ -151,20 +147,20 @@ MINLINE void star_m3_v3(float rmat[3][3], float a[3]); /*********************************** Length **********************************/ -MINLINE float len_squared_v2(const float v[2]) UNUSED_RESULT_ATTR; -MINLINE float len_squared_v3(const float v[3]) UNUSED_RESULT_ATTR; -MINLINE float len_manhattan_v2(const float v[2]) UNUSED_RESULT_ATTR; -MINLINE int len_manhattan_v2_int(const int v[2]) UNUSED_RESULT_ATTR; -MINLINE float len_manhattan_v3(const float v[3]) UNUSED_RESULT_ATTR; -MINLINE float len_v2(const float a[2]) UNUSED_RESULT_ATTR; -MINLINE float len_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; -MINLINE float len_squared_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; -MINLINE float len_squared_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR; -MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; -MINLINE int len_manhattan_v2v2_int(const int a[2], const int b[2]) UNUSED_RESULT_ATTR; -MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR; -MINLINE float len_v3(const float a[3]) UNUSED_RESULT_ATTR; -MINLINE float len_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR; +MINLINE float len_squared_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_manhattan_v2(const float v[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE int len_manhattan_v2_int(const int v[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_manhattan_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_v2(const float a[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_squared_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_manhattan_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE int len_manhattan_v2v2_int(const int a[2], const int b[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_manhattan_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; MINLINE float normalize_v2(float r[2]); MINLINE float normalize_v2_v2(float r[2], const float a[2]); @@ -196,35 +192,41 @@ void flip_v2_v2v2(float v[2], const float v1[2], const float v2[2]); /********************************* Comparison ********************************/ -MINLINE int is_zero_v3(const float a[3]) UNUSED_RESULT_ATTR; -MINLINE int is_zero_v4(const float a[4]) UNUSED_RESULT_ATTR; -MINLINE int is_one_v3(const float a[3]) UNUSED_RESULT_ATTR; +MINLINE bool is_zero_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_zero_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT; + +MINLINE bool is_finite_v2(const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_finite_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool is_finite_v4(const float a[4]) ATTR_WARN_UNUSED_RESULT; + +MINLINE bool is_one_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT; -MINLINE int equals_v2v2(const float v1[2], const float v2[2]) UNUSED_RESULT_ATTR; -MINLINE int equals_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR; -MINLINE int compare_v2v2(const float a[2], const float b[2], const float limit) UNUSED_RESULT_ATTR; -MINLINE int compare_v3v3(const float a[3], const float b[3], const float limit) UNUSED_RESULT_ATTR; -MINLINE int compare_len_v3v3(const float a[3], const float b[3], const float limit) UNUSED_RESULT_ATTR; +MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool equals_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; +MINLINE bool compare_v2v2(const float a[2], const float b[2], const float limit) ATTR_WARN_UNUSED_RESULT; +MINLINE bool compare_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT; +MINLINE bool compare_len_v3v3(const float a[3], const float b[3], const float limit) ATTR_WARN_UNUSED_RESULT; -MINLINE int compare_v4v4(const float a[4], const float b[4], const float limit) UNUSED_RESULT_ATTR; -MINLINE int equals_v4v4(const float a[4], const float b[4]) UNUSED_RESULT_ATTR; +MINLINE bool compare_v4v4(const float a[4], const float b[4], const float limit) ATTR_WARN_UNUSED_RESULT; +MINLINE bool equals_v4v4(const float a[4], const float b[4]) ATTR_WARN_UNUSED_RESULT; -MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) UNUSED_RESULT_ATTR; +MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) ATTR_WARN_UNUSED_RESULT; /********************************** Angles ***********************************/ /* - angle with 2 arguments is angle between vector */ /* - angle with 3 arguments is angle between 3 points at the middle point */ /* - angle_normalized_* is faster equivalent if vectors are normalized */ -float angle_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; -float angle_signed_v2v2(const float v1[2], const float v2[2]) UNUSED_RESULT_ATTR; -float angle_v2v2v2(const float a[2], const float b[2], const float c[2]) UNUSED_RESULT_ATTR; -float angle_normalized_v2v2(const float a[2], const float b[2]) UNUSED_RESULT_ATTR; -float angle_v3v3(const float a[3], const float b[3]) UNUSED_RESULT_ATTR; -float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) UNUSED_RESULT_ATTR; -float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) UNUSED_RESULT_ATTR; -float angle_normalized_v3v3(const float v1[3], const float v2[3]) UNUSED_RESULT_ATTR; -float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) UNUSED_RESULT_ATTR; +float angle_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +float angle_signed_v2v2(const float v1[2], const float v2[2]) ATTR_WARN_UNUSED_RESULT; +float angle_v2v2v2(const float a[2], const float b[2], const float c[2]) ATTR_WARN_UNUSED_RESULT; +float angle_normalized_v2v2(const float a[2], const float b[2]) ATTR_WARN_UNUSED_RESULT; +float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT; +float angle_v3v3v3(const float a[3], const float b[3], const float c[3]) ATTR_WARN_UNUSED_RESULT; +float cos_v3v3v3(const float p1[3], const float p2[3], const float p3[3]) ATTR_WARN_UNUSED_RESULT; +float angle_normalized_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT; +float angle_on_axis_v3v3v3_v3(const float v1[3], const float v2[3], const float v3[3], const float axis[3]) ATTR_WARN_UNUSED_RESULT; void angle_tri_v3(float angles[3], const float v1[3], const float v2[3], const float v3[3]); void angle_quad_v3(float angles[4], const float v1[3], const float v2[3], const float v3[3], const float v4[3]); void angle_poly_v3(float *angles, const float *verts[3], int len); @@ -260,7 +262,7 @@ void axis_sort_v3(const float axis_values[3], int r_axis_order[3]); /***************************** Array Functions *******************************/ /* attempted to follow fixed length vertex functions. names could be improved*/ -double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) UNUSED_RESULT_ATTR; +double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) ATTR_WARN_UNUSED_RESULT; float normalize_vn_vn(float *array_tar, const float *array_src, const int size); float normalize_vn(float *array_tar, const int size); void range_vn_i(int *array_tar, const int size, const int start); @@ -291,7 +293,6 @@ void fill_vn_fl(float *array_tar, const int size, const float val); #ifdef BLI_MATH_GCC_WARN_PRAGMA # pragma GCC diagnostic pop #endif -#undef UNUSED_RESULT_ATTR #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index d54dab42e05..9ff4883c89c 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -41,62 +41,28 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + /* A reasonable standard buffer size, big * enough to not cause much internal fragmentation, * small enough not to waste resources */ #define BLI_MEMARENA_STD_BUFSIZE (1 << 14) -/* some GNU attributes are only available from GCC 4.3 */ -#define MEM_GNU_ATTRIBUTES (defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 403)) - struct MemArena; typedef struct MemArena MemArena; -struct MemArena *BLI_memarena_new(const int bufsize, const char *name) -#if MEM_GNU_ATTRIBUTES -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull(2))) -#endif -; - -void BLI_memarena_free(struct MemArena *ma) -#if MEM_GNU_ATTRIBUTES -__attribute__((nonnull(1))) -#endif -; - -void BLI_memarena_use_malloc(struct MemArena *ma) -#if MEM_GNU_ATTRIBUTES -__attribute__((nonnull(1))) -#endif -; -void BLI_memarena_use_calloc(struct MemArena *ma) -#if MEM_GNU_ATTRIBUTES -__attribute__((nonnull(1))) -#endif -; - -void BLI_memarena_use_align(struct MemArena *ma, const int align) -#if MEM_GNU_ATTRIBUTES -__attribute__((nonnull(1))) -#endif -; +struct MemArena *BLI_memarena_new(const int bufsize, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(2) ATTR_MALLOC; +void BLI_memarena_free(struct MemArena *ma) ATTR_NONNULL(1); +void BLI_memarena_use_malloc(struct MemArena *ma) ATTR_NONNULL(1); +void BLI_memarena_use_calloc(struct MemArena *ma) ATTR_NONNULL(1); +void BLI_memarena_use_align(struct MemArena *ma, const int align) ATTR_NONNULL(1); +void *BLI_memarena_alloc(struct MemArena *ma, int size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2); -void *BLI_memarena_alloc(struct MemArena *ma, int size) -#if MEM_GNU_ATTRIBUTES -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull(1))) -__attribute__((alloc_size(2))) -#endif -; +void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1); #ifdef __cplusplus } #endif - -#endif - +#endif /* __BLI_MEMARENA_H__ */ diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 1c470d59062..88650719712 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -39,6 +39,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct BLI_mempool; struct BLI_mempool_chunk; @@ -48,81 +50,29 @@ typedef struct BLI_mempool BLI_mempool; * first four bytes of the elements never contain the character string * 'free'. use with care.*/ -BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -#endif -; -void *BLI_mempool_alloc(BLI_mempool *pool) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull(1))) -#endif -; -void *BLI_mempool_calloc(BLI_mempool *pool) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull(1))) -#endif -; -void BLI_mempool_free(BLI_mempool *pool, void *addr) -#ifdef __GNUC__ -__attribute__((nonnull(1, 2))) -#endif -; -void BLI_mempool_destroy(BLI_mempool *pool) -#ifdef __GNUC__ -__attribute__((nonnull(1))) -#endif -; -int BLI_mempool_count(BLI_mempool *pool) -#ifdef __GNUC__ -__attribute__((nonnull(1))) -#endif -; -void *BLI_mempool_findelem(BLI_mempool *pool, int index) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull(1))) -#endif -; -void BLI_mempool_as_table(BLI_mempool *pool, void **data) -#ifdef __GNUC__ -__attribute__((nonnull(1, 2))) -#endif -; - -void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull(1, 2))) -#endif -; - -void BLI_mempool_as_array(BLI_mempool *pool, void *data) -#ifdef __GNUC__ -__attribute__((nonnull(1, 2))) -#endif -; +BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem, + unsigned int pchunk, unsigned int flag) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +void *BLI_mempool_alloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void *BLI_mempool_calloc(BLI_mempool *pool) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void BLI_mempool_free(BLI_mempool *pool, void *addr) ATTR_NONNULL(1, 2); +void BLI_mempool_clear_ex(BLI_mempool *pool, + const int totelem_reserve) ATTR_NONNULL(1); +void BLI_mempool_clear(BLI_mempool *pool) ATTR_NONNULL(1); +void BLI_mempool_destroy(BLI_mempool *pool) ATTR_NONNULL(1); +int BLI_mempool_count(BLI_mempool *pool) ATTR_NONNULL(1); +void *BLI_mempool_findelem(BLI_mempool *pool, unsigned int index) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); -void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull(1, 2))) -#endif -; +void BLI_mempool_as_table(BLI_mempool *pool, void **data) ATTR_NONNULL(1, 2); +void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); +void BLI_mempool_as_array(BLI_mempool *pool, void *data) ATTR_NONNULL(1, 2); +void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1, 2); /** iteration stuff. note: this may easy to produce bugs with **/ /* private structure */ typedef struct BLI_mempool_iter { BLI_mempool *pool; struct BLI_mempool_chunk *curchunk; - int curindex; + unsigned int curindex; } BLI_mempool_iter; /* flag */ @@ -131,17 +81,8 @@ enum { BLI_MEMPOOL_ALLOW_ITER = (1 << 1) }; -void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) -#ifdef __GNUC__ -__attribute__((nonnull(1, 2))) -#endif -; -void *BLI_mempool_iterstep(BLI_mempool_iter *iter) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull(1))) -#endif -; +void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL(); +void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index cb812fe8595..d4c5d5fed9f 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -35,6 +35,8 @@ extern "C" { #endif +#include "BLI_compiler_attrs.h" + struct ListBase; struct direntry; @@ -90,17 +92,9 @@ void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t d 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_path_append(char *__restrict dst, const size_t maxlen, - const char *__restrict file) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; + const char *__restrict file) ATTR_NONNULL(); void BLI_join_dirfile(char *__restrict string, const size_t maxlen, - const char *__restrict dir, const char *__restrict file) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; + const char *__restrict dir, const char *__restrict file) ATTR_NONNULL(); const char *BLI_path_basename(const char *path); typedef enum bli_rebase_state { @@ -122,6 +116,7 @@ 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); +bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename); 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); @@ -131,11 +126,7 @@ void BLI_stringenc(char *string, const char *head, const char *tail, unsigned sh int BLI_split_name_num(char *left, int *nr, const char *name, const char delim); /* make sure path separators conform to system one */ -void BLI_clean(char *path) -#ifdef __GNUC__ -__attribute__((nonnull(1))) -#endif -; +void BLI_clean(char *path) ATTR_NONNULL(); /** * dir can be any input, like from buttons, and this function @@ -181,11 +172,7 @@ bool BLI_path_is_rel(const char *path); # define BLI_path_ncmp strncmp #endif -void BLI_char_switch(char *string, char from, char to) -#ifdef __GNUC__ -__attribute__((nonnull(1))) -#endif -; +void BLI_char_switch(char *string, char from, char to) ATTR_NONNULL(); /* Initialize path to program executable */ void BLI_init_program_path(const char *argv0); diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 21197670640..e7d2130e473 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -46,20 +46,13 @@ typedef struct ScanFillContext { ListBase filledgebase; ListBase fillfacebase; - /* simple optimization for allocating thousands of small memory blocks - * only to be used within loops, and not by one function at a time - * free in the end, with argument '-1' - */ -#define MEM_ELEM_BLOCKSIZE 16384 - struct mem_elements *melem__cur; - int melem__offs; /* the current free address */ - ListBase melem__lb; - /* private */ struct ScanFillVertLink *_scdata; + struct MemArena *arena; } ScanFillContext; -/* note; changing this also might affect the undo copy in editmesh.c */ +#define BLI_SCANFILL_ARENA_SIZE 16384 + typedef struct ScanFillVert { struct ScanFillVert *next, *prev; union { @@ -68,10 +61,10 @@ typedef struct ScanFillVert { intptr_t l; unsigned int u; } tmp; - float co[3]; /* vertex location */ - float xy[2]; /* 2D copy of vertex location (using dominant axis) */ - unsigned int keyindex; /* original index #, for restoring key information */ - short poly_nr; + float co[3]; /* vertex location */ + float xy[2]; /* 2D projection of vertex location */ + unsigned int keyindex; /* index, caller can use how it likes to match the scanfill result with own data */ + unsigned short poly_nr; unsigned char edge_tot; /* number of edges using this vertex */ unsigned char f; } ScanFillVert; @@ -79,7 +72,7 @@ typedef struct ScanFillVert { typedef struct ScanFillEdge { struct ScanFillEdge *next, *prev; struct ScanFillVert *v1, *v2; - short poly_nr; + unsigned short poly_nr; unsigned char f; union { unsigned char c; @@ -91,7 +84,7 @@ typedef struct ScanFillFace { struct ScanFillVert *v1, *v2, *v3; } ScanFillFace; -/* scanfill.c: used in displist only... */ +/* scanfill.c */ struct ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]); struct ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, struct ScanFillVert *v1, struct ScanFillVert *v2); @@ -108,11 +101,14 @@ enum { BLI_SCANFILL_CALC_HOLES = (1 << 2) }; void BLI_scanfill_begin(ScanFillContext *sf_ctx); -int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag); -int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, +unsigned int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag); +unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]); void BLI_scanfill_end(ScanFillContext *sf_ctx); +void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, struct MemArena *arena); +void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, struct MemArena *arena); + /* These callbacks are needed to make the lib finction properly */ void BLI_setErrorCallBack(void (*f)(const char *)); diff --git a/source/blender/blenlib/BLI_smallhash.h b/source/blender/blenlib/BLI_smallhash.h index 275599a612c..4f5446043da 100644 --- a/source/blender/blenlib/BLI_smallhash.h +++ b/source/blender/blenlib/BLI_smallhash.h @@ -37,6 +37,8 @@ /* based on a doubling non-chaining approach */ +#include "BLI_compiler_attrs.h" + typedef struct { uintptr_t key; void *val; @@ -59,27 +61,15 @@ typedef struct { unsigned int i; } SmallHashIter; -#ifdef __GNUC__ -# define ATTR_NONULL_FIRST __attribute__((nonnull(1))) -# define ATTR_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -# define ATTR_NONULL_FIRST -# define ATTR_UNUSED_RESULT -#endif - - -void BLI_smallhash_init(SmallHash *hash) ATTR_NONULL_FIRST; -void BLI_smallhash_release(SmallHash *hash) ATTR_NONULL_FIRST; -void BLI_smallhash_insert(SmallHash *hash, uintptr_t key, void *item) ATTR_NONULL_FIRST; -void BLI_smallhash_remove(SmallHash *hash, uintptr_t key) ATTR_NONULL_FIRST; -void *BLI_smallhash_lookup(SmallHash *hash, uintptr_t key) ATTR_NONULL_FIRST ATTR_UNUSED_RESULT; -int BLI_smallhash_haskey(SmallHash *hash, uintptr_t key) ATTR_NONULL_FIRST; -int BLI_smallhash_count(SmallHash *hash) ATTR_NONULL_FIRST; -void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONULL_FIRST ATTR_UNUSED_RESULT; -void *BLI_smallhash_iternew(SmallHash *hash, SmallHashIter *iter, uintptr_t *key) ATTR_NONULL_FIRST ATTR_UNUSED_RESULT; +void BLI_smallhash_init(SmallHash *hash) ATTR_NONNULL(1); +void BLI_smallhash_release(SmallHash *hash) ATTR_NONNULL(1); +void BLI_smallhash_insert(SmallHash *hash, uintptr_t key, void *item) ATTR_NONNULL(1); +void BLI_smallhash_remove(SmallHash *hash, uintptr_t key) ATTR_NONNULL(1); +void *BLI_smallhash_lookup(SmallHash *hash, uintptr_t key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; +int BLI_smallhash_haskey(SmallHash *hash, uintptr_t key) ATTR_NONNULL(1); +int BLI_smallhash_count(SmallHash *hash) ATTR_NONNULL(1); +void *BLI_smallhash_iternext(SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; +void *BLI_smallhash_iternew(SmallHash *hash, SmallHashIter *iter, uintptr_t *key) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; /* void BLI_smallhash_print(SmallHash *hash); */ /* UNUSED */ -#undef ATTR_NONULL_FIRST -#undef ATTR_UNUSED_RESULT - #endif /* __BLI_SMALLHASH_H__ */ diff --git a/source/blender/compositor/operations/COM_MixBlendOperation.h b/source/blender/blenlib/BLI_sort.h index ce3f187a5e2..4df17d98a4b 100644 --- a/source/blender/compositor/operations/COM_MixBlendOperation.h +++ b/source/blender/blenlib/BLI_sort.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, Blender Foundation. + * ***** 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 @@ -15,31 +15,31 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor: - * Jeroen Bakker - * Monique Dewanchand + * The Original Code is Copyright (C) 2013 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Benoit Bolsee, + * Sergey Sharybin. + * + * ***** END GPL LICENSE BLOCK ***** */ -#ifndef _COM_MixBlendOperation_h -#define _COM_MixBlendOperation_h -#include "COM_MixBaseOperation.h" +#ifndef __BLI_SORT_H__ +#define __BLI_SORT_H__ - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. +/** \file BLI_sort.h + * \ingroup bli */ -class MixBlendOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixBlendOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); -}; +/* Quick sort reentrant */ +typedef int (*BLI_sort_cmp_t)(void *ctx, const void *a, const void *b); + +void BLI_qsort_r(void *a, size_t n, size_t es, void *thunk, BLI_sort_cmp_t cmp) +#ifdef __GNUC__ +__attribute__((nonnull(1, 5))) #endif +; + +#endif /* __BLI_SORT_H__ */ diff --git a/source/blender/blenlib/BLI_sort_utils.h b/source/blender/blenlib/BLI_sort_utils.h new file mode 100644 index 00000000000..e08f4e5ac83 --- /dev/null +++ b/source/blender/blenlib/BLI_sort_utils.h @@ -0,0 +1,61 @@ +/* + * ***** 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_SORT_UTILS_H__ +#define __BLI_SORT_UTILS_H__ + +/** \file BLI_sort_utils.h + * \ingroup bli + */ + +/** + * \note keep \a sort_value first, + * so cmp functions can be reused. + */ +struct SortPointerByFloat { + float sort_value; + void *data; +}; + +struct SortIntByFloat { + float sort_value; + int data; +}; + +struct SortPointerByInt { + int sort_value; + void *data; +}; + +struct SortIntByInt { + int sort_value; + int data; +}; + +int BLI_sortutil_cmp_float(const void *a_, const void *b_); +int BLI_sortutil_cmp_float_reverse(const void *a_, const void *b_); + +int BLI_sortutil_cmp_int(const void *a_, const void *b_); +int BLI_sortutil_cmp_int_reverse(const void *a_, const void *b_); + +#endif /* __BLI_SORT_UTILS_H__ */ diff --git a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h b/source/blender/blenlib/BLI_strict_flags.h index 9d3ab156555..5c5a6f45f0c 100644 --- a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.h +++ b/source/blender/blenlib/BLI_strict_flags.h @@ -1,5 +1,5 @@ /* - * Copyright 2012, Blender Foundation. + * ***** 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 @@ -15,34 +15,27 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor: - * Dalai Felinto + * ***** END GPL LICENSE BLOCK ***** */ -#ifndef _COM_ConvertPremulToStraightOperation_h -#define _COM_ConvertPremulToStraightOperation_h -#include "COM_NodeOperation.h" +#ifndef __BLI_STRICT_FLAGS_H__ +#define __BLI_STRICT_FLAGS_H__ - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. +/** \file BLI_strict_flags.h + * \ingroup bli + * \brief Strict compiler flags for areas of code we want + * to ensure don't do conversions without us knowing about it. */ -class ConvertPremulToStraightOperation : public NodeOperation { -private: - SocketReader *m_inputColor; -public: - /** - * Default constructor - */ - ConvertPremulToStraightOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); -}; +#ifdef __GNUC__ +# pragma GCC diagnostic error "-Wsign-conversion" +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ +# pragma GCC diagnostic error "-Wsign-compare" +# pragma GCC diagnostic error "-Wconversion" +# endif +# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 /* gcc4.8+ only (behavior changed to ignore globals)*/ +# pragma GCC diagnostic error "-Wshadow" +# endif #endif + +#endif /* __BLI_STRICT_FLAGS_H__ */ diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 6c66d2f4e18..b995f2565e1 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -38,152 +38,43 @@ extern "C" { #endif -char *BLI_strdupn(const char *str, const size_t len) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +#include "BLI_compiler_attrs.h" -char *BLI_strdup(const char *str) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +char *BLI_strdupn(const char *str, const size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +char *BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; -char *BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +char *BLI_strdupcat(const char *__restrict str1, const char *__restrict str2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; -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_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL(); -size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +size_t BLI_strncpy_rlen(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +size_t BLI_strcpy_rlen(char *__restrict dst, const char *__restrict src) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +char *BLI_str_quoted_substrN(const char *__restrict str, const char *__restrict prefix) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; -size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 3, 4))) -__attribute__((nonnull)) -#endif -; +char *BLI_replacestrN(const char *__restrict str, const char *__restrict substr_old, const char *__restrict substr_new) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC; -size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) -#ifdef __GNUC__ -__attribute__ ((format(printf, 3, 0))) -#endif -; - -char *BLI_sprintfN(const char *__restrict format, ...) -#ifdef __GNUC__ -__attribute__((malloc)) -__attribute__ ((format(printf, 1, 2))) -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, ...) ATTR_NONNULL() ATTR_PRINTF_FORMAT(3, 4); -size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +size_t BLI_vsnprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format, va_list arg) ATTR_PRINTF_FORMAT(3, 0); -int BLI_strcaseeq(const char *a, const char *b) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; +char *BLI_sprintfN(const char *__restrict format, ...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC ATTR_PRINTF_FORMAT(1, 2); -char *BLI_strcasestr(const char *s, const char *find) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -int BLI_strcasecmp(const char *s1, const char *s2) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -int BLI_strncasecmp(const char *s1, const char *s2, size_t len) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -int BLI_natstrcmp(const char *s1, const char *s2) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -size_t BLI_strnlen(const char *str, const size_t maxlen) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -__attribute__((nonnull)) -#endif -; -void BLI_timestr(double _time, char *str, size_t maxlen) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +size_t BLI_strescape(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL(); -void BLI_ascii_strtolower(char *str, const size_t len) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; -void BLI_ascii_strtoupper(char *str, const size_t len) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; -int BLI_str_rstrip_float_zero(char *str, const char pad) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +int BLI_strcaseeq(const char *a, const char *b) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +char *BLI_strcasestr(const char *s, const char *find) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +int BLI_natstrcmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +size_t BLI_strnlen(const char *str, const size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BLI_timestr(double _time, char *str, size_t maxlen) ATTR_NONNULL(); + +void BLI_ascii_strtolower(char *str, const size_t len) ATTR_NONNULL(); +void BLI_ascii_strtoupper(char *str, const size_t len) ATTR_NONNULL(); +int BLI_str_rstrip_float_zero(char *str, const char pad) ATTR_NONNULL(); #ifdef __cplusplus } diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index db32190494a..4aef2318683 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -31,57 +31,45 @@ extern "C" { #endif -#ifdef __GNUC__ -# define ATTR_NONULL __attribute__((nonnull)) -# define ATTR_NONULL_FIRST __attribute__((nonnull(1))) -# define ATTR_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -# define ATTR_NONULL -# define ATTR_NONULL_FIRST -# define ATTR_UNUSED_RESULT -#endif +#include "BLI_compiler_attrs.h" -char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONULL; -char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONULL; -int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONULL; -int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONULL; +char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL(); +char *BLI_strncat_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL(); +int BLI_utf8_invalid_byte(const char *str, int length) ATTR_NONNULL(); +int BLI_utf8_invalid_strip(char *str, int length) ATTR_NONNULL(); -int BLI_str_utf8_size(const char *p) ATTR_NONULL; /* warning, can return -1 on bad chars */ -int BLI_str_utf8_size_safe(const char *p) ATTR_NONULL; +int BLI_str_utf8_size(const char *p) ATTR_NONNULL(); /* warning, can return -1 on bad chars */ +int BLI_str_utf8_size_safe(const char *p) ATTR_NONNULL(); /* copied from glib */ -unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONULL; -unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) ATTR_NONULL; -unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) ATTR_NONULL; -unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) ATTR_NONULL; +unsigned int BLI_str_utf8_as_unicode(const char *p) ATTR_NONNULL(); +unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index) ATTR_NONNULL(); +unsigned int BLI_str_utf8_as_unicode_and_size_safe(const char *__restrict p, size_t *__restrict index) ATTR_NONNULL(); +unsigned int BLI_str_utf8_as_unicode_step(const char *__restrict p, size_t *__restrict index) ATTR_NONNULL(); size_t BLI_str_utf8_from_unicode(unsigned int c, char *outbuf); -char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONULL; -char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONULL_FIRST; -char *BLI_str_prev_char_utf8(const char *p) ATTR_NONULL; +char *BLI_str_find_prev_char_utf8(const char *str, const char *p) ATTR_NONNULL(); +char *BLI_str_find_next_char_utf8(const char *p, const char *end) ATTR_NONNULL(1); +char *BLI_str_prev_char_utf8(const char *p) ATTR_NONNULL(); /* wchar_t functions, copied from blenders own font.c originally */ -size_t BLI_wstrlen_utf8(const wchar_t *src) ATTR_NONULL; -size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONULL; -size_t BLI_strlen_utf8(const char *strc) ATTR_NONULL; -size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) ATTR_NONULL; -size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) ATTR_NONULL; -size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy) ATTR_NONULL; -size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy) ATTR_NONULL; +size_t BLI_wstrlen_utf8(const wchar_t *src) ATTR_NONNULL(); +size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONNULL(); +size_t BLI_strlen_utf8(const char *strc) ATTR_NONNULL(); +size_t BLI_strnlen_utf8_ex(const char *strc, const size_t maxlen, size_t *r_len_bytes) ATTR_NONNULL(); +size_t BLI_strnlen_utf8(const char *strc, const size_t maxlen) ATTR_NONNULL(); +size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, const size_t maxcpy) ATTR_NONNULL(); +size_t BLI_strncpy_wchar_from_utf8(wchar_t *__restrict dst, const char *__restrict src, const size_t maxcpy) ATTR_NONNULL(); /* 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) ATTR_NONULL; -int BLI_str_utf8_char_width(const char *p) ATTR_NONULL; /* warning, can return -1 on bad chars */ -int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONULL; +int BLI_wcswidth(const wchar_t *pwcs, size_t n) ATTR_NONNULL(); +int BLI_str_utf8_char_width(const char *p) ATTR_NONNULL(); /* warning, can return -1 on bad chars */ +int BLI_str_utf8_char_width_safe(const char *p) ATTR_NONNULL(); #define BLI_UTF8_MAX 6 /* mem */ #define BLI_UTF8_WIDTH_MAX 2 /* columns */ #define BLI_UTF8_ERR ((unsigned int)-1) -#undef ATTR_NONULL -#undef ATTR_NONULL_FIRST -#undef ATTR_UNUSED_RESULT - #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index 154986936a2..38ad0827246 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -50,6 +50,7 @@ struct ListBase; /*this is run once at startup*/ void BLI_threadapi_init(void); +void BLI_threadapi_exit(void); void BLI_init_threads(struct ListBase *threadbase, void *(*do_thread)(void *), int tot); int BLI_available_threads(struct ListBase *threadbase); diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index 327a997bf39..c3a3c035ed3 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -337,12 +337,6 @@ # define UNUSED_FUNCTION(x) UNUSED_ ## x #endif -#ifdef __GNUC__ -# define WARN_UNUSED __attribute__((warn_unused_result)) -#else -# define WARN_UNUSED -#endif - /*little macro so inline keyword works*/ #if defined(_MSC_VER) # define BLI_INLINE static __forceinline diff --git a/source/blender/blenlib/BLI_winstuff.h b/source/blender/blenlib/BLI_winstuff.h index 20a4c3c274e..e75ec7eef2c 100644 --- a/source/blender/blenlib/BLI_winstuff.h +++ b/source/blender/blenlib/BLI_winstuff.h @@ -100,7 +100,6 @@ extern "C" { // not accepted by access() on windows //# define X_OK 1 # define F_OK 0 -# define PATH_MAX 4096 #endif #ifndef FREE_WINDOWS diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 8b604e41824..82f07268521 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -86,6 +86,8 @@ set(SRC intern/rct.c intern/scanfill.c intern/smallhash.c + intern/sort.c + intern/sort_utils.c intern/stack.c intern/storage.c intern/string.c @@ -98,14 +100,15 @@ set(SRC intern/voxel.c intern/winstuff.c - BLI_args.h BLI_alloca.h + BLI_args.h BLI_array.h BLI_bitmap.h BLI_blenlib.h - BLI_buffer.h BLI_boxpack2d.h + BLI_buffer.h BLI_callbacks.h + BLI_compiler_attrs.h BLI_cpu.h BLI_dlrbTree.h BLI_dynlib.h @@ -147,7 +150,10 @@ set(SRC BLI_rect.h BLI_scanfill.h BLI_smallhash.h + BLI_sort.h + BLI_sort_utils.h BLI_stack.h + BLI_strict_flags.h BLI_string.h BLI_string_cursor_utf8.h BLI_string_utf8.h @@ -160,6 +166,7 @@ set(SRC BLI_voxel.h BLI_winstuff.h PIL_time.h + PIL_time_utildefines.h ) if(WITH_BINRELOC) diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h index c3e7e8486d9..158559fa3d9 100644 --- a/source/blender/blenlib/PIL_time.h +++ b/source/blender/blenlib/PIL_time.h @@ -51,44 +51,8 @@ double PIL_check_seconds_timer(void); */ void PIL_sleep_ms(int ms); -/** Utility defines for timing. - * requires BLI_utildefines.h for 'AT' - * TIMEIT_VALUE returns the time since TIMEIT_START was called. - */ -#define TIMEIT_START(var) \ - { \ - double _timeit_##var = PIL_check_seconds_timer(); \ - printf("time start (" #var "): " AT "\n"); \ - fflush(stdout); \ - { (void)0 - -#define TIMEIT_VALUE(var) (float)(PIL_check_seconds_timer() - _timeit_##var) - -#define TIMEIT_VALUE_PRINT(var) \ - { \ - printf("time update(" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var));\ - fflush(stdout); \ - } (void)0 - -#define TIMEIT_END(var) \ - } \ - printf("time end (" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var)); \ - fflush(stdout); \ -} (void)0 - -/** - * Given some function/expression: - * TIMEIT_BENCH(some_function(), some_unique_description); - */ -#define TIMEIT_BENCH(expr, id) \ - { \ - TIMEIT_START(id); \ - (expr); \ - TIMEIT_END(id); \ - } (void)0 - #ifdef __cplusplus } #endif -#endif /* !__PIL_TIME_H__ */ +#endif /* __PIL_TIME_H__ */ diff --git a/source/blender/blenlib/PIL_time_utildefines.h b/source/blender/blenlib/PIL_time_utildefines.h new file mode 100644 index 00000000000..c253aba875f --- /dev/null +++ b/source/blender/blenlib/PIL_time_utildefines.h @@ -0,0 +1,95 @@ +/* + * ***** 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): Campbell Barton + * Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/PIL_time_utildefines.h + * \ingroup bli + * \brief Utility defines for timing/benchmarks. + * + * \note requires BLI_utildefines.h for 'AT'. + */ + +#ifndef __PIL_TIME_UTILDEFINES_H__ +#define __PIL_TIME_UTILDEFINES_H__ + +#define TIMEIT_START(var) \ + { \ + double _timeit_##var = PIL_check_seconds_timer(); \ + printf("time start (" #var "): " AT "\n"); \ + fflush(stdout); \ + { (void)0 + +/** + * \return the time since TIMEIT_START was called. + */ +#define TIMEIT_VALUE(var) (float)(PIL_check_seconds_timer() - _timeit_##var) + +#define TIMEIT_VALUE_PRINT(var) \ + { \ + printf("time update(" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var));\ + fflush(stdout); \ + } (void)0 + +#define TIMEIT_END(var) \ + } \ + printf("time end (" #var "): %.6f" " " AT "\n", TIMEIT_VALUE(var)); \ + fflush(stdout); \ +} (void)0 + +/** + * Given some function/expression: + * TIMEIT_BENCH(some_function(), some_unique_description); + */ +#define TIMEIT_BENCH(expr, id) \ + { \ + TIMEIT_START(id); \ + (expr); \ + TIMEIT_END(id); \ + } (void)0 + +#define TIMEIT_BLOCK_INIT(id) \ + double _timeit_var_##id = 0; \ + (void) 0 + +#define TIMEIT_BLOCK_START(id) \ + { \ + double _timeit_block_start_##id = PIL_check_seconds_timer(); \ + { (void)0 + +#define TIMEIT_BLOCK_END(id) \ + } \ + _timeit_var_##id += (PIL_check_seconds_timer() - \ + _timeit_block_start_##id); \ + } (void)0 + +#define TIMEIT_BLOCK_STATS(id) \ + { \ + printf("%s time (in seconds): %f\n", #id, _timeit_var_##id); \ + fflush(stdout); \ + } (void)0 + +#endif /* __PIL_TIME_UTILDEFINES_H__ */ diff --git a/source/blender/blenlib/intern/BLI_ghash.c b/source/blender/blenlib/intern/BLI_ghash.c index 8221393d4d5..fcca6cd59ba 100644 --- a/source/blender/blenlib/intern/BLI_ghash.c +++ b/source/blender/blenlib/intern/BLI_ghash.c @@ -43,16 +43,8 @@ #include "BLI_utildefines.h" #include "BLI_mempool.h" #include "BLI_ghash.h" +#include "BLI_strict_flags.h" -/***/ - -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif const unsigned int hashsizes[] = { 5, 11, 17, 37, 67, 131, 257, 521, 1031, 2053, 4099, 8209, @@ -61,6 +53,16 @@ const unsigned int hashsizes[] = { 268435459 }; +/* internal flag to ensure sets values aren't used */ +#ifndef NDEBUG +# define GHASH_FLAG_IS_SET (1 << 8) +# define IS_GHASH_ASSERT(gh) BLI_assert((gh->flag & GHASH_FLAG_IS_SET) == 0) +// # define IS_GSET_ASSERT(gs) BLI_assert((gs->flag & GHASH_FLAG_IS_SET) != 0) +#else +# define IS_GHASH_ASSERT(gh) +// # define IS_GSET_ASSERT(eh) +#endif + /***/ typedef struct Entry { @@ -69,7 +71,7 @@ typedef struct Entry { void *key, *val; } Entry; -typedef struct GHash { +struct GHash { GHashHashFP hashfp; GHashCmpFP cmpfp; @@ -77,275 +79,481 @@ typedef struct GHash { struct BLI_mempool *entrypool; unsigned int nbuckets; unsigned int nentries; - unsigned short cursize, flag; -} GHash; + unsigned int cursize, flag; +}; /* -------------------------------------------------------------------- */ /* GHash API */ -/* internal utility API */ +/** \name Internal Utility API + * \{ */ +/** + * Get the hash for a key. + */ BLI_INLINE unsigned int ghash_keyhash(GHash *gh, const void *key) { return gh->hashfp(key) % gh->nbuckets; } +/** + * Check if the number of items in the GHash is large enough to require more buckets. + */ +BLI_INLINE bool ghash_test_expand_buckets(const unsigned int nentries, const unsigned int nbuckets) +{ + return (nentries > nbuckets * 3); +} + +/** + * Expand buckets to the next size up. + */ +BLI_INLINE void ghash_resize_buckets(GHash *gh, const unsigned int nbuckets) +{ + Entry **buckets_old = gh->buckets; + Entry **buckets_new; + const unsigned int nbuckets_old = gh->nbuckets; + unsigned int i; + Entry *e; + + BLI_assert(gh->nbuckets != nbuckets); + + gh->nbuckets = nbuckets; + buckets_new = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); + + for (i = 0; i < nbuckets_old; i++) { + Entry *e_next; + for (e = buckets_old[i]; e; e = e_next) { + const unsigned hash = ghash_keyhash(gh, e->key); + e_next = e->next; + e->next = buckets_new[hash]; + buckets_new[hash] = e; + } + } + + gh->buckets = buckets_new; + MEM_freeN(buckets_old); +} + +/** + * Increase initial bucket size to match a reserved ammount. + */ +BLI_INLINE void ghash_buckets_reserve(GHash *gh, const unsigned int nentries_reserve) +{ + while (ghash_test_expand_buckets(nentries_reserve, gh->nbuckets)) { + gh->nbuckets = hashsizes[++gh->cursize]; + } +} + +/** + * Internal lookup function. + * Takes a hash argument to avoid calling #ghash_keyhash multiple times. + */ BLI_INLINE Entry *ghash_lookup_entry_ex(GHash *gh, const void *key, const unsigned int hash) { Entry *e; for (e = gh->buckets[hash]; e; e = e->next) { - if (gh->cmpfp(key, e->key) == 0) { + if (UNLIKELY(gh->cmpfp(key, e->key) == 0)) { return e; } } return NULL; } +/** + * Internal lookup function. Only wraps #ghash_lookup_entry_ex + */ BLI_INLINE Entry *ghash_lookup_entry(GHash *gh, const void *key) { const unsigned int hash = ghash_keyhash(gh, key); return ghash_lookup_entry_ex(gh, key, hash); } -static void ghash_insert_ex(GHash *gh, void *key, void *val, - unsigned int hash) +static GHash *ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, + const unsigned int nentries_reserve, + const unsigned int entry_size) { - Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool); + GHash *gh = MEM_mallocN(sizeof(*gh), info); + + gh->hashfp = hashfp; + gh->cmpfp = cmpfp; + + gh->nbuckets = hashsizes[0]; /* gh->cursize */ + gh->nentries = 0; + gh->cursize = 0; + gh->flag = 0; + + /* if we have reserved the number of elements that this hash will contain */ + if (nentries_reserve) { + ghash_buckets_reserve(gh, nentries_reserve); + } + gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); + gh->entrypool = BLI_mempool_create(entry_size, 64, 64, 0); + + return gh; +} + +/** + * Internal insert function. + * Takes a hash argument to avoid calling #ghash_keyhash multiple times. + */ +BLI_INLINE void ghash_insert_ex(GHash *gh, void *key, void *val, + unsigned int hash) +{ + Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool); BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); + IS_GHASH_ASSERT(gh); e->next = gh->buckets[hash]; e->key = key; e->val = val; gh->buckets[hash] = e; - if (UNLIKELY(++gh->nentries > gh->nbuckets / 2)) { - Entry **old = gh->buckets; - const unsigned nold = gh->nbuckets; - unsigned int i; + if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) { + ghash_resize_buckets(gh, hashsizes[++gh->cursize]); + } +} - gh->nbuckets = hashsizes[++gh->cursize]; - gh->buckets = (Entry **)MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); - - for (i = 0; i < nold; i++) { - Entry *e_next; - for (e = old[i]; e; e = e_next) { - e_next = e->next; - hash = ghash_keyhash(gh, e->key); - e->next = gh->buckets[hash]; - gh->buckets[hash] = e; - } - } +/** + * Insert function that doesn't set the value (use for GSet) + */ +BLI_INLINE void ghash_insert_ex_keyonly(GHash *gh, void *key, + unsigned int hash) +{ + Entry *e = (Entry *)BLI_mempool_alloc(gh->entrypool); + BLI_assert((gh->flag & GHASH_FLAG_ALLOW_DUPES) || (BLI_ghash_haskey(gh, key) == 0)); + e->next = gh->buckets[hash]; + e->key = key; + /* intentionally leave value unset */ + gh->buckets[hash] = e; - MEM_freeN(old); + if (UNLIKELY(ghash_test_expand_buckets(++gh->nentries, gh->nbuckets))) { + ghash_resize_buckets(gh, hashsizes[++gh->cursize]); } } +BLI_INLINE void ghash_insert(GHash *gh, void *key, void *val) +{ + const unsigned int hash = ghash_keyhash(gh, key); + ghash_insert_ex(gh, key, val, hash); +} -/* Public API */ +/** + * Remove the entry and return it, caller must free from gh->entrypool. + */ +static Entry *ghash_remove_ex(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, + unsigned int hash) +{ + Entry *e; + Entry *e_prev = NULL; -GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) + for (e = gh->buckets[hash]; e; e = e->next) { + if (UNLIKELY(gh->cmpfp(key, e->key) == 0)) { + Entry *e_next = e->next; + + if (keyfreefp) keyfreefp(e->key); + if (valfreefp) valfreefp(e->val); + + if (e_prev) e_prev->next = e_next; + else gh->buckets[hash] = e_next; + + gh->nentries--; + return e; + } + e_prev = e; + } + + return NULL; +} + +/** + * Run free callbacks for freeing entries. + */ +static void ghash_free_cb(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - GHash *gh = MEM_mallocN(sizeof(*gh), info); - gh->hashfp = hashfp; - gh->cmpfp = cmpfp; - gh->entrypool = BLI_mempool_create(sizeof(Entry), 64, 64, 0); + unsigned int i; - gh->cursize = 0; - gh->nentries = 0; - gh->nbuckets = hashsizes[gh->cursize]; + BLI_assert(keyfreefp || valfreefp); - gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); + for (i = 0; i < gh->nbuckets; i++) { + Entry *e; - return gh; + for (e = gh->buckets[i]; e; ) { + Entry *e_next = e->next; + + if (keyfreefp) keyfreefp(e->key); + if (valfreefp) valfreefp(e->val); + + e = e_next; + } + } +} +/** \} */ + + +/** \name Public API + * \{ */ + +/** + * Creates a new, empty GHash. + * + * \param hashfp Hash callback. + * \param cmpfp Comparison callback. + * \param info Identifier string for the GHash. + * \param nentries_reserve Optionally reserve the number of members that the hash will hold. + * Use this to avoid resizing buckets if the size is known or can be closely approximated. + * \return An empty GHash. + */ +GHash *BLI_ghash_new_ex(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info, + const unsigned int nentries_reserve) +{ + return ghash_new(hashfp, cmpfp, info, + nentries_reserve, + (unsigned int)sizeof(Entry)); +} + +/** + * Wraps #BLI_ghash_new_ex with zero entries reserved. + */ +GHash *BLI_ghash_new(GHashHashFP hashfp, GHashCmpFP cmpfp, const char *info) +{ + return BLI_ghash_new_ex(hashfp, cmpfp, info, 0); } +/** + * \return size of the GHash. + */ int BLI_ghash_size(GHash *gh) { return (int)gh->nentries; } +/** + * Insert a key/value pair into the \a gh. + * + * \note Duplicates are not checked, + * the caller is expected to ensure elements are unique unless + * GHASH_FLAG_ALLOW_DUPES flag is set. + */ void BLI_ghash_insert(GHash *gh, void *key, void *val) { - const unsigned int hash = ghash_keyhash(gh, key); - ghash_insert_ex(gh, key, val, hash); + ghash_insert(gh, key, val); } /** - * Assign a new value to a key that may already be in ghash. + * Inserts a new value to a key that may already be in ghash. + * * Avoids #BLI_ghash_remove, #BLI_ghash_insert calls (double lookups) * - * \note We may want to have 'BLI_ghash_assign_ex' function that takes - * GHashKeyFreeFP & GHashValFreeFP args. for now aren't needed. + * \returns true if a new key has been added. */ -void BLI_ghash_assign(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +bool BLI_ghash_reinsert(GHash *gh, void *key, void *val, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { const unsigned int hash = ghash_keyhash(gh, key); Entry *e = ghash_lookup_entry_ex(gh, key, hash); if (e) { if (keyfreefp) keyfreefp(e->key); if (valfreefp) valfreefp(e->val); - e->key = key; e->val = val; + return false; } else { ghash_insert_ex(gh, key, val, hash); + return true; } } +/** + * Lookup the value of \a key in \a gh. + * + * \param key The key to lookup. + * \returns the value for \a key or NULL. + * + * \note When NULL is a valid value, use #BLI_ghash_lookup_p to differentiate a missing key + * from a key with a NULL value. (Avoids calling #BLI_ghash_haskey before #BLI_ghash_lookup) + */ void *BLI_ghash_lookup(GHash *gh, const void *key) { Entry *e = ghash_lookup_entry(gh, key); + IS_GHASH_ASSERT(gh); return e ? e->val : NULL; } +/** + * Lookup a pointer to the value of \a key in \a gh. + * + * \param key The key to lookup. + * \returns the pointer to value for \a key or NULL. + * + * \note This has 2 main benifits over #BLI_ghash_lookup. + * - A NULL return always means that \a key isn't in \a gh. + * - The value can be modified in-place without further function calls (faster). + */ void **BLI_ghash_lookup_p(GHash *gh, const void *key) { Entry *e = ghash_lookup_entry(gh, key); + IS_GHASH_ASSERT(gh); return e ? &e->val : NULL; } +/** + * Remove \a key from \a gh, or return false if the key wasn't found. + * + * \param key The key to remove. + * \param keyfreefp Optional callback to free the key. + * \param valfreefp Optional callback to free the value. + * \return true if \a key was removed from \a gh. + */ bool BLI_ghash_remove(GHash *gh, void *key, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { const unsigned int hash = ghash_keyhash(gh, key); - Entry *e; - Entry *p = NULL; - - for (e = gh->buckets[hash]; e; e = e->next) { - if (gh->cmpfp(key, e->key) == 0) { - Entry *n = e->next; - - if (keyfreefp) keyfreefp(e->key); - if (valfreefp) valfreefp(e->val); - BLI_mempool_free(gh->entrypool, e); - - /* correct but 'e' isn't used before return */ - /* e = n; *//*UNUSED*/ - if (p) p->next = n; - else gh->buckets[hash] = n; - - gh->nentries--; - return true; - } - p = e; + Entry *e = ghash_remove_ex(gh, key, keyfreefp, valfreefp, hash); + if (e) { + BLI_mempool_free(gh->entrypool, e); + return true; + } + else { + return false; } - - return false; } /* same as above but return the value, * no free value argument since it will be returned */ -void *BLI_ghash_pop(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) +/** + * Remove \a key from \a gh, returning the value or NULL if the key wasn't found. + * + * \param key The key to remove. + * \param keyfreefp Optional callback to free the key. + * \return the value of \a key int \a gh or NULL. + */ +void *BLI_ghash_popkey(GHash *gh, void *key, GHashKeyFreeFP keyfreefp) { const unsigned int hash = ghash_keyhash(gh, key); - Entry *e; - Entry *p = NULL; - - for (e = gh->buckets[hash]; e; e = e->next) { - if (gh->cmpfp(key, e->key) == 0) { - Entry *n = e->next; - void *value = e->val; - - if (keyfreefp) keyfreefp(e->key); - BLI_mempool_free(gh->entrypool, e); - - /* correct but 'e' isn't used before return */ - /* e = n; *//*UNUSED*/ - if (p) p->next = n; - else gh->buckets[hash] = n; - - gh->nentries--; - return value; - } - p = e; + Entry *e = ghash_remove_ex(gh, key, keyfreefp, NULL, hash); + IS_GHASH_ASSERT(gh); + if (e) { + void *val = e->val; + BLI_mempool_free(gh->entrypool, e); + return val; + } + else { + return NULL; } - - return NULL; } +/** + * \return true if the \a key is in \a gh. + */ bool BLI_ghash_haskey(GHash *gh, const void *key) { return (ghash_lookup_entry(gh, key) != NULL); } -void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +/** + * Reset \a gh clearing all entries. + * + * \param keyfreefp Optional callback to free the key. + * \param valfreefp Optional callback to free the value. + * \param nentries_reserve Optionally reserve the number of members that the hash will hold. + */ +void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, + const unsigned int nentries_reserve) { - unsigned int i; + if (keyfreefp || valfreefp) + ghash_free_cb(gh, keyfreefp, valfreefp); - if (keyfreefp || valfreefp) { - for (i = 0; i < gh->nbuckets; i++) { - Entry *e; - - for (e = gh->buckets[i]; e; ) { - Entry *n = e->next; - - if (keyfreefp) keyfreefp(e->key); - if (valfreefp) valfreefp(e->val); + gh->nbuckets = hashsizes[0]; /* gh->cursize */ + gh->nentries = 0; + gh->cursize = 0; - e = n; - } - } + if (nentries_reserve) { + ghash_buckets_reserve(gh, nentries_reserve); } - gh->cursize = 0; - gh->nentries = 0; - gh->nbuckets = hashsizes[gh->cursize]; - MEM_freeN(gh->buckets); gh->buckets = MEM_callocN(gh->nbuckets * sizeof(*gh->buckets), "buckets"); + + BLI_mempool_clear_ex(gh->entrypool, nentries_reserve ? (int)nentries_reserve : -1); } -void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +/** + * Wraps #BLI_ghash_clear_ex with zero entries reserved. + */ +void BLI_ghash_clear(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) { - unsigned int i; - - if (keyfreefp || valfreefp) { - for (i = 0; i < gh->nbuckets; i++) { - Entry *e; - - for (e = gh->buckets[i]; e; ) { - Entry *n = e->next; - - if (keyfreefp) keyfreefp(e->key); - if (valfreefp) valfreefp(e->val); + BLI_ghash_clear_ex(gh, keyfreefp, valfreefp, 0); +} - e = n; - } - } - } +/** + * Frees the GHash and its members. + * + * \param gh The GHash to free. + * \param keyfreefp Optional callback to free the key. + * \param valfreefp Optional callback to free the value. + */ +void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp) +{ + BLI_assert((int)gh->nentries == BLI_mempool_count(gh->entrypool)); + if (keyfreefp || valfreefp) + ghash_free_cb(gh, keyfreefp, valfreefp); MEM_freeN(gh->buckets); BLI_mempool_destroy(gh->entrypool); - gh->buckets = NULL; - gh->nentries = 0; - gh->nbuckets = 0; MEM_freeN(gh); } -void BLI_ghash_flag_set(GHash *gh, unsigned short flag) +/** + * Sets a GHash flag. + */ +void BLI_ghash_flag_set(GHash *gh, unsigned int flag) { gh->flag |= flag; } -void BLI_ghash_flag_clear(GHash *gh, unsigned short flag) +/** + * Clear a GHash flag. + */ +void BLI_ghash_flag_clear(GHash *gh, unsigned int flag) { - gh->flag &= (unsigned short)~flag; + gh->flag &= ~flag; } +/** \} */ + /* -------------------------------------------------------------------- */ /* GHash Iterator API */ +/** \name Iterator API + * \{ */ + +/** + * Create a new GHashIterator. The hash table must not be mutated + * while the iterator is in use, and the iterator will step exactly + * BLI_ghash_size(gh) times before becoming done. + * + * \param gh The GHash to iterate over. + * \return Pointer to a new DynStr. + */ GHashIterator *BLI_ghashIterator_new(GHash *gh) { GHashIterator *ghi = MEM_mallocN(sizeof(*ghi), "ghash iterator"); BLI_ghashIterator_init(ghi, gh); return ghi; } + +/** + * Init an already allocated GHashIterator. The hash table must not + * be mutated while the iterator is in use, and the iterator will + * step exactly BLI_ghash_size(gh) times before becoming done. + * + * \param ghi The GHashIterator to initialize. + * \param gh The GHash to iterate over. + */ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh) { ghi->gh = gh; @@ -358,20 +566,58 @@ void BLI_ghashIterator_init(GHashIterator *ghi, GHash *gh) ghi->curEntry = ghi->gh->buckets[ghi->curBucket]; } } + +/** + * Free a GHashIterator. + * + * \param ghi The iterator to free. + */ void BLI_ghashIterator_free(GHashIterator *ghi) { MEM_freeN(ghi); } +/** + * Retrieve the key from an iterator. + * + * \param ghi The iterator. + * \return The key at the current index, or NULL if the + * iterator is done. + */ void *BLI_ghashIterator_getKey(GHashIterator *ghi) { return ghi->curEntry ? ghi->curEntry->key : NULL; } + +/** + * Retrieve the value from an iterator. + * + * \param ghi The iterator. + * \return The value at the current index, or NULL if the + * iterator is done. + */ void *BLI_ghashIterator_getValue(GHashIterator *ghi) { return ghi->curEntry ? ghi->curEntry->val : NULL; } +/** + * Retrieve the value from an iterator. + * + * \param ghi The iterator. + * \return The value at the current index, or NULL if the + * iterator is done. + */ +void **BLI_ghashIterator_getValue_p(GHashIterator *ghi) +{ + return ghi->curEntry ? &ghi->curEntry->val : NULL; +} + +/** + * Steps the iterator to the next index. + * + * \param ghi The iterator. + */ void BLI_ghashIterator_step(GHashIterator *ghi) { if (ghi->curEntry) { @@ -384,17 +630,44 @@ void BLI_ghashIterator_step(GHashIterator *ghi) } } } + +/** + * Determine if an iterator is done (has reached the end of + * the hash table). + * + * \param ghi The iterator. + * \return True if done, False otherwise. + */ bool BLI_ghashIterator_done(GHashIterator *ghi) { return ghi->curEntry == NULL; } +/** \} */ + + +/** \name Generic Key Hash & Comparison Functions + * \{ */ + /***/ +#if 0 +/* works but slower */ unsigned int BLI_ghashutil_ptrhash(const void *key) { return (unsigned int)(intptr_t)key; } +#else +/* based python3.3's pointer hashing function */ +unsigned int BLI_ghashutil_ptrhash(const void *key) +{ + size_t y = (size_t)key; + /* bottom 3 or 4 bits are likely to be 0; rotate y by 4 to avoid + * excessive hash collisions for dicts and sets */ + y = (y >> 4) | (y << (8 * sizeof(void *) - 4)); + return (unsigned int)y; +} +#endif int BLI_ghashutil_ptrcmp(const void *a, const void *b) { if (a == b) @@ -450,23 +723,6 @@ int BLI_ghashutil_strcmp(const void *a, const void *b) return strcmp(a, b); } -GHash *BLI_ghash_ptr_new(const char *info) -{ - return BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info); -} -GHash *BLI_ghash_str_new(const char *info) -{ - return BLI_ghash_new(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, info); -} -GHash *BLI_ghash_int_new(const char *info) -{ - return BLI_ghash_new(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, info); -} -GHash *BLI_ghash_pair_new(const char *info) -{ - return BLI_ghash_new(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info); -} - GHashPair *BLI_ghashutil_pairalloc(const void *first, const void *second) { GHashPair *pair = MEM_mallocN(sizeof(GHashPair), "GHashPair"); @@ -497,3 +753,176 @@ void BLI_ghashutil_pairfree(void *ptr) { MEM_freeN(ptr); } + +/** \} */ + + +/** \name Convenience GHash Creation Functions + * \{ */ + +GHash *BLI_ghash_ptr_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_ghash_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, + nentries_reserve); +} +GHash *BLI_ghash_ptr_new(const char *info) +{ + return BLI_ghash_ptr_new_ex(info, 0); +} + +GHash *BLI_ghash_str_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_ghash_new_ex(BLI_ghashutil_strhash, BLI_ghashutil_strcmp, info, + nentries_reserve); +} +GHash *BLI_ghash_str_new(const char *info) +{ + return BLI_ghash_str_new_ex(info, 0); +} + +GHash *BLI_ghash_int_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_ghash_new_ex(BLI_ghashutil_inthash, BLI_ghashutil_intcmp, info, + nentries_reserve); +} +GHash *BLI_ghash_int_new(const char *info) +{ + return BLI_ghash_int_new_ex(info, 0); +} + +GHash *BLI_ghash_pair_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_ghash_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, + nentries_reserve); +} +GHash *BLI_ghash_pair_new(const char *info) +{ + return BLI_ghash_pair_new_ex(info, 0); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ +/* GSet API */ + +/* Use ghash API to give 'set' functionality */ + +/* TODO: typical set functions + * isdisjoint/issubset/issuperset/union/intersection/difference etc */ + +/** \name GSet Functions + * \{ */ +GSet *BLI_gset_new_ex(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info, + const unsigned int nentries_reserve) +{ + GSet *gs = (GSet *)ghash_new(hashfp, cmpfp, info, + nentries_reserve, + sizeof(Entry) - sizeof(void *)); +#ifndef NDEBUG + ((GHash *)gs)->flag |= GHASH_FLAG_IS_SET; +#endif + return gs; +} + +GSet *BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) +{ + return BLI_gset_new_ex(hashfp, cmpfp, info, 0); +} + +int BLI_gset_size(GSet *gs) +{ + return (int)((GHash *)gs)->nentries; +} + +/** + * Adds the key to the set (no checks for unique keys!). + * Matching #BLI_ghash_insert + */ +void BLI_gset_insert(GSet *gs, void *key) +{ + const unsigned int hash = ghash_keyhash((GHash *)gs, key); + ghash_insert_ex_keyonly((GHash *)gs, key, hash); +} + +/** + * Adds the key to the set (duplicates are managed). + * Matching #BLI_ghash_reinsert + * + * \returns true if a new key has been added. + */ +bool BLI_gset_reinsert(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) +{ + const unsigned int hash = ghash_keyhash((GHash *)gs, key); + Entry *e = ghash_lookup_entry_ex((GHash *)gs, key, hash); + if (e) { + if (keyfreefp) keyfreefp(e->key); + e->key = key; + return false; + } + else { + ghash_insert_ex_keyonly((GHash *)gs, key, hash); + return true; + } +} + +bool BLI_gset_remove(GSet *gs, void *key, GSetKeyFreeFP keyfreefp) +{ + return BLI_ghash_remove((GHash *)gs, key, keyfreefp, NULL); +} + + +bool BLI_gset_haskey(GSet *gs, const void *key) +{ + return (ghash_lookup_entry((GHash *)gs, key) != NULL); +} + +void BLI_gset_clear_ex(GSet *gs, GSetKeyFreeFP keyfreefp, + const unsigned int nentries_reserve) +{ + BLI_ghash_clear_ex((GHash *)gs, keyfreefp, NULL, + nentries_reserve); +} + +void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp) +{ + BLI_ghash_clear((GHash *)gs, keyfreefp, NULL); +} + +void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp) +{ + BLI_ghash_free((GHash *)gs, keyfreefp, NULL); +} +/** \} */ + + +/** \name Convenience GSet Creation Functions + * \{ */ + +GSet *BLI_gset_ptr_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_gset_new_ex(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, info, + nentries_reserve); +} +GSet *BLI_gset_ptr_new(const char *info) +{ + return BLI_gset_ptr_new_ex(info, 0); +} + +GSet *BLI_gset_pair_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + return BLI_gset_new_ex(BLI_ghashutil_pairhash, BLI_ghashutil_paircmp, info, + nentries_reserve); +} +GSet *BLI_gset_pair_new(const char *info) +{ + return BLI_gset_pair_new_ex(info, 0); +} + +/** \} */ diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 0aaa3e13b3f..45bdeeedcf9 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -34,14 +34,7 @@ #include "BLI_utildefines.h" #include "BLI_memarena.h" #include "BLI_heap.h" - -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif +#include "BLI_strict_flags.h" /***/ diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index a4c72aa26b0..80483fbfa38 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -36,6 +36,7 @@ #include "BLI_utildefines.h" #include "BLI_kdopbvh.h" #include "BLI_math.h" +#include "BLI_strict_flags.h" #ifdef _OPENMP #include <omp.h> @@ -65,8 +66,8 @@ struct BVHTree { int totleaf; /* leafs */ int totbranch; axis_t start_axis, stop_axis; /* KDOP_AXES array indices according to axis */ - axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ - char tree_type; /* type of tree (4 => quadtree) */ + axis_t axis; /* kdop type (6 => OBB, 7 => AABB, ...) */ + char tree_type; /* type of tree (4 => quadtree) */ }; /* optimization, ensure we stay small */ @@ -77,7 +78,8 @@ BLI_STATIC_ASSERT((sizeof(void *) == 8 && sizeof(BVHTree) <= 48) || typedef struct BVHOverlapData { BVHTree *tree1, *tree2; BVHTreeOverlap *overlap; - int i, max_overlap; /* i is number of overlaps */ + unsigned int i; + unsigned int max_overlap; /* i is number of overlaps */ axis_t start_axis, stop_axis; } BVHOverlapData; @@ -437,7 +439,7 @@ static void refit_kdop_hull(BVHTree *tree, BVHNode *node, int start, int end) /* only supports x,y,z axis in the moment * but we should use a plain and simple function here for speed sake */ -static char get_largest_axis(float *bv) +static char get_largest_axis(const float *bv) { float middle_point[3]; @@ -497,9 +499,13 @@ static void bvhtree_print_tree(BVHTree *tree, BVHNode *node, int depth) axis_t axis_iter; for (i = 0; i < depth; i++) printf(" "); - printf(" - %d (%ld): ", node->index, node - tree->nodearray); - for (axis_iter = 2 * tree->start_axis; axis_iter < 2 * tree->stop_axis; axis_iter++) + printf(" - %d (%ld): ", node->index, (long int)(node - tree->nodearray)); + for (axis_iter = (axis_t)(2 * tree->start_axis); + axis_iter < (axis_t)(2 * tree->stop_axis); + axis_iter++) + { printf("%.3f ", node->bv[axis_iter]); + } printf("\n"); for (i = 0; i < tree->tree_type; i++) @@ -513,7 +519,7 @@ static void bvhtree_info(BVHTree *tree) printf("tree_type = %d, axis = %d, epsilon = %f\n", tree->tree_type, tree->axis, tree->epsilon); printf("nodes = %d, branches = %d, leafs = %d\n", tree->totbranch + tree->totleaf, tree->totbranch, tree->totleaf); printf("Memory per node = %ldbytes\n", sizeof(BVHNode) + sizeof(BVHNode *) * tree->tree_type + sizeof(float) * tree->axis); - printf("BV memory = %dbytes\n", MEM_allocN_len(tree->nodebv)); + printf("BV memory = %dbytes\n", (int)MEM_allocN_len(tree->nodebv)); printf("Total memory = %ldbytes\n", sizeof(BVHTree) + MEM_allocN_len(tree->nodes) + @@ -792,7 +798,7 @@ static void non_recursive_bvh_div_nodes(BVHTree *tree, BVHNode *branches_array, break; } - parent->totnode = k + 1; + parent->totnode = (char)(k + 1); } } } @@ -811,10 +817,9 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) if (tree_type < 2) return NULL; - if (tree_type > MAX_TREETYPE) - return NULL; + BLI_assert(tree_type <= MAX_TREETYPE); - tree = (BVHTree *)MEM_callocN(sizeof(BVHTree), "BVHTree"); + tree = MEM_callocN(sizeof(BVHTree), "BVHTree"); /* tree epsilon must be >= FLT_EPSILON * so that tangent rays can still hit a bounding volume.. @@ -855,27 +860,27 @@ BVHTree *BLI_bvhtree_new(int maxsize, float epsilon, char tree_type, char axis) /* Allocate arrays */ numnodes = maxsize + implicit_needed_branches(tree_type, maxsize) + tree_type; - tree->nodes = (BVHNode **)MEM_callocN(sizeof(BVHNode *) * numnodes, "BVHNodes"); + tree->nodes = MEM_callocN(sizeof(BVHNode *) * (size_t)numnodes, "BVHNodes"); if (!tree->nodes) { MEM_freeN(tree); return NULL; } - - tree->nodebv = (float *)MEM_callocN(sizeof(float) * axis * numnodes, "BVHNodeBV"); + + tree->nodebv = MEM_callocN(sizeof(float) * (size_t)(axis * numnodes), "BVHNodeBV"); if (!tree->nodebv) { MEM_freeN(tree->nodes); MEM_freeN(tree); } - tree->nodechild = (BVHNode **)MEM_callocN(sizeof(BVHNode *) * tree_type * numnodes, "BVHNodeBV"); + tree->nodechild = MEM_callocN(sizeof(BVHNode *) * (size_t)(tree_type * numnodes), "BVHNodeBV"); if (!tree->nodechild) { MEM_freeN(tree->nodebv); MEM_freeN(tree->nodes); MEM_freeN(tree); } - tree->nodearray = (BVHNode *)MEM_callocN(sizeof(BVHNode) * numnodes, "BVHNodeArray"); + tree->nodearray = MEM_callocN(sizeof(BVHNode) * (size_t)numnodes, "BVHNodeArray"); if (!tree->nodearray) { MEM_freeN(tree->nodechild); @@ -915,7 +920,7 @@ void BLI_bvhtree_balance(BVHTree *tree) BVHNode **leafs_array = tree->nodes; /* This function should only be called once (some big bug goes here if its being called more than once per tree) */ - assert(tree->totbranch == 0); + BLI_assert(tree->totbranch == 0); /* Build the implicit tree */ non_recursive_bvh_div_nodes(tree, branches_array, leafs_array, tree->totleaf); @@ -930,19 +935,14 @@ void BLI_bvhtree_balance(BVHTree *tree) /* bvhtree_info(tree); */ } -int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints) +void BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoints) { axis_t axis_iter; BVHNode *node = NULL; /* insert should only possible as long as tree->totbranch is 0 */ - if (tree->totbranch > 0) - return 0; - - if (tree->totleaf + 1 >= MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))) - return 0; - - /* TODO check if have enough nodes in array */ + BLI_assert(tree->totbranch <= 0); + BLI_assert((size_t)tree->totleaf < MEM_allocN_len(tree->nodes) / sizeof(*(tree->nodes))); node = tree->nodes[tree->totleaf] = &(tree->nodearray[tree->totleaf]); tree->totleaf++; @@ -955,8 +955,6 @@ int BLI_bvhtree_insert(BVHTree *tree, int index, const float co[3], int numpoint node->bv[(2 * axis_iter)] -= tree->epsilon; /* minimum */ node->bv[(2 * axis_iter) + 1] += tree->epsilon; /* maximum */ } - - return 1; } @@ -1012,10 +1010,10 @@ float BLI_bvhtree_getepsilon(const BVHTree *tree) * overlap - is it possible for 2 bv's to collide ? */ static int tree_overlap(BVHNode *node1, BVHNode *node2, axis_t start_axis, axis_t stop_axis) { - float *bv1 = node1->bv; - float *bv2 = node2->bv; + const float *bv1 = node1->bv; + const float *bv2 = node2->bv; - float *bv1_end = bv1 + (stop_axis << 1); + const float *bv1_end = bv1 + (stop_axis << 1); bv1 += start_axis << 1; bv2 += start_axis << 1; @@ -1045,7 +1043,7 @@ static void traverse(BVHOverlapData *data, BVHNode *node1, BVHNode *node2) if (data->i >= data->max_overlap) { /* try to make alloc'ed memory bigger */ - data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap) * data->max_overlap * 2); + data->overlap = realloc(data->overlap, sizeof(BVHTreeOverlap) * (size_t)data->max_overlap * 2); if (!data->overlap) { printf("Out of Memory in traverse\n"); @@ -1099,13 +1097,13 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int data = MEM_callocN(sizeof(BVHOverlapData *) * tree1->tree_type, "BVHOverlapData_star"); for (j = 0; j < tree1->tree_type; j++) { - data[j] = (BVHOverlapData *)MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); + data[j] = MEM_callocN(sizeof(BVHOverlapData), "BVHOverlapData"); /* init BVHOverlapData */ - data[j]->overlap = (BVHTreeOverlap *)malloc(sizeof(BVHTreeOverlap) * max_ii(tree1->totleaf, tree2->totleaf)); + data[j]->overlap = malloc(sizeof(BVHTreeOverlap) * (size_t)max_ii(tree1->totleaf, tree2->totleaf)); data[j]->tree1 = tree1; data[j]->tree2 = tree2; - data[j]->max_overlap = max_ii(tree1->totleaf, tree2->totleaf); + data[j]->max_overlap = (unsigned int)max_ii(tree1->totleaf, tree2->totleaf); data[j]->i = 0; data[j]->start_axis = min_axis(tree1->start_axis, tree2->start_axis); data[j]->stop_axis = min_axis(tree1->stop_axis, tree2->stop_axis); @@ -1119,7 +1117,7 @@ BVHTreeOverlap *BLI_bvhtree_overlap(BVHTree *tree1, BVHTree *tree2, unsigned int for (j = 0; j < tree1->tree_type; j++) total += data[j]->i; - to = overlap = (BVHTreeOverlap *)MEM_callocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); + to = overlap = MEM_callocN(sizeof(BVHTreeOverlap) * total, "BVHTreeOverlap"); for (j = 0; j < tree1->tree_type; j++) { memcpy(to, data[j]->overlap, data[j]->i * sizeof(BVHTreeOverlap)); diff --git a/source/blender/blenlib/intern/BLI_kdtree.c b/source/blender/blenlib/intern/BLI_kdtree.c index dd54fe681b0..57227dc5d5f 100644 --- a/source/blender/blenlib/intern/BLI_kdtree.c +++ b/source/blender/blenlib/intern/BLI_kdtree.c @@ -30,28 +30,37 @@ #include "BLI_math.h" #include "BLI_kdtree.h" #include "BLI_utildefines.h" +#include "BLI_strict_flags.h" typedef struct KDTreeNode { struct KDTreeNode *left, *right; float co[3], nor[3]; int index; - short d; + unsigned int d; /* range is only (0-2) */ } KDTreeNode; struct KDTree { KDTreeNode *nodes; - int totnode; + unsigned int totnode; KDTreeNode *root; }; -KDTree *BLI_kdtree_new(int maxsize) +#define KD_STACK_INIT 100 /* initial size for array (on the stack) */ +#define KD_NEAR_ALLOC_INC 100 /* alloc increment for collecting nearest */ +#define KD_FOUND_ALLOC_INC 50 /* alloc increment for collecting nearest */ + +/** + * Creates or free a kdtree + */ +KDTree *BLI_kdtree_new(unsigned int maxsize) { KDTree *tree; - tree = MEM_callocN(sizeof(KDTree), "KDTree"); - tree->nodes = MEM_callocN(sizeof(KDTreeNode) * maxsize, "KDTreeNode"); + tree = MEM_mallocN(sizeof(KDTree), "KDTree"); + tree->nodes = MEM_mallocN(sizeof(KDTreeNode) * maxsize, "KDTreeNode"); tree->totnode = 0; + tree->root = NULL; return tree; } @@ -64,20 +73,32 @@ void BLI_kdtree_free(KDTree *tree) } } +/** + * Construction: first insert points, then call balance. Normal is optional. + */ void BLI_kdtree_insert(KDTree *tree, int index, const float co[3], const float nor[3]) { KDTreeNode *node = &tree->nodes[tree->totnode++]; - node->index = index; + /* note, array isn't calloc'd, + * need to initialize all struct members */ + + node->left = node->right = NULL; copy_v3_v3(node->co, co); - if (nor) copy_v3_v3(node->nor, nor); + if (nor) + copy_v3_v3(node->nor, nor); + else + zero_v3(node->nor); + + node->index = index; + node->d = 0; } -static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis) +static KDTreeNode *kdtree_balance(KDTreeNode *nodes, unsigned int totnode, unsigned int axis) { KDTreeNode *node; float co; - int left, right, median, i, j; + unsigned int left, right, median, i, j; if (totnode <= 0) return NULL; @@ -98,7 +119,9 @@ static KDTreeNode *kdtree_balance(KDTreeNode *nodes, int totnode, int axis) while (nodes[++i].co[axis] < co) ; while (nodes[--j].co[axis] > co && j > left) ; - if (i >= j) break; + if (i >= j) + break; + SWAP(KDTreeNode, nodes[i], nodes[j]); } @@ -143,18 +166,33 @@ static float squared_distance(const float v2[3], const float v1[3], const float return dist; } -int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], KDTreeNearest *nearest) +static KDTreeNode **realloc_nodes(KDTreeNode **stack, unsigned int *totstack, const bool is_alloc) +{ + KDTreeNode **stack_new = MEM_mallocN((*totstack + KD_NEAR_ALLOC_INC) * sizeof(KDTreeNode *), "KDTree.treestack"); + memcpy(stack_new, stack, *totstack * sizeof(KDTreeNode *)); + // memset(stack_new + *totstack, 0, sizeof(KDTreeNode *) * KD_NEAR_ALLOC_INC); + if (is_alloc) + MEM_freeN(stack); + *totstack += KD_NEAR_ALLOC_INC; + return stack_new; +} + +/** + * Find nearest returns index, and -1 if no node is found. + */ +int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], + KDTreeNearest *r_nearest) { KDTreeNode *root, *node, *min_node; - KDTreeNode **stack, *defaultstack[100]; + KDTreeNode **stack, *defaultstack[KD_STACK_INIT]; float min_dist, cur_dist; - int totstack, cur = 0; + unsigned int totstack, cur = 0; if (!tree->root) return -1; stack = defaultstack; - totstack = 100; + totstack = KD_STACK_INIT; root = tree->root; min_node = root; @@ -208,20 +246,15 @@ int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], if (node->left) stack[cur++] = node->left; } - if (cur + 3 > totstack) { - KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack"); - memcpy(temp, stack, totstack * sizeof(KDTreeNode *)); - if (stack != defaultstack) - MEM_freeN(stack); - stack = temp; - totstack += 100; + if (UNLIKELY(cur + 3 > totstack)) { + stack = realloc_nodes(stack, &totstack, defaultstack != stack); } } - if (nearest) { - nearest->index = min_node->index; - nearest->dist = sqrt(min_dist); - copy_v3_v3(nearest->co, min_node->co); + if (r_nearest) { + r_nearest->index = min_node->index; + r_nearest->dist = sqrtf(min_dist); + copy_v3_v3(r_nearest->co, min_node->co); } if (stack != defaultstack) @@ -230,9 +263,10 @@ int BLI_kdtree_find_nearest(KDTree *tree, const float co[3], const float nor[3], return min_node->index; } -static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float dist, float *co) +static void add_nearest(KDTreeNearest *ptn, unsigned int *found, unsigned int n, int index, + float dist, const float *co) { - int i; + unsigned int i; if (*found < n) (*found)++; @@ -248,24 +282,32 @@ static void add_nearest(KDTreeNearest *ptn, int *found, int n, int index, float copy_v3_v3(ptn[i].co, co); } -/* finds the nearest n entries in tree to specified coordinates */ -int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const float nor[3], KDTreeNearest *nearest) +/** + * Find n nearest returns number of points found, with results in nearest. + * Normal is optional, but if given will limit results to points in normal direction from co. + * + * \param r_nearest An array of nearest, sized at least \a n. + */ +int BLI_kdtree_find_nearest_n(KDTree *tree, const float co[3], const float nor[3], + KDTreeNearest r_nearest[], + unsigned int n) { KDTreeNode *root, *node = NULL; - KDTreeNode **stack, *defaultstack[100]; + KDTreeNode **stack, *defaultstack[KD_STACK_INIT]; float cur_dist; - int i, totstack, cur = 0, found = 0; + unsigned int totstack, cur = 0; + unsigned int i, found = 0; - if (!tree->root) + if (!tree->root || n == 0) return 0; stack = defaultstack; - totstack = 100; + totstack = KD_STACK_INIT; root = tree->root; cur_dist = squared_distance(root->co, co, root->nor, nor); - add_nearest(nearest, &found, n, root->index, cur_dist, root->co); + add_nearest(r_nearest, &found, n, root->index, cur_dist, root->co); if (co[root->d] < root->co[root->d]) { if (root->right) @@ -288,11 +330,11 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const floa if (cur_dist < 0.0f) { cur_dist = -cur_dist * cur_dist; - if (found < n || -cur_dist < nearest[found - 1].dist) { + if (found < n || -cur_dist < r_nearest[found - 1].dist) { cur_dist = squared_distance(node->co, co, node->nor, nor); - if (found < n || cur_dist < nearest[found - 1].dist) - add_nearest(nearest, &found, n, node->index, cur_dist, node->co); + if (found < n || cur_dist < r_nearest[found - 1].dist) + add_nearest(r_nearest, &found, n, node->index, cur_dist, node->co); if (node->left) stack[cur++] = node->left; @@ -303,10 +345,10 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const floa else { cur_dist = cur_dist * cur_dist; - if (found < n || cur_dist < nearest[found - 1].dist) { + if (found < n || cur_dist < r_nearest[found - 1].dist) { cur_dist = squared_distance(node->co, co, node->nor, nor); - if (found < n || cur_dist < nearest[found - 1].dist) - add_nearest(nearest, &found, n, node->index, cur_dist, node->co); + if (found < n || cur_dist < r_nearest[found - 1].dist) + add_nearest(r_nearest, &found, n, node->index, cur_dist, node->co); if (node->right) stack[cur++] = node->right; @@ -314,23 +356,18 @@ int BLI_kdtree_find_n_nearest(KDTree *tree, int n, const float co[3], const floa if (node->left) stack[cur++] = node->left; } - if (cur + 3 > totstack) { - KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack"); - memcpy(temp, stack, totstack * sizeof(KDTreeNode *)); - if (stack != defaultstack) - MEM_freeN(stack); - stack = temp; - totstack += 100; + if (UNLIKELY(cur + 3 > totstack)) { + stack = realloc_nodes(stack, &totstack, defaultstack != stack); } } for (i = 0; i < found; i++) - nearest[i].dist = sqrt(nearest[i].dist); + r_nearest[i].dist = sqrtf(r_nearest[i].dist); if (stack != defaultstack) MEM_freeN(stack); - return found; + return (int)found; } static int range_compare(const void *a, const void *b) @@ -345,38 +382,45 @@ static int range_compare(const void *a, const void *b) else return 0; } -static void add_in_range(KDTreeNearest **ptn, int found, int *totfoundstack, int index, float dist, float *co) +static void add_in_range(KDTreeNearest **ptn, unsigned int found, unsigned int *totfoundstack, int index, float dist, float *co) { KDTreeNearest *to; if (found >= *totfoundstack) { - KDTreeNearest *temp = MEM_callocN((*totfoundstack + 50) * sizeof(KDTreeNode), "psys_treefoundstack"); + KDTreeNearest *temp = MEM_mallocN((*totfoundstack + KD_FOUND_ALLOC_INC) * sizeof(KDTreeNode), "KDTree.treefoundstack"); memcpy(temp, *ptn, *totfoundstack * sizeof(KDTreeNearest)); if (*ptn) MEM_freeN(*ptn); *ptn = temp; - *totfoundstack += 50; + *totfoundstack += KD_FOUND_ALLOC_INC; } to = (*ptn) + found; to->index = index; - to->dist = sqrt(dist); + to->dist = sqrtf(dist); copy_v3_v3(to->co, co); } -int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const float nor[3], KDTreeNearest **nearest) + +/** + * Range search returns number of points found, with results in nearest + * Normal is optional, but if given will limit results to points in normal direction from co. + * Remember to free nearest after use! + */ +int BLI_kdtree_range_search(KDTree *tree, const float co[3], const float nor[3], + KDTreeNearest **r_nearest, float range) { KDTreeNode *root, *node = NULL; - KDTreeNode **stack, *defaultstack[100]; + KDTreeNode **stack, *defaultstack[KD_STACK_INIT]; KDTreeNearest *foundstack = NULL; float range2 = range * range, dist2; - int totstack, cur = 0, found = 0, totfoundstack = 0; + unsigned int totstack, cur = 0, found = 0, totfoundstack = 0; if (!tree || !tree->root) return 0; stack = defaultstack; - totstack = 100; + totstack = KD_STACK_INIT; root = tree->root; @@ -421,13 +465,8 @@ int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const stack[cur++] = node->right; } - if (cur + 3 > totstack) { - KDTreeNode **temp = MEM_callocN((totstack + 100) * sizeof(KDTreeNode *), "psys_treestack"); - memcpy(temp, stack, totstack * sizeof(KDTreeNode *)); - if (stack != defaultstack) - MEM_freeN(stack); - stack = temp; - totstack += 100; + if (UNLIKELY(cur + 3 > totstack)) { + stack = realloc_nodes(stack, &totstack, defaultstack != stack); } } @@ -437,7 +476,7 @@ int BLI_kdtree_range_search(KDTree *tree, float range, const float co[3], const if (found) qsort(foundstack, found, sizeof(KDTreeNearest), range_compare); - *nearest = foundstack; + *r_nearest = foundstack; - return found; + return (int)found; } diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index ef10cb805ad..747c2f0c2b7 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -30,18 +30,13 @@ * \ingroup bli */ +#include <string.h> + #include "MEM_guardedalloc.h" #include "BLI_memarena.h" #include "BLI_linklist.h" - -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif +#include "BLI_strict_flags.h" struct MemArena { unsigned char *curbuf; @@ -89,6 +84,16 @@ void BLI_memarena_free(MemArena *ma) /* amt must be power of two */ #define PADUP(num, amt) (((num) + ((amt) - 1)) & ~((amt) - 1)) +/* align alloc'ed memory (needed if align > 8) */ +static void memarena_curbuf_align(MemArena *ma) +{ + unsigned char *tmp; + + tmp = (unsigned char *)PADUP( (intptr_t) ma->curbuf, ma->align); + ma->cursize -= (int)(tmp - ma->curbuf); + ma->curbuf = tmp; +} + void *BLI_memarena_alloc(MemArena *ma, int size) { void *ptr; @@ -98,8 +103,6 @@ void *BLI_memarena_alloc(MemArena *ma, int size) size = PADUP(size, ma->align); if (size > ma->cursize) { - unsigned char *tmp; - if (size > ma->bufsize - (ma->align - 1)) { ma->cursize = PADUP(size + 1, ma->align); } @@ -112,11 +115,7 @@ void *BLI_memarena_alloc(MemArena *ma, int size) ma->curbuf = MEM_mallocN((size_t)ma->cursize, ma->name); BLI_linklist_prepend(&ma->bufs, ma->curbuf); - - /* align alloc'ed memory (needed if align > 8) */ - tmp = (unsigned char *)PADUP( (intptr_t) ma->curbuf, ma->align); - ma->cursize -= (int)(tmp - ma->curbuf); - ma->curbuf = tmp; + memarena_curbuf_align(ma); } ptr = ma->curbuf; @@ -125,3 +124,32 @@ void *BLI_memarena_alloc(MemArena *ma, int size) return ptr; } + +/** + * Clear for reuse, avoids re-allocation when an arena may + * otherwise be free'd and recreated. + */ +void BLI_memarena_clear(MemArena *ma) +{ + if (ma->bufs) { + unsigned char *curbuf_prev; + int curbuf_used; + + if (ma->bufs->next) { + BLI_linklist_freeN(ma->bufs->next); + ma->bufs->next = NULL; + } + + curbuf_prev = ma->curbuf; + ma->curbuf = ma->bufs->link; + memarena_curbuf_align(ma); + + /* restore to original size */ + curbuf_used = (int)(curbuf_prev - ma->curbuf); + ma->cursize += curbuf_used; + + if (ma->use_calloc) { + memset(ma->curbuf, 0, (size_t)curbuf_used); + } + } +} diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index bb326a23d59..febf09745fb 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -31,6 +31,9 @@ * Simple, fast memory allocator for allocating many elements of the same size. */ +#include <string.h> +#include <stdlib.h> + #include "BLI_utildefines.h" #include "BLI_listbase.h" @@ -40,16 +43,8 @@ #include "MEM_guardedalloc.h" -#include <string.h> -#include <stdlib.h> +#include "BLI_strict_flags.h" /* keep last */ -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif /* note: copied from BLO_blend_defs.h, don't use here because we're in BLI */ #ifdef __BIG_ENDIAN__ @@ -65,37 +60,181 @@ /* currently totalloc isnt used */ // #define USE_TOTALLOC +/* when undefined, merge the allocs for BLI_mempool_chunk and its data */ +// #define USE_DATA_PTR + +/** + * A free element from #BLI_mempool_chunk. Data is cast to this type and stored in + * #BLI_mempool.free as a single linked list, each item #BLI_mempool.esize large. + * + * Each element represents a block which BLI_mempool_alloc may return. + */ typedef struct BLI_freenode { struct BLI_freenode *next; int freeword; /* used to identify this as a freed node */ } BLI_freenode; +/** + * A chunk of memory in the mempool stored in + * #BLI_mempool.chunks as a double linked list. + */ typedef struct BLI_mempool_chunk { struct BLI_mempool_chunk *next, *prev; - void *data; +#ifdef USE_DATA_PTR + void *_data; +#endif } BLI_mempool_chunk; +/** + * The mempool, stores and tracks memory \a chunks and elements within those chunks \a free. + */ struct BLI_mempool { struct ListBase chunks; - int esize; /* element size in bytes */ - int csize; /* chunk size in bytes */ - int pchunk; /* number of elements per chunk */ - int flag; + unsigned int esize; /* element size in bytes */ + unsigned int csize; /* chunk size in bytes */ + unsigned int pchunk; /* number of elements per chunk */ + unsigned int flag; /* keeps aligned to 16 bits */ - BLI_freenode *free; /* free element list. Interleaved into chunk datas. */ - int totalloc, totused; /* total number of elements allocated in total, - * and currently in use */ + BLI_freenode *free; /* free element list. Interleaved into chunk datas. */ + unsigned int maxchunks; /* use to know how many chunks to keep for BLI_mempool_clear */ + unsigned int totused; /* number of elements currently in use */ +#ifdef USE_TOTALLOC + unsigned int totalloc; /* number of elements allocated in total */ +#endif }; #define MEMPOOL_ELEM_SIZE_MIN (sizeof(void *) * 2) -BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag) +#ifdef USE_DATA_PTR +# define CHUNK_DATA(chunk) (chunk)->_data +#else +# define CHUNK_DATA(chunk) (CHECK_TYPE_INLINE(chunk, BLI_mempool_chunk *), (void *)((chunk) + 1)) +#endif + +/** + * \return the number of chunks to allocate based on how many elements are needed. + */ +BLI_INLINE unsigned int mempool_maxchunks(const unsigned int totelem, const unsigned int pchunk) +{ + return totelem / pchunk + 1; +} + +static BLI_mempool_chunk *mempool_chunk_alloc(BLI_mempool *pool) { - BLI_mempool *pool = NULL; - BLI_freenode *lasttail = NULL, *curnode = NULL; - int i, j, maxchunks; + BLI_mempool_chunk *mpchunk; +#ifdef USE_DATA_PTR + if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { + mpchunk = malloc(sizeof(BLI_mempool_chunk)); + CHUNK_DATA(mpchunk) = malloc((size_t)pool->csize); + } + else { + mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); + CHUNK_DATA(mpchunk) = MEM_mallocN((size_t)pool->csize, "BLI Mempool Chunk Data"); + } +#else + if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { + mpchunk = malloc(sizeof(BLI_mempool_chunk) + (size_t)pool->csize); + } + else { + mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk) + (size_t)pool->csize, "BLI_Mempool Chunk"); + } +#endif + + return mpchunk; +} + +/** + * Initialize a chunk and add into \a pool->chunks + * + * \param pool The pool to add the chunk into. + * \param mpchunk The new uninitialized chunk (can be malloc'd) + * \param lasttail The last element of the previous chunk + * (used when building free chunks initially) + * \return The last chunk, + */ +static BLI_freenode *mempool_chunk_add(BLI_mempool *pool, BLI_mempool_chunk *mpchunk, + BLI_freenode *lasttail) +{ + BLI_freenode *curnode = NULL; + const unsigned int pchunk_last = pool->pchunk - 1; char *addr; + unsigned int j; + + mpchunk->next = mpchunk->prev = NULL; + BLI_addtail(&(pool->chunks), mpchunk); + + if (pool->free == NULL) { + pool->free = CHUNK_DATA(mpchunk); /* start of the list */ + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { + pool->free->freeword = FREEWORD; + } + } + + /* loop through the allocated data, building the pointer structures */ + for (addr = CHUNK_DATA(mpchunk), j = 0; j != pchunk_last; j++) { + curnode = ((BLI_freenode *)addr); + addr += pool->esize; + curnode->next = (BLI_freenode *)addr; + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { + if (j != pchunk_last) + curnode->next->freeword = FREEWORD; + curnode->freeword = FREEWORD; + } + } + + /* terminate the list, + * will be overwritten if 'curnode' gets passed in again as 'lasttail' */ + curnode->next = NULL; + +#ifdef USE_TOTALLOC + pool->totalloc += pool->pchunk; +#endif + + /* final pointer in the previously allocated chunk is wrong */ + if (lasttail) { + lasttail->next = CHUNK_DATA(mpchunk); + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { + lasttail->freeword = FREEWORD; + } + } + + return curnode; +} + +static void mempool_chunk_free(BLI_mempool_chunk *mpchunk, const unsigned int flag) +{ + if (flag & BLI_MEMPOOL_SYSMALLOC) { +#ifdef USE_DATA_PTR + free(CHUNK_DATA(mpchunk)); +#endif + free(mpchunk); + } + else { +#ifdef USE_DATA_PTR + MEM_freeN(CHUNK_DATA(mpchunk)); +#endif + MEM_freeN(mpchunk); + } +} + +static void mempool_chunk_free_all(ListBase *chunks, const unsigned int flag) +{ + BLI_mempool_chunk *mpchunk, *mpchunk_next; + + for (mpchunk = chunks->first; mpchunk; mpchunk = mpchunk_next) { + mpchunk_next = mpchunk->next; + mempool_chunk_free(mpchunk, flag); + } + chunks->first = chunks->last = NULL; +} + +BLI_mempool *BLI_mempool_create(unsigned int esize, unsigned int totelem, + unsigned int pchunk, unsigned int flag) +{ + BLI_mempool *pool = NULL; + BLI_freenode *lasttail = NULL; + unsigned int i, maxchunks; /* allocate the pool structure */ if (flag & BLI_MEMPOOL_SYSMALLOC) { @@ -117,68 +256,25 @@ BLI_mempool *BLI_mempool_create(int esize, int totelem, int pchunk, int flag) pool->esize = esize; } + maxchunks = mempool_maxchunks(totelem, pchunk); + pool->flag = flag; pool->pchunk = pchunk; pool->csize = esize * pchunk; pool->chunks.first = pool->chunks.last = NULL; + pool->free = NULL; /* mempool_chunk_add assigns */ + pool->maxchunks = maxchunks; +#ifdef USE_TOTALLOC pool->totalloc = 0; +#endif pool->totused = 0; - maxchunks = totelem / pchunk + 1; - if (maxchunks == 0) { - maxchunks = 1; - } - /* allocate the actual chunks */ for (i = 0; i < maxchunks; i++) { - BLI_mempool_chunk *mpchunk; - - if (flag & BLI_MEMPOOL_SYSMALLOC) { - mpchunk = malloc(sizeof(BLI_mempool_chunk)); - mpchunk->data = malloc((size_t)pool->csize); - } - else { - mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); - mpchunk->data = MEM_mallocN((size_t)pool->csize, "BLI Mempool Chunk Data"); - } - - mpchunk->next = mpchunk->prev = NULL; - BLI_addtail(&(pool->chunks), mpchunk); - - if (i == 0) { - pool->free = mpchunk->data; /* start of the list */ - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - pool->free->freeword = FREEWORD; - } - } - - /* loop through the allocated data, building the pointer structures */ - for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) { - curnode = ((BLI_freenode *)addr); - addr += pool->esize; - curnode->next = (BLI_freenode *)addr; - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - if (j != pool->pchunk - 1) - curnode->next->freeword = FREEWORD; - curnode->freeword = FREEWORD; - } - } - /* final pointer in the previously allocated chunk is wrong */ - if (lasttail) { - lasttail->next = mpchunk->data; - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - lasttail->freeword = FREEWORD; - } - } - - /* set the end of this chunks memory to the new tail for next iteration */ - lasttail = curnode; -#ifdef USE_TOTALLOC - pool->totalloc += pool->pchunk; -#endif + BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); + lasttail = mempool_chunk_add(pool, mpchunk, lasttail); } - /* terminate the list */ - curnode->next = NULL; + return pool; } @@ -189,46 +285,9 @@ void *BLI_mempool_alloc(BLI_mempool *pool) pool->totused++; if (!(pool->free)) { - BLI_freenode *curnode = NULL; - char *addr; - int j; - /* need to allocate a new chunk */ - BLI_mempool_chunk *mpchunk; - - if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { - mpchunk = malloc(sizeof(BLI_mempool_chunk)); - mpchunk->data = malloc((size_t)pool->csize); - } - else { - mpchunk = MEM_mallocN(sizeof(BLI_mempool_chunk), "BLI_Mempool Chunk"); - mpchunk->data = MEM_mallocN((size_t)pool->csize, "BLI_Mempool Chunk Data"); - } - - mpchunk->next = mpchunk->prev = NULL; - BLI_addtail(&(pool->chunks), mpchunk); - - pool->free = mpchunk->data; /* start of the list */ - - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - pool->free->freeword = FREEWORD; - } - - for (addr = mpchunk->data, j = 0; j < pool->pchunk; j++) { - curnode = ((BLI_freenode *)addr); - addr += pool->esize; - curnode->next = (BLI_freenode *)addr; - - if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { - curnode->freeword = FREEWORD; - if (j != pool->pchunk - 1) - curnode->next->freeword = FREEWORD; - } - } - curnode->next = NULL; /* terminate the list */ -#ifdef USE_TOTALLOC - pool->totalloc += pool->pchunk; -#endif + BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); + mempool_chunk_add(pool, mpchunk, NULL); } retval = pool->free; @@ -238,7 +297,6 @@ void *BLI_mempool_alloc(BLI_mempool *pool) } pool->free = pool->free->next; - //memset(retval, 0, pool->esize); return retval; } @@ -258,6 +316,22 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) { BLI_freenode *newhead = addr; +#ifndef NDEBUG + { + BLI_mempool_chunk *chunk; + bool found = false; + for (chunk = pool->chunks.first; chunk; chunk = chunk->next) { + if (ARRAY_HAS_ITEM((char *)addr, (char *)CHUNK_DATA(chunk), pool->csize)) { + found = true; + break; + } + } + if (!found) { + BLI_assert(!"Attempt to free data which is not in pool.\n"); + } + } +#endif + if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { #ifndef NDEBUG /* this will detect double free's */ @@ -275,33 +349,18 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) if (pool->totused == 0) { BLI_freenode *curnode = NULL; char *tmpaddr = NULL; - int i; - - BLI_mempool_chunk *mpchunk = NULL; - BLI_mempool_chunk *first = pool->chunks.first; - - BLI_remlink(&pool->chunks, first); - - if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { - for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { - free(mpchunk->data); - } - BLI_freelist(&(pool->chunks)); - } - else { - for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk->next) { - MEM_freeN(mpchunk->data); - } - BLI_freelistN(&(pool->chunks)); - } + unsigned int i; + BLI_mempool_chunk *first; + first = BLI_pophead(&pool->chunks); + mempool_chunk_free_all(&pool->chunks, pool->flag); BLI_addtail(&pool->chunks, first); #ifdef USE_TOTALLOC pool->totalloc = pool->pchunk; #endif - pool->free = first->data; /* start of the list */ - for (tmpaddr = first->data, i = 0; i < pool->pchunk; i++) { + pool->free = CHUNK_DATA(first); /* start of the list */ + for (tmpaddr = CHUNK_DATA(first), i = 0; i < pool->pchunk; i++) { curnode = ((BLI_freenode *)tmpaddr); tmpaddr += pool->esize; curnode->next = (BLI_freenode *)tmpaddr; @@ -312,14 +371,14 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) int BLI_mempool_count(BLI_mempool *pool) { - return pool->totused; + return (int)pool->totused; } -void *BLI_mempool_findelem(BLI_mempool *pool, int index) +void *BLI_mempool_findelem(BLI_mempool *pool, unsigned int index) { BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); - if ((index >= 0) && (index < pool->totused)) { + if (index < pool->totused) { /* we could have some faster mem chunk stepping code inline */ BLI_mempool_iter iter; void *elem; @@ -337,6 +396,7 @@ void *BLI_mempool_findelem(BLI_mempool *pool, int index) * Fill in \a data with pointers to each element of the mempool, * to create lookup table. * + * \param pool Pool to create a table from. * \param data array of pointers at least the size of 'pool->totused' */ void BLI_mempool_as_table(BLI_mempool *pool, void **data) @@ -349,7 +409,7 @@ void BLI_mempool_as_table(BLI_mempool *pool, void **data) while ((elem = BLI_mempool_iterstep(&iter))) { *p++ = elem; } - BLI_assert((p - data) == pool->totused); + BLI_assert((unsigned int)(p - data) == pool->totused); } /** @@ -375,7 +435,7 @@ void BLI_mempool_as_array(BLI_mempool *pool, void *data) memcpy(p, elem, (size_t)pool->esize); p += pool->esize; } - BLI_assert((p - (char *)data) == pool->totused * pool->esize); + BLI_assert((unsigned int)(p - (char *)data) == pool->totused * pool->esize); } /** @@ -388,6 +448,9 @@ void *BLI_mempool_as_arrayN(BLI_mempool *pool, const char *allocstr) return data; } +/** + * Create a new mempool iterator, \a BLI_MEMPOOL_ALLOW_ITER flag must be set. + */ void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) { BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); @@ -406,11 +469,11 @@ static void *bli_mempool_iternext(BLI_mempool_iter *iter) if (!iter->curchunk || !iter->pool->totused) return NULL; - ret = ((char *)iter->curchunk->data) + iter->pool->esize * iter->curindex; + ret = ((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex); iter->curindex++; - if (iter->curindex >= iter->pool->pchunk) { + if (iter->curindex == iter->pool->pchunk) { iter->curchunk = iter->curchunk->next; iter->curindex = 0; } @@ -433,23 +496,22 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) /* optimized version of code above */ +/** + * Step over the iterator, returning the mempool item or NULL. + */ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) { BLI_freenode *ret; - if (UNLIKELY(iter->pool->totused == 0)) { - return NULL; - } - do { if (LIKELY(iter->curchunk)) { - ret = (BLI_freenode *)(((char *)iter->curchunk->data) + iter->pool->esize * iter->curindex); + ret = (BLI_freenode *)(((char *)CHUNK_DATA(iter->curchunk)) + (iter->pool->esize * iter->curindex)); } else { return NULL; } - if (UNLIKELY(++iter->curindex >= iter->pool->pchunk)) { + if (UNLIKELY(++iter->curindex == iter->pool->pchunk)) { iter->curindex = 0; iter->curchunk = iter->curchunk->next; } @@ -461,27 +523,69 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) #endif /** + * Empty the pool, as if it were just created. + * + * \param pool The pool to clear. + * \param totelem_reserve Optionally reserve how many items should be kept from clearing. + */ +void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve) +{ + BLI_mempool_chunk *mpchunk; + BLI_mempool_chunk *mpchunk_next; + unsigned int maxchunks; + + ListBase chunks_temp; + BLI_freenode *lasttail = NULL; + + if (totelem_reserve == -1) { + maxchunks = pool->maxchunks; + } + else { + maxchunks = mempool_maxchunks((unsigned int)totelem_reserve, pool->pchunk); + } + + /* free all after pool->maxchunks */ + + for (mpchunk = BLI_findlink(&pool->chunks, (int)maxchunks); mpchunk; mpchunk = mpchunk_next) { + mpchunk_next = mpchunk->next; + BLI_remlink(&pool->chunks, mpchunk); + mempool_chunk_free(mpchunk, pool->flag); + } + + /* re-initialize */ + pool->free = NULL; + pool->totused = 0; +#ifdef USE_TOTALLOC + pool->totalloc = 0; +#endif + + chunks_temp = pool->chunks; + pool->chunks.first = pool->chunks.last = NULL; + + while ((mpchunk = BLI_pophead(&chunks_temp))) { + lasttail = mempool_chunk_add(pool, mpchunk, lasttail); + } +} + +/** + * Wrap #BLI_mempool_clear_ex with no reserve set. + */ +void BLI_mempool_clear(BLI_mempool *pool) +{ + BLI_mempool_clear_ex(pool, -1); +} + +/** * Free the mempool its self (and all elements). */ void BLI_mempool_destroy(BLI_mempool *pool) { - BLI_mempool_chunk *mpchunk = NULL; - BLI_mempool_chunk *mpchunk_next; + mempool_chunk_free_all(&pool->chunks, pool->flag); if (pool->flag & BLI_MEMPOOL_SYSMALLOC) { - for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk_next) { - mpchunk_next = mpchunk->next; - free(mpchunk->data); - free(mpchunk); - } free(pool); } else { - for (mpchunk = pool->chunks.first; mpchunk; mpchunk = mpchunk_next) { - mpchunk_next = mpchunk->next; - MEM_freeN(mpchunk->data); - MEM_freeN(mpchunk); - } MEM_freeN(pool); } } diff --git a/source/blender/blenlib/intern/boxpack2d.c b/source/blender/blenlib/intern/boxpack2d.c index 8a97fdcab67..1087b02b3bb 100644 --- a/source/blender/blenlib/intern/boxpack2d.c +++ b/source/blender/blenlib/intern/boxpack2d.c @@ -27,7 +27,9 @@ #include <stdlib.h> /* for qsort */ #include "MEM_guardedalloc.h" -#include "BLI_boxpack2d.h" +#include "BLI_strict_flags.h" + +#include "BLI_boxpack2d.h" /* own include */ /* BoxPacker for backing 2D rectangles into a square * @@ -169,11 +171,11 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float * } /* Sort boxes, biggest first */ - qsort(boxarray, len, sizeof(BoxPack), box_areasort); + qsort(boxarray, (size_t)len, sizeof(BoxPack), box_areasort); /* add verts to the boxes, these are only used internally */ - vert = vertarray = MEM_mallocN(len * 4 * sizeof(BoxVert), "BoxPack Verts"); - vertex_pack_indices = MEM_mallocN(len * 3 * sizeof(int), "BoxPack Indices"); + vert = vertarray = MEM_mallocN((size_t)len * 4 * sizeof(BoxVert), "BoxPack Verts"); + vertex_pack_indices = MEM_mallocN((size_t)len * 3 * sizeof(int), "BoxPack Indices"); for (box = boxarray, box_index = 0, i = 0; box_index < len; box_index++, box++) { @@ -241,7 +243,7 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float * box_width = box->w; box_height = box->h; - qsort(vertex_pack_indices, verts_pack_len, sizeof(int), vertex_sort); + qsort(vertex_pack_indices, (size_t)verts_pack_len, sizeof(int), vertex_sort); /* Pack the box in with the others */ /* sort the verts */ @@ -318,7 +320,7 @@ void BLI_box_pack_2D(BoxPack *boxarray, const int len, float *tot_width, float * (*tot_height) = max_ff(BOXTOP(box), (*tot_height)); /* Place the box */ - vert->free &= ~quad_flags[j]; + vert->free &= (short)~quad_flags[j]; switch (j) { case TR: diff --git a/source/blender/blenlib/intern/edgehash.c b/source/blender/blenlib/intern/edgehash.c index bac69183f0c..b26e007b3e6 100644 --- a/source/blender/blenlib/intern/edgehash.c +++ b/source/blender/blenlib/intern/edgehash.c @@ -38,14 +38,7 @@ #include "BLI_utildefines.h" #include "BLI_edgehash.h" #include "BLI_mempool.h" - -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif +#include "BLI_strict_flags.h" /**************inlined code************/ static const unsigned int _ehash_hashsizes[] = { @@ -55,6 +48,16 @@ static const unsigned int _ehash_hashsizes[] = { 268435459 }; +/* internal flag to ensure sets values aren't used */ +#ifndef NDEBUG +# define EDGEHASH_FLAG_IS_SET (1 << 8) +# define IS_EDGEHASH_ASSERT(eh) BLI_assert((eh->flag & EDGEHASH_FLAG_IS_SET) == 0) +// # define IS_EDGESET_ASSERT(es) BLI_assert((es->flag & EDGEHASH_FLAG_IS_SET) != 0) +#else +# define IS_EDGEHASH_ASSERT(eh) +// # define IS_EDGESET_ASSERT(es) +#endif + /* ensure v0 is smaller */ #define EDGE_ORD(v0, v1) \ if (v0 > v1) { \ @@ -75,36 +78,94 @@ struct EdgeHash { EdgeEntry **buckets; BLI_mempool *epool; unsigned int nbuckets, nentries; - unsigned short cursize, flag; + unsigned int cursize, flag; }; /* -------------------------------------------------------------------- */ /* EdgeHash API */ -/* internal utility API */ - -#define EDGE_HASH(v0, v1) ((v0 * 39) ^ (v1 * 31)) +/** \name Internal Utility API + * \{ */ +/** + * Get the hash for a key. + */ BLI_INLINE unsigned int edgehash_keyhash(EdgeHash *eh, unsigned int v0, unsigned int v1) { BLI_assert(v0 < v1); - return EDGE_HASH(v0, v1) % eh->nbuckets; + + return ((v0 * 39) ^ (v1 * 31)) % eh->nbuckets; +} + +/** + * Check if the number of items in the GHash is large enough to require more buckets. + */ +BLI_INLINE bool edgehash_test_expand_buckets(const unsigned int nentries, const unsigned int nbuckets) +{ + return (nentries > nbuckets * 3); } +/** + * Expand buckets to the next size up. + */ +BLI_INLINE void edgehash_resize_buckets(EdgeHash *eh, const unsigned int nbuckets) +{ + EdgeEntry **buckets_old = eh->buckets; + EdgeEntry **buckets_new; + const unsigned int nbuckets_old = eh->nbuckets; + unsigned int i; + EdgeEntry *e; + + BLI_assert(eh->nbuckets != nbuckets); + + eh->nbuckets = nbuckets; + buckets_new = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets"); + + for (i = 0; i < nbuckets_old; i++) { + EdgeEntry *e_next; + for (e = buckets_old[i]; e; e = e_next) { + const unsigned hash = edgehash_keyhash(eh, e->v0, e->v1); + e_next = e->next; + e->next = buckets_new[hash]; + buckets_new[hash] = e; + } + } + + eh->buckets = buckets_new; + MEM_freeN(buckets_old); +} + +/** + * Increase initial bucket size to match a reserved ammount. + */ +BLI_INLINE void edgehash_buckets_reserve(EdgeHash *eh, const unsigned int nentries_reserve) +{ + while (edgehash_test_expand_buckets(nentries_reserve, eh->nbuckets)) { + eh->nbuckets = _ehash_hashsizes[++eh->cursize]; + } +} + +/** + * Internal lookup function. + * Takes a hash argument to avoid calling #ghash_keyhash multiple times. + */ BLI_INLINE EdgeEntry *edgehash_lookup_entry_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, const unsigned int hash) { EdgeEntry *e; BLI_assert(v0 < v1); for (e = eh->buckets[hash]; e; e = e->next) { - if (v0 == e->v0 && v1 == e->v1) { + if (UNLIKELY(v0 == e->v0 && v1 == e->v1)) { return e; } } return NULL; } +/** + * Internal lookup function. Only wraps #edgehash_lookup_entry_ex + */ BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsigned int v1) { unsigned int hash; @@ -113,12 +174,40 @@ BLI_INLINE EdgeEntry *edgehash_lookup_entry(EdgeHash *eh, unsigned int v0, unsig return edgehash_lookup_entry_ex(eh, v0, v1, hash); } -static void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val, - unsigned int hash) + +static EdgeHash *edgehash_new(const char *info, + const unsigned int nentries_reserve, + const unsigned int entry_size) +{ + EdgeHash *eh = MEM_mallocN(sizeof(*eh), info); + + eh->nbuckets = _ehash_hashsizes[0]; /* eh->cursize */ + eh->nentries = 0; + eh->cursize = 0; + eh->flag = 0; + + /* if we have reserved the number of elements that this hash will contain */ + if (nentries_reserve) { + edgehash_buckets_reserve(eh, nentries_reserve); + } + + eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets"); + eh->epool = BLI_mempool_create(entry_size, 512, 512, BLI_MEMPOOL_SYSMALLOC); + + return eh; +} + +/** + * Internal insert function. + * Takes a hash argument to avoid calling #edgehash_keyhash multiple times. + */ +BLI_INLINE void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val, + unsigned int hash) { EdgeEntry *e = BLI_mempool_alloc(eh->epool); BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0)); + IS_EDGEHASH_ASSERT(eh); /* this helps to track down errors with bad edge data */ BLI_assert(v0 < v1); @@ -130,44 +219,85 @@ static void edgehash_insert_ex(EdgeHash *eh, unsigned int v0, unsigned int v1, v e->val = val; eh->buckets[hash] = e; - if (UNLIKELY(++eh->nentries > eh->nbuckets / 2)) { - EdgeEntry **old = eh->buckets; - const unsigned int nold = eh->nbuckets; - unsigned int i; + if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) { + edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]); + } +} - eh->nbuckets = _ehash_hashsizes[++eh->cursize]; - eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets"); - - for (i = 0; i < nold; i++) { - EdgeEntry *e_next; - for (e = old[i]; e; e = e_next) { - e_next = e->next; - hash = edgehash_keyhash(eh, e->v0, e->v1); - e->next = eh->buckets[hash]; - eh->buckets[hash] = e; - } - } +/** + * Insert function that doesn't set the value (use for EdgeSet) + */ +BLI_INLINE void edgehash_insert_ex_keyonly(EdgeHash *eh, unsigned int v0, unsigned int v1, + unsigned int hash) +{ + EdgeEntry *e = BLI_mempool_alloc(eh->epool); + + BLI_assert((eh->flag & EDGEHASH_FLAG_ALLOW_DUPES) || (BLI_edgehash_haskey(eh, v0, v1) == 0)); + + /* this helps to track down errors with bad edge data */ + BLI_assert(v0 < v1); + BLI_assert(v0 != v1); + + e->next = eh->buckets[hash]; + e->v0 = v0; + e->v1 = v1; + /* intentionally leave value unset */ + eh->buckets[hash] = e; + + if (UNLIKELY(edgehash_test_expand_buckets(++eh->nentries, eh->nbuckets))) { + edgehash_resize_buckets(eh, _ehash_hashsizes[++eh->cursize]); + } +} + +BLI_INLINE void edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) +{ + unsigned int hash; + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ + hash = edgehash_keyhash(eh, v0, v1); + edgehash_insert_ex(eh, v0, v1, val, hash); +} + +/** + * Run free callbacks for freeing entries. + */ +static void edgehash_free_cb(EdgeHash *eh, EdgeHashFreeFP valfreefp) +{ + unsigned int i; - MEM_freeN(old); + BLI_assert(valfreefp); + + for (i = 0; i < eh->nbuckets; i++) { + EdgeEntry *e; + + for (e = eh->buckets[i]; e; ) { + EdgeEntry *e_next = e->next; + + if (valfreefp) valfreefp(e->val); + + e = e_next; + } } } -#undef EDGE_HASH +/** \} */ +/** \name Public API + * \{ */ + /* Public API */ -EdgeHash *BLI_edgehash_new(void) +EdgeHash *BLI_edgehash_new_ex(const char *info, + const unsigned int nentries_reserve) { - EdgeHash *eh = MEM_callocN(sizeof(*eh), "EdgeHash"); - eh->cursize = 0; - eh->nentries = 0; - eh->nbuckets = _ehash_hashsizes[eh->cursize]; - - eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets 2"); - eh->epool = BLI_mempool_create(sizeof(EdgeEntry), 512, 512, BLI_MEMPOOL_SYSMALLOC); + return edgehash_new(info, + nentries_reserve, + sizeof(EdgeEntry)); +} - return eh; +EdgeHash *BLI_edgehash_new(const char *info) +{ + return BLI_edgehash_new_ex(info, 0); } /** @@ -176,29 +306,30 @@ EdgeHash *BLI_edgehash_new(void) */ void BLI_edgehash_insert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) { - unsigned int hash; - EDGE_ORD(v0, v1); /* ensure v0 is smaller */ - hash = edgehash_keyhash(eh, v0, v1); - edgehash_insert_ex(eh, v0, v1, val, hash); + edgehash_insert(eh, v0, v1, val); } /** * Assign a new value to a key that may already be in edgehash. */ -void BLI_edgehash_assign(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) +bool BLI_edgehash_reinsert(EdgeHash *eh, unsigned int v0, unsigned int v1, void *val) { unsigned int hash; EdgeEntry *e; + IS_EDGEHASH_ASSERT(eh); + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ hash = edgehash_keyhash(eh, v0, v1); e = edgehash_lookup_entry_ex(eh, v0, v1, hash); if (e) { e->val = val; + return false; } else { edgehash_insert_ex(eh, v0, v1, val, hash); + return true; } } @@ -209,6 +340,7 @@ void BLI_edgehash_assign(EdgeHash *eh, unsigned int v0, unsigned int v1, void *v void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) { EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1); + IS_EDGEHASH_ASSERT(eh); return e ? &e->val : NULL; } @@ -221,6 +353,7 @@ void **BLI_edgehash_lookup_p(EdgeHash *eh, unsigned int v0, unsigned int v1) void *BLI_edgehash_lookup(EdgeHash *eh, unsigned int v0, unsigned int v1) { EdgeEntry *e = edgehash_lookup_entry(eh, v0, v1); + IS_EDGEHASH_ASSERT(eh); return e ? e->val : NULL; } @@ -243,30 +376,32 @@ int BLI_edgehash_size(EdgeHash *eh) /** * Remove all edges from hash. */ -void BLI_edgehash_clear(EdgeHash *eh, EdgeHashFreeFP valfreefp) +void BLI_edgehash_clear_ex(EdgeHash *eh, EdgeHashFreeFP valfreefp, + const unsigned int nentries_reserve) { - unsigned int i; - - for (i = 0; i < eh->nbuckets; i++) { - EdgeEntry *e; - - for (e = eh->buckets[i]; e; ) { - EdgeEntry *n = e->next; - - if (valfreefp) valfreefp(e->val); - BLI_mempool_free(eh->epool, e); - - e = n; - } - eh->buckets[i] = NULL; - } + if (valfreefp) + edgehash_free_cb(eh, valfreefp); + eh->nbuckets = _ehash_hashsizes[0]; /* eh->cursize */ eh->nentries = 0; + eh->cursize = 0; + + if (nentries_reserve) { + edgehash_buckets_reserve(eh, nentries_reserve); + } + + MEM_freeN(eh->buckets); + eh->buckets = MEM_callocN(eh->nbuckets * sizeof(*eh->buckets), "eh buckets"); + + BLI_mempool_clear_ex(eh->epool, nentries_reserve ? (int)nentries_reserve : -1); } void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) { - BLI_edgehash_clear(eh, valfreefp); + BLI_assert((int)eh->nentries == BLI_mempool_count(eh->epool)); + + if (valfreefp) + edgehash_free_cb(eh, valfreefp); BLI_mempool_destroy(eh->epool); @@ -275,20 +410,25 @@ void BLI_edgehash_free(EdgeHash *eh, EdgeHashFreeFP valfreefp) } -void BLI_edgehash_flag_set(EdgeHash *eh, unsigned short flag) +void BLI_edgehash_flag_set(EdgeHash *eh, unsigned int flag) { eh->flag |= flag; } -void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned short flag) +void BLI_edgehash_flag_clear(EdgeHash *eh, unsigned int flag) { - eh->flag &= (unsigned short)~flag; + eh->flag &= ~flag; } +/** \} */ + /* -------------------------------------------------------------------- */ /* EdgeHash Iterator API */ +/** \name Iterator API + * \{ */ + struct EdgeHashIterator { EdgeHash *eh; unsigned int curBucket; @@ -344,6 +484,14 @@ void *BLI_edgehashIterator_getValue(EdgeHashIterator *ehi) } /** + * Retrieve the pointer to the value from an iterator. + */ +void **BLI_edgehashIterator_getValue_p(EdgeHashIterator *ehi) +{ + return ehi->curEntry ? &ehi->curEntry->val : NULL; +} + +/** * Set the value for an iterator. */ void BLI_edgehashIterator_setValue(EdgeHashIterator *ehi, void *val) @@ -378,3 +526,80 @@ bool BLI_edgehashIterator_isDone(EdgeHashIterator *ehi) { return (ehi->curEntry == NULL); } + +/** \} */ + +/* -------------------------------------------------------------------- */ +/* EdgeSet API */ + +/* Use edgehash API to give 'set' functionality */ + +/** \name EdgeSet Functions + * \{ */ +EdgeSet *BLI_edgeset_new_ex(const char *info, + const unsigned int nentries_reserve) +{ + EdgeSet *es = (EdgeSet *)edgehash_new(info, + nentries_reserve, + sizeof(EdgeEntry) - sizeof(void *)); +#ifndef NDEBUG + ((EdgeHash *)es)->flag |= EDGEHASH_FLAG_IS_SET; +#endif + return es; +} + +EdgeSet *BLI_edgeset_new(const char *info) +{ + return BLI_edgeset_new_ex(info, 0); +} + +int BLI_edgeset_size(EdgeSet *es) +{ + return (int)((EdgeHash *)es)->nentries; +} + +/** + * Adds the key to the set (no checks for unique keys!). + * Matching #BLI_edgehash_insert + */ +void BLI_edgeset_insert(EdgeSet *es, unsigned int v0, unsigned int v1) +{ + unsigned int hash; + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ + hash = edgehash_keyhash((EdgeHash *)es, v0, v1); + edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, hash); +} + +/** + * Assign a new value to a key that may already be in edgehash. + */ +bool BLI_edgeset_reinsert(EdgeSet *es, unsigned int v0, unsigned int v1) +{ + unsigned int hash; + EdgeEntry *e; + + EDGE_ORD(v0, v1); /* ensure v0 is smaller */ + hash = edgehash_keyhash((EdgeHash *)es, v0, v1); + + e = edgehash_lookup_entry_ex((EdgeHash *)es, v0, v1, hash); + if (e) { + return false; + } + else { + edgehash_insert_ex_keyonly((EdgeHash *)es, v0, v1, hash); + return true; + } +} + +bool BLI_edgeset_haskey(EdgeSet *es, unsigned int v0, unsigned int v1) +{ + return (edgehash_lookup_entry((EdgeHash *)es, v0, v1) != NULL); +} + + +void BLI_edgeset_free(EdgeSet *es) +{ + BLI_edgehash_free((EdgeHash *)es, NULL); +} + +/** \} */ diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c index 4809ba59aaf..55726565f59 100644 --- a/source/blender/blenlib/intern/fileops.c +++ b/source/blender/blenlib/intern/fileops.c @@ -215,6 +215,11 @@ bool BLI_file_touch(const char *file) #ifdef WIN32 +static void callLocalErrorCallBack(const char *err) +{ + printf("%s\n", err); +} + static char str[MAXPATHLEN + 12]; FILE *BLI_fopen(const char *filename, const char *mode) diff --git a/source/blender/blenlib/intern/gsqueue.c b/source/blender/blenlib/intern/gsqueue.c index 7f158bc3efb..6967742f89b 100644 --- a/source/blender/blenlib/intern/gsqueue.c +++ b/source/blender/blenlib/intern/gsqueue.c @@ -35,6 +35,7 @@ #include "BLI_utildefines.h" #include "BLI_gsqueue.h" +#include "BLI_strict_flags.h" typedef struct _GSQueueElem GSQueueElem; struct _GSQueueElem { @@ -93,7 +94,7 @@ int BLI_gsqueue_size(GSQueue *gq) */ void BLI_gsqueue_peek(GSQueue *gq, void *item_r) { - memcpy(item_r, &gq->head[1], gq->elem_size); + memcpy(item_r, &gq->head[1], (size_t)gq->elem_size); } /** @@ -114,7 +115,7 @@ void BLI_gsqueue_pop(GSQueue *gq, void *item_r) gq->head = gq->head->next; } - if (item_r) memcpy(item_r, &elem[1], gq->elem_size); + if (item_r) memcpy(item_r, &elem[1], (size_t)gq->elem_size); MEM_freeN(elem); } @@ -130,11 +131,11 @@ void BLI_gsqueue_push(GSQueue *gq, void *item) /* compare: prevent events added double in row */ if (!BLI_gsqueue_is_empty(gq)) { - if (0 == memcmp(item, &gq->head[1], gq->elem_size)) + if (0 == memcmp(item, &gq->head[1], (size_t)gq->elem_size)) return; } - elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push"); - memcpy(&elem[1], item, gq->elem_size); + elem = MEM_mallocN(sizeof(*elem) + (size_t)gq->elem_size, "gqueue_push"); + memcpy(&elem[1], item, (size_t)gq->elem_size); elem->next = NULL; if (BLI_gsqueue_is_empty(gq)) { @@ -154,8 +155,8 @@ void BLI_gsqueue_push(GSQueue *gq, void *item) */ void BLI_gsqueue_pushback(GSQueue *gq, void *item) { - GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + gq->elem_size, "gqueue_push"); - memcpy(&elem[1], item, gq->elem_size); + GSQueueElem *elem = MEM_mallocN(sizeof(*elem) + (size_t)gq->elem_size, "gqueue_push"); + memcpy(&elem[1], item, (size_t)gq->elem_size); elem->next = gq->head; if (BLI_gsqueue_is_empty(gq)) { @@ -176,5 +177,3 @@ void BLI_gsqueue_free(GSQueue *gq) } MEM_freeN(gq); } - - diff --git a/source/blender/blenlib/intern/lasso.c b/source/blender/blenlib/intern/lasso.c index aa08a780394..8e22d6f1182 100644 --- a/source/blender/blenlib/intern/lasso.c +++ b/source/blender/blenlib/intern/lasso.c @@ -34,12 +34,13 @@ #include "BLI_math.h" #include "BLI_rect.h" +#include "BLI_strict_flags.h" #include "BLI_lasso.h" /* own include */ -void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves) +void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const unsigned int moves) { - short a; + unsigned int a; rect->xmin = rect->xmax = mcords[0][0]; rect->ymin = rect->ymax = mcords[0][1]; @@ -53,11 +54,11 @@ void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const short moves) } -bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves, +bool BLI_lasso_is_point_inside(const int mcords[][2], const unsigned int moves, const int sx, const int sy, const int error_value) { - if (sx == error_value) { + if (sx == error_value || moves == 0) { return false; } else { @@ -67,14 +68,14 @@ bool BLI_lasso_is_point_inside(const int mcords[][2], const short moves, } /* edge version for lasso select. we assume boundbox check was done */ -bool BLI_lasso_is_edge_inside(const int mcords[][2], const short moves, +bool BLI_lasso_is_edge_inside(const int mcords[][2], const unsigned int moves, int x0, int y0, int x1, int y1, const int error_value) { int v1[2], v2[2]; - int a; + unsigned int a; - if (x0 == error_value || x1 == error_value) { + if (x0 == error_value || x1 == error_value || moves == 0) { return false; } diff --git a/source/blender/blenlib/intern/listbase.c b/source/blender/blenlib/intern/listbase.c index ded4f31ae05..2c59b940f8c 100644 --- a/source/blender/blenlib/intern/listbase.c +++ b/source/blender/blenlib/intern/listbase.c @@ -129,6 +129,30 @@ bool BLI_remlink_safe(ListBase *listbase, void *vlink) } } +/** + * Removes the head from \a listbase and returns it. + */ +void *BLI_pophead(ListBase *listbase) +{ + Link *link; + if ((link = listbase->first)) { + BLI_remlink(listbase, link); + } + return link; +} + + +/** + * Removes the tail from \a listbase and returns it. + */ +void *BLI_poptail(ListBase *listbase) +{ + Link *link; + if ((link = listbase->last)) { + BLI_remlink(listbase, link); + } + return link; +} /** * Removes \a vlink from listbase and disposes of it. Assumes it is linked into there! @@ -557,19 +581,34 @@ void BLI_reverselist(ListBase *lb) /** * \param vlink Link to make first. */ -void BLI_rotatelist(ListBase *lb, void *vlink) +void BLI_rotatelist_first(ListBase *lb, void *vlink) { /* make circular */ - ((LinkData *)lb->first)->prev = lb->last; - ((LinkData *)lb->last)->next = lb->first; + ((Link *)lb->first)->prev = lb->last; + ((Link *)lb->last)->next = lb->first; lb->first = vlink; - lb->last = ((LinkData *)vlink)->prev; + lb->last = ((Link *)vlink)->prev; - ((LinkData *)lb->first)->prev = NULL; - ((LinkData *)lb->last)->next = NULL; + ((Link *)lb->first)->prev = NULL; + ((Link *)lb->last)->next = NULL; } +/** + * \param vlink Link to make last. + */ +void BLI_rotatelist_last(ListBase *lb, void *vlink) +{ + /* make circular */ + ((Link *)lb->first)->prev = lb->last; + ((Link *)lb->last)->next = lb->first; + + lb->first = ((Link *)vlink)->next; + lb->last = vlink; + + ((Link *)lb->first)->prev = NULL; + ((Link *)lb->last)->next = NULL; +} /* create a generic list node containing link to provided data */ LinkData *BLI_genericNodeN(void *data) diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 3ffd96f62c7..e6509db1c5e 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -131,8 +131,9 @@ MINLINE int power_of_2_max_i(int n) if (is_power_of_2_i(n)) return n; - while (!is_power_of_2_i(n)) + do { n = n & (n - 1); + } while (!is_power_of_2_i(n)); return n * 2; } @@ -152,6 +153,14 @@ MINLINE int divide_round_i(int a, int b) return (2 * a + b) / (2 * b); } +/** + * modulo that handles negative numbers, works the same as Python's. + */ +MINLINE int mod_i(int i, int n) +{ + return (i % n + n) % n; +} + MINLINE unsigned int highest_order_bit_i(unsigned int n) { n |= (n >> 1); diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 9b8fd0ad85b..cf1377f6627 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -183,6 +183,28 @@ float area_poly_v2(int nr, float verts[][2]) return fabsf(0.5f * area); } +/********************************* Planes **********************************/ + +/** + * Calculate a plane from a point and a direction, + * \note \a point_no isn't required to be normalized. + */ +void plane_from_point_normal_v3(float r_plane[4], const float plane_co[3], const float plane_no[3]) +{ + copy_v3_v3(r_plane, plane_no); + r_plane[3] = -dot_v3v3(r_plane, plane_co); +} + +/** + * Get a point and a normal from a plane. + */ +void plane_to_point_normal_v3(const float plane[4], float r_plane_co[3], float r_plane_no[3]) +{ + const float length = normalize_v3_v3(r_plane_no, plane); + madd_v3_v3v3fl(r_plane_co, r_plane_no, r_plane_no, (-plane[3] / length) - 1.0f); +} + + /********************************* Volume **********************************/ /** @@ -283,45 +305,39 @@ void closest_to_line_segment_v3(float close_r[3], const float v1[3], const float copy_v3_v3(close_r, cp); } -/* find the closest point on a plane to another point and store it in close_r - * close_r: return coordinate - * plane_co: a point on the plane - * plane_no_unit: the plane's normal, and d is the last number in the plane equation 0 = ax + by + cz + d - * pt: the point that you want the nearest of +/** + * Find the closest point on a plane. + * + * \param close_r Return coordinate + * \param plane The plane to test against. + * \param pt The point to find the nearest of + * + * \note non-unit-length planes are supported. */ - -void closest_to_plane_v3(float close_r[3], const float plane_co[3], const float plane_no_unit[3], const float pt[3]) +void closest_to_plane_v3(float close_r[3], const float plane[4], const float pt[3]) { - float temp[3]; - float dotprod; - - sub_v3_v3v3(temp, pt, plane_co); - dotprod = dot_v3v3(temp, plane_no_unit); - - close_r[0] = pt[0] - (plane_no_unit[0] * dotprod); - close_r[1] = pt[1] - (plane_no_unit[1] * dotprod); - close_r[2] = pt[2] - (plane_no_unit[2] * dotprod); + const float length = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + madd_v3_v3v3fl(close_r, pt, plane, -side / length); } -/* signed distance from the point to the plane in 3D */ -float dist_to_plane_normalized_v3(const float p[3], const float plane_co[3], const float plane_no_unit[3]) +float dist_squared_to_plane_v3(const float pt[3], const float plane[4]) { - float plane_co_other[3]; - - add_v3_v3v3(plane_co_other, plane_co, plane_no_unit); - - return line_point_factor_v3(p, plane_co, plane_co_other); + const float length = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + const float fac = side / length; + return copysign(length * (fac * fac), side); } -float dist_to_plane_v3(const float p[3], const float plane_co[3], const float plane_no[3]) +/** + * Return the signed distance from the point to the plane. + */ +float dist_to_plane_v3(const float pt[3], const float plane[4]) { - float plane_no_unit[3]; - float plane_co_other[3]; - - normalize_v3_v3(plane_no_unit, plane_no); - add_v3_v3v3(plane_co_other, plane_co, plane_no_unit); - - return line_point_factor_v3(p, plane_co, plane_co_other); + const float length = len_squared_v3(plane); + const float side = plane_point_side_v3(plane, pt); + const float fac = side / length; + return sqrtf(length) * fac; } /* distance v1 to line-piece l1-l2 in 3D */ @@ -696,16 +712,15 @@ int isect_line_sphere_v2(const float l1[2], const float l2[2], } /* 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) +bool isect_point_poly_v2(const float pt[2], const float verts[][2], const unsigned 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; + unsigned int i; const float *p1, *p2; p1 = verts[nr - 1]; - p2 = verts[0]; /* first vector */ fp1[0] = (float)(p1[0] - pt[0]); @@ -714,6 +729,8 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr for (i = 0; i < nr; i++) { float dot, ang, cross; + p2 = verts[i]; + /* second vector */ fp2[0] = (float)(p2[0] - pt[0]); fp2[1] = (float)(p2[1] - pt[1]); @@ -730,21 +747,19 @@ bool isect_point_poly_v2(const float pt[2], const float verts[][2], const int nr /* 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) +bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const unsigned 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; + unsigned int i; const int *p1, *p2; p1 = verts[nr - 1]; - p2 = verts[0]; /* first vector */ fp1[0] = (float)(p1[0] - pt[0]); @@ -753,6 +768,8 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr for (i = 0; i < nr; i++) { float dot, ang, cross; + p2 = verts[i]; + /* second vector */ fp2[0] = (float)(p2[0] - pt[0]); fp2[1] = (float)(p2[1] - pt[1]); @@ -769,7 +786,6 @@ bool isect_point_poly_v2_int(const int pt[2], const int verts[][2], const int nr /* circulate */ copy_v2_v2(fp1, fp2); p1 = p2; - p2 = verts[i + 1]; } return (fabsf(angletot) > 4.0f); @@ -878,6 +894,45 @@ bool isect_line_tri_v3(const float p1[3], const float p2[3], return 1; } +/* like isect_line_tri_v3, but allows epsilon tolerance around triangle */ +bool isect_line_tri_epsilon_v3(const float p1[3], const float p2[3], + const float v0[3], const float v1[3], const float v2[3], + float *r_lambda, float r_uv[2], const float epsilon) +{ + + float p[3], s[3], d[3], e1[3], e2[3], q[3]; + float a, f, u, v; + + sub_v3_v3v3(e1, v1, v0); + sub_v3_v3v3(e2, v2, v0); + sub_v3_v3v3(d, p2, p1); + + cross_v3_v3v3(p, d, e2); + a = dot_v3v3(e1, p); + if ((a > -0.000001f) && (a < 0.000001f)) return 0; + f = 1.0f / a; + + sub_v3_v3v3(s, p1, v0); + + u = f * dot_v3v3(s, p); + if ((u < -epsilon) || (u > 1.0f + epsilon)) return 0; + + cross_v3_v3v3(q, s, e1); + + v = f * dot_v3v3(d, q); + if ((v < -epsilon) || ((u + v) > 1.0f + epsilon)) return 0; + + *r_lambda = f * dot_v3v3(e2, q); + if ((*r_lambda < 0.0f) || (*r_lambda > 1.0f)) return 0; + + if (r_uv) { + r_uv[0] = u; + r_uv[1] = v; + } + + return 1; +} + /* moved from effect.c * test if the ray starting at p1 going in d direction intersects the triangle v0..v2 * return non zero if it does @@ -1043,6 +1098,22 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3], } /** + * Check if a point is behind all planes. + */ +bool isect_point_planes_v3(float (*planes)[4], int totplane, const float p[3]) +{ + int i; + + for (i = 0; i < totplane; i++) { + if (plane_point_side_v3(planes[i], p) > 0.0f) { + return false; + } + } + + return true; +} + +/** * Intersect line/plane, optionally treat line as directional (like a ray) with the no_flip argument. * * \param out The intersection point. @@ -1050,50 +1121,28 @@ bool isect_ray_tri_threshold_v3(const float p1[3], const float d[3], * \param l2 The second point of the line. * \param plane_co A point on the plane to intersect with. * \param plane_no The direction of the plane (does not need to be normalized). - * \param no_flip When true, the intersection point will always be from l1 to l2, even if this is not on the plane. + * + * \note #line_plane_factor_v3() shares logic. */ bool isect_line_plane_v3(float out[3], const float l1[3], const float l2[3], - const float plane_co[3], const float plane_no[3], const bool no_flip) + const float plane_co[3], const float plane_no[3]) { - float l_vec[3]; /* l1 -> l2 normalized vector */ - float p_no[3]; /* 'plane_no' normalized */ + float u[3], h[3]; float dot; - sub_v3_v3v3(l_vec, l2, l1); - - normalize_v3(l_vec); - normalize_v3_v3(p_no, plane_no); + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, l1, plane_co); + dot = dot_v3v3(plane_no, u); - dot = dot_v3v3(l_vec, p_no); - if (dot == 0.0f) { - return 0; + if (fabsf(dot) > FLT_EPSILON) { + float lambda = -dot_v3v3(plane_no, h) / dot; + madd_v3_v3v3fl(out, l1, u, lambda); + return true; } else { - float l1_plane[3]; /* line point aligned with the plane */ - float dist; /* 'plane_no' aligned distance to the 'plane_co' */ - - /* for predictable flipping since the plane is only used to - * define a direction, ignore its flipping and aligned with 'l_vec' */ - if (dot < 0.0f) { - dot = -dot; - negate_v3(p_no); - } - - add_v3_v3v3(l1_plane, l1, p_no); - - dist = line_point_factor_v3(plane_co, l1, l1_plane); - - /* treat line like a ray, when 'no_flip' is set */ - if (no_flip && dist < 0.0f) { - dist = -dist; - } - - mul_v3_fl(l_vec, dist / dot); - - add_v3_v3v3(out, l1, l_vec); - - return 1; + /* The segment is parallel to plane */ + return false; } } @@ -1119,7 +1168,7 @@ void isect_plane_plane_v3(float r_isect_co[3], float r_isect_no[3], cross_v3_v3v3(r_isect_no, plane_a_no, plane_b_no); /* direction is simply the cross product */ cross_v3_v3v3(plane_a_co_other, plane_a_no, r_isect_no); add_v3_v3(plane_a_co_other, plane_a_co); - isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no, FALSE); + isect_line_plane_v3(r_isect_co, plane_a_co, plane_a_co_other, plane_b_co, plane_b_no); } @@ -1645,6 +1694,20 @@ float line_point_factor_v2(const float p[2], const float l1[2], const float l2[2 #endif } +/** + * \note #isect_line_plane_v3() shares logic + */ +float line_plane_factor_v3(const float plane_co[3], const float plane_no[3], + const float l1[3], const float l2[3]) +{ + float u[3], h[3]; + float dot; + sub_v3_v3v3(u, l2, l1); + sub_v3_v3v3(h, l1, plane_co); + dot = dot_v3v3(plane_no, u); + return (dot != 0.0f) ? -dot_v3v3(plane_no, h) / dot : 0.0f; +} + /* ensure the distance between these points is no greater then 'dist' * if it is, scale then both into the center */ void limit_dist_v3(float v1[3], float v2[3], const float dist) @@ -1757,7 +1820,7 @@ bool clip_segment_v3_plane(float p1[3], float p2[3], const float plane[4]) if (div == 0.0f) /* parallel */ return 1; - t = -(dot_v3v3(p1, plane) + plane[3]) / div; + t = -plane_point_side_v3(plane, p1) / div; if (div > 0.0f) { /* behind plane, completely clipped */ @@ -1811,7 +1874,7 @@ bool clip_segment_v3_plane_n(float r_p1[3], float r_p2[3], float plane_array[][4 const float div = dot_v3v3(dp, plane); if (div != 0.0f) { - const float t = -(dot_v3v3(p1, plane) + plane[3]) / div; + const float t = -plane_point_side_v3(plane, p1) / div; if (div > 0.0f) { /* clip a */ if (t >= 1.0f) { @@ -2137,8 +2200,6 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo ((_area = cross_v2v2(dirs[i1], dirs[i2])) != 0.0f ? \ fabsf(((lens[i1] * lens[i2]) - dot_v2v2(dirs[i1], dirs[i2])) / _area) : 0.0f) - float wtot, area; - const float dirs[4][2] = { {v1[0] - co[0], v1[1] - co[1]}, {v2[0] - co[0], v2[1] - co[1]}, @@ -2153,20 +2214,29 @@ 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 */ + /* avoid divide by zero */ + if (UNLIKELY(lens[0] < FLT_EPSILON)) { w[0] = 1.0f; w[1] = w[2] = w[3] = 0.0f; } + else if (UNLIKELY(lens[1] < FLT_EPSILON)) { w[1] = 1.0f; w[0] = w[2] = w[3] = 0.0f; } + else if (UNLIKELY(lens[2] < FLT_EPSILON)) { w[2] = 1.0f; w[0] = w[1] = w[3] = 0.0f; } + else if (UNLIKELY(lens[3] < FLT_EPSILON)) { w[3] = 1.0f; w[0] = w[1] = w[2] = 0.0f; + } + else { + float wtot, area; + + /* 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), - MEAN_VALUE_HALF_TAN_V2(area, 1, 2), - MEAN_VALUE_HALF_TAN_V2(area, 2, 3), - MEAN_VALUE_HALF_TAN_V2(area, 3, 0), - }; + /* inline mean_value_half_tan four times here */ + float t[4] = { + MEAN_VALUE_HALF_TAN_V2(area, 0, 1), + MEAN_VALUE_HALF_TAN_V2(area, 1, 2), + MEAN_VALUE_HALF_TAN_V2(area, 2, 3), + MEAN_VALUE_HALF_TAN_V2(area, 3, 0), + }; #ifdef __clang__ # pragma clang diagnostic pop @@ -2174,18 +2244,19 @@ void barycentric_weights_v2_quad(const float v1[2], const float v2[2], const flo #undef MEAN_VALUE_HALF_TAN_V2 - w[0] = (t[3] + t[0]) / lens[0]; - w[1] = (t[0] + t[1]) / lens[1]; - w[2] = (t[1] + t[2]) / lens[2]; - w[3] = (t[2] + t[3]) / lens[3]; + w[0] = (t[3] + t[0]) / lens[0]; + w[1] = (t[0] + t[1]) / lens[1]; + w[2] = (t[1] + t[2]) / lens[2]; + w[3] = (t[2] + t[3]) / lens[3]; - wtot = w[0] + w[1] + w[2] + w[3]; + wtot = w[0] + w[1] + w[2] + w[3]; - if (wtot != 0.0f) { - mul_v4_fl(w, 1.0f / wtot); - } - else { /* dummy values for zero area face */ - copy_v4_fl(w, 1.0f / 4.0f); + if (wtot != 0.0f) { + mul_v4_fl(w, 1.0f / wtot); + } + else { /* dummy values for zero area face */ + copy_v4_fl(w, 1.0f / 4.0f); + } } } @@ -3616,4 +3687,3 @@ int is_quad_convex_v2(const float v1[2], const float v2[2], const float v3[2], c /* linetests, the 2 diagonals have to instersect to be convex */ return (isect_line_line_v2(v1, v3, v2, v4) > 0); } - diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index f32b477787b..ac5c0033067 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -185,4 +185,9 @@ MINLINE int poly_to_tri_count(const int poly_count, const int corner_count) } } +MINLINE float plane_point_side_v3(const float plane[4], const float co[3]) +{ + return dot_v3v3(co, plane) + plane[3]; +} + #endif /* __MATH_GEOM_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 9fd8c479d6e..c9919e7be37 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -62,7 +62,7 @@ void copy_qt_qt(float q1[4], const float q2[4]) q1[3] = q2[3]; } -int is_zero_qt(float *q) +bool is_zero_qt(const float q[4]) { return (q[0] == 0 && q[1] == 0 && q[2] == 0 && q[3] == 0); } @@ -993,7 +993,7 @@ void quat_to_eul(float *eul, const float quat[4]) } /* XYZ order */ -void eul_to_quat(float *quat, const float eul[3]) +void eul_to_quat(float quat[4], const float eul[3]) { float ti, tj, th, ci, cj, ch, si, sj, sh, cc, cs, sc, ss; @@ -1018,7 +1018,7 @@ void eul_to_quat(float *quat, const float eul[3]) } /* XYZ order */ -void rotate_eul(float *beul, const char axis, const float ang) +void rotate_eul(float beul[3], const char axis, const float ang) { float eul[3], mat1[3][3], mat2[3][3], totmat[3][3]; @@ -1229,7 +1229,7 @@ void eulO_to_mat3(float M[3][3], const float e[3], const short order) } /* returns two euler calculation methods, so we can pick the best */ -static void mat3_to_eulo2(float M[3][3], float *e1, float *e2, const short order) +static void mat3_to_eulo2(float M[3][3], float e1[3], float e2[3], const short order) { const RotOrderInfo *R = GET_ROTATIONORDER_INFO(order); short i = R->axis[0], j = R->axis[1], k = R->axis[2]; @@ -1478,9 +1478,10 @@ void mat4_to_dquat(DualQuat *dq, float basemat[4][4], float mat[4][4]) dq->trans[3] = 0.5f * ( t[0] * q[2] - t[1] * q[1] + t[2] * q[0]); } -void dquat_to_mat4(float mat[4][4], DualQuat *dq) +void dquat_to_mat4(float mat[4][4], const DualQuat *dq) { - float len, *t, q0[4]; + float len, q0[4]; + const float *t; /* regular quaternion */ copy_qt_qt(q0, dq->quat); @@ -1502,7 +1503,7 @@ void dquat_to_mat4(float mat[4][4], DualQuat *dq) /* note: this does not handle scaling */ } -void add_weighted_dq_dq(DualQuat *dqsum, DualQuat *dq, float weight) +void add_weighted_dq_dq(DualQuat *dqsum, const DualQuat *dq, float weight) { int flipped = 0; @@ -1530,7 +1531,7 @@ void add_weighted_dq_dq(DualQuat *dqsum, DualQuat *dq, float weight) if (flipped) /* we don't want negative weights for scaling */ weight = -weight; - copy_m4_m4(wmat, dq->scale); + copy_m4_m4(wmat, (float(*)[4])dq->scale); mul_m4_fl(wmat, weight); add_m4_m4m4(dqsum->scale, dqsum->scale, wmat); dqsum->scale_weight += weight; @@ -1609,7 +1610,7 @@ void mul_v3m3_dq(float co[3], float mat[3][3], DualQuat *dq) } } -void copy_dq_dq(DualQuat *dq1, DualQuat *dq2) +void copy_dq_dq(DualQuat *dq1, const DualQuat *dq2) { memcpy(dq1, dq2, sizeof(DualQuat)); } diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index 8e5040d983b..ce5d9657c7f 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -771,61 +771,76 @@ MINLINE void normal_float_to_short_v3(short out[3], const float in[3]) /********************************* Comparison ********************************/ -MINLINE int is_zero_v2(const float v[2]) +MINLINE bool is_zero_v2(const float v[2]) { return (v[0] == 0 && v[1] == 0); } -MINLINE int is_zero_v3(const float v[3]) +MINLINE bool is_zero_v3(const float v[3]) { return (v[0] == 0 && v[1] == 0 && v[2] == 0); } -MINLINE int is_zero_v4(const float v[4]) +MINLINE bool is_zero_v4(const float v[4]) { return (v[0] == 0 && v[1] == 0 && v[2] == 0 && v[3] == 0); } -MINLINE int is_one_v3(const float v[3]) +MINLINE bool is_finite_v2(const float v[2]) +{ + return (finite(v[0]) && finite(v[1])); +} + +MINLINE bool is_finite_v3(const float v[3]) +{ + return (finite(v[0]) && finite(v[1]) && finite(v[2])); +} + +MINLINE bool is_finite_v4(const float v[4]) +{ + return (finite(v[0]) && finite(v[1]) && finite(v[2]) && finite(v[3])); +} + +MINLINE bool is_one_v3(const float v[3]) { return (v[0] == 1 && v[1] == 1 && v[2] == 1); } -MINLINE int equals_v2v2(const float v1[2], const float v2[2]) +MINLINE bool equals_v2v2(const float v1[2], const float v2[2]) { return ((v1[0] == v2[0]) && (v1[1] == v2[1])); } -MINLINE int equals_v3v3(const float v1[3], const float v2[3]) +MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) { return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2])); } -MINLINE int equals_v4v4(const float v1[4], const float v2[4]) +MINLINE bool equals_v4v4(const float v1[4], const float v2[4]) { return ((v1[0] == v2[0]) && (v1[1] == v2[1]) && (v1[2] == v2[2]) && (v1[3] == v2[3])); } -MINLINE int compare_v2v2(const float v1[2], const float v2[2], const float limit) +MINLINE bool compare_v2v2(const float v1[2], const float v2[2], const float limit) { if (fabsf(v1[0] - v2[0]) < limit) if (fabsf(v1[1] - v2[1]) < limit) - return 1; + return true; - return 0; + return false; } -MINLINE int compare_v3v3(const float v1[3], const float v2[3], const float limit) +MINLINE bool compare_v3v3(const float v1[3], const float v2[3], const float limit) { if (fabsf(v1[0] - v2[0]) < limit) if (fabsf(v1[1] - v2[1]) < limit) if (fabsf(v1[2] - v2[2]) < limit) - return 1; + return true; - return 0; + return false; } -MINLINE int compare_len_v3v3(const float v1[3], const float v2[3], const float limit) +MINLINE bool compare_len_v3v3(const float v1[3], const float v2[3], const float limit) { float x, y, z; @@ -836,15 +851,15 @@ MINLINE int compare_len_v3v3(const float v1[3], const float v2[3], const float l return ((x * x + y * y + z * z) < (limit * limit)); } -MINLINE int compare_v4v4(const float v1[4], const float v2[4], const float limit) +MINLINE bool compare_v4v4(const float v1[4], const float v2[4], const float limit) { if (fabsf(v1[0] - v2[0]) < limit) if (fabsf(v1[1] - v2[1]) < limit) if (fabsf(v1[2] - v2[2]) < limit) if (fabsf(v1[3] - v2[3]) < limit) - return 1; + return true; - return 0; + return false; } MINLINE float line_point_side_v2(const float l1[2], const float l2[2], const float pt[2]) diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 2c06a812c8a..68e0f2c4026 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -46,20 +46,12 @@ #include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_string_utf8.h" +#include "BLI_fnmatch.h" #include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */ #include "GHOST_Path-api.h" -#if defined WIN32 && !defined _LIBC || defined __sun -# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ -#else -# ifndef _GNU_SOURCE -# define _GNU_SOURCE -# endif -# include <fnmatch.h> -#endif - #ifdef WIN32 # include "utf_winfunc.h" # include "utfconv.h" @@ -1649,6 +1641,16 @@ bool BLI_ensure_extension(char *path, size_t maxlen, const char *ext) return true; } +bool BLI_ensure_filename(char *filepath, size_t maxlen, const char *filename) +{ + char *c = (char *)BLI_last_slash(filepath); + if (!c || ((c - filepath) < maxlen - (strlen(filename) + 1))) { + strcpy(c ? &c[1] : filepath, filename); + return true; + } + return false; +} + /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt" * - wont change 'string' * - wont create any directories @@ -1693,7 +1695,7 @@ void BLI_split_file_part(const char *string, char *file, const size_t filelen) /** * Append a filename to a dir, ensuring slash separates. */ -void BLI_path_append(char *dst, const size_t maxlen, const char *file) +void BLI_path_append(char *__restrict dst, const size_t maxlen, const char *__restrict file) { size_t dirlen = BLI_strnlen(dst, maxlen); @@ -1714,7 +1716,7 @@ void BLI_path_append(char *dst, const size_t maxlen, const char *file) * 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) +void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) { size_t dirlen = BLI_strnlen(dir, maxlen); diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index b06534d282a..8c831bdada0 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -35,6 +35,8 @@ //#include <string.h> #include "BLI_math.h" +#include "BLI_strict_flags.h" + #include "BLI_quadric.h" /* own include */ diff --git a/source/blender/blenlib/intern/rand.c b/source/blender/blenlib/intern/rand.c index 743d910e418..c5b58e5a61b 100644 --- a/source/blender/blenlib/intern/rand.c +++ b/source/blender/blenlib/intern/rand.c @@ -175,20 +175,10 @@ float BLI_frand(void) float BLI_hash_frand(unsigned int seed) { - r_uint64 X; - - seed = seed + hash[seed & 255]; - X = (((r_uint64) seed) << 16) | LOWSEED; - seed = (int)(((MULTIPLIER * X + ADDEND) & MASK) >> 17); - - seed = seed + hash[seed & 255]; - X = (((r_uint64) seed) << 16) | LOWSEED; - X = (int)(((MULTIPLIER * X + ADDEND) & MASK) >> 17); - - seed = seed + hash[seed & 255]; - X = (((r_uint64) seed) << 16) | LOWSEED; + RNG rng; - return (int)(((MULTIPLIER * X + ADDEND) & MASK) >> 17); + BLI_rng_srandom(&rng, seed); + return BLI_rng_get_float(&rng); } void BLI_array_randomize(void *data, int elemSize, int numElems, unsigned int seed) diff --git a/source/blender/blenlib/intern/scanfill.c b/source/blender/blenlib/intern/scanfill.c index c7163874dca..a292c2275c9 100644 --- a/source/blender/blenlib/intern/scanfill.c +++ b/source/blender/blenlib/intern/scanfill.c @@ -40,49 +40,17 @@ #include "BLI_callbacks.h" #include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_scanfill.h" +#include "BLI_memarena.h" #include "BLI_utildefines.h" +#include "BLI_strict_flags.h" -/* callbacks for errors and interrupts and some goo */ -static void (*BLI_localErrorCallBack)(const char *) = NULL; - -/** - * Set a function taking a (char *) as argument to flag errors. If the - * callback is not set, the error is discarded. - * \param f The function to use as callback - * \attention used in creator.c - */ -void BLI_setErrorCallBack(void (*f)(const char *)) -{ - BLI_localErrorCallBack = f; -} - -/* just flush the error to /dev/null if the error handler is missing */ -void callLocalErrorCallBack(const char *msg) -{ - if (BLI_localErrorCallBack) { - BLI_localErrorCallBack(msg); - } -} - -#if 0 -/* ignore if the interrupt wasn't set */ -static int callLocalInterruptCallBack(void) -{ - if (BLI_localInterruptCallBack) { - return BLI_localInterruptCallBack(); - } - else { - return 0; - } -} -#endif +#include "BLI_scanfill.h" /* own include */ /* local types */ typedef struct PolyFill { - int edges, verts; + unsigned int edges, verts; float min_xy[2], max_xy[2]; - short f, nr; + unsigned short f, nr; } PolyFill; typedef struct ScanFillVertLink { @@ -132,99 +100,45 @@ static int vergpoly(const void *a1, const void *a2) return 0; } -/* ************* MEMORY MANAGEMENT ************* */ - -/* memory management */ -struct mem_elements { - struct mem_elements *next, *prev; - char *data; -}; +/* **** FILL ROUTINES *************************** */ -static void *mem_element_new(ScanFillContext *sf_ctx, int size) +ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]) { - BLI_assert(!(size > 10000 || size == 0)); /* this is invalid use! */ - - size = (size + 3) & ~3; /* allocate in units of 4 */ + ScanFillVert *sf_v; - if (sf_ctx->melem__cur && (size + sf_ctx->melem__offs < MEM_ELEM_BLOCKSIZE)) { - void *adr = (void *) (sf_ctx->melem__cur->data + sf_ctx->melem__offs); - sf_ctx->melem__offs += size; - return adr; - } - else { - sf_ctx->melem__cur = MEM_callocN(sizeof(struct mem_elements), "newmem"); - sf_ctx->melem__cur->data = MEM_callocN(MEM_ELEM_BLOCKSIZE, "newmem"); - BLI_addtail(&sf_ctx->melem__lb, sf_ctx->melem__cur); - - sf_ctx->melem__offs = size; - return sf_ctx->melem__cur->data; - } -} -static void mem_element_reset(ScanFillContext *sf_ctx, int keep_first) -{ - struct mem_elements *first; - - if ((first = sf_ctx->melem__lb.first)) { /* can be false if first fill fails */ - if (keep_first) { - BLI_remlink(&sf_ctx->melem__lb, first); - } - - sf_ctx->melem__cur = sf_ctx->melem__lb.first; - while (sf_ctx->melem__cur) { - MEM_freeN(sf_ctx->melem__cur->data); - sf_ctx->melem__cur = sf_ctx->melem__cur->next; - } - BLI_freelistN(&sf_ctx->melem__lb); + sf_v = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillVert)); - /*reset the block we're keeping*/ - if (keep_first) { - BLI_addtail(&sf_ctx->melem__lb, first); - memset(first->data, 0, MEM_ELEM_BLOCKSIZE); - } - else { - first = NULL; - - } - } - - sf_ctx->melem__cur = first; - sf_ctx->melem__offs = 0; -} - -void BLI_scanfill_end(ScanFillContext *sf_ctx) -{ - mem_element_reset(sf_ctx, FALSE); - - sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL; - sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL; - sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL; -} + BLI_addtail(&sf_ctx->fillvertbase, sf_v); -/* **** FILL ROUTINES *************************** */ + sf_v->tmp.p = NULL; + copy_v3_v3(sf_v->co, vec); -ScanFillVert *BLI_scanfill_vert_add(ScanFillContext *sf_ctx, const float vec[3]) -{ - ScanFillVert *eve; - - eve = mem_element_new(sf_ctx, sizeof(ScanFillVert)); - BLI_addtail(&sf_ctx->fillvertbase, eve); - - copy_v3_v3(eve->co, vec); + /* just zero out the rest */ + zero_v2(sf_v->xy); + sf_v->keyindex = 0; + sf_v->poly_nr = 0; + sf_v->edge_tot = 0; + sf_v->f = 0; - return eve; + return sf_v; } ScanFillEdge *BLI_scanfill_edge_add(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2) { - ScanFillEdge *newed; + ScanFillEdge *sf_ed; - newed = mem_element_new(sf_ctx, sizeof(ScanFillEdge)); - BLI_addtail(&sf_ctx->filledgebase, newed); + sf_ed = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillEdge)); + BLI_addtail(&sf_ctx->filledgebase, sf_ed); - newed->v1 = v1; - newed->v2 = v2; + sf_ed->v1 = v1; + sf_ed->v2 = v2; - return newed; + /* just zero out the rest */ + sf_ed->poly_nr = 0; + sf_ed->f = 0; + sf_ed->tmp.c = 0; + + return sf_ed; } static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert *v2, ScanFillVert *v3) @@ -232,7 +146,7 @@ static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert /* does not make edges */ ScanFillFace *sf_tri; - sf_tri = mem_element_new(sf_ctx, sizeof(ScanFillFace)); + sf_tri = BLI_memarena_alloc(sf_ctx->arena, sizeof(ScanFillFace)); BLI_addtail(&sf_ctx->fillfacebase, sf_tri); sf_tri->v1 = v1; @@ -240,7 +154,7 @@ static void addfillface(ScanFillContext *sf_ctx, ScanFillVert *v1, ScanFillVert sf_tri->v3 = v3; } -static int boundisect(PolyFill *pf2, PolyFill *pf1) +static bool boundisect(PolyFill *pf2, PolyFill *pf1) { /* has pf2 been touched (intersected) by pf1 ? with bounding box */ /* test first if polys exist */ @@ -287,7 +201,7 @@ static void mergepolysSimp(ScanFillContext *sf_ctx, PolyFill *pf1, PolyFill *pf2 pf1->f = (pf1->f | pf2->f); } -static short testedgeside(const float v1[2], const float v2[2], const float v3[2]) +static bool testedgeside(const float v1[2], const float v2[2], const float v3[2]) /* is v3 to the right of v1-v2 ? With exception: v3 == v1 || v3 == v2 */ { float inp; @@ -298,14 +212,14 @@ static short testedgeside(const float v1[2], const float v2[2], const float v3[2 if (inp < 0.0f) { return 0; } - else if (inp == 0) { + else if (inp == 0.0f) { if (v1[0] == v3[0] && v1[1] == v3[1]) return 0; if (v2[0] == v3[0] && v2[1] == v3[1]) return 0; } return 1; } -static short addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed) +static bool addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed) { /* find first edge to the right of eed, and insert eed before that */ ScanFillEdge *ed; @@ -354,7 +268,7 @@ static short addedgetoscanvert(ScanFillVertLink *sc, ScanFillEdge *eed) } -static ScanFillVertLink *addedgetoscanlist(ScanFillContext *sf_ctx, ScanFillEdge *eed, int len) +static ScanFillVertLink *addedgetoscanlist(ScanFillContext *sf_ctx, ScanFillEdge *eed, unsigned int len) { /* inserts edge at correct location in ScanFillVertLink list */ /* returns sc when edge already exists */ @@ -379,13 +293,17 @@ static ScanFillVertLink *addedgetoscanlist(ScanFillContext *sf_ctx, ScanFillEdge sc = (ScanFillVertLink *)bsearch(&scsearch, sf_ctx->_scdata, len, sizeof(ScanFillVertLink), vergscdata); - if (sc == NULL) printf("Error in search edge: %p\n", (void *)eed); - else if (addedgetoscanvert(sc, eed) == 0) return sc; + if (UNLIKELY(sc == NULL)) { + printf("Error in search edge: %p\n", (void *)eed); + } + else if (addedgetoscanvert(sc, eed) == false) { + return sc; + } return NULL; } -static short boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve) +static bool boundinsideEV(ScanFillEdge *eed, ScanFillVert *eve) /* is eve inside boundbox eed */ { float minx, maxx, miny, maxy; @@ -476,7 +394,7 @@ static void testvertexnearedge(ScanFillContext *sf_ctx) } } -static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, short nr) +static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *temped, unsigned short nr) { /* everything is in templist, write only poly nr to fillist */ ScanFillVert *eve, *nextve; @@ -505,15 +423,14 @@ static void splitlist(ScanFillContext *sf_ctx, ListBase *tempve, ListBase *tempe } } -static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) +static unsigned int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) { ScanFillVertLink *sc = NULL, *sc1; ScanFillVert *eve, *v1, *v2, *v3; ScanFillEdge *eed, *nexted, *ed1, *ed2, *ed3; - int a, b, verts, maxface, totface; - short nr, twoconnected = 0; - - nr = pf->nr; + unsigned int a, b, verts, maxface, totface; + const unsigned short nr = pf->nr; + bool twoconnected = false; /* PRINTS */ #if 0 @@ -629,7 +546,8 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) /* STEP 2: FILL LOOP */ - if (pf->f == 0) twoconnected = 1; + if (pf->f == 0) + twoconnected = true; /* (temporal) security: never much more faces than vertices */ totface = 0; @@ -826,14 +744,36 @@ static int scanfill(ScanFillContext *sf_ctx, PolyFill *pf, const int flag) void BLI_scanfill_begin(ScanFillContext *sf_ctx) { memset(sf_ctx, 0, sizeof(*sf_ctx)); + sf_ctx->arena = BLI_memarena_new(BLI_SCANFILL_ARENA_SIZE, __func__); } -int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) +void BLI_scanfill_begin_arena(ScanFillContext *sf_ctx, MemArena *arena) { - return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); + memset(sf_ctx, 0, sizeof(*sf_ctx)); + sf_ctx->arena = arena; } -int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) +void BLI_scanfill_end(ScanFillContext *sf_ctx) +{ + BLI_memarena_free(sf_ctx->arena); + sf_ctx->arena = NULL; + + sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL; + sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL; + sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL; +} + +void BLI_scanfill_end_arena(ScanFillContext *sf_ctx, MemArena *arena) +{ + BLI_memarena_clear(arena); + BLI_assert(sf_ctx->arena == arena); + + sf_ctx->fillvertbase.first = sf_ctx->fillvertbase.last = NULL; + sf_ctx->filledgebase.first = sf_ctx->filledgebase.last = NULL; + sf_ctx->fillfacebase.first = sf_ctx->fillfacebase.last = NULL; +} + +unsigned int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float nor_proj[3]) { /* * - fill works with its own lists, so create that first (no faces!) @@ -845,34 +785,36 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no */ ListBase tempve, temped; ScanFillVert *eve; - ScanFillEdge *eed, *nexted; + ScanFillEdge *eed, *eed_next; PolyFill *pflist, *pf; float *min_xy_p, *max_xy_p; - short a, c, poly = 0, ok = 0, toggle = 0; - int totfaces = 0; /* total faces added */ + unsigned int totverts = 0, toggle = 0; + unsigned int totfaces = 0; /* total faces added */ + unsigned short a, c, poly = 0; + bool ok; float mat_2d[3][3]; BLI_assert(!nor_proj || len_squared_v3(nor_proj) > FLT_EPSILON); - /* reset variables */ eve = sf_ctx->fillvertbase.first; - a = 0; while (eve) { - eve->f = 0; - eve->poly_nr = 0; - eve->edge_tot = 0; + /* these values used to be set, + * however they should always be zero'd so check instead */ + BLI_assert(eve->f == 0); + BLI_assert(eve->poly_nr == 0); + BLI_assert(eve->edge_tot == 0); + totverts++; eve = eve->next; - a += 1; } if (flag & BLI_SCANFILL_CALC_QUADTRI_FASTPATH) { - if (a == 3) { + if (totverts == 3) { eve = sf_ctx->fillvertbase.first; addfillface(sf_ctx, eve, eve->next, eve->next->next); return 1; } - else if (a == 4) { + else if (totverts == 4) { float vec1[3], vec2[3]; eve = sf_ctx->fillvertbase.first; @@ -897,23 +839,24 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no /* including resetting of flags */ eed = sf_ctx->filledgebase.first; while (eed) { - eed->poly_nr = 0; + BLI_assert(eed->poly_nr == 0); eed->v1->f = SF_VERT_AVAILABLE; eed->v2->f = SF_VERT_AVAILABLE; eed = eed->next; } + ok = false; eve = sf_ctx->fillvertbase.first; while (eve) { if (eve->f & SF_VERT_AVAILABLE) { - ok = 1; + ok = true; break; } eve = eve->next; } - if (ok == 0) { + if (UNLIKELY(ok == false)) { return 0; } else { @@ -959,35 +902,33 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no if (eve->poly_nr == 0) { poly++; /* now a sort of select connected */ - ok = 1; + ok = true; eve->poly_nr = poly; while (ok) { - ok = 0; - toggle++; - if (toggle & 1) eed = sf_ctx->filledgebase.first; - else eed = sf_ctx->filledgebase.last; + ok = false; + toggle++; + eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; while (eed) { if (eed->v1->poly_nr == 0 && eed->v2->poly_nr == poly) { eed->v1->poly_nr = poly; eed->poly_nr = poly; - ok = 1; + ok = true; } else if (eed->v2->poly_nr == 0 && eed->v1->poly_nr == poly) { eed->v2->poly_nr = poly; eed->poly_nr = poly; - ok = 1; + ok = true; } else if (eed->poly_nr == 0) { if (eed->v1->poly_nr == poly && eed->v2->poly_nr == poly) { eed->poly_nr = poly; - ok = 1; + ok = true; } } - if (toggle & 1) eed = eed->next; - else eed = eed->prev; + eed = (toggle & 1) ? eed->next : eed->prev; } } } @@ -1020,35 +961,36 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no } if (eed) { /* otherwise it's impossible to be sure you can clear vertices */ - callLocalErrorCallBack("No vertices with 250 edges allowed!"); +#ifdef DEBUG + printf("No vertices with 250 edges allowed!\n"); +#endif return 0; } /* does it only for vertices with (->h == 1) */ testvertexnearedge(sf_ctx); - ok = 1; + ok = true; while (ok) { - ok = 0; + ok = false; + toggle++; - if (toggle & 1) eed = sf_ctx->filledgebase.first; - else eed = sf_ctx->filledgebase.last; + eed = (toggle & 1) ? sf_ctx->filledgebase.first : sf_ctx->filledgebase.last; while (eed) { - if (toggle & 1) nexted = eed->next; - else nexted = eed->prev; + eed_next = (toggle & 1) ? eed->next : eed->prev; if (eed->v1->edge_tot == 1) { eed->v2->edge_tot--; BLI_remlink(&sf_ctx->fillvertbase, eed->v1); BLI_remlink(&sf_ctx->filledgebase, eed); - ok = 1; + ok = true; } else if (eed->v2->edge_tot == 1) { eed->v1->edge_tot--; BLI_remlink(&sf_ctx->fillvertbase, eed->v2); BLI_remlink(&sf_ctx->filledgebase, eed); - ok = 1; + ok = true; } - eed = nexted; + eed = eed_next; } } if (sf_ctx->filledgebase.first == NULL) { @@ -1069,12 +1011,12 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no /* STEP 3: MAKE POLYFILL STRUCT */ - pflist = (PolyFill *)MEM_callocN(poly * sizeof(PolyFill), "edgefill"); + pflist = (PolyFill *)MEM_callocN((size_t)poly * sizeof(PolyFill), "edgefill"); pf = pflist; for (a = 1; a <= poly; a++) { pf->nr = a; - pf->min_xy[0] = pf->min_xy[1] = 1.0e20; - pf->max_xy[0] = pf->max_xy[1] = -1.0e20; + pf->min_xy[0] = pf->min_xy[1] = 1.0e20f; + pf->max_xy[0] = pf->max_xy[1] = -1.0e20f; pf++; } eed = sf_ctx->filledgebase.first; @@ -1104,10 +1046,10 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no * WATCH IT: ONLY WORKS WITH SORTED POLYS!!! */ if (poly > 1) { - short *polycache, *pc; + unsigned short *polycache, *pc; /* so, sort first */ - qsort(pflist, poly, sizeof(PolyFill), vergpoly); + qsort(pflist, (size_t)poly, sizeof(PolyFill), vergpoly); #if 0 pf = pflist; @@ -1118,10 +1060,10 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no } #endif - polycache = pc = MEM_callocN(sizeof(short) * poly, "polycache"); + polycache = pc = MEM_callocN(sizeof(short) * (size_t)poly, "polycache"); pf = pflist; for (a = 0; a < poly; a++, pf++) { - for (c = a + 1; c < poly; c++) { + for (c = (unsigned short)(a + 1); c < poly; c++) { /* if 'a' inside 'c': join (bbox too) * Careful: 'a' can also be inside another poly. @@ -1177,3 +1119,8 @@ int BLI_scanfill_calc_ex(ScanFillContext *sf_ctx, const int flag, const float no return totfaces; } + +unsigned int BLI_scanfill_calc(ScanFillContext *sf_ctx, const int flag) +{ + return BLI_scanfill_calc_ex(sf_ctx, flag, NULL); +} diff --git a/source/blender/blenlib/intern/smallhash.c b/source/blender/blenlib/intern/smallhash.c index 525bb37ae40..7bb0747daaa 100644 --- a/source/blender/blenlib/intern/smallhash.c +++ b/source/blender/blenlib/intern/smallhash.c @@ -31,6 +31,7 @@ #include "BLI_utildefines.h" #include "BLI_smallhash.h" +#include "BLI_strict_flags.h" /* SMHASH_CELL_UNUSED means this cell is inside a key series, * while SMHASH_CELL_FREE means this cell terminates a key series. @@ -43,14 +44,6 @@ #define SMHASH_CELL_UNUSED ((void *)0x7FFFFFFF) #define SMHASH_CELL_FREE ((void *)0x7FFFFFFD) -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif - /* typically this re-assigns 'h' */ #define SMHASH_NEXT(h, hoff) ( \ CHECK_TYPE_INLINE(&(h), unsigned int *), \ diff --git a/source/blender/blenlib/intern/sort.c b/source/blender/blenlib/intern/sort.c new file mode 100644 index 00000000000..44110564948 --- /dev/null +++ b/source/blender/blenlib/intern/sort.c @@ -0,0 +1,173 @@ +/* + * ***** 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): Benoit Bolsee, + * Sergey Sharybin. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/sort.c + * \ingroup bli + */ + +#include <stdlib.h> + +#include "BLI_utildefines.h" + +#include "BLI_sort.h" + +/* **** qsort based on FreeBSD source (libkern\qsort.c) **** */ +BLI_INLINE char *med3(char *, char *, char *, BLI_sort_cmp_t, void *); +BLI_INLINE void swapfunc(char *, char *, int, int); + +#define min(a, b) (a) < (b) ? a : b +#define swapcode(TYPE, parmi, parmj, n) \ +{ \ + long i = (n) / sizeof(TYPE); \ + TYPE *pi = (TYPE *) (parmi); \ + TYPE *pj = (TYPE *) (parmj); \ + do { \ + TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +BLI_INLINE void swapfunc(char *a, char *b, int n, int swaptype) +{ + if (swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b);\ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) +#define CMP(t, x, y) (cmp((t), (x), (y))) + +BLI_INLINE char *med3(char *a, char *b, char *c, BLI_sort_cmp_t cmp, void *thunk) +{ + return CMP(thunk, a, b) < 0 ? + (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) + :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); +} + +/** + * Quick sort reentrant. + * + * \note Follows BSD arg order (incompatible with glibc). + */ +void BLI_qsort_r(void *a, size_t n, size_t es, void *thunk, BLI_sort_cmp_t cmp) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + int d, r, swaptype, swap_cnt; + +loop: + SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) { + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + { + swap(pl, pl - es); + } + } + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = (char *)a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); + pm = med3(pm - d, pm, pm + d, cmp, thunk); + pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); + } + pm = med3(pl, pm, pn, cmp, thunk); + } + swap((char *)a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (r = CMP(thunk, pb, a)) <= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (r = CMP(thunk, pc, a)) >= 0) { + if (r == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) { + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + { + swap(pl, pl - es); + } + } + return; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap((char *)a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) + BLI_qsort_r(a, r / es, es, thunk, cmp); + if ((r = pd - pc) > es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +} diff --git a/source/blender/blenlib/intern/sort_utils.c b/source/blender/blenlib/intern/sort_utils.c new file mode 100644 index 00000000000..c75e8e7455f --- /dev/null +++ b/source/blender/blenlib/intern/sort_utils.c @@ -0,0 +1,74 @@ +/* + * ***** 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/sort_utils.c + * \ingroup bli + * + * Utility functions for sorting common types. + */ + +#include "BLI_sort_utils.h" /* own include */ + +struct SortAnyByFloat { + float sort_value; +}; + +struct SortAnyByInt { + int sort_value; +}; + +int BLI_sortutil_cmp_float(const void *a_, const void *b_) +{ + const struct SortAnyByFloat *a = a_; + const struct SortAnyByFloat *b = b_; + if (a->sort_value > b->sort_value) return 1; + else if (a->sort_value < b->sort_value) return -1; + else return 0; +} + +int BLI_sortutil_cmp_float_reverse(const void *a_, const void *b_) +{ + const struct SortAnyByFloat *a = a_; + const struct SortAnyByFloat *b = b_; + if (a->sort_value < b->sort_value) return 1; + else if (a->sort_value > b->sort_value) return -1; + else return 0; +} + +int BLI_sortutil_cmp_int(const void *a_, const void *b_) +{ + const struct SortAnyByInt *a = a_; + const struct SortAnyByInt *b = b_; + if (a->sort_value > b->sort_value) return 1; + else if (a->sort_value < b->sort_value) return -1; + else return 0; +} + +int BLI_sortutil_cmp_int_reverse(const void *a_, const void *b_) +{ + const struct SortAnyByInt *a = a_; + const struct SortAnyByInt *b = b_; + if (a->sort_value < b->sort_value) return 1; + else if (a->sort_value > b->sort_value) return -1; + else return 0; +} diff --git a/source/blender/blenlib/intern/storage.c b/source/blender/blenlib/intern/storage.c index 34c6e632131..e40527b1bb6 100644 --- a/source/blender/blenlib/intern/storage.c +++ b/source/blender/blenlib/intern/storage.c @@ -70,7 +70,6 @@ #ifdef WIN32 # include <io.h> # include <direct.h> -# include <limits.h> /* PATH_MAX */ # include "BLI_winstuff.h" # include "utfconv.h" #else diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 2b6fb52c49c..c8b84d9310a 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -107,7 +107,7 @@ static void *thread_tls_data; * BLI_end_threads(&lb); * ************************************************ */ -static pthread_mutex_t _malloc_lock = PTHREAD_MUTEX_INITIALIZER; +static SpinLock _malloc_lock; static pthread_mutex_t _image_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _image_draw_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t _viewer_lock = PTHREAD_MUTEX_INITIALIZER; @@ -134,17 +134,24 @@ typedef struct ThreadSlot { static void BLI_lock_malloc_thread(void) { - pthread_mutex_lock(&_malloc_lock); + BLI_spin_lock(&_malloc_lock); } static void BLI_unlock_malloc_thread(void) { - pthread_mutex_unlock(&_malloc_lock); + BLI_spin_unlock(&_malloc_lock); } void BLI_threadapi_init(void) { mainid = pthread_self(); + + BLI_spin_init(&_malloc_lock); +} + +void BLI_threadapi_exit(void) +{ + BLI_spin_end(&_malloc_lock); } /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) diff --git a/source/blender/blenloader/intern/readblenentry.c b/source/blender/blenloader/intern/readblenentry.c index aec91dedf8f..9ae2858f526 100644 --- a/source/blender/blenloader/intern/readblenentry.c +++ b/source/blender/blenloader/intern/readblenentry.c @@ -222,7 +222,7 @@ LinkNode *BLO_blendhandle_get_previews(BlendHandle *bh, int ofblocktype, int *to LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) { FileData *fd = (FileData *) bh; - GHash *gathered = BLI_ghash_ptr_new("linkable_groups gh"); + GSet *gathered = BLI_gset_ptr_new("linkable_groups gh"); LinkNode *names = NULL; BHead *bhead; @@ -234,15 +234,15 @@ LinkNode *BLO_blendhandle_get_linkable_groups(BlendHandle *bh) if (BKE_idcode_is_linkable(bhead->code)) { const char *str = BKE_idcode_to_name(bhead->code); - if (!BLI_ghash_haskey(gathered, (void *)str)) { + if (!BLI_gset_haskey(gathered, (void *)str)) { BLI_linklist_prepend(&names, strdup(str)); - BLI_ghash_insert(gathered, (void *)str, NULL); + BLI_gset_insert(gathered, (void *)str); } } } } - BLI_ghash_free(gathered, NULL, NULL); + BLI_gset_free(gathered, NULL); return names; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 37cebc3063d..0cd473fd74d 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -151,6 +151,7 @@ #include "BKE_text.h" // for txt_extended_ascii_as_utf8 #include "BKE_texture.h" #include "BKE_tracking.h" +#include "BKE_treehash.h" #include "BKE_sound.h" #include "IMB_imbuf.h" // for proxy / timecode versioning stuff @@ -249,11 +250,7 @@ static void convert_tface_mt(FileData *fd, Main *main); * we could alternatively have a versions of a report function which forces printing - campbell */ -static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 3, 4))) -#endif -; +static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4); static void BKE_reportf_wrap(ReportList *reports, ReportType type, const char *format, ...) { char fixed_buf[1024]; /* should be long enough */ @@ -3123,7 +3120,6 @@ static void direct_link_mball(FileData *fd, MetaBall *mb) mb->disp.first = mb->disp.last = NULL; mb->editelems = NULL; - mb->bb = NULL; /* mb->edit_elems.first= mb->edit_elems.last= NULL;*/ mb->lastelem = NULL; } @@ -3399,11 +3395,9 @@ static void direct_link_curve(FileData *fd, Curve *cu) if (cu->wordspace == 0.0f) cu->wordspace = 1.0f; } - cu->bev.first = cu->bev.last = NULL; cu->disp.first = cu->disp.last = NULL; cu->editnurb = NULL; cu->lastsel = NULL; - cu->path = NULL; cu->editfont = NULL; for (nu = cu->nurb.first; nu; nu = nu->next) { @@ -4373,12 +4367,8 @@ static void lib_link_object(FileData *fd, Main *main) for (sens = ob->sensors.first; sens; sens = sens->next) { for (a = 0; a < sens->totlinks; a++) sens->links[a] = newglobadr(fd, sens->links[a]); - - if (sens->type == SENS_TOUCH) { - bTouchSensor *ts = sens->data; - ts->ma = newlibadr(fd, ob->id.lib, ts->ma); - } - else if (sens->type == SENS_MESSAGE) { + + if (sens->type == SENS_MESSAGE) { bMessageSensor *ms = sens->data; ms->fromObject = newlibadr(fd, ob->id.lib, ms->fromObject); @@ -4829,8 +4819,6 @@ static void direct_link_object(FileData *fd, Object *ob) ob->mode &= ~(OB_MODE_EDIT | OB_MODE_PARTICLE_EDIT); } - ob->disp.first = ob->disp.last = NULL; - ob->adt = newdataadr(fd, ob->adt); direct_link_animdata(fd, ob->adt); @@ -5025,6 +5013,9 @@ static void direct_link_object(FileData *fd, Object *ob) ob->gpulamp.first= ob->gpulamp.last = NULL; link_list(fd, &ob->pc_ids); + /* Runtime curve data */ + ob->curve_cache = NULL; + /* in case this value changes in future, clamp else we get undefined behavior */ CLAMP(ob->rotmode, ROT_MODE_MIN, ROT_MODE_MAX); @@ -5443,10 +5434,10 @@ static void direct_link_scene(FileData *fd, Scene *sce) link_list(fd, &(sce->transform_spaces)); link_list(fd, &(sce->r.layers)); - for(srl = sce->r.layers.first; srl; srl = srl->next) { + for (srl = sce->r.layers.first; srl; srl = srl->next) { link_list(fd, &(srl->freestyleConfig.modules)); } - for(srl = sce->r.layers.first; srl; srl = srl->next) { + for (srl = sce->r.layers.first; srl; srl = srl->next) { link_list(fd, &(srl->freestyleConfig.linesets)); } @@ -5703,12 +5694,8 @@ static void lib_link_screen(FileData *fd, Main *main) tselem->id = newlibadr(fd, NULL, tselem->id); } if (so->treehash) { - /* update hash table, because it depends on ids too */ - BLI_ghash_clear(so->treehash, NULL, NULL); - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BLI_ghash_insert(so->treehash, tselem, tselem); - } + /* rebuild hash table, because it depends on ids too */ + BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore); } } } @@ -6044,12 +6031,8 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc tselem->id = restore_pointer_by_name(newmain, tselem->id, 0); } if (so->treehash) { - /* update hash table, because it depends on ids too */ - BLI_ghash_clear(so->treehash, NULL, NULL); - BLI_mempool_iternew(so->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BLI_ghash_insert(so->treehash, tselem, tselem); - } + /* rebuild hash table, because it depends on ids too */ + BKE_treehash_rebuild_from_treestore(so->treehash, so->treestore); } } } @@ -6136,6 +6119,10 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype) for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) { ui_list->type = NULL; + ui_list->dyn_data = NULL; + ui_list->properties = newdataadr(fd, ui_list->properties); + if (ui_list->properties) + IDP_DirectLinkProperty(ui_list->properties, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } if (spacetype == SPACE_EMPTY) { @@ -6324,7 +6311,7 @@ static bool direct_link_screen(FileData *fd, bScreen *sc) else if (sl->spacetype == SPACE_OUTLINER) { SpaceOops *soops = (SpaceOops *) sl; - /* use newdataadr_no_us and do not free old memory avoidign double + /* use newdataadr_no_us and do not free old memory avoiding double * frees and use of freed memory. this could happen because of a * bug fixed in revision 58959 where the treestore memory address * was not unique */ @@ -7033,16 +7020,16 @@ static void direct_link_linestyle(FileData *fd, FreestyleLineStyle *linestyle) linestyle->adt= newdataadr(fd, linestyle->adt); direct_link_animdata(fd, linestyle->adt); link_list(fd, &linestyle->color_modifiers); - for(modifier = linestyle->color_modifiers.first; modifier; modifier = modifier->next) + for (modifier = linestyle->color_modifiers.first; modifier; modifier = modifier->next) direct_link_linestyle_color_modifier(fd, modifier); link_list(fd, &linestyle->alpha_modifiers); - for(modifier = linestyle->alpha_modifiers.first; modifier; modifier = modifier->next) + for (modifier = linestyle->alpha_modifiers.first; modifier; modifier = modifier->next) direct_link_linestyle_alpha_modifier(fd, modifier); link_list(fd, &linestyle->thickness_modifiers); - for(modifier = linestyle->thickness_modifiers.first; modifier; modifier = modifier->next) + for (modifier = linestyle->thickness_modifiers.first; modifier; modifier = modifier->next) direct_link_linestyle_thickness_modifier(fd, modifier); link_list(fd, &linestyle->geometry_modifiers); - for(modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next) + for (modifier = linestyle->geometry_modifiers.first; modifier; modifier = modifier->next) direct_link_linestyle_geometry_modifier(fd, modifier); } @@ -7148,7 +7135,7 @@ static BHead *read_libblock(FileData *fd, Main *main, BHead *bhead, int flag, ID if (id->flag & LIB_FAKEUSER) id->us= 1; else id->us = 0; id->icon_id = 0; - id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA); + id->flag &= ~(LIB_ID_RECALC|LIB_ID_RECALC_DATA|LIB_DOIT); /* this case cannot be direct_linked: it's just the ID part */ if (bhead->code == ID_ID) { @@ -9455,12 +9442,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main) SceneRenderLayer *srl; FreestyleLineStyle *linestyle; - for(sce = main->scene.first; sce; sce = sce->id.next) { + for (sce = main->scene.first; sce; sce = sce->id.next) { if (sce->r.line_thickness_mode == 0) { sce->r.line_thickness_mode = R_LINE_THICKNESS_ABSOLUTE; sce->r.unit_line_thickness = 1.0f; } - for(srl = sce->r.layers.first; srl; srl = srl->next) { + for (srl = sce->r.layers.first; srl; srl = srl->next) { if (srl->freestyleConfig.mode == 0) srl->freestyleConfig.mode = FREESTYLE_CONTROL_EDITOR_MODE; if (srl->freestyleConfig.raycasting_algorithm == FREESTYLE_ALGO_CULLED_ADAPTIVE_CUMULATIVE || @@ -9490,7 +9477,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - for(linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) { + for (linestyle = main->linestyle.first; linestyle; linestyle = linestyle->id.next) { #if 1 /* disable the Misc panel for now */ if (linestyle->panel == LS_PANEL_MISC) { @@ -9578,11 +9565,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) for (brush = main->brush.first; brush; brush = brush->id.next) { brush->flag &= ~BRUSH_FIXED; - if(brush->cursor_overlay_alpha < 2) + if (brush->cursor_overlay_alpha < 2) brush->cursor_overlay_alpha = 33; - if(brush->texture_overlay_alpha < 2) + if (brush->texture_overlay_alpha < 2) brush->texture_overlay_alpha = 33; - if(brush->mask_overlay_alpha <2) + if (brush->mask_overlay_alpha <2) brush->mask_overlay_alpha = 33; } #undef BRUSH_FIXED @@ -9625,6 +9612,32 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } } + + for (ob = main->object.first; ob; ob = ob->id.next) { + bSensor *sens; + bTouchSensor *ts; + bCollisionSensor *cs; + Material *ma; + + for (sens = ob->sensors.first; sens; sens = sens->next) { + if (sens->type == SENS_TOUCH) { + ts = sens->data; + cs = MEM_callocN(sizeof(bCollisionSensor), "touch -> collision sensor do_version"); + + if (ts->ma) { + ma = blo_do_versions_newlibadr(fd, ob->id.lib, ts->ma); + BLI_strncpy(cs->materialName, ma->id.name+2, sizeof(cs->materialName)); + } + + cs->mode = SENS_COLLISION_MATERIAL; + + MEM_freeN(ts); + + sens->data = cs; + sens->type = sens->otype = SENS_COLLISION; + } + } + } } /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -10526,11 +10539,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) expand_doit(fd, mainvar, psys->part); for (sens = ob->sensors.first; sens; sens = sens->next) { - if (sens->type == SENS_TOUCH) { - bTouchSensor *ts = sens->data; - expand_doit(fd, mainvar, ts->ma); - } - else if (sens->type == SENS_MESSAGE) { + if (sens->type == SENS_MESSAGE) { bMessageSensor *ms = sens->data; expand_doit(fd, mainvar, ms->fromObject); } @@ -10954,13 +10963,17 @@ static void give_base_to_groups(Main *mainvar, Scene *scene) { Group *group; - /* give all objects which are LIB_INDIRECT a base, or for a group when *lib has been set */ + /* give all objects which are tagged a base */ for (group = mainvar->group.first; group; group = group->id.next) { - if (((group->id.flag & LIB_INDIRECT)==0 && (group->id.flag & LIB_PRE_EXISTING)==0)) { + if (group->id.flag & LIB_DOIT) { Base *base; + Object *ob; + + /* any indirect group should not have been tagged */ + BLI_assert((group->id.flag & LIB_INDIRECT)==0); /* BKE_object_add(...) messes with the selection */ - Object *ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); + ob = BKE_object_add_only_object(mainvar, OB_EMPTY, group->id.name + 2); ob->type = OB_EMPTY; ob->lay = scene->lay; @@ -11085,6 +11098,11 @@ static ID *append_named_part_ex(const bContext *C, Main *mainl, FileData *fd, co } } } + else if (id && (GS(id->name) == ID_GR)) { + /* tag as needing to be instanced */ + if (flag & FILE_GROUP_INSTANCE) + id->flag |= LIB_DOIT; + } return id; } @@ -11130,6 +11148,9 @@ static Main *library_append_begin(Main *mainvar, FileData **fd, const char *file (*fd)->mainlist = MEM_callocN(sizeof(ListBase), "FileData.mainlist"); + /* clear for group instancing tag */ + tag_main_lb(&(mainvar->group), 0); + /* make mains */ blo_split_main((*fd)->mainlist, mainvar); @@ -11206,6 +11227,10 @@ static void library_append_end(const bContext *C, Main *mainl, FileData **fd, in printf("library_append_end, scene is NULL (objects wont get bases)\n"); } } + + /* clear group instancing tag */ + tag_main_lb(&(mainvar->group), 0); + /* has been removed... erm, why? s..ton) */ /* 20040907: looks like they are give base already in append_named_part(); -Nathan L */ /* 20041208: put back. It only linked direct, not indirect objects (ton) */ diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c index 2b63d13a9dd..12f4a295a34 100644 --- a/source/blender/blenloader/intern/undofile.c +++ b/source/blender/blenloader/intern/undofile.c @@ -51,9 +51,9 @@ void BLO_free_memfile(MemFile *memfile) { MemFileChunk *chunk; - while ( (chunk = (memfile->chunks.first) ) ) { - if (chunk->ident == 0) MEM_freeN(chunk->buf); - BLI_remlink(&memfile->chunks, chunk); + while ((chunk = BLI_pophead(&memfile->chunks))) { + if (chunk->ident == 0) + MEM_freeN(chunk->buf); MEM_freeN(chunk); } memfile->size = 0; diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index 82040020ce4..dad132f45df 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -518,11 +518,8 @@ static void do_version_free_effects_245(ListBase *lb) { Effect *eff; - eff = lb->first; - while (eff) { - BLI_remlink(lb, eff); + while ((eff = BLI_pophead(lb))) { do_version_free_effect_245(eff); - eff = lb->first; } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index b7254ffe1a9..90405583544 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -1108,9 +1108,6 @@ static void write_sensors(WriteData *wd, ListBase *lb) case SENS_MOUSE: writestruct(wd, DATA, "bMouseSensor", 1, sens->data); break; - case SENS_TOUCH: - writestruct(wd, DATA, "bTouchSensor", 1, sens->data); - break; case SENS_KEYBOARD: writestruct(wd, DATA, "bKeyboardSensor", 1, sens->data); break; @@ -2394,6 +2391,15 @@ static void write_region(WriteData *wd, ARegion *ar, int spacetype) } } +static void write_uilist(WriteData *wd, uiList *ui_list) +{ + writestruct(wd, DATA, "uiList", 1, ui_list); + + if (ui_list->properties) { + IDP_WriteProperty(ui_list->properties, wd); + } +} + static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list) { BLI_mempool *ts = so->treestore; @@ -2475,7 +2481,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) writestruct(wd, DATA, "Panel", 1, pa); for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) - writestruct(wd, DATA, "uiList", 1, ui_list); + write_uilist(wd, ui_list); } sl= sa->spacedata.first; diff --git a/source/blender/bmesh/CMakeLists.txt b/source/blender/bmesh/CMakeLists.txt index 533593d6f77..67f95cca6aa 100644 --- a/source/blender/bmesh/CMakeLists.txt +++ b/source/blender/bmesh/CMakeLists.txt @@ -41,6 +41,7 @@ set(INC_SYS set(SRC operators/bmo_beautify.c operators/bmo_bevel.c + operators/bmo_bisect_plane.c operators/bmo_bridge.c operators/bmo_connect.c operators/bmo_connect_nonplanar.c @@ -50,6 +51,7 @@ set(SRC operators/bmo_dupe.c operators/bmo_edgenet.c operators/bmo_extrude.c + operators/bmo_fill_attribute.c operators/bmo_fill_edgeloop.c operators/bmo_fill_grid.c operators/bmo_fill_holes.c @@ -119,6 +121,8 @@ set(SRC tools/bmesh_bevel.c tools/bmesh_bevel.h + tools/bmesh_bisect_plane.c + tools/bmesh_bisect_plane.h tools/bmesh_decimate_collapse.c tools/bmesh_decimate_dissolve.c tools/bmesh_decimate_unsubdivide.c @@ -132,8 +136,11 @@ set(SRC tools/bmesh_triangulate.c tools/bmesh_triangulate.h - bmesh.h bmesh_class.h + + # public includes + bmesh.h + bmesh_tools.h ) if(MSVC) diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 1f7c9ee97f6..7905a57633e 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -222,7 +222,7 @@ * - skip BMO flag allocation, its not needed in many cases, this is fairly redundant to calc by default. * - ability to call BMO's with option not to create return data (will save some time) * - binary diff UNDO, currently this uses huge amount of ram when all shapes are stored for each undo step for eg. - * - use two differnt iterator types for BMO map/buffer types. + * - use two different iterator types for BMO map/buffer types. * - avoid string lookups for BMO slot lookups _especially_ when used in loops, this is very crappy. * * @@ -251,8 +251,8 @@ extern "C" { #include "intern/bmesh_operator_api.h" #include "intern/bmesh_error.h" -#include "intern/bmesh_construct.h" #include "intern/bmesh_core.h" +#include "intern/bmesh_construct.h" #include "intern/bmesh_edgeloop.h" #include "intern/bmesh_interp.h" #include "intern/bmesh_iterators.h" @@ -269,13 +269,6 @@ extern "C" { #include "intern/bmesh_inline.h" -#include "tools/bmesh_bevel.h" -#include "tools/bmesh_decimate.h" -#include "tools/bmesh_edgenet.h" -#include "tools/bmesh_edgesplit.h" -#include "tools/bmesh_path.h" -#include "tools/bmesh_triangulate.h" - #ifdef __cplusplus } #endif diff --git a/source/blender/bmesh/bmesh_class.h b/source/blender/bmesh/bmesh_class.h index 0e4c014a06a..13ed505a8d8 100644 --- a/source/blender/bmesh/bmesh_class.h +++ b/source/blender/bmesh/bmesh_class.h @@ -65,7 +65,7 @@ typedef struct BMHeader { void *data; /* customdata layers */ int index; /* notes: * - Use BM_elem_index_get/set macros for index - * - Unitialized to -1 so we can easily tell its not set. + * - Uninitialized to -1 so we can easily tell its not set. * - Used for edge/vert/face, check BMesh.elem_index_dirty for valid index values, * this is abused by various tools which set it dirty. * - For loops this is used for sorting during tessellation. */ diff --git a/source/blender/compositor/operations/COM_MixBurnOperation.h b/source/blender/bmesh/bmesh_tools.h index 131ccfa2130..b2dac810bce 100644 --- a/source/blender/compositor/operations/COM_MixBurnOperation.h +++ b/source/blender/bmesh/bmesh_tools.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, Blender Foundation. + * ***** 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 @@ -15,31 +15,35 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor: - * Jeroen Bakker - * Monique Dewanchand + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** */ -#ifndef _COM_MixBurnOperation_h -#define _COM_MixBurnOperation_h -#include "COM_MixBaseOperation.h" - +#ifndef __BMESH_TOOLS_H__ +#define __BMESH_TOOLS_H__ -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. +/** \file blender/bmesh/bmesh_tools.h + * \ingroup bmesh + * + * Utility functions that operate directly on the BMesh, + * These can be used by both Modifiers and BMesh-Operators. */ -class MixBurnOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixBurnOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); -}; +#ifdef __cplusplus +extern "C" { #endif + +#include "tools/bmesh_bevel.h" +#include "tools/bmesh_bisect_plane.h" +#include "tools/bmesh_decimate.h" +#include "tools/bmesh_edgenet.h" +#include "tools/bmesh_edgesplit.h" +#include "tools/bmesh_path.h" +#include "tools/bmesh_triangulate.h" + +#ifdef __cplusplus +} +#endif + +#endif /* __BMESH_TOOLS_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index f5856ee94b3..1633a54398a 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -35,6 +35,7 @@ #include "BLI_alloca.h" #include "BLI_math.h" +#include "BLI_sort_utils.h" #include "BKE_customdata.h" @@ -65,64 +66,10 @@ static void bm_loop_attrs_copy(BMesh *source_mesh, BMesh *target_mesh, BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *example, const bool no_double) + const BMFace *f_example, const eBMCreateFlag create_flag) { BMVert *vtar[4] = {v1, v2, v3, v4}; - return BM_face_create_quad_tri_v(bm, vtar, v4 ? 4 : 3, example, no_double); -} - -BMFace *BM_face_create_quad_tri_v(BMesh *bm, BMVert **verts, int len, const BMFace *example, const bool no_double) -{ - BMFace *f = NULL; - bool is_overlap = false; - - /* sanity check - debug mode only */ - if (len == 3) { - BLI_assert(verts[0] != verts[1]); - BLI_assert(verts[0] != verts[2]); - BLI_assert(verts[1] != verts[2]); - } - else if (len == 4) { - BLI_assert(verts[0] != verts[1]); - BLI_assert(verts[0] != verts[2]); - BLI_assert(verts[0] != verts[3]); - - BLI_assert(verts[1] != verts[2]); - BLI_assert(verts[1] != verts[3]); - - BLI_assert(verts[2] != verts[3]); - } - else { - BLI_assert(0); - } - - - if (no_double) { - /* check if face exists or overlaps */ - is_overlap = BM_face_exists(verts, len, &f); - } - - /* make new face */ - if ((f == NULL) && (!is_overlap)) { - BMEdge *edar[4] = {NULL}; - edar[0] = BM_edge_create(bm, verts[0], verts[1], NULL, BM_CREATE_NO_DOUBLE); - edar[1] = BM_edge_create(bm, verts[1], verts[2], NULL, BM_CREATE_NO_DOUBLE); - if (len == 4) { - edar[2] = BM_edge_create(bm, verts[2], verts[3], NULL, BM_CREATE_NO_DOUBLE); - edar[3] = BM_edge_create(bm, verts[3], verts[0], NULL, BM_CREATE_NO_DOUBLE); - } - else { - edar[2] = BM_edge_create(bm, verts[2], verts[0], NULL, BM_CREATE_NO_DOUBLE); - } - - f = BM_face_create(bm, verts, edar, len, 0); - - if (example && f) { - BM_elem_attrs_copy(bm, bm, example, f); - } - } - - return f; + return BM_face_create_verts(bm, vtar, v4 ? 4 : 3, f_example, create_flag, true); } /** @@ -171,7 +118,8 @@ void BM_face_copy_shared(BMesh *bm, BMFace *f) * #BM_face_create should be considered over this function as it * avoids some unnecessary work. */ -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag) +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { BMEdge **edges_sort = BLI_array_alloca(edges_sort, len); BMVert **verts_sort = BLI_array_alloca(verts_sort, len + 1); @@ -290,7 +238,7 @@ BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, c BM_ELEM_API_FLAG_DISABLE(verts_sort[i], _FLAG_MV); } - f = BM_face_create(bm, verts_sort, edges_sort, len, create_flag); + f = BM_face_create(bm, verts_sort, edges_sort, len, f_example, create_flag); /* clean up flags */ for (i = 0; i < len; i++) { @@ -318,7 +266,8 @@ err: * - Optionally create edges between vertices. * - Uses verts so no need to find edges (handy when you only have verts) */ -BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag, +BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, const bool calc_winding, const bool create_edges) { BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); @@ -378,21 +327,8 @@ BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, c bm, v_winding[winding[0]], v_winding[winding[1]], - edge_arr, len, create_flag); -} - - -typedef struct AngleIndexPair { - float angle; - int index; -} AngleIndexPair; - -static int angle_index_pair_cmp(const void *e1, const void *e2) -{ - const AngleIndexPair *p1 = e1, *p2 = e2; - if (p1->angle > p2->angle) return 1; - else if (p1->angle < p2->angle) return -1; - else return 0; + edge_arr, len, + f_example, create_flag); } /** @@ -411,8 +347,12 @@ static int angle_index_pair_cmp(const void *e1, const void *e2) * * \note Since this is a vcloud there is no direction. */ -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag) +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { + struct SortIntByFloat *vang = BLI_array_alloca(vang, len); + BMVert **vert_arr_map = BLI_array_alloca(vert_arr_map, len); + BMFace *f; float totv_inv = 1.0f / (float)len; @@ -429,10 +369,6 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const float far_dist, far_best; float far_cross_dist, far_cross_best = 0.0f; - AngleIndexPair *vang; - - BMVert **vert_arr_map; - /* get the center point and collect vector array since we loop over these a lot */ zero_v3(cent); for (i = 0; i < len; i++) { @@ -492,8 +428,6 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const /* --- */ /* now calculate every points angle around the normal (signed) */ - vang = MEM_mallocN(sizeof(AngleIndexPair) * len, __func__); - for (i = 0; i < len; i++) { float co[3]; float proj_vec[3]; @@ -513,26 +447,21 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const angle = -angle; } - vang[i].angle = angle; - vang[i].index = i; + vang[i].sort_value = angle; + vang[i].data = i; } /* sort by angle and magic! - we have our ngon */ - qsort(vang, len, sizeof(AngleIndexPair), angle_index_pair_cmp); + qsort(vang, len, sizeof(*vang), BLI_sortutil_cmp_float); /* --- */ /* create edges and find the winding (if faces are attached to any existing edges) */ - vert_arr_map = MEM_mallocN(sizeof(BMVert *) * len, __func__); - for (i = 0; i < len; i++) { - vert_arr_map[i] = vert_arr[vang[i].index]; + vert_arr_map[i] = vert_arr[vang[i].data]; } - MEM_freeN(vang); - - f = BM_face_create_ngon_verts(bm, vert_arr_map, len, create_flag, true, true); - MEM_freeN(vert_arr_map); + f = BM_face_create_ngon_verts(bm, vert_arr_map, len, f_example, create_flag, true, true); return f; } @@ -824,6 +753,7 @@ void BM_elem_attrs_copy_ex(BMesh *bm_src, BMesh *bm_dst, const void *ele_src_v, BMHeader *ele_dst = ele_dst_v; BLI_assert(ele_src->htype == ele_dst->htype); + BLI_assert(ele_src != ele_dst); if ((hflag_mask & BM_ELEM_SELECT) == 0) { /* First we copy select */ @@ -903,7 +833,7 @@ static BMFace *bm_mesh_copy_new_face(BMesh *bm_new, BMesh *bm_old, j++; } while ((l_iter = l_iter->next) != l_first); - f_new = BM_face_create(bm_new, verts, edges, f->len, BM_CREATE_SKIP_CD); + f_new = BM_face_create(bm_new, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); if (UNLIKELY(f_new == NULL)) { return NULL; diff --git a/source/blender/bmesh/intern/bmesh_construct.h b/source/blender/bmesh/intern/bmesh_construct.h index f0bd7b316e9..0ee626dec64 100644 --- a/source/blender/bmesh/intern/bmesh_construct.h +++ b/source/blender/bmesh/intern/bmesh_construct.h @@ -29,20 +29,19 @@ struct BMAllocTemplate; -BMFace *BM_face_create_quad_tri_v(BMesh *bm, - BMVert **verts, int len, - const BMFace *example, const bool no_double); - BMFace *BM_face_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - const BMFace *example, const bool no_double); + const BMFace *f_example, const eBMCreateFlag create_flag); void BM_face_copy_shared(BMesh *bm, BMFace *f); -BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, const int create_flag); -BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, const int create_flag, +BMFace *BM_face_create_ngon(BMesh *bm, BMVert *v1, BMVert *v2, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_ngon_verts(BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, const bool calc_winding, const bool create_edges); -BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, const int create_flag); +BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int len, + const BMFace *f_example, const eBMCreateFlag create_flag); void BMO_remove_tagged_faces(BMesh *bm, const short oflag); void BMO_remove_tagged_edges(BMesh *bm, const short oflag); diff --git a/source/blender/bmesh/intern/bmesh_core.c b/source/blender/bmesh/intern/bmesh_core.c index b296c367575..34e11f5c9f9 100644 --- a/source/blender/bmesh/intern/bmesh_core.c +++ b/source/blender/bmesh/intern/bmesh_core.c @@ -56,7 +56,8 @@ /** * \brief Main function for creating a new vertex. */ -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag) +BMVert *BM_vert_create(BMesh *bm, const float co[3], + const BMVert *v_example, const eBMCreateFlag create_flag) { BMVert *v = BLI_mempool_calloc(bm->vpool); @@ -86,10 +87,10 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons } if (!(create_flag & BM_CREATE_SKIP_CD)) { - if (example) { + if (v_example) { int *keyi; - BM_elem_attrs_copy(bm, bm, example, v); + BM_elem_attrs_copy(bm, bm, v_example, v); /* exception: don't copy the original shapekey index */ keyi = CustomData_bmesh_get(&bm->vdata, v->head.data, CD_SHAPE_KEYINDEX); @@ -113,7 +114,8 @@ BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, cons * \note Duplicate edges are supported by the API however users should _never_ see them. * so unless you need a unique edge or know the edge won't exist, you should call with \a no_double = true */ -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag) +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, + const BMEdge *e_example, const eBMCreateFlag create_flag) { BMEdge *e; @@ -148,8 +150,8 @@ BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, bmesh_disk_edge_append(e, e->v2); if (!(create_flag & BM_CREATE_SKIP_CD)) { - if (example) { - BM_elem_attrs_copy(bm, bm, example, e); + if (e_example) { + BM_elem_attrs_copy(bm, bm, e_example, e); } else { CustomData_bmesh_set_default(&bm->edata, &e->head.data); @@ -190,7 +192,8 @@ static BMLoop *bm_loop_create(BMesh *bm, BMVert *v, BMEdge *e, BMFace *f, return l; } -static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, const int create_flag) +static BMLoop *bm_face_boundary_add(BMesh *bm, BMFace *f, BMVert *startv, BMEdge *starte, + const eBMCreateFlag create_flag) { #ifdef USE_BMESH_HOLES BMLoopList *lst = BLI_mempool_calloc(bm->looplistpool); @@ -228,7 +231,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, i = 0; do { if (copy_verts) { - verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, 0); + verts[i] = BM_vert_create(bm_dst, l_iter->v->co, l_iter->v, BM_CREATE_NOP); } else { verts[i] = l_iter->v; @@ -251,7 +254,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, v1 = verts[(i + 1) % f->len]; } - edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, 0); + edges[i] = BM_edge_create(bm_dst, v1, v2, l_iter->e, BM_CREATE_NOP); } else { edges[i] = l_iter->e; @@ -259,7 +262,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, i++; } while ((l_iter = l_iter->next) != l_first); - f_copy = BM_face_create(bm_dst, verts, edges, f->len, BM_CREATE_SKIP_CD); + f_copy = BM_face_create(bm_dst, verts, edges, f->len, NULL, BM_CREATE_SKIP_CD); BM_elem_attrs_copy(bm_src, bm_dst, f, f_copy); @@ -320,11 +323,12 @@ BLI_INLINE BMFace *bm_face_create__internal(BMesh *bm, const eBMCreateFlag creat * \param len Length of the face * \param create_flag Options for creating the face */ -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag) +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag) { BMFace *f = NULL; BMLoop *l, *startl, *lastl; - int i, overlap; + int i; if (len == 0) { /* just return NULL for now */ @@ -333,8 +337,8 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, if (create_flag & BM_CREATE_NO_DOUBLE) { /* Check if face already exists */ - overlap = BM_face_exists(verts, len, &f); - if (overlap) { + const bool is_overlap = BM_face_exists(verts, len, &f); + if (is_overlap) { return f; } else { @@ -364,11 +368,48 @@ BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, f->len = len; + if (!(create_flag & BM_CREATE_SKIP_CD)) { + if (f_example) { + BM_elem_attrs_copy(bm, bm, f_example, f); + } + else { + CustomData_bmesh_set_default(&bm->pdata, &f->head.data); + } + } + BM_CHECK_ELEMENT(f); return f; } +/** + * Wrapper for #BM_face_create when you don't have an edge array + */ +BMFace *BM_face_create_verts(BMesh *bm, BMVert **vert_arr, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, const bool create_edges) +{ + BMEdge **edge_arr = BLI_array_alloca(edge_arr, len); + int i, i_prev = len - 1; + + if (create_edges) { + for (i = 0; i < len; i++) { + edge_arr[i_prev] = BM_edge_create(bm, vert_arr[i_prev], vert_arr[i], NULL, BM_CREATE_NO_DOUBLE); + i_prev = i; + } + } + else { + for (i = 0; i < len; i++) { + edge_arr[i_prev] = BM_edge_exists(vert_arr[i_prev], vert_arr[i]); + if (edge_arr[i_prev] == NULL) { + return NULL; + } + i_prev = i; + } + } + + return BM_face_create(bm, vert_arr, edge_arr, len, f_example, create_flag); +} + #ifndef NDEBUG /** @@ -1053,7 +1094,7 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) } /* create region face */ - f_new = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, 0) : NULL; + f_new = tote ? BM_face_create_ngon(bm, v1, v2, edges, tote, faces[0], BM_CREATE_NOP) : NULL; if (UNLIKELY(!f_new || BMO_error_occurred(bm))) { if (!BMO_error_occurred(bm)) err = N_("Invalid boundary region to join faces"); @@ -1080,8 +1121,6 @@ BMFace *BM_faces_join(BMesh *bm, BMFace **faces, int totface, const bool do_del) BM_elem_attrs_copy(bm, bm, l2, l_iter); } } while ((l_iter = l_iter->next) != l_first); - - BM_elem_attrs_copy(bm, bm, faces[0], f_new); #ifdef USE_BMESH_HOLES /* add holes */ @@ -1243,7 +1282,7 @@ BMFace *bmesh_sfme(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, } /* allocate new edge between v1 and v2 */ - e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : 0); + e = BM_edge_create(bm, v1, v2, example, no_double ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP); f2 = bm_face_create__sfme(bm, f); l_f1 = bm_loop_create(bm, v2, e, f, l_v2, 0); @@ -1384,8 +1423,8 @@ BMVert *bmesh_semv(BMesh *bm, BMVert *tv, BMEdge *e, BMEdge **r_e) valence2 = bmesh_disk_count(tv); #endif - v_new = BM_vert_create(bm, tv->co, tv, 0); - e_new = BM_edge_create(bm, v_new, tv, e, 0); + v_new = BM_vert_create(bm, tv->co, tv, BM_CREATE_NOP); + e_new = BM_edge_create(bm, v_new, tv, e, BM_CREATE_NOP); bmesh_disk_edge_remove(e_new, tv); bmesh_disk_edge_remove(e_new, v_new); @@ -1970,7 +2009,7 @@ void bmesh_vert_separate(BMesh *bm, BMVert *v, BMVert ***r_vout, int *r_vout_len verts[0] = v; for (i = 1; i < maxindex; i++) { - verts[i] = BM_vert_create(bm, v->co, v, 0); + verts[i] = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); if (copy_select) { BM_elem_select_copy(bm, bm, verts[i], v); } @@ -2136,7 +2175,7 @@ void bmesh_edge_separate(BMesh *bm, BMEdge *e, BMLoop *l_sep, e->l = l_sep->radial_next; } - e_new = BM_edge_create(bm, e->v1, e->v2, e, 0); + e_new = BM_edge_create(bm, e->v1, e->v2, e, BM_CREATE_NOP); bmesh_radial_loop_remove(l_sep, e); bmesh_radial_append(e_new, l_sep); l_sep->e = e_new; diff --git a/source/blender/bmesh/intern/bmesh_core.h b/source/blender/bmesh/intern/bmesh_core.h index c9e806335dd..a18c2ebd32c 100644 --- a/source/blender/bmesh/intern/bmesh_core.h +++ b/source/blender/bmesh/intern/bmesh_core.h @@ -31,6 +31,7 @@ BMFace *BM_face_copy(BMesh *bm_dst, BMesh *bm_src, BMFace *f, const bool copy_verts, const bool copy_edges); typedef enum eBMCreateFlag { + BM_CREATE_NOP = 0, /* faces and edges only */ BM_CREATE_NO_DOUBLE = (1 << 1), /* Skip CustomData - for all element types data, @@ -39,9 +40,15 @@ typedef enum eBMCreateFlag { BM_CREATE_SKIP_CD = (1 << 2), } eBMCreateFlag; -BMVert *BM_vert_create(BMesh *bm, const float co[3], const BMVert *example, const eBMCreateFlag create_flag); -BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, const BMEdge *example, const eBMCreateFlag create_flag); -BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, const eBMCreateFlag create_flag); +BMVert *BM_vert_create(BMesh *bm, const float co[3], + const BMVert *v_example, const eBMCreateFlag create_flag); +BMEdge *BM_edge_create(BMesh *bm, BMVert *v1, BMVert *v2, + const BMEdge *e_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create(BMesh *bm, BMVert **verts, BMEdge **edges, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag); +BMFace *BM_face_create_verts(BMesh *bm, BMVert **verts, const int len, + const BMFace *f_example, const eBMCreateFlag create_flag, + const bool create_edges); void BM_face_edges_kill(BMesh *bm, BMFace *f); void BM_face_verts_kill(BMesh *bm, BMFace *f); diff --git a/source/blender/bmesh/intern/bmesh_edgeloop.c b/source/blender/bmesh/intern/bmesh_edgeloop.c index 1f052bd206a..fe3f6551b70 100644 --- a/source/blender/bmesh/intern/bmesh_edgeloop.c +++ b/source/blender/bmesh/intern/bmesh_edgeloop.c @@ -230,7 +230,7 @@ static bool bm_loop_path_build_step(BLI_mempool *vs_pool, ListBase *lb, const in /* on the same side - do nothing */ } else { - /* we have met out match! (vertices from differnt sides meet) */ + /* we have met out match! (vertices from different sides meet) */ if (dir == 1) { v_match[0] = vs->v; v_match[1] = v_next; @@ -361,8 +361,7 @@ bool BM_mesh_edgeloops_find_path(BMesh *bm, ListBase *r_eloops, void BM_mesh_edgeloops_free(ListBase *eloops) { BMEdgeLoopStore *el_store; - while ((el_store = eloops->first)) { - BLI_remlink(eloops, el_store); + while ((el_store = BLI_pophead(eloops))) { BM_edgeloop_free(el_store); } } diff --git a/source/blender/bmesh/intern/bmesh_inline.h b/source/blender/bmesh/intern/bmesh_inline.h index 102e9d47ffd..5ac6d7da61b 100644 --- a/source/blender/bmesh/intern/bmesh_inline.h +++ b/source/blender/bmesh/intern/bmesh_inline.h @@ -56,7 +56,7 @@ BLI_INLINE void _bm_elem_flag_enable(BMHeader *head, const char hflag) BLI_INLINE void _bm_elem_flag_disable(BMHeader *head, const char hflag) { - head->hflag &= ~hflag; + head->hflag &= (char)~hflag; } BLI_INLINE void _bm_elem_flag_set(BMHeader *head, const char hflag, const int val) diff --git a/source/blender/bmesh/intern/bmesh_iterators.h b/source/blender/bmesh/intern/bmesh_iterators.h index b5535b59321..bb25d3fabd1 100644 --- a/source/blender/bmesh/intern/bmesh_iterators.h +++ b/source/blender/bmesh/intern/bmesh_iterators.h @@ -39,6 +39,7 @@ * */ +#include "BLI_compiler_attrs.h" #include "BLI_mempool.h" /* Defines for passing to BM_iter_new. @@ -181,18 +182,10 @@ typedef struct BMIter { char itype; } BMIter; -void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -#endif -; +void *BM_iter_at_index(BMesh *bm, const char itype, void *data, int index) ATTR_WARN_UNUSED_RESULT; int BM_iter_as_array(BMesh *bm, const char itype, void *data, void **array, const int len); void *BM_iter_as_arrayN(BMesh *bm, const char itype, void *data, int *r_len, - void **stack_array, int stack_array_size) -#ifdef __GNUC__ -__attribute__((warn_unused_result)) -#endif -; + void **stack_array, int stack_array_size) ATTR_WARN_UNUSED_RESULT; int BMO_iter_as_array(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, void **array, const int len); void *BMO_iter_as_arrayN(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name, const char restrictmask, diff --git a/source/blender/bmesh/intern/bmesh_log.c b/source/blender/bmesh/intern/bmesh_log.c index b50f35be4f3..30728636a58 100644 --- a/source/blender/bmesh/intern/bmesh_log.c +++ b/source/blender/bmesh/intern/bmesh_log.c @@ -95,6 +95,7 @@ struct BMLog { typedef struct { float co[3]; + short no[3]; float mask; char hflag; } BMLogVert; @@ -117,8 +118,8 @@ static void bm_log_vert_id_set(BMLog *log, BMVert *v, unsigned int id) { void *vid = SET_INT_IN_POINTER(id); - BLI_ghash_assign(log->id_to_elem, vid, v, NULL, NULL); - BLI_ghash_assign(log->elem_to_id, v, vid, NULL, NULL); + BLI_ghash_reinsert(log->id_to_elem, vid, v, NULL, NULL); + BLI_ghash_reinsert(log->elem_to_id, v, vid, NULL, NULL); } /* Get a vertex from its unique ID */ @@ -141,8 +142,8 @@ static void bm_log_face_id_set(BMLog *log, BMFace *f, unsigned int id) { void *fid = SET_INT_IN_POINTER(id); - BLI_ghash_assign(log->id_to_elem, fid, f, NULL, NULL); - BLI_ghash_assign(log->elem_to_id, f, fid, NULL, NULL); + BLI_ghash_reinsert(log->id_to_elem, fid, f, NULL, NULL); + BLI_ghash_reinsert(log->elem_to_id, f, fid, NULL, NULL); } /* Get a face from its unique ID */ @@ -187,6 +188,7 @@ static void vert_mask_set(BMesh *bm, BMVert *v, float new_mask) static void bm_log_vert_bmvert_copy(BMesh *bm, BMLogVert *lv, BMVert *v) { copy_v3_v3(lv->co, v->co); + normal_float_to_short_v3(lv->no, v->no); lv->mask = vert_mask_get(bm, v); lv->hflag = v->head.hflag; } @@ -273,9 +275,10 @@ static void bm_log_verts_restore(BMesh *bm, BMLog *log, GHash *verts) GHASH_ITER (gh_iter, verts) { void *key = BLI_ghashIterator_getKey(&gh_iter); BMLogVert *lv = BLI_ghashIterator_getValue(&gh_iter); - BMVert *v = BM_vert_create(bm, lv->co, NULL, 0); + BMVert *v = BM_vert_create(bm, lv->co, NULL, BM_CREATE_NOP); v->head.hflag = lv->hflag; vert_mask_set(bm, v, lv->mask); + normal_short_to_float_v3(v->no, lv->no); bm_log_vert_id_set(log, v, GET_INT_FROM_POINTER(key)); } } @@ -291,7 +294,7 @@ static void bm_log_faces_restore(BMesh *bm, BMLog *log, GHash *faces) bm_log_vert_from_id(log, lf->v_ids[2])}; BMFace *f; - f = BM_face_create_quad_tri_v(bm, v, 3, NULL, false); + f = BM_face_create_verts(bm, v, 3, NULL, BM_CREATE_NOP, true); bm_log_face_id_set(log, f, GET_INT_FROM_POINTER(key)); } } @@ -305,8 +308,12 @@ static void bm_log_vert_values_swap(BMesh *bm, BMLog *log, GHash *verts) unsigned int id = GET_INT_FROM_POINTER(key); BMVert *v = bm_log_vert_from_id(log, id); float mask; + short normal[3]; swap_v3_v3(v->co, lv->co); + copy_v3_v3_short(normal, lv->no); + normal_float_to_short_v3(lv->no, v->no); + normal_short_to_float_v3(v->no, normal); SWAP(char, v->head.hflag, lv->hflag); mask = lv->mask; lv->mask = vert_mask_get(bm, v); @@ -400,7 +407,7 @@ static int uint_compare(const void *a_v, const void *b_v) */ static GHash *bm_log_compress_ids_to_indices(unsigned int *ids, int totid) { - GHash *map = BLI_ghash_int_new(AT); + GHash *map = BLI_ghash_int_new_ex(AT, totid); int i; qsort(ids, totid, sizeof(*ids), uint_compare); @@ -434,8 +441,8 @@ BMLog *BM_log_create(BMesh *bm) BMLog *log = MEM_callocN(sizeof(*log), AT); log->unused_ids = range_tree_uint_alloc(0, (unsigned)-1); - log->id_to_elem = BLI_ghash_ptr_new(AT); - log->elem_to_id = BLI_ghash_ptr_new(AT); + log->id_to_elem = BLI_ghash_ptr_new_ex(AT, bm->totvert + bm->totface); + log->elem_to_id = BLI_ghash_ptr_new_ex(AT, bm->totvert + bm->totface); /* Assign IDs to all existing vertices and faces */ bm_log_assign_ids(bm, log); @@ -927,6 +934,24 @@ const float *BM_log_original_vert_co(BMLog *log, BMVert *v) return lv->co; } +/* Get the logged normal of a vertex + * + * Does not modify the log or the vertex */ +const short *BM_log_original_vert_no(BMLog *log, BMVert *v) +{ + BMLogEntry *entry = log->current_entry; + const BMLogVert *lv; + unsigned v_id = bm_log_vert_id_get(log, v); + void *key = SET_INT_IN_POINTER(v_id); + + BLI_assert(entry); + + BLI_assert(BLI_ghash_haskey(entry->modified_verts, key)); + + lv = BLI_ghash_lookup(entry->modified_verts, key); + return lv->no; +} + /* Get the logged mask of a vertex * * Does not modify the log or the vertex */ diff --git a/source/blender/bmesh/intern/bmesh_log.h b/source/blender/bmesh/intern/bmesh_log.h index 958ff340b43..4767c82ff2f 100644 --- a/source/blender/bmesh/intern/bmesh_log.h +++ b/source/blender/bmesh/intern/bmesh_log.h @@ -92,6 +92,9 @@ void BM_log_before_all_removed(BMesh *bm, BMLog *log); /* Get the logged coordinates of a vertex */ const float *BM_log_original_vert_co(BMLog *log, BMVert *v); +/* Get the logged normal of a vertex */ +const short *BM_log_original_vert_no(BMLog *log, BMVert *v); + /* Get the logged mask of a vertex */ float BM_log_original_mask(BMLog *log, BMVert *v); diff --git a/source/blender/bmesh/intern/bmesh_mesh.c b/source/blender/bmesh/intern/bmesh_mesh.c index 64368390444..cc2324ba34a 100644 --- a/source/blender/bmesh/intern/bmesh_mesh.c +++ b/source/blender/bmesh/intern/bmesh_mesh.c @@ -667,14 +667,14 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx) if (!(vert_idx || edge_idx || face_idx)) return; - /* Remap vertices */ + /* Remap Verts */ if (vert_idx) { BMVert **verts_pool, *verts_copy, **vep; int i, totvert = bm->totvert; int *new_idx = NULL; /* Init the old-to-new vert pointers mapping */ - vptr_map = BLI_ghash_ptr_new("BM_mesh_remap vert pointers mapping"); + vptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap vert pointers mapping", bm->totvert); /* Make a copy of all vertices. */ verts_pool = MEM_callocN(sizeof(BMVert *) * totvert, "BM_mesh_remap verts pool"); @@ -701,14 +701,14 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx) MEM_freeN(verts_copy); } - /* XXX Code not tested yet (though I don't why it would fail)! */ + /* Remap Edges */ if (edge_idx) { BMEdge **edges_pool, *edges_copy, **edp; int i, totedge = bm->totedge; int *new_idx = NULL; /* Init the old-to-new vert pointers mapping */ - eptr_map = BLI_ghash_ptr_new("BM_mesh_remap edge pointers mapping"); + eptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap edge pointers mapping", bm->totedge); /* Make a copy of all vertices. */ edges_pool = MEM_callocN(sizeof(BMEdge *) * totedge, "BM_mesh_remap edges pool"); @@ -734,14 +734,14 @@ void BM_mesh_remap(BMesh *bm, int *vert_idx, int *edge_idx, int *face_idx) MEM_freeN(edges_copy); } - /* XXX Code not tested yet (though I don't why it would fail)! */ + /* Remap Faces */ if (face_idx) { BMFace **faces_pool, *faces_copy, **fap; int i, totface = bm->totface; int *new_idx = NULL; /* Init the old-to-new vert pointers mapping */ - fptr_map = BLI_ghash_ptr_new("BM_mesh_remap face pointers mapping"); + fptr_map = BLI_ghash_ptr_new_ex("BM_mesh_remap face pointers mapping", bm->totface); /* Make a copy of all vertices. */ faces_pool = MEM_callocN(sizeof(BMFace *) * totface, "BM_mesh_remap faces pool"); diff --git a/source/blender/bmesh/intern/bmesh_mesh_conv.c b/source/blender/bmesh/intern/bmesh_mesh_conv.c index 81d4aad0fdf..d92fe45afcd 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_conv.c +++ b/source/blender/bmesh/intern/bmesh_mesh_conv.c @@ -212,7 +212,7 @@ static BMFace *bm_face_create_from_mpoly(MPoly *mp, MLoop *ml, edges[j] = etable[ml->e]; } - return BM_face_create(bm, verts, edges, mp->totloop, BM_CREATE_SKIP_CD); + return BM_face_create(bm, verts, edges, mp->totloop, NULL, BM_CREATE_SKIP_CD); } diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 418fc16ea55..3ffdd0f86a6 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -356,10 +356,9 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l 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 && (f_new != f)) { + if (has_mdisp) { BMLoop *l_iter; BMLoop *l_first; @@ -373,8 +372,6 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l BM_loop_interp_multires(bm, l_iter, f_tmp); } while ((l_iter = l_iter->next) != l_first); - 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); @@ -383,6 +380,10 @@ BMFace *BM_face_split(BMesh *bm, BMFace *f, BMVert *v1, BMVert *v2, BMLoop **r_l } } + if (has_mdisp) { + BM_face_kill(bm, f_tmp); + } + return f_new; } @@ -1067,7 +1068,7 @@ BMEdge *BM_edge_rotate(BMesh *bm, BMEdge *e, const bool ccw, const short check_f /* first create the new edge, this is so we can copy the customdata from the old one * if splice if disabled, always add in a new edge even if theres one there. */ - e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) != 0); + e_new = BM_edge_create(bm, v1, v2, e, (check_flag & BM_EDGEROT_CHECK_SPLICE) ? BM_CREATE_NO_DOUBLE : BM_CREATE_NOP); f_hflag_prev_1 = l1->f->head.hflag; f_hflag_prev_2 = l2->f->head.hflag; diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 371d55f385e..e6291cac241 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -577,6 +577,28 @@ static BMOpDefine bmo_holes_fill_def = { /* + * Face Attribute Fill. + * + * Fill in faces with data from adjacent faces. + */ +static BMOpDefine bmo_face_attribute_fill_def = { + "face_attribute_fill", + /* slots_in */ + {{"faces", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* input faces */ + {"use_normals", BMO_OP_SLOT_BOOL}, /* copy face winding */ + {"use_data", BMO_OP_SLOT_BOOL}, /* copy face data */ + {{'\0'}}, + }, + /* slots_out */ + /* maps new faces to the group numbers they came from */ + {{"faces_fail.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_FACE}}, /* faces that could not be handled */ + {{'\0'}}, + }, + bmo_face_attribute_fill_exec, + BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH, +}; + +/* * Edge Loop Fill. * * Create faces defined by one or more non overlapping edge loops. @@ -609,8 +631,9 @@ static BMOpDefine bmo_edgenet_fill_def = { "edgenet_fill", /* slots_in */ {{"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ - {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ - {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ + {"mat_nr", BMO_OP_SLOT_INT}, /* material to use */ + {"use_smooth", BMO_OP_SLOT_BOOL}, /* smooth state to use */ + {"sides", BMO_OP_SLOT_INT}, /* number of sides */ {{'\0'}}, }, /* slots_out */ @@ -1095,6 +1118,30 @@ static BMOpDefine bmo_subdivide_edgering_def = { }; /* + * Bisect Plane. + * + * Bisects the mesh by a plane (cut the mesh in half). + */ +static BMOpDefine bmo_bisect_plane_def = { + "bisect_plane", + /* slots_in */ + {{"geom", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance when testing if a vert is exactly on the plane */ + {"plane_co", BMO_OP_SLOT_VEC}, /* point on the plane */ + {"plane_no", BMO_OP_SLOT_VEC}, /* direction of the plane */ + {"use_snap_center", BMO_OP_SLOT_BOOL}, /* snap axis aligned verts to the center */ + {"clear_outer", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the positive side of the plane */ + {"clear_inner", BMO_OP_SLOT_BOOL}, /* when enabled. remove all geometry on the negative side of the plane */ + {{'\0'}}, + }, + {{"geom_cut.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE}}, /* output new geometry from the cut */ + {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* input and output geometry (result of cut) */ + {{'\0'}}}, + bmo_bisect_plane_exec, + BMO_OPTYPE_FLAG_UNTAN_MULTIRES | BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH, +}; + +/* * Delete Geometry. * * Utility operator to delete geometry. @@ -1130,6 +1177,8 @@ static BMOpDefine bmo_duplicate_def = { {"geom.out", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, /* facemap maps from source faces to dupe * faces, and from dupe faces to source faces */ + {"vert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, + {"edge_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, {"face_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, {"boundary_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, {"isovert_map.out", BMO_OP_SLOT_MAPPING, {BMO_OP_SLOT_SUBTYPE_MAP_ELEM}}, @@ -1549,7 +1598,9 @@ static BMOpDefine bmo_triangle_fill_def = { "triangle_fill", /* slots_in */ {{"use_beauty", BMO_OP_SLOT_BOOL}, + {"use_dissolve", BMO_OP_SLOT_BOOL}, /* dissolve resulting faces */ {"edges", BMO_OP_SLOT_ELEMENT_BUF, {BM_EDGE}}, /* input edges */ + {"normal", BMO_OP_SLOT_VEC}, /* optionally pass the fill normal to use */ {{'\0'}}, }, /* slots_out */ @@ -1601,7 +1652,7 @@ static BMOpDefine bmo_inset_individual_def = { {{'\0'}}, }, bmo_inset_individual_exec, - BMO_OPTYPE_FLAG_NORMALS_CALC | BMO_OPTYPE_FLAG_SELECT_FLUSH, + BMO_OPTYPE_FLAG_NORMALS_CALC, /* caller needs to handle BMO_OPTYPE_FLAG_SELECT_FLUSH */ }; /* @@ -1728,6 +1779,7 @@ static BMOpDefine bmo_symmetrize_def = { /* slots_in */ {{"input", BMO_OP_SLOT_ELEMENT_BUF, {BM_VERT | BM_EDGE | BM_FACE}}, {"direction", BMO_OP_SLOT_INT}, + {"dist", BMO_OP_SLOT_FLT}, /* minimum distance */ {{'\0'}}, }, /* slots_out */ @@ -1770,6 +1822,7 @@ const BMOpDefine *bmo_opdefines[] = { &bmo_dissolve_verts_def, &bmo_duplicate_def, &bmo_holes_fill_def, + &bmo_face_attribute_fill_def, &bmo_edgeloop_fill_def, &bmo_edgenet_fill_def, &bmo_edgenet_prepare_def, @@ -1810,6 +1863,7 @@ const BMOpDefine *bmo_opdefines[] = { &bmo_split_edges_def, &bmo_subdivide_edges_def, &bmo_subdivide_edgering_def, + &bmo_bisect_plane_def, &bmo_symmetrize_def, &bmo_transform_def, &bmo_translate_def, diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index 24bfcd70d75..7de158f3c29 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -335,6 +335,11 @@ void BMO_slot_mat3_get(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *op, const char htype, const short oflag); +void BMO_mesh_selected_remap(BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map); + /* copies the values from another slot to the end of the output slot */ #define BMO_slot_buffer_append(op_src, slots_src, slot_name_src, \ op_dst, slots_dst, slot_name_dst) \ @@ -398,7 +403,7 @@ int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name); void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, const void *data, const int len); + const void *element, const void *data); /* flags all elements in a mapping. note that the mapping must only have * bmesh elements in it.*/ @@ -452,7 +457,7 @@ typedef struct BMOIter { BMOpSlot *slot; int cur; //for arrays GHashIterator giter; - void *val; + void **val; char restrictmask; /* bitwise '&' with BMHeader.htype */ } BMOIter; @@ -463,15 +468,12 @@ void *BMO_iter_new(BMOIter *iter, const char restrictmask); void *BMO_iter_step(BMOIter *iter); -/* returns a pointer to the key value when iterating over mappings. - * remember for pointer maps this will be a pointer to a pointer.*/ -void *BMO_iter_map_value(BMOIter *iter); - -/* use this for pointer mappings */ -void *BMO_iter_map_value_p(BMOIter *iter); +void **BMO_iter_map_value_p(BMOIter *iter); +void *BMO_iter_map_value_ptr(BMOIter *iter); -/* use this for float mappings */ -float BMO_iter_map_value_f(BMOIter *iter); +float BMO_iter_map_value_float(BMOIter *iter); +int BMO_iter_map_value_int(BMOIter *iter); +bool BMO_iter_map_value_bool(BMOIter *iter); #define BMO_ITER(ele, iter, slot_args, slot_name, restrict_flag) \ for (ele = BMO_iter_new(iter, slot_args, slot_name, restrict_flag); ele; ele = BMO_iter_step(iter)) @@ -479,16 +481,6 @@ float BMO_iter_map_value_f(BMOIter *iter); /******************* Inlined Functions********************/ typedef void (*opexec)(BMesh *bm, BMOperator *op); -/* mappings map elements to data, which - * follows the mapping struct in memory. */ -typedef struct BMOElemMapping { - BMHeader *element; - int len; -} BMOElemMapping; - -/* pointer after BMOElemMapping */ -#define BMO_OP_SLOT_MAPPING_DATA(var) (void *)(((BMOElemMapping *)var) + 1) - extern const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES]; int BMO_opcode_from_opname(const char *opname); diff --git a/source/blender/bmesh/intern/bmesh_operator_api_inline.h b/source/blender/bmesh/intern/bmesh_operator_api_inline.h index 724ddcf3b04..77310d958e6 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api_inline.h +++ b/source/blender/bmesh/intern/bmesh_operator_api_inline.h @@ -55,13 +55,13 @@ BLI_INLINE void _bmo_elem_flag_enable(BMesh *bm, BMFlagLayer *oflags, const shor BLI_INLINE void _bmo_elem_flag_disable(BMesh *bm, BMFlagLayer *oflags, const short oflag) { - oflags[bm->stackdepth - 1].f &= ~oflag; + oflags[bm->stackdepth - 1].f &= (short)~oflag; } BLI_INLINE void _bmo_elem_flag_set(BMesh *bm, BMFlagLayer *oflags, const short oflag, int val) { if (val) oflags[bm->stackdepth - 1].f |= oflag; - else oflags[bm->stackdepth - 1].f &= ~oflag; + else oflags[bm->stackdepth - 1].f &= (short)~oflag; } BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const short oflag) @@ -72,23 +72,26 @@ BLI_INLINE void _bmo_elem_flag_toggle(BMesh *bm, BMFlagLayer *oflags, const shor BLI_INLINE void BMO_slot_map_int_insert(BMOperator *op, BMOpSlot *slot, void *element, const int val) { + union { void *ptr; int val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); - BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); + BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } BLI_INLINE void BMO_slot_map_bool_insert(BMOperator *op, BMOpSlot *slot, void *element, const int val) { + union { void *ptr; int val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); BLI_assert(val == false || val == true); - BMO_slot_map_insert(op, slot, element, &val, sizeof(int)); + BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } BLI_INLINE void BMO_slot_map_float_insert(BMOperator *op, BMOpSlot *slot, void *element, const float val) { + union { void *ptr; float val; } t = {NULL}; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); - BMO_slot_map_insert(op, slot, element, &val, sizeof(float)); + BMO_slot_map_insert(op, slot, element, ((t.val = val), t.ptr)); } @@ -101,14 +104,14 @@ BLI_INLINE void BMO_slot_map_ptr_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); - BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); + BMO_slot_map_insert(op, slot, element, val); } BLI_INLINE void BMO_slot_map_elem_insert(BMOperator *op, BMOpSlot *slot, const void *element, void *val) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_ELEM); - BMO_slot_map_insert(op, slot, element, &val, sizeof(void *)); + BMO_slot_map_insert(op, slot, element, val); } @@ -117,77 +120,66 @@ BLI_INLINE void BMO_slot_map_empty_insert(BMOperator *op, BMOpSlot *slot, const void *element) { BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_EMPTY); - BMO_slot_map_insert(op, slot, element, NULL, 0); + BMO_slot_map_insert(op, slot, element, NULL); } 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 false; - } - return BLI_ghash_haskey(slot->data.ghash, element); } -BLI_INLINE void *BMO_slot_map_data_get(BMOpSlot *slot, const void *element) +BLI_INLINE void **BMO_slot_map_data_get(BMOpSlot *slot, const void *element) { - BMOElemMapping *mapping; - BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - - /* sanity check */ - if (UNLIKELY(slot->data.ghash == NULL)) { - return NULL; - } - - mapping = (BMOElemMapping *)BLI_ghash_lookup(slot->data.ghash, element); - - if (!mapping) { - return NULL; - } - return mapping + 1; + return BLI_ghash_lookup_p(slot->data.ghash, element); } BLI_INLINE float BMO_slot_map_float_get(BMOpSlot *slot, const void *element) { - float *val; + void **data; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); - val = (float *) BMO_slot_map_data_get(slot, element); - if (val) return *val; - - return 0.0f; + data = BMO_slot_map_data_get(slot, element); + if (data) { + return **(float **)data; + } + else { + return 0.0f; + } } BLI_INLINE int BMO_slot_map_int_get(BMOpSlot *slot, const void *element) { - int *val; + void **data; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); - val = (int *) BMO_slot_map_data_get(slot, element); - if (val) return *val; - - return 0; + data = BMO_slot_map_data_get(slot, element); + if (data) { + return **(int **)data; + } + else { + return 0; + } } BLI_INLINE bool BMO_slot_map_bool_get(BMOpSlot *slot, const void *element) { - int *val; + void **data; BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); - val = (int *) BMO_slot_map_data_get(slot, element); - BLI_assert(val == NULL || *val == false || *val == true); - if (val) return (bool)*val; - - return false; + data = BMO_slot_map_data_get(slot, element); + if (data) { + return **(int **)data; + } + else { + return false; + } } BLI_INLINE void *BMO_slot_map_ptr_get(BMOpSlot *slot, const void *element) { - void **val = (void **) BMO_slot_map_data_get(slot, element); + void **val = BMO_slot_map_data_get(slot, element); BLI_assert(slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL); if (val) return *val; diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index b71d5a7e7d4..9551c55959e 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -74,7 +74,7 @@ const int BMO_OPSLOT_TYPEINFO[BMO_OP_SLOT_TOTAL_TYPES] = { 0, /* 7: unused */ sizeof(float) * 3, /* 8: BMO_OP_SLOT_VEC */ sizeof(void *), /* 9: BMO_OP_SLOT_ELEMENT_BUF */ - sizeof(BMOElemMapping) /* 10: BMO_OP_SLOT_MAPPING */ + sizeof(void *) /* 10: BMO_OP_SLOT_MAPPING */ }; /* Dummy slot so there is something to return when slot name lookup fails */ @@ -127,12 +127,38 @@ void BMO_pop(BMesh *bm) /* use for both slot_types_in and slot_types_out */ static void bmo_op_slots_init(const BMOSlotType *slot_types, BMOpSlot *slot_args) { + BMOpSlot *slot; + unsigned int i; + for (i = 0; slot_types[i].type; i++) { + slot = &slot_args[i]; + slot->slot_name = slot_types[i].name; + slot->slot_type = slot_types[i].type; + slot->slot_subtype = slot_types[i].subtype; + // slot->index = i; // UNUSED + + switch (slot->slot_type) { + case BMO_OP_SLOT_MAPPING: + slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); + break; + default: + break; + } + } +} + +static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) +{ + BMOpSlot *slot; unsigned int i; for (i = 0; slot_types[i].type; i++) { - slot_args[i].slot_name = slot_types[i].name; - slot_args[i].slot_type = slot_types[i].type; - slot_args[i].slot_subtype = slot_types[i].subtype; - // slot_args[i].index = i; // UNUSED + slot = &slot_args[i]; + switch (slot->slot_type) { + case BMO_OP_SLOT_MAPPING: + BLI_ghash_free(slot->data.ghash, NULL, NULL); + break; + default: + break; + } } } @@ -198,20 +224,6 @@ void BMO_op_exec(BMesh *bm, BMOperator *op) BMO_pop(bm); } -static void bmo_op_slots_free(const BMOSlotType *slot_types, BMOpSlot *slot_args) -{ - BMOpSlot *slot; - unsigned int i; - for (i = 0; slot_types[i].type; i++) { - slot = &slot_args[i]; - if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - if (slot->data.ghash) { - BLI_ghash_free(slot->data.ghash, NULL, NULL); - } - } - } -} - /** * \brief BMESH OPSTACK FINISH OP * @@ -333,28 +345,13 @@ void _bmo_slot_copy(BMOpSlot slot_args_src[BMO_OP_MAX_SLOTS], const char *slot_n } else if (slot_dst->slot_type == BMO_OP_SLOT_MAPPING) { GHashIterator it; - BMOElemMapping *srcmap, *dstmap; - - /* sanity check */ - if (!slot_src->data.ghash) { - return; - } - - if (!slot_dst->data.ghash) { - slot_dst->data.ghash = BLI_ghash_ptr_new("bmesh operator 2"); - } - for (BLI_ghashIterator_init(&it, slot_src->data.ghash); - (srcmap = BLI_ghashIterator_getValue(&it)); + BLI_ghashIterator_done(&it) == false; BLI_ghashIterator_step(&it)) { - dstmap = BLI_memarena_alloc(arena_dst, sizeof(*dstmap) + srcmap->len); - - dstmap->element = srcmap->element; - dstmap->len = srcmap->len; - memcpy(BMO_OP_SLOT_MAPPING_DATA(dstmap), BMO_OP_SLOT_MAPPING_DATA(srcmap), srcmap->len); - - BLI_ghash_insert(slot_dst->data.ghash, dstmap->element, dstmap); + void *key = BLI_ghashIterator_getKey(&it); + void *val = BLI_ghashIterator_getValue(&it); + BLI_ghash_insert(slot_dst->data.ghash, key, val); } } else { @@ -605,6 +602,44 @@ void BMO_mesh_flag_disable_all(BMesh *bm, BMOperator *UNUSED(op), const char hty } } +void BMO_mesh_selected_remap(BMesh *bm, + BMOpSlot *slot_vert_map, + BMOpSlot *slot_edge_map, + BMOpSlot *slot_face_map) +{ + if (bm->selected.first) { + BMEditSelection *ese, *ese_next; + BMOpSlot *slot_elem_map; + + for (ese = bm->selected.first; ese; ese = ese_next) { + ese_next = ese->next; + + switch (ese->htype) { + case BM_VERT: slot_elem_map = slot_vert_map; break; + case BM_EDGE: slot_elem_map = slot_edge_map; break; + default: slot_elem_map = slot_face_map; break; + } + + ese->ele = BMO_slot_map_elem_get(slot_elem_map, ese->ele); + + if (UNLIKELY((ese->ele == NULL) || + (BM_elem_flag_test(ese->ele, BM_ELEM_SELECT) == false))) + { + BLI_remlink(&bm->selected, ese); + MEM_freeN(ese); + } + } + } + + if (bm->act_face) { + BMFace *f = BMO_slot_map_elem_get(slot_face_map, bm->act_face); + if (f) { + bm->act_face = f; + } + } +} + + int BMO_slot_buffer_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_name) { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); @@ -621,38 +656,21 @@ int BMO_slot_map_count(BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const char *slot_na { BMOpSlot *slot = BMO_slot_get(slot_args, slot_name); BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - - /* check if its actually a buffer */ - if (!(slot->slot_type == BMO_OP_SLOT_MAPPING)) - return 0; - - return slot->data.ghash ? BLI_ghash_size(slot->data.ghash) : 0; + return BLI_ghash_size(slot->data.ghash); } /* inserts a key/value mapping into a mapping slot. note that it copies the * value, it doesn't store a reference to it. */ void BMO_slot_map_insert(BMOperator *op, BMOpSlot *slot, - const void *element, const void *data, const int len) + const void *element, const void *data) { - BMOElemMapping *mapping; + (void) op; /* Ignored in release builds. */ + BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); BMO_ASSERT_SLOT_IN_OP(slot, op); - mapping = (BMOElemMapping *) BLI_memarena_alloc(op->arena, sizeof(*mapping) + len); - - mapping->element = (BMHeader *) element; - mapping->len = len; - memcpy(BMO_OP_SLOT_MAPPING_DATA(mapping), data, len); - - if (!slot->data.ghash) { - slot->data.ghash = BLI_ghash_ptr_new("bmesh slot map hash"); - } - else { - BLI_assert(slot->data.ghash); - } - - BLI_ghash_insert(slot->data.ghash, (void *)element, mapping); + BLI_ghash_insert(slot->data.ghash, (void *)element, (void *)data); } #if 0 @@ -707,11 +725,11 @@ void BMO_slot_map_to_flag(BMesh *bm, BMOpSlot slot_args[BMO_OP_MAX_SLOTS], const BLI_assert(slot->slot_type == BMO_OP_SLOT_MAPPING); - /* sanity check */ - if (!slot->data.ghash) return; - BLI_ghashIterator_init(&it, slot->data.ghash); - for ( ; (ele_f = BLI_ghashIterator_getKey(&it)); BLI_ghashIterator_step(&it)) { + for (BLI_ghashIterator_init(&it, slot->data.ghash); + (ele_f = BLI_ghashIterator_getKey(&it)); + BLI_ghashIterator_step(&it)) + { if (ele_f->head.htype & htype) { BMO_elem_flag_enable(bm, ele_f, oflag); } @@ -1360,12 +1378,7 @@ void *BMO_iter_new(BMOIter *iter, iter->restrictmask = restrictmask; if (iter->slot->slot_type == BMO_OP_SLOT_MAPPING) { - if (iter->slot->data.ghash) { - BLI_ghashIterator_init(&iter->giter, slot->data.ghash); - } - else { - return NULL; - } + BLI_ghashIterator_init(&iter->giter, slot->data.ghash); } else if (iter->slot->slot_type == BMO_OP_SLOT_ELEMENT_BUF) { BLI_assert(restrictmask & slot->slot_subtype.elem); @@ -1402,11 +1415,8 @@ void *BMO_iter_step(BMOIter *iter) return ele; } else if (slot->slot_type == BMO_OP_SLOT_MAPPING) { - BMOElemMapping *map; void *ret = BLI_ghashIterator_getKey(&iter->giter); - map = BLI_ghashIterator_getValue(&iter->giter); - - iter->val = BMO_OP_SLOT_MAPPING_DATA(map); + iter->val = BLI_ghashIterator_getValue_p(&iter->giter); BLI_ghashIterator_step(&iter->giter); @@ -1420,19 +1430,40 @@ void *BMO_iter_step(BMOIter *iter) } /* used for iterating over mappings */ -void *BMO_iter_map_value(BMOIter *iter) + +/** + * Returns a pointer to the key-value when iterating over mappings. + * remember for pointer maps this will be a pointer to a pointer. + */ +void **BMO_iter_map_value_p(BMOIter *iter) { return iter->val; } -void *BMO_iter_map_value_p(BMOIter *iter) +void *BMO_iter_map_value_ptr(BMOIter *iter) +{ + BLI_assert(ELEM(iter->slot->slot_subtype.map, + BMO_OP_SLOT_SUBTYPE_MAP_ELEM, BMO_OP_SLOT_SUBTYPE_MAP_INTERNAL)); + return iter->val ? *iter->val : NULL; +} + + +float BMO_iter_map_value_float(BMOIter *iter) +{ + BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_FLT); + return **((float **)iter->val); +} + +int BMO_iter_map_value_int(BMOIter *iter) { - return *((void **)iter->val); + BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_INT); + return **((int **)iter->val); } -float BMO_iter_map_value_f(BMOIter *iter) +bool BMO_iter_map_value_bool(BMOIter *iter) { - return *((float *)iter->val); + BLI_assert(iter->slot->slot_subtype.map == BMO_OP_SLOT_SUBTYPE_MAP_BOOL); + return **((int **)iter->val); } /* error system */ diff --git a/source/blender/bmesh/intern/bmesh_operators_private.h b/source/blender/bmesh/intern/bmesh_operators_private.h index 33c10411c0f..07d0ceb3aa3 100644 --- a/source/blender/bmesh/intern/bmesh_operators_private.h +++ b/source/blender/bmesh/intern/bmesh_operators_private.h @@ -35,6 +35,7 @@ void bmo_average_vert_facedata_exec(BMesh *bm, BMOperator *op); void bmo_beautify_fill_exec(BMesh *bm, BMOperator *op); void bmo_bevel_exec(BMesh *bm, BMOperator *op); void bmo_bisect_edges_exec(BMesh *bm, BMOperator *op); +void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op); void bmo_bmesh_to_mesh_exec(BMesh *bm, BMOperator *op); void bmo_bridge_loops_exec(BMesh *bm, BMOperator *op); void bmo_collapse_exec(BMesh *bm, BMOperator *op); @@ -59,6 +60,7 @@ void bmo_dissolve_limit_exec(BMesh *bm, BMOperator *op); void bmo_dissolve_verts_exec(BMesh *bm, BMOperator *op); void bmo_duplicate_exec(BMesh *bm, BMOperator *op); void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op); +void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op); void bmo_holes_fill_exec(BMesh *bm, BMOperator *op); void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op); void bmo_edgenet_prepare_exec(BMesh *bm, BMOperator *op); diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 43b261c118d..a82d3d07712 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -875,7 +875,7 @@ static BMLoop *poly_find_ear(BMFace *f, float (*projectverts)[2], const bool use i++; } while ((l_iter = l_iter->next) != l_first); - /* pick 0/1 based on best lenth */ + /* pick 0/1 based on best length */ /* XXX Can't only rely on such test, also must check we do not get (too much) degenerated triangles!!! */ i = (((len_squared_v3v3(larr[0]->v->co, larr[2]->v->co) > len_squared_v3v3(larr[1]->v->co, larr[3]->v->co) * bias)) != use_beauty); @@ -1203,3 +1203,37 @@ void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) r_verts[2] = l->v; l = l->next; r_verts[3] = l->v; } + + +/** + * Small utility functions for fast access + * + * faster alternative to: + * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 3); + */ +void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) +{ + BMLoop *l = BM_FACE_FIRST_LOOP(f); + + BLI_assert(f->len == 3); + + r_loops[0] = l; l = l->next; + r_loops[1] = l; l = l->next; + r_loops[2] = l; +} + +/** + * faster alternative to: + * BM_iter_as_array(bm, BM_LOOPS_OF_FACE, f, (void **)l, 4); + */ +void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) +{ + BMLoop *l = BM_FACE_FIRST_LOOP(f); + + BLI_assert(f->len == 4); + + r_loops[0] = l; l = l->next; + r_loops[1] = l; l = l->next; + r_loops[2] = l; l = l->next; + r_loops[3] = l; +} diff --git a/source/blender/bmesh/intern/bmesh_polygon.h b/source/blender/bmesh/intern/bmesh_polygon.h index e5dc5c081c3..14fe1e76360 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.h +++ b/source/blender/bmesh/intern/bmesh_polygon.h @@ -27,40 +27,40 @@ * \ingroup bmesh */ -int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*r_index)[3]) -#ifdef __GNUC__ - __attribute__((warn_unused_result)) - __attribute__((nonnull)) -#endif -; -void BM_face_calc_normal(const BMFace *f, float r_no[3]); +#include "BLI_compiler_attrs.h" + +int BM_face_calc_tessellation(const BMFace *f, BMLoop **r_loops, int (*r_index)[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BM_face_calc_normal(const BMFace *f, float r_no[3]) ATTR_NONNULL(); void BM_face_calc_normal_vcos(BMesh *bm, BMFace *f, float r_no[3], - float const (*vertexCos)[3]); -float BM_face_calc_area(BMFace *f); -float BM_face_calc_perimeter(BMFace *f); -void BM_face_calc_plane(BMFace *f, float r_plane[3]); -void BM_face_calc_center_bounds(BMFace *f, float center[3]); -void BM_face_calc_center_mean(BMFace *f, float center[3]); + float const (*vertexCos)[3]) ATTR_NONNULL(); +float BM_face_calc_area(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +float BM_face_calc_perimeter(BMFace *f) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void BM_face_calc_plane(BMFace *f, float r_plane[3]) ATTR_NONNULL(); +void BM_face_calc_center_bounds(BMFace *f, float center[3]) ATTR_NONNULL(); +void BM_face_calc_center_mean(BMFace *f, float center[3]) ATTR_NONNULL(); void BM_face_calc_center_mean_vcos(BMesh *bm, BMFace *f, float r_cent[3], - float const (*vertexCos)[3]); -void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]); + float const (*vertexCos)[3]) ATTR_NONNULL(); +void BM_face_calc_center_mean_weighted(BMFace *f, float center[3]) ATTR_NONNULL(); -void BM_face_normal_update(BMFace *f); +void BM_face_normal_update(BMFace *f) ATTR_NONNULL(); -void BM_edge_normals_update(BMEdge *e); +void BM_edge_normals_update(BMEdge *e) ATTR_NONNULL(); -void BM_vert_normal_update(BMVert *v); -void BM_vert_normal_update_all(BMVert *v); +void BM_vert_normal_update(BMVert *v) ATTR_NONNULL(); +void BM_vert_normal_update_all(BMVert *v) ATTR_NONNULL(); -void BM_face_normal_flip(BMesh *bm, BMFace *f); -bool BM_face_point_inside_test(BMFace *f, const float co[3]); +void BM_face_normal_flip(BMesh *bm, BMFace *f) ATTR_NONNULL(); +bool BM_face_point_inside_test(BMFace *f, const float co[3]) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void BM_face_triangulate(BMesh *bm, BMFace *f, BMFace **newfaces, - const bool use_beauty, const bool use_tag); + const bool use_beauty, const bool use_tag) ATTR_NONNULL(1, 2); + +void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len) ATTR_NONNULL(); -void BM_face_legal_splits(BMFace *f, BMLoop *(*loops)[2], int len); +void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]) ATTR_NONNULL(); +void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]) ATTR_NONNULL(); -void BM_face_as_array_vert_tri(BMFace *f, BMVert *r_verts[3]); -void BM_face_as_array_vert_quad(BMFace *f, BMVert *r_verts[4]); +void BM_face_as_array_loop_tri(BMFace *f, BMLoop *r_loops[3]) ATTR_NONNULL(); +void BM_face_as_array_loop_quad(BMFace *f, BMLoop *r_loops[4]) ATTR_NONNULL(); #endif /* __BMESH_POLYGON_H__ */ diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 20769872012..9b4f34d18f2 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -992,6 +992,25 @@ BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2) } /** + * \brief Return the Loop Shared by Edge and Vert + * + * Finds the loop used which uses \a in face loop \a l + * + * \note this function takes a loop rather then an edge + * so we can select the face that the loop should be from. + */ +BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v) +{ + BLI_assert(BM_vert_in_edge(l->e, v)); + if (l->v == v) { + return l; + } + else { + return l->next; + } +} + +/** * \brief Return the Loop Shared by Face and Vertex * * Finds the loop used which uses \a v in face loop \a l @@ -1714,14 +1733,14 @@ bool BM_face_exists_overlap(BMVert **varr, const int len, BMFace **r_f_overlap) #ifdef DEBUG /* check flag isn't already set */ - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0); } } #endif - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { if (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0) { if (len <= BM_verts_in_face_count(f, varr, len)) { @@ -1764,7 +1783,7 @@ bool BM_face_exists_overlap_subset(BMVert **varr, const int len) #ifdef DEBUG /* check flag isn't already set */ - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { BLI_assert(BM_ELEM_API_FLAG_TEST(varr[i], _FLAG_OVERLAP) == 0); BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { BLI_assert(BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0); @@ -1772,7 +1791,7 @@ bool BM_face_exists_overlap_subset(BMVert **varr, const int len) } #endif - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { BM_ITER_ELEM (f, &viter, varr[i], BM_FACES_OF_VERT) { if ((f->len <= len) && (BM_ELEM_API_FLAG_TEST(f, _FLAG_OVERLAP) == 0)) { /* check if all vers in this face are flagged*/ @@ -1780,7 +1799,7 @@ bool BM_face_exists_overlap_subset(BMVert **varr, const int len) if (is_init == false) { is_init = true; - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { BM_ELEM_API_FLAG_ENABLE(varr[i], _FLAG_OVERLAP); } } @@ -1805,7 +1824,7 @@ bool BM_face_exists_overlap_subset(BMVert **varr, const int len) } if (is_init == true) { - for(i = 0; i < len; i++) { + for (i = 0; i < len; i++) { BM_ELEM_API_FLAG_DISABLE(varr[i], _FLAG_OVERLAP); } } diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 38d30b2d005..16c8875dce3 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -108,6 +108,7 @@ bool BM_edge_share_quad_check(BMEdge *e1, BMEdge *e2); bool BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); +BMLoop *BM_edge_vert_share_loop(BMLoop *l, BMVert *v); BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v); BMLoop *BM_face_edge_share_loop(BMFace *f, BMEdge *e); diff --git a/source/blender/bmesh/intern/bmesh_walkers.c b/source/blender/bmesh/intern/bmesh_walkers.c index 80b85ab6edd..af901b3359c 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.c +++ b/source/blender/bmesh/intern/bmesh_walkers.c @@ -87,8 +87,8 @@ void BMW_init(BMWalker *walker, BMesh *bm, int type, walker->mask_edge = mask_edge; walker->mask_face = mask_face; - walker->visithash = BLI_ghash_ptr_new("bmesh walkers 1"); - walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers sec 1"); + walker->visit_set = BLI_gset_ptr_new("bmesh walkers"); + walker->visit_set_alt = BLI_gset_ptr_new("bmesh walkers sec"); if (UNLIKELY(type >= BMW_MAXWALKERS || type < 0)) { fprintf(stderr, @@ -127,8 +127,8 @@ void BMW_init(BMWalker *walker, BMesh *bm, int type, void BMW_end(BMWalker *walker) { BLI_mempool_destroy(walker->worklist); - BLI_ghash_free(walker->visithash, NULL, NULL); - BLI_ghash_free(walker->secvisithash, NULL, NULL); + BLI_gset_free(walker->visit_set, NULL); + BLI_gset_free(walker->visit_set_alt, NULL); } @@ -253,8 +253,6 @@ void BMW_reset(BMWalker *walker) BMW_state_remove(walker); } walker->depth = 0; - BLI_ghash_free(walker->visithash, NULL, NULL); - BLI_ghash_free(walker->secvisithash, NULL, NULL); - walker->visithash = BLI_ghash_ptr_new("bmesh walkers 1"); - walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers sec 1"); + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_clear(walker->visit_set_alt, NULL); } diff --git a/source/blender/bmesh/intern/bmesh_walkers.h b/source/blender/bmesh/intern/bmesh_walkers.h index 8be362b5afa..ea1dbc61cc6 100644 --- a/source/blender/bmesh/intern/bmesh_walkers.h +++ b/source/blender/bmesh/intern/bmesh_walkers.h @@ -67,8 +67,8 @@ typedef struct BMWalker { BMWFlag flag; - GHash *visithash; - GHash *secvisithash; + GSet *visit_set; + GSet *visit_set_alt; int depth; } BMWalker; diff --git a/source/blender/bmesh/intern/bmesh_walkers_impl.c b/source/blender/bmesh/intern/bmesh_walkers_impl.c index 6a8ce32991e..a68d9ccd2bc 100644 --- a/source/blender/bmesh/intern/bmesh_walkers_impl.c +++ b/source/blender/bmesh/intern/bmesh_walkers_impl.c @@ -85,7 +85,7 @@ static void bmw_ShellWalker_visitEdge(BMWalker *walker, BMEdge *e) { BMwShellWalker *shellWalk = NULL; - if (BLI_ghash_haskey(walker->visithash, e)) { + if (BLI_gset_haskey(walker->visit_set, e)) { return; } @@ -95,7 +95,7 @@ static void bmw_ShellWalker_visitEdge(BMWalker *walker, BMEdge *e) shellWalk = BMW_state_add(walker); shellWalk->curedge = e; - BLI_ghash_insert(walker->visithash, e, NULL); + BLI_gset_insert(walker->visit_set, e); } static void bmw_ShellWalker_begin(BMWalker *walker, void *data) @@ -167,8 +167,8 @@ static void *bmw_ShellWalker_step(BMWalker *walker) bool restrictpass = true; BMwShellWalker shellWalk = *((BMwShellWalker *)BMW_current_state(walker)); - if (!BLI_ghash_haskey(walker->visithash, shellWalk.base)) { - BLI_ghash_insert(walker->visithash, shellWalk.base, NULL); + if (!BLI_gset_haskey(walker->visit_set, shellWalk.base)) { + BLI_gset_insert(walker->visit_set, shellWalk.base); } BMW_state_remove(walker); @@ -177,7 +177,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker) /* find the next edge whose other vertex has not been visite */ curedge = shellWalk.curedge; do { - if (!BLI_ghash_haskey(walker->visithash, curedge)) { + if (!BLI_gset_haskey(walker->visit_set, curedge)) { if (!walker->restrictflag || (walker->restrictflag && BMO_elem_flag_test(walker->bm, curedge, walker->restrictflag))) { @@ -187,7 +187,7 @@ static void *bmw_ShellWalker_step(BMWalker *walker) /* push a new state onto the stac */ newState = BMW_state_add(walker); - BLI_ghash_insert(walker->visithash, curedge, NULL); + BLI_gset_insert(walker->visit_set, curedge); /* populate the new stat */ @@ -211,7 +211,7 @@ static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v) { BMwConnectedVertexWalker *vwalk; - if (BLI_ghash_haskey(walker->visithash, v)) { + if (BLI_gset_haskey(walker->visit_set, v)) { /* already visited */ return; } @@ -223,7 +223,7 @@ static void bmw_ConnectedVertexWalker_visitVertex(BMWalker *walker, BMVert *v) vwalk = BMW_state_add(walker); vwalk->curvert = v; - BLI_ghash_insert(walker->visithash, v, NULL); + BLI_gset_insert(walker->visit_set, v); } static void bmw_ConnectedVertexWalker_begin(BMWalker *walker, void *data) @@ -251,7 +251,7 @@ static void *bmw_ConnectedVertexWalker_step(BMWalker *walker) BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { v2 = BM_edge_other_vert(e, v); - if (!BLI_ghash_haskey(walker->visithash, v2)) { + if (!BLI_gset_haskey(walker->visit_set, v2)) { bmw_ConnectedVertexWalker_visitVertex(walker, v2); } } @@ -276,7 +276,7 @@ static void bmw_IslandboundWalker_begin(BMWalker *walker, void *data) iwalk->base = iwalk->curloop = l; iwalk->lastv = l->v; - BLI_ghash_insert(walker->visithash, data, NULL); + BLI_gset_insert(walker->visit_set, data); } @@ -334,11 +334,11 @@ static void *bmw_IslandboundWalker_step(BMWalker *walker) if (l == owalk.curloop) { return NULL; } - else if (BLI_ghash_haskey(walker->visithash, l)) { + else if (BLI_gset_haskey(walker->visit_set, l)) { return owalk.curloop; } - BLI_ghash_insert(walker->visithash, l, NULL); + BLI_gset_insert(walker->visit_set, l); iwalk = BMW_state_add(walker); iwalk->base = owalk.base; @@ -367,7 +367,7 @@ static void bmw_IslandWalker_begin(BMWalker *walker, void *data) } iwalk = BMW_state_add(walker); - BLI_ghash_insert(walker->visithash, data, NULL); + BLI_gset_insert(walker->visit_set, data); iwalk->cur = data; } @@ -403,18 +403,18 @@ static void *bmw_IslandWalker_step(BMWalker *walker) continue; } - /* saves checking BLI_ghash_haskey below (manifold edges theres a 50% chance) */ + /* saves checking BLI_gset_haskey below (manifold edges theres a 50% chance) */ if (f == iwalk->cur) { continue; } - if (BLI_ghash_haskey(walker->visithash, f)) { + if (BLI_gset_haskey(walker->visit_set, f)) { continue; } iwalk = BMW_state_add(walker); iwalk->cur = f; - BLI_ghash_insert(walker->visithash, f, NULL); + BLI_gset_insert(walker->visit_set, f); break; } } @@ -448,7 +448,7 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data) v = e->v1; lwalk = BMW_state_add(walker); - BLI_ghash_insert(walker->visithash, e, NULL); + BLI_gset_insert(walker->visit_set, e); lwalk->cur = lwalk->start = e; lwalk->lastv = lwalk->startv = v; @@ -494,9 +494,8 @@ static void bmw_LoopWalker_begin(BMWalker *walker, void *data) lwalk->lastv = lwalk->startv = BM_edge_other_vert(owalk.cur, lwalk->lastv); - BLI_ghash_free(walker->visithash, NULL, NULL); - walker->visithash = BLI_ghash_ptr_new("bmesh walkers 2"); - BLI_ghash_insert(walker->visithash, owalk.cur, NULL); + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_insert(walker->visit_set, owalk.cur); } static void *bmw_LoopWalker_yield(BMWalker *walker) @@ -531,7 +530,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) nexte = BM_edge_exists(v, l->v); if (bmw_mask_check_edge(walker, nexte) && - !BLI_ghash_haskey(walker->visithash, nexte) && + !BLI_gset_haskey(walker->visit_set, nexte) && /* never step onto a boundary edge, this gives odd-results */ (BM_edge_is_boundary(nexte) == false)) { @@ -543,7 +542,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) lwalk->is_single = owalk.is_single; lwalk->f_hub = owalk.f_hub; - BLI_ghash_insert(walker->visithash, nexte, NULL); + BLI_gset_insert(walker->visit_set, nexte); } } } @@ -557,7 +556,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) BM_ITER_ELEM (nexte, &eiter, v, BM_EDGES_OF_VERT) { if ((nexte->l == NULL) && bmw_mask_check_edge(walker, nexte) && - !BLI_ghash_haskey(walker->visithash, nexte)) + !BLI_gset_haskey(walker->visit_set, nexte)) { lwalk = BMW_state_add(walker); lwalk->cur = nexte; @@ -567,7 +566,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) lwalk->is_single = owalk.is_single; lwalk->f_hub = owalk.f_hub; - BLI_ghash_insert(walker->visithash, nexte, NULL); + BLI_gset_insert(walker->visit_set, nexte); } } } @@ -602,7 +601,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) if (l != NULL) { if (l != e->l && bmw_mask_check_edge(walker, l->e) && - !BLI_ghash_haskey(walker->visithash, l->e)) + !BLI_gset_haskey(walker->visit_set, l->e)) { lwalk = BMW_state_add(walker); lwalk->cur = l->e; @@ -612,7 +611,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) lwalk->is_single = owalk.is_single; lwalk->f_hub = owalk.f_hub; - BLI_ghash_insert(walker->visithash, l->e, NULL); + BLI_gset_insert(walker->visit_set, l->e); } } } @@ -655,7 +654,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) if (l != NULL) { if (l != e->l && bmw_mask_check_edge(walker, l->e) && - !BLI_ghash_haskey(walker->visithash, l->e)) + !BLI_gset_haskey(walker->visit_set, l->e)) { lwalk = BMW_state_add(walker); lwalk->cur = l->e; @@ -665,7 +664,7 @@ static void *bmw_LoopWalker_step(BMWalker *walker) lwalk->is_single = owalk.is_single; lwalk->f_hub = owalk.f_hub; - BLI_ghash_insert(walker->visithash, l->e, NULL); + BLI_gset_insert(walker->visit_set, l->e); } } } @@ -694,8 +693,8 @@ static bool bmw_FaceLoopWalker_include_face(BMWalker *walker, BMLoop *l) return false; } - /* the face must not have been already visite */ - if (BLI_ghash_haskey(walker->visithash, l->f) && BLI_ghash_haskey(walker->secvisithash, l->e)) { + /* the face must not have been already visited */ + if (BLI_gset_haskey(walker->visit_set, l->f) && BLI_gset_haskey(walker->visit_set_alt, l->e)) { return false; } @@ -739,9 +738,9 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) lwalk = BMW_state_add(walker); lwalk->l = e->l; lwalk->no_calc = false; - BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL); + BLI_gset_insert(walker->visit_set, lwalk->l->f); - /* rewin */ + /* rewind */ while ((owalk_pt = BMW_current_state(walker))) { owalk = *((BMwFaceLoopWalker *)owalk_pt); BMW_walk(walker); @@ -751,13 +750,11 @@ static void bmw_FaceLoopWalker_begin(BMWalker *walker, void *data) *lwalk = owalk; lwalk->no_calc = false; - BLI_ghash_free(walker->secvisithash, NULL, NULL); - walker->secvisithash = BLI_ghash_ptr_new("bmesh walkers 3"); - BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL); + BLI_gset_clear(walker->visit_set_alt, NULL); + BLI_gset_insert(walker->visit_set_alt, lwalk->l->e); - BLI_ghash_free(walker->visithash, NULL, NULL); - walker->visithash = BLI_ghash_ptr_new("bmesh walkers 3"); - BLI_ghash_insert(walker->visithash, lwalk->l->f, NULL); + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_insert(walker->visit_set, lwalk->l->f); } static void *bmw_FaceLoopWalker_yield(BMWalker *walker) @@ -806,8 +803,9 @@ static void *bmw_FaceLoopWalker_step(BMWalker *walker) lwalk->no_calc = false; } - BLI_ghash_insert(walker->secvisithash, l->e, NULL); - BLI_ghash_insert(walker->visithash, l->f, NULL); + /* both may already exist */ + BLI_gset_reinsert(walker->visit_set_alt, l->e, NULL); + BLI_gset_reinsert(walker->visit_set, l->f, NULL); } return f; @@ -838,7 +836,7 @@ static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data) lwalk->wireedge = NULL; } - BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL); + BLI_gset_insert(walker->visit_set, lwalk->l->e); /* rewind */ while ((owalk_pt = BMW_current_state(walker))) { @@ -858,9 +856,8 @@ static void bmw_EdgeringWalker_begin(BMWalker *walker, void *data) lwalk->l = lwalk->l->radial_next; } - BLI_ghash_free(walker->visithash, NULL, NULL); - walker->visithash = BLI_ghash_ptr_new("bmesh walkers 4"); - BLI_ghash_insert(walker->visithash, lwalk->l->e, NULL); + BLI_gset_clear(walker->visit_set, NULL); + BLI_gset_insert(walker->visit_set, lwalk->l->e); } static void *bmw_EdgeringWalker_yield(BMWalker *walker) @@ -925,7 +922,7 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) } /* only walk to manifold edge */ if ((l->f->len % 2 == 0) && EDGE_CHECK(l->e) && - !BLI_ghash_haskey(walker->visithash, l->e)) + !BLI_gset_haskey(walker->visit_set, l->e)) #else @@ -937,14 +934,14 @@ static void *bmw_EdgeringWalker_step(BMWalker *walker) } /* only walk to manifold edge */ if ((l->f->len == 4) && EDGE_CHECK(l->e) && - !BLI_ghash_haskey(walker->visithash, l->e)) + !BLI_gset_haskey(walker->visit_set, l->e)) #endif { lwalk = BMW_state_add(walker); lwalk->l = l; lwalk->wireedge = NULL; - BLI_ghash_insert(walker->visithash, l->e, NULL); + BLI_gset_insert(walker->visit_set, l->e); } return e; @@ -957,12 +954,12 @@ static void bmw_UVEdgeWalker_begin(BMWalker *walker, void *data) BMwUVEdgeWalker *lwalk; BMLoop *l = data; - if (BLI_ghash_haskey(walker->visithash, l)) + if (BLI_gset_haskey(walker->visit_set, l)) return; lwalk = BMW_state_add(walker); lwalk->l = l; - BLI_ghash_insert(walker->visithash, l, NULL); + BLI_gset_insert(walker->visit_set, l); } static void *bmw_UVEdgeWalker_yield(BMWalker *walker) @@ -1004,7 +1001,7 @@ static void *bmw_UVEdgeWalker_step(BMWalker *walker) rlen = BM_edge_face_count(l2->e); for (j = 0; j < rlen; j++) { - if (BLI_ghash_haskey(walker->visithash, l2)) { + if (BLI_gset_haskey(walker->visit_set, l2)) { continue; } @@ -1022,7 +1019,7 @@ static void *bmw_UVEdgeWalker_step(BMWalker *walker) continue; lwalk = BMW_state_add(walker); - BLI_ghash_insert(walker->visithash, l2, NULL); + BLI_gset_insert(walker->visit_set, l2); lwalk->l = l2; diff --git a/source/blender/bmesh/operators/bmo_beautify.c b/source/blender/bmesh/operators/bmo_beautify.c index 22b686db64e..a6d781c2066 100644 --- a/source/blender/bmesh/operators/bmo_beautify.c +++ b/source/blender/bmesh/operators/bmo_beautify.c @@ -28,7 +28,7 @@ * * In principle this is very simple however there is the possibility of * going into an eternal loop where edges keep rotating. - * To avoid this - each edge stores a hash of it previous + * To avoid this - each edge stores a set of it previous * states so as not to rotate back. * * TODO @@ -47,6 +47,7 @@ #ifdef DEBUG_TIME # include "PIL_time.h" +# include "PIL_time_utildefines.h" #endif enum { @@ -54,14 +55,14 @@ enum { }; /* -------------------------------------------------------------------- */ -/* GHash for edge rotation */ +/* GSet for edge rotation */ typedef struct EdRotState { int v1, v2; /* edge vert, small -> large */ int f1, f2; /* face vert, small -> large */ } EdRotState; -static unsigned int erot_ghashutil_hash(const void *ptr) +static unsigned int erot_gsetutil_hash(const void *ptr) { const EdRotState *e_state = (const EdRotState *)ptr; unsigned int @@ -71,7 +72,7 @@ static unsigned int erot_ghashutil_hash(const void *ptr) hash ^= BLI_ghashutil_inthash(SET_INT_IN_POINTER(e_state->f2)); return hash; } -static int erot_ghashutil_cmp(const void *a, const void *b) +static int erot_gsetutil_cmp(const void *a, const void *b) { const EdRotState *e_state_a = (const EdRotState *)a; const EdRotState *e_state_b = (const EdRotState *)b; @@ -86,9 +87,9 @@ static int erot_ghashutil_cmp(const void *a, const void *b) else return 0; } -static GHash *erot_ghash_new(void) +static GSet *erot_gset_new(void) { - return BLI_ghash_new(erot_ghashutil_hash, erot_ghashutil_cmp, __func__); + return BLI_gset_new(erot_gsetutil_hash, erot_gsetutil_cmp, __func__); } /* ensure v0 is smaller */ @@ -236,12 +237,12 @@ static float bm_edge_calc_rotate_beauty(const BMEdge *e, const int flag) /* Update the edge cost of rotation in the heap */ /* recalc an edge in the heap (surrounding geometry has changed) */ -static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GHash **edge_state_arr, +static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, const int flag) { if (BM_elem_flag_test(e, BM_ELEM_TAG)) { const int i = BM_elem_index_get(e); - GHash *e_state_hash = edge_state_arr[i]; + GSet *e_state_set = edge_state_arr[i]; if (eheap_table[i]) { BLI_heap_remove(eheap, eheap_table[i]); @@ -254,10 +255,10 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode * // BMO_elem_flag_test(bm, e->l->radial_next->f, FACE_MARK)); /* check we're not moving back into a state we have been in before */ - if (e_state_hash != NULL) { + if (e_state_set != NULL) { EdRotState e_state_alt; erot_state_alternate(e, &e_state_alt); - if (BLI_ghash_haskey(e_state_hash, (void *)&e_state_alt)) { + if (BLI_gset_haskey(e_state_set, (void *)&e_state_alt)) { // printf(" skipping, we already have this state\n"); return; } @@ -277,7 +278,7 @@ static void bm_edge_update_beauty_cost_single(BMEdge *e, Heap *eheap, HeapNode * } /* we have rotated an edge, tag other edges and clear this one */ -static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GHash **edge_state_arr, +static void bm_edge_update_beauty_cost(BMEdge *e, Heap *eheap, HeapNode **eheap_table, GSet **edge_state_arr, const int flag) { BMLoop *l; @@ -308,7 +309,7 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge Heap *eheap; /* edge heap */ HeapNode **eheap_table; /* edge index aligned table pointing to the eheap */ - GHash **edge_state_arr = MEM_callocN(edge_array_len * sizeof(GHash *), __func__); + GSet **edge_state_arr = MEM_callocN(edge_array_len * sizeof(GSet *), __func__); BLI_mempool *edge_state_pool = BLI_mempool_create(sizeof(EdRotState), 512, 512, BLI_MEMPOOL_SYSMALLOC); int i; @@ -338,18 +339,18 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge e = BM_edge_rotate(bm, e, false, BM_EDGEROT_CHECK_EXISTS); if (LIKELY(e)) { - GHash *e_state_hash = edge_state_arr[i]; + GSet *e_state_set = edge_state_arr[i]; - /* add the new state into the hash so we don't move into this state again + /* add the new state into the set so we don't move into this state again * note: we could add the previous state too but this isn't essential) * for avoiding eternal loops */ EdRotState *e_state = BLI_mempool_alloc(edge_state_pool); erot_state_current(e, e_state); - if (UNLIKELY(e_state_hash == NULL)) { - edge_state_arr[i] = e_state_hash = erot_ghash_new(); /* store previous state */ + if (UNLIKELY(e_state_set == NULL)) { + edge_state_arr[i] = e_state_set = erot_gset_new(); /* store previous state */ } - BLI_assert(BLI_ghash_haskey(e_state_hash, (void *)e_state) == false); - BLI_ghash_insert(e_state_hash, e_state, NULL); + BLI_assert(BLI_gset_haskey(e_state_set, (void *)e_state) == false); + BLI_gset_insert(e_state_set, e_state); // printf(" %d -> %d, %d\n", i, BM_elem_index_get(e->v1), BM_elem_index_get(e->v2)); @@ -373,7 +374,7 @@ static void bm_mesh_beautify_fill(BMesh *bm, BMEdge **edge_array, const int edge for (i = 0; i < edge_array_len; i++) { if (edge_state_arr[i]) { - BLI_ghash_free(edge_state_arr[i], NULL, NULL); + BLI_gset_free(edge_state_arr[i], NULL); } } diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index dc06b0b4f13..eef470e0d85 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -29,6 +29,7 @@ #include "BLI_utildefines.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "intern/bmesh_operators_private.h" /* own include */ diff --git a/source/blender/bmesh/operators/bmo_bisect_plane.c b/source/blender/bmesh/operators/bmo_bisect_plane.c new file mode 100644 index 00000000000..74cb9d67e88 --- /dev/null +++ b/source/blender/bmesh/operators/bmo_bisect_plane.c @@ -0,0 +1,112 @@ +/* + * ***** 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): + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/bmesh/operators/bmo_bisect_plane.c + * \ingroup bmesh + * + * Wrapper around #BM_mesh_bisect_plane + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "bmesh.h" +#include "bmesh_tools.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +#define ELE_NEW 1 +#define ELE_INPUT 2 + +void bmo_bisect_plane_exec(BMesh *bm, BMOperator *op) +{ + const float dist = BMO_slot_float_get(op->slots_in, "dist"); + const bool use_snap_center = BMO_slot_bool_get(op->slots_in, "use_snap_center"); + const bool clear_outer = BMO_slot_bool_get(op->slots_in, "clear_outer"); + const bool clear_inner = BMO_slot_bool_get(op->slots_in, "clear_inner"); + + float plane_co[3]; + float plane_no[3]; + float plane[4]; + + BMO_slot_vec_get(op->slots_in, "plane_co", plane_co); + BMO_slot_vec_get(op->slots_in, "plane_no", plane_no); + + if (is_zero_v3(plane_no)) { + BMO_error_raise(bm, op, BMERR_MESH_ERROR, "Zero normal given"); + return; + } + + plane_from_point_normal_v3(plane, plane_co, plane_no); + + /* tag geometry to bisect */ + BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "geom", BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + + BMO_slot_buffer_flag_enable(bm, op->slots_in, "geom", BM_ALL_NOLOOP, ELE_INPUT); + + + BM_mesh_bisect_plane(bm, plane, use_snap_center, true, + ELE_NEW, dist); + + + if (clear_outer || clear_inner) { + /* Use an array of vertices because 'geom' contains both vers and edges that may use them. + * Removing a vert may remove and edge which is later checked by BMO_ITER. + * over-alloc the total possible vert count */ + const int vert_arr_max = min_ii(bm->totvert, BMO_slot_buffer_count(op->slots_in, "geom")); + BMVert **vert_arr = MEM_mallocN(sizeof(*vert_arr) * (size_t)vert_arr_max, __func__); + BMOIter siter; + BMVert *v; + float plane_inner[4]; + float plane_outer[4]; + + STACK_DECLARE(vert_arr); + + copy_v3_v3(plane_outer, plane); + copy_v3_v3(plane_inner, plane); + plane_outer[3] = plane[3] - dist; + plane_inner[3] = plane[3] + dist; + + STACK_INIT(vert_arr); + + BMO_ITER (v, &siter, op->slots_in, "geom", BM_VERT) { + if ((clear_outer && plane_point_side_v3(plane_outer, v->co) > 0.0f) || + (clear_inner && plane_point_side_v3(plane_inner, v->co) < 0.0f)) + { + STACK_PUSH(vert_arr, v); + } + } + + while ((v = STACK_POP(vert_arr))) { + BM_vert_kill(bm, v); + } + + STACK_FREE(vert_arr); + MEM_freeN(vert_arr); + } + + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_NEW | ELE_INPUT); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom_cut.out", BM_VERT | BM_EDGE, ELE_NEW); +} diff --git a/source/blender/bmesh/operators/bmo_bridge.c b/source/blender/bmesh/operators/bmo_bridge.c index f63e742d8ba..f4bb73f87ea 100644 --- a/source/blender/bmesh/operators/bmo_bridge.c +++ b/source/blender/bmesh/operators/bmo_bridge.c @@ -121,7 +121,7 @@ static void bm_bridge_best_rotation(struct BMEdgeLoopStore *el_store_a, struct B } if (el_b_best) { - BLI_rotatelist(lb_b, el_b_best); + BLI_rotatelist_first(lb_b, el_b_best); } } @@ -273,9 +273,8 @@ static void bridge_loop_pair(BMesh *bm, if (twist_offset != 0) { const int len_b = BM_edgeloop_length_get(el_store_b); ListBase *lb_b = BM_edgeloop_verts_get(el_store_b); - const int offset = twist_offset % len_b; - LinkData *el_b = BLI_rfindlink(lb_b, (offset < 0) ? (offset + len_b) : offset); - BLI_rotatelist(lb_b, el_b); + LinkData *el_b = BLI_rfindlink(lb_b, mod_i(twist_offset, len_b)); + BLI_rotatelist_first(lb_b, el_b); } } @@ -343,7 +342,7 @@ static void bridge_loop_pair(BMesh *bm, BMVert *v_arr[4] = {v_a, v_b, v_b_next, v_a_next}; if (BM_face_exists(v_arr, 4, &f) == false) { /* copy if loop data if its is missing on one ring */ - f = BM_face_create_ngon_verts(bm, v_arr, 4, 0, false, true); + f = BM_face_create_verts(bm, v_arr, 4, NULL, BM_CREATE_NOP, true); l_iter = BM_FACE_FIRST_LOOP(f); if (l_b) BM_elem_attrs_copy(bm, bm, l_b, l_iter); l_iter = l_iter->next; @@ -356,7 +355,7 @@ static void bridge_loop_pair(BMesh *bm, BMVert *v_arr[3] = {v_a, v_b, v_a_next}; if (BM_face_exists(v_arr, 3, &f) == false) { /* fan-fill a triangle */ - f = BM_face_create_ngon_verts(bm, v_arr, 3, 0, false, true); + f = BM_face_create_verts(bm, v_arr, 3, NULL, BM_CREATE_NOP, true); l_iter = BM_FACE_FIRST_LOOP(f); if (l_b) BM_elem_attrs_copy(bm, bm, l_b, l_iter); l_iter = l_iter->next; diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index cce5c992d2a..dd814fa8bfb 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -153,8 +153,8 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &op_sub); BMO_op_initf(bm, &op_sub, op->flag, - "edgenet_fill edges=%fe mat_nr=%i use_smooth=%b", - ELE_NEW, mat_nr, use_smooth); + "edgenet_fill edges=%fe mat_nr=%i use_smooth=%b sides=%i", + ELE_NEW, mat_nr, use_smooth, 10000); BMO_op_exec(bm, &op_sub); @@ -182,7 +182,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) /* if we dissolved anything, then return */ if (BMO_slot_buffer_count(op_sub.slots_out, "region.out")) { BMO_slot_copy(&op_sub, slots_out, "region.out", - op, slots_out, "faces.out"); + op, slots_out, "faces.out"); BMO_op_finish(bm, &op_sub); return; } @@ -283,7 +283,7 @@ void bmo_contextual_create_exec(BMesh *bm, BMOperator *op) BMFace *f; BMO_iter_as_array(op->slots_in, "geom", BM_VERT, (void **)vert_arr, totv); - f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, BM_CREATE_NO_DOUBLE); + f = BM_face_create_ngon_vcloud(bm, vert_arr, totv, NULL, BM_CREATE_NO_DOUBLE); if (f) { BMO_elem_flag_enable(bm, f, ELE_OUT); diff --git a/source/blender/bmesh/operators/bmo_dissolve.c b/source/blender/bmesh/operators/bmo_dissolve.c index e038b6b9f05..d3c7a6864c3 100644 --- a/source/blender/bmesh/operators/bmo_dissolve.c +++ b/source/blender/bmesh/operators/bmo_dissolve.c @@ -32,6 +32,8 @@ #include "BLI_math.h" #include "bmesh.h" +#include "bmesh_tools.h" + #include "intern/bmesh_operators_private.h" diff --git a/source/blender/bmesh/operators/bmo_dupe.c b/source/blender/bmesh/operators/bmo_dupe.c index 1dc7b0a414d..bd2485b92fb 100644 --- a/source/blender/bmesh/operators/bmo_dupe.c +++ b/source/blender/bmesh/operators/bmo_dupe.c @@ -46,23 +46,27 @@ * * Copy an existing vertex from one bmesh to another. */ -static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *target_mesh, GHash *vhash) +static BMVert *bmo_vert_copy(BMOperator *op, + BMOpSlot *slot_vertmap_out, + BMesh *bm_dst, BMesh *bm_src, BMVert *v_src, GHash *vhash) { - BMVert *target_vertex = NULL; + BMVert *v_dst; /* Create a new vertex */ - target_vertex = BM_vert_create(target_mesh, source_vertex->co, NULL, BM_CREATE_SKIP_CD); - + v_dst = BM_vert_create(bm_dst, v_src->co, NULL, BM_CREATE_SKIP_CD); + BMO_slot_map_elem_insert(op, slot_vertmap_out, v_src, v_dst); + BMO_slot_map_elem_insert(op, slot_vertmap_out, v_dst, v_src); + /* Insert new vertex into the vert hash */ - BLI_ghash_insert(vhash, source_vertex, target_vertex); - + BLI_ghash_insert(vhash, v_src, v_dst); + /* Copy attributes */ - BM_elem_attrs_copy(source_mesh, target_mesh, source_vertex, target_vertex); - - /* Set internal op flags */ - BMO_elem_flag_enable(target_mesh, target_vertex, DUPE_NEW); + BM_elem_attrs_copy(bm_src, bm_dst, v_src, v_dst); + + /* Mark the vert for output */ + BMO_elem_flag_enable(bm_dst, v_dst, DUPE_NEW); - return target_vertex; + return v_dst; } /** @@ -70,55 +74,58 @@ static BMVert *copy_vertex(BMesh *source_mesh, BMVert *source_vertex, BMesh *tar * * Copy an existing edge from one bmesh to another. */ -static BMEdge *copy_edge(BMOperator *op, - BMOpSlot *slot_boundarymap_out, - BMesh *source_mesh, - BMEdge *source_edge, BMesh *target_mesh, - GHash *vhash, GHash *ehash) +static BMEdge *bmo_edge_copy(BMOperator *op, + BMOpSlot *slot_edgemap_out, + BMOpSlot *slot_boundarymap_out, + BMesh *bm_dst, BMesh *bm_src, + BMEdge *e_src, + GHash *vhash, GHash *ehash) { - BMEdge *target_edge = NULL; - BMVert *target_vert1, *target_vert2; - BMFace *face; - BMIter fiter; - int rlen; + BMEdge *e_dst; + BMVert *e_dst_v1, *e_dst_v2; + unsigned int rlen; /* see if any of the neighboring faces are * not being duplicated. in that case, * add it to the new/old map. */ + /* lookup edge */ rlen = 0; - for (face = BM_iter_new(&fiter, source_mesh, BM_FACES_OF_EDGE, source_edge); - face; - face = BM_iter_step(&fiter)) - { - if (BMO_elem_flag_test(source_mesh, face, DUPE_INPUT)) { - rlen++; - } + if (e_src->l) { + BMLoop *l_iter_src, *l_first_src; + l_iter_src = l_first_src = e_src->l; + do { + if (BMO_elem_flag_test(bm_src, l_iter_src->f, DUPE_INPUT)) { + rlen++; + } + } while ((l_iter_src = l_iter_src->radial_next) != l_first_src); } /* Lookup v1 and v2 */ - target_vert1 = BLI_ghash_lookup(vhash, source_edge->v1); - target_vert2 = BLI_ghash_lookup(vhash, source_edge->v2); + e_dst_v1 = BLI_ghash_lookup(vhash, e_src->v1); + e_dst_v2 = BLI_ghash_lookup(vhash, e_src->v2); /* Create a new edge */ - target_edge = BM_edge_create(target_mesh, target_vert1, target_vert2, NULL, BM_CREATE_SKIP_CD); - + e_dst = BM_edge_create(bm_dst, e_dst_v1, e_dst_v2, NULL, BM_CREATE_SKIP_CD); + BMO_slot_map_elem_insert(op, slot_edgemap_out, e_src, e_dst); + BMO_slot_map_elem_insert(op, slot_edgemap_out, e_dst, e_src); + /* add to new/old edge map if necassary */ if (rlen < 2) { /* not sure what non-manifold cases of greater then three * radial should do. */ - BMO_slot_map_elem_insert(op, slot_boundarymap_out, source_edge, target_edge); + BMO_slot_map_elem_insert(op, slot_boundarymap_out, e_src, e_dst); } /* Insert new edge into the edge hash */ - BLI_ghash_insert(ehash, source_edge, target_edge); - + BLI_ghash_insert(ehash, e_src, e_dst); + /* Copy attributes */ - BM_elem_attrs_copy(source_mesh, target_mesh, source_edge, target_edge); - - /* Set internal op flags */ - BMO_elem_flag_enable(target_mesh, target_edge, DUPE_NEW); + BM_elem_attrs_copy(bm_src, bm_dst, e_src, e_dst); + + /* Mark the edge for output */ + BMO_elem_flag_enable(bm_dst, e_dst, DUPE_NEW); - return target_edge; + return e_dst; } /** @@ -126,56 +133,49 @@ static BMEdge *copy_edge(BMOperator *op, * * Copy an existing face from one bmesh to another. */ -static BMFace *copy_face(BMOperator *op, - BMOpSlot *slot_facemap_out, - BMesh *source_mesh, - BMFace *source_face, BMesh *target_mesh, - GHash *vhash, GHash *ehash) +static BMFace *bmo_face_copy(BMOperator *op, + BMOpSlot *slot_facemap_out, + BMesh *bm_dst, BMesh *bm_src, + BMFace *f_src, + GHash *vhash, GHash *ehash) { - /* BMVert *target_vert1, *target_vert2; */ /* UNUSED */ - BMVert **vtar = BLI_array_alloca(vtar, source_face->len); - BMEdge **edar = BLI_array_alloca(edar, source_face->len); - BMLoop *source_loop, *target_loop; - BMFace *target_face = NULL; - BMIter iter, iter2; + BMFace *f_dst; + BMVert **vtar = BLI_array_alloca(vtar, f_src->len); + BMEdge **edar = BLI_array_alloca(edar, f_src->len); + BMLoop *l_iter_src, *l_iter_dst, *l_first_src; int i; - - /* lookup the first and second vert */ -#if 0 /* UNUSED */ - target_vert1 = BLI_ghash_lookup(vhash, BM_iter_new(&iter, source_mesh, BM_VERTS_OF_FACE, source_face)); - target_vert2 = BLI_ghash_lookup(vhash, BM_iter_step(&iter)); -#else - BM_iter_new(&iter, source_mesh, BM_VERTS_OF_FACE, source_face); - BM_iter_step(&iter); -#endif + + l_first_src = BM_FACE_FIRST_LOOP(f_src); /* lookup edge */ - BM_ITER_ELEM_INDEX (source_loop, &iter, source_face, BM_LOOPS_OF_FACE, i) { - vtar[i] = BLI_ghash_lookup(vhash, source_loop->v); - edar[i] = BLI_ghash_lookup(ehash, source_loop->e); - } + l_iter_src = l_first_src; + i = 0; + do { + vtar[i] = BLI_ghash_lookup(vhash, l_iter_src->v); + edar[i] = BLI_ghash_lookup(ehash, l_iter_src->e); + i++; + } while ((l_iter_src = l_iter_src->next) != l_first_src); /* create new face */ - target_face = BM_face_create(target_mesh, vtar, edar, source_face->len, BM_CREATE_SKIP_CD); - BMO_slot_map_elem_insert(op, slot_facemap_out, source_face, target_face); - BMO_slot_map_elem_insert(op, slot_facemap_out, target_face, source_face); - - BM_elem_attrs_copy(source_mesh, target_mesh, source_face, target_face); + f_dst = BM_face_create(bm_dst, vtar, edar, f_src->len, NULL, BM_CREATE_SKIP_CD); + BMO_slot_map_elem_insert(op, slot_facemap_out, f_src, f_dst); + BMO_slot_map_elem_insert(op, slot_facemap_out, f_dst, f_src); - /* mark the face for output */ - BMO_elem_flag_enable(target_mesh, target_face, DUPE_NEW); + /* Copy attributes */ + BM_elem_attrs_copy(bm_src, bm_dst, f_src, f_dst); /* copy per-loop custom data */ - BM_ITER_ELEM (source_loop, &iter, source_face, BM_LOOPS_OF_FACE) { - BM_ITER_ELEM (target_loop, &iter2, target_face, BM_LOOPS_OF_FACE) { - if (BLI_ghash_lookup(vhash, source_loop->v) == target_loop->v) { - BM_elem_attrs_copy(source_mesh, target_mesh, source_loop, target_loop); - break; - } - } - } + l_iter_src = l_first_src; + l_iter_dst = BM_FACE_FIRST_LOOP(f_dst); + do { + BM_elem_attrs_copy(bm_src, bm_dst, l_iter_src, l_iter_dst); + } while ((l_iter_dst = l_iter_dst->next), + (l_iter_src = l_iter_src->next) != l_first_src); + + /* Mark the face for output */ + BMO_elem_flag_enable(bm_dst, f_dst, DUPE_NEW); - return target_face; + return f_dst; } /** @@ -183,7 +183,7 @@ static BMFace *copy_face(BMOperator *op, * * Internal Copy function. */ -static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) +static void bmo_mesh_copy(BMOperator *op, BMesh *bm_dst, BMesh *bm_src) { BMVert *v = NULL, *v2; @@ -194,9 +194,12 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) GHash *vhash, *ehash; BMOpSlot *slot_boundary_map_out = BMO_slot_get(op->slots_out, "boundary_map.out"); - BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out"); BMOpSlot *slot_isovert_map_out = BMO_slot_get(op->slots_out, "isovert_map.out"); + BMOpSlot *slot_vert_map_out = BMO_slot_get(op->slots_out, "vert_map.out"); + BMOpSlot *slot_edge_map_out = BMO_slot_get(op->slots_out, "edge_map.out"); + BMOpSlot *slot_face_map_out = BMO_slot_get(op->slots_out, "face_map.out"); + /* initialize pointer hashes */ vhash = BLI_ghash_ptr_new("bmesh dupeops v"); ehash = BLI_ghash_ptr_new("bmesh dupeops e"); @@ -209,7 +212,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) BMIter iter; bool isolated = true; - v2 = copy_vertex(bm_src, v, bm_dst, vhash); + v2 = bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash); BM_ITER_ELEM (f, &iter, v, BM_FACES_OF_VERT) { if (BMO_elem_flag_test(bm_src, f, DUPE_INPUT)) { @@ -242,15 +245,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) { /* make sure that verts are copied */ if (!BMO_elem_flag_test(bm_src, e->v1, DUPE_DONE)) { - copy_vertex(bm_src, e->v1, bm_dst, vhash); + bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v1, vhash); BMO_elem_flag_enable(bm_src, e->v1, DUPE_DONE); } if (!BMO_elem_flag_test(bm_src, e->v2, DUPE_DONE)) { - copy_vertex(bm_src, e->v2, bm_dst, vhash); + bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, e->v2, vhash); BMO_elem_flag_enable(bm_src, e->v2, DUPE_DONE); } /* now copy the actual edge */ - copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); + bmo_edge_copy(op, slot_edge_map_out, slot_boundary_map_out, + bm_dst, bm_src, e, vhash, ehash); BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } @@ -261,7 +265,7 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) /* vertex pass */ BM_ITER_ELEM (v, &viter, f, BM_VERTS_OF_FACE) { if (!BMO_elem_flag_test(bm_src, v, DUPE_DONE)) { - copy_vertex(bm_src, v, bm_dst, vhash); + bmo_vert_copy(op, slot_vert_map_out, bm_dst, bm_src, v, vhash); BMO_elem_flag_enable(bm_src, v, DUPE_DONE); } } @@ -269,12 +273,13 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) /* edge pass */ BM_ITER_ELEM (e, &eiter, f, BM_EDGES_OF_FACE) { if (!BMO_elem_flag_test(bm_src, e, DUPE_DONE)) { - copy_edge(op, slot_boundary_map_out, bm_src, e, bm_dst, vhash, ehash); + bmo_edge_copy(op, slot_edge_map_out, slot_boundary_map_out, + bm_dst, bm_src, e, vhash, ehash); BMO_elem_flag_enable(bm_src, e, DUPE_DONE); } } - copy_face(op, slot_face_map_out, bm_src, f, bm_dst, vhash, ehash); + bmo_face_copy(op, slot_face_map_out, bm_dst, bm_src, f, vhash, ehash); BMO_elem_flag_enable(bm_src, f, DUPE_DONE); } } @@ -307,16 +312,16 @@ static void bmo_mesh_copy(BMOperator *op, BMesh *bm_src, BMesh *bm_dst) void bmo_duplicate_exec(BMesh *bm, BMOperator *op) { BMOperator *dupeop = op; - BMesh *bm2 = BMO_slot_ptr_get(op->slots_in, "dest"); + BMesh *bm_dst = BMO_slot_ptr_get(op->slots_in, "dest"); - if (!bm2) - bm2 = bm; + if (!bm_dst) + bm_dst = bm; /* flag input */ BMO_slot_buffer_flag_enable(bm, dupeop->slots_in, "geom", BM_ALL_NOLOOP, DUPE_INPUT); /* use the internal copy function */ - bmo_mesh_copy(dupeop, bm, bm2); + bmo_mesh_copy(dupeop, bm_dst, bm); /* Output */ /* First copy the input buffers to output buffers - original data */ @@ -466,13 +471,14 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) float axis[3]; float rmat[3][3]; float phi; - int steps, do_dupli, a, usedvec; + int steps, do_dupli, a; + bool use_dvec; BMO_slot_vec_get(op->slots_in, "cent", cent); BMO_slot_vec_get(op->slots_in, "axis", axis); normalize_v3(axis); BMO_slot_vec_get(op->slots_in, "dvec", dvec); - usedvec = !is_zero_v3(dvec); + use_dvec = !is_zero_v3(dvec); steps = BMO_slot_int_get(op->slots_in, "steps"); phi = BMO_slot_float_get(op->slots_in, "angle") / steps; do_dupli = BMO_slot_bool_get(op->slots_in, "use_duplicate"); @@ -504,7 +510,7 @@ void bmo_spin_exec(BMesh *bm, BMOperator *op) BMO_op_finish(bm, &extop); } - if (usedvec) { + if (use_dvec) { mul_m3_v3(rmat, dvec); BMO_op_callf(bm, op->flag, "translate vec=%v space=%s verts=%S", diff --git a/source/blender/bmesh/operators/bmo_edgenet.c b/source/blender/bmesh/operators/bmo_edgenet.c index 6c88161ca35..c58a11f21ec 100644 --- a/source/blender/bmesh/operators/bmo_edgenet.c +++ b/source/blender/bmesh/operators/bmo_edgenet.c @@ -37,6 +37,7 @@ #include "BLI_heap.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "intern/bmesh_operators_private.h" /* own include */ @@ -50,19 +51,23 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) { + BMOperator op_attr; BMOIter siter; BMFace *f; const short mat_nr = BMO_slot_int_get(op->slots_in, "mat_nr"); const bool use_smooth = BMO_slot_bool_get(op->slots_in, "use_smooth"); +// const int sides = BMO_slot_int_get(op->slots_in, "sides"); if (!bm->totvert || !bm->totedge) return; + BM_mesh_elem_hflag_disable_all(bm, BM_EDGE, BM_ELEM_TAG, false); BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false); - BM_mesh_edgenet(bm, true, FACE_NEW); + BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); + BM_mesh_edgenet(bm, true, true); // TODO, sides - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, FACE_NEW); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) { f->mat_nr = mat_nr; @@ -73,13 +78,20 @@ void bmo_edgenet_fill_exec(BMesh *bm, BMOperator *op) BM_face_normal_update(f); } - /* recalc normals, - * TODO, could do checks to make normals consistent */ - { - BMO_op_callf(bm, op->flag, - "recalc_face_normals faces=%S", - op, "faces.out"); + /* --- Attribute Fill --- */ + /* may as well since we have the faces already in a buffer */ + BMO_op_initf(bm, &op_attr, op->flag, + "face_attribute_fill faces=%S use_normals=%b", + op, "faces.out", true); + + BMO_op_exec(bm, &op_attr); + + /* check if some faces couldn't be touched */ + if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) { + BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out"); } + BMO_op_finish(bm, &op_attr); + } static BMEdge *edge_next(BMesh *bm, BMEdge *e) diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index e388205552e..90c514bfd02 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -77,7 +77,7 @@ void bmo_extrude_discrete_faces_exec(BMesh *bm, BMOperator *op) f_side = BM_face_create_quad_tri(bm, l_org->next->v, l_new->next->v, l_new->v, l_org->v, - f_org, false); + f_org, BM_CREATE_NOP); l_side_iter = BM_FACE_FIRST_LOOP(f_side); @@ -170,7 +170,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) for (e = BMO_iter_new(&siter, dupeop.slots_out, "boundary_map.out", 0); e; e = BMO_iter_step(&siter)) { BMVert *f_verts[4]; - e_new = *(BMEdge **)BMO_iter_map_value(&siter); + e_new = BMO_iter_map_value_ptr(&siter); if (e->l && e->v1 != e->l->v) { f_verts[0] = e->v1; @@ -185,7 +185,7 @@ void bmo_extrude_edge_only_exec(BMesh *bm, BMOperator *op) f_verts[3] = e_new->v2; } /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false); + f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); bm_extrude_copy_face_loop_attributes(bm, f); if (BMO_elem_flag_test(bm, e, EXT_INPUT)) @@ -211,11 +211,11 @@ void bmo_extrude_vert_indiv_exec(BMesh *bm, BMOperator *op) const bool has_vskin = CustomData_has_layer(&bm->vdata, CD_MVERT_SKIN); for (v = BMO_iter_new(&siter, op->slots_in, "verts", BM_VERT); v; v = BMO_iter_step(&siter)) { - dupev = BM_vert_create(bm, v->co, v, 0); + dupev = BM_vert_create(bm, v->co, v, BM_CREATE_NOP); if (has_vskin) bm_extrude_disable_skin_root(bm, v); - e = BM_edge_create(bm, v, dupev, NULL, 0); + e = BM_edge_create(bm, v, dupev, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, e, EXT_KEEP); BMO_elem_flag_enable(bm, dupev, EXT_KEEP); @@ -372,7 +372,7 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } - e_new = *(BMEdge **)BMO_iter_map_value(&siter); + e_new = BMO_iter_map_value_ptr(&siter); if (!e_new) { continue; @@ -401,13 +401,13 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } /* not sure what to do about example face, pass NULL for now */ - f = BM_face_create_quad_tri_v(bm, f_verts, 4, NULL, false); + f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); bm_extrude_copy_face_loop_attributes(bm, f); } /* link isolated vert */ for (v = BMO_iter_new(&siter, dupeop.slots_out, "isovert_map.out", 0); v; v = BMO_iter_step(&siter)) { - BMVert *v2 = *((void **)BMO_iter_map_value(&siter)); + BMVert *v2 = BMO_iter_map_value_ptr(&siter); BM_edge_create(bm, v, v2, v->e, BM_CREATE_NO_DOUBLE); } diff --git a/source/blender/bmesh/operators/bmo_fill_attribute.c b/source/blender/bmesh/operators/bmo_fill_attribute.c new file mode 100644 index 00000000000..f53b4536e44 --- /dev/null +++ b/source/blender/bmesh/operators/bmo_fill_attribute.c @@ -0,0 +1,176 @@ + +/* + * ***** 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/bmesh/operators/bmo_fill_attribute.c + * \ingroup bmesh + * + * Fill in geometry with the attributes of their adjacent data. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_linklist_stack.h" + +#include "bmesh.h" + +#include "intern/bmesh_operators_private.h" /* own include */ + +/** + * Check if all other loops are tagged. + */ +static bool bm_loop_is_all_radial_tag(BMLoop *l) +{ + BMLoop *l_iter; + l_iter = l->radial_next; + do { + if (BM_elem_flag_test(l_iter->f, BM_ELEM_TAG) == 0) { + return false; + } + } while ((l_iter = l_iter->radial_next) != l); + + return true; +} + +/** + * Callback to run on source-loops for #BM_face_copy_shared + */ +static bool bm_loop_is_face_untag(BMElem *ele, void *UNUSED(user_data)) +{ + return (BM_elem_flag_test(((BMLoop *)ele)->f, BM_ELEM_TAG) == 0); +} + +/** + * Copy all attributes from adjacent untagged faces. + */ +static void bm_face_copy_shared_all(BMesh *bm, BMLoop *l, + const bool use_normals, const bool use_data) +{ + BMLoop *l_other = l->radial_next; + BMFace *f = l->f, *f_other; + while (BM_elem_flag_test(l_other->f, BM_ELEM_TAG)) { + l_other = l_other->radial_next; + } + f_other = l_other->f; + + if (use_data) { + /* copy face-attrs */ + BM_elem_attrs_copy(bm, bm, f_other, f); + + /* copy loop-attrs */ + BM_face_copy_shared(bm, f, bm_loop_is_face_untag, NULL); + } + + if (use_normals) { + /* copy winding (flipping) */ + if (l->v == l_other->v) { + BM_face_normal_flip(bm, f); + } + } +} + +/** + * Flood fill attributes. + */ +static unsigned int bmesh_face_attribute_fill(BMesh *bm, + const bool use_normals, const bool use_data) +{ + BLI_LINKSTACK_DECLARE(loop_queue_prev, BMLoop *); + BLI_LINKSTACK_DECLARE(loop_queue_next, BMLoop *); + + BMFace *f; + BMIter iter; + BMLoop *l; + + unsigned int face_tot = 0; + + + BLI_LINKSTACK_INIT(loop_queue_prev); + BLI_LINKSTACK_INIT(loop_queue_next); + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(f, BM_ELEM_TAG)) { + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + if (bm_loop_is_all_radial_tag(l_iter) == false) { + BLI_LINKSTACK_PUSH(loop_queue_prev, l_iter); + } + } while ((l_iter = l_iter->next) != l_first); + } + } + + while (BLI_LINKSTACK_SIZE(loop_queue_prev)) { + while ((l = BLI_LINKSTACK_POP(loop_queue_prev))) { + /* check we're still un-assigned */ + if (BM_elem_flag_test(l->f, BM_ELEM_TAG)) { + BMLoop *l_iter; + + BM_elem_flag_disable(l->f, BM_ELEM_TAG); + + l_iter = l->next; + do { + 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)) { + BLI_LINKSTACK_PUSH(loop_queue_next, l_radial_iter); + } + } while ((l_radial_iter = l_radial_iter->radial_next) != l_iter); + } + } while ((l_iter = l_iter->next) != l); + + /* do last because of face flipping */ + bm_face_copy_shared_all(bm, l, + use_normals, use_data); + face_tot += 1; + } + } + + BLI_LINKSTACK_SWAP(loop_queue_prev, loop_queue_next); + } + + BLI_LINKSTACK_FREE(loop_queue_prev); + BLI_LINKSTACK_FREE(loop_queue_next); + + return face_tot; +} + +void bmo_face_attribute_fill_exec(BMesh *bm, BMOperator *op) +{ + const bool use_normals = BMO_slot_bool_get(op->slots_in, "use_normals"); + const bool use_data = BMO_slot_bool_get(op->slots_in, "use_data"); + + int face_tot; + + BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); /* do inline */ + + /* now we can copy adjacent data */ + face_tot = bmesh_face_attribute_fill(bm, use_normals, use_data); + + if (face_tot != BMO_slot_buffer_count(op->slots_in, "faces")) { + /* any remaining tags will be skipped */ + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces_fail.out", BM_FACE, BM_ELEM_TAG); + } +} diff --git a/source/blender/bmesh/operators/bmo_fill_edgeloop.c b/source/blender/bmesh/operators/bmo_fill_edgeloop.c index bd0466ff499..0fbaf5ff11a 100644 --- a/source/blender/bmesh/operators/bmo_fill_edgeloop.c +++ b/source/blender/bmesh/operators/bmo_fill_edgeloop.c @@ -140,7 +140,7 @@ void bmo_edgeloop_fill_exec(BMesh *bm, BMOperator *op) BMFace *f; /* don't use calc_edges option because we already have the edges */ - f = BM_face_create_ngon_verts(bm, f_verts, i, 0, true, false); + f = BM_face_create_ngon_verts(bm, f_verts, i, NULL, BM_CREATE_NOP, true, false); BMO_elem_flag_enable(bm, f, ELE_OUT); f->mat_nr = mat_nr; if (use_smooth) { diff --git a/source/blender/bmesh/operators/bmo_fill_grid.c b/source/blender/bmesh/operators/bmo_fill_grid.c index 7d4b780baf5..35916c76e85 100644 --- a/source/blender/bmesh/operators/bmo_fill_grid.c +++ b/source/blender/bmesh/operators/bmo_fill_grid.c @@ -103,6 +103,94 @@ static void quad_verts_to_barycentric_tri( #endif +/* -------------------------------------------------------------------- */ +/* Handle Loop Pairs */ + +/** \name Loop Pairs + * \{ */ + +/** + * Assign a loop pair from 2 verts (which _must_ share an edge) + */ +static void bm_loop_pair_from_verts(BMVert *v_a, BMVert *v_b, + BMLoop *l_pair[2]) +{ + BMEdge *e = BM_edge_exists(v_a, v_b); + if (e->l) { + if (e->l->v == v_a) { + l_pair[0] = e->l; + l_pair[1] = e->l->next; + } + else { + l_pair[0] = e->l->next; + l_pair[1] = e->l; + } + } + else { + l_pair[0] = NULL; + l_pair[1] = NULL; + } +} + +/** + * Copy loop pair from one side to the other if either is missing, + * this simplifies interpolation code so we only need to check if x/y are missing, + * rather then checking each loop. + */ +static void bm_loop_pair_test_copy(BMLoop *l_pair_a[2], BMLoop *l_pair_b[2]) +{ + /* if the first one is set, we know the second is too */ + if (l_pair_a[0] && l_pair_b[0] == NULL) { + l_pair_b[0] = l_pair_a[1]; + l_pair_b[1] = l_pair_a[0]; + } + else if (l_pair_b[0] && l_pair_a[0] == NULL) { + l_pair_a[0] = l_pair_b[1]; + l_pair_a[1] = l_pair_b[0]; + } +} + +/** + * Interpolate from boundary loops. + * + * \note These weights will be calculated multiple times per vertex. + * Since this runs on each loop, could reduce calls to #barycentric_weights_v2_quad. + */ +static void bm_loop_interp_from_grid_boundary_4(BMesh *bm, BMLoop *l, BMLoop *l_bound[4], const float uv[2]) +{ + float cos[4][2] = { + {uv[0], 0}, + {0, uv[1]}, + {uv[0], 1}, + {1, uv[1]}}; + + void *l_cdata[4] = { + l_bound[0]->head.data, + l_bound[1]->head.data, + l_bound[2]->head.data, + l_bound[3]->head.data}; + + float w[4]; + + barycentric_weights_v2_quad(UNPACK4(cos), uv, w); + CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 4, l->head.data); +} + +static void bm_loop_interp_from_grid_boundary_2(BMesh *bm, BMLoop *l, BMLoop *l_bound[2], const float t) +{ + + void *l_cdata[2] = { + l_bound[0]->head.data, + l_bound[1]->head.data}; + + const float w[2] = {1.0f - t, t}; + + CustomData_bmesh_interp(&bm->ldata, l_cdata, w, NULL, 2, l->head.data); +} + +/** \} */ + + /** * This may be useful outside the bmesh operator. * @@ -113,8 +201,12 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const const bool use_flip) { const bool use_vert_interp = CustomData_has_interp(&bm->vdata); + const bool use_loop_interp = CustomData_has_interp(&bm->ldata); int x, y; + /* for use_loop_interp */ + BMLoop *((*larr_x_a)[2]), *((*larr_x_b)[2]), *((*larr_y_a)[2]), *((*larr_y_b)[2]); + #define XY(_x, _y) ((_x) + ((_y) * (xtot))) #ifdef BARYCENTRIC_INTERP @@ -141,6 +233,31 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const true); #endif + + /* Store loops */ + if (use_loop_interp) { + /* x2 because each edge connects 2 loops */ + larr_x_a = MEM_mallocN(sizeof(*larr_x_a) * (xtot - 1), __func__); + larr_x_b = MEM_mallocN(sizeof(*larr_x_b) * (xtot - 1), __func__); + + larr_y_a = MEM_mallocN(sizeof(*larr_y_a) * (ytot - 1), __func__); + larr_y_b = MEM_mallocN(sizeof(*larr_y_b) * (ytot - 1), __func__); + + /* fill in the loops */ + for (x = 0; x < xtot - 1; x++) { + bm_loop_pair_from_verts(v_grid[XY(x, 0)], v_grid[XY(x + 1, 0)], larr_x_a[x]); + bm_loop_pair_from_verts(v_grid[XY(x, ytot - 1)], v_grid[XY(x + 1, ytot - 1)], larr_x_b[x]); + bm_loop_pair_test_copy(larr_x_a[x], larr_x_b[x]); + } + + for (y = 0; y < ytot - 1; y++) { + bm_loop_pair_from_verts(v_grid[XY(0, y)], v_grid[XY(0, y + 1)], larr_y_a[y]); + bm_loop_pair_from_verts(v_grid[XY(xtot - 1, y)], v_grid[XY(xtot - 1, y + 1)], larr_y_b[y]); + bm_loop_pair_test_copy(larr_y_a[y], larr_y_b[y]); + } + } + + /* Build Verts */ for (y = 1; y < ytot - 1; y++) { #ifdef BARYCENTRIC_INTERP @@ -187,7 +304,7 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const (float)y / ((float)ytot - 1)); #endif - v = BM_vert_create(bm, co, NULL, 0); + v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP); v_grid[(y * xtot) + x] = v; /* interpolate only along one axis, this could be changed @@ -218,7 +335,7 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const v_grid[XY(x + 1, y + 1)], /* TR */ v_grid[XY(x + 1, y + 0)], /* BR */ NULL, - false); + BM_CREATE_NOP); } else { f = BM_face_create_quad_tri( @@ -228,8 +345,90 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const v_grid[XY(x, y + 1)], /* TL */ v_grid[XY(x, y + 0)], /* BL */ NULL, - false); + BM_CREATE_NOP); + } + + + if (use_loop_interp && (larr_x_a[x][0] || larr_y_a[y][0])) { + /* bottom/left/top/right */ + BMLoop *l_quad[4]; + BMLoop *l_bound[4]; + BMLoop *l_tmp; + float uv[2]; /* xy in the grid */ + int x_side, y_side, i; + char interp_from; + + + if (larr_x_a[x][0] && larr_y_a[y][0]) { + interp_from = 'B'; /* B == both */ + l_tmp = larr_x_a[x][0]; + } + else if (larr_x_a[x][0]) { + interp_from = 'X'; + l_tmp = larr_x_a[x][0]; + } + else { + interp_from = 'Y'; + l_tmp = larr_y_a[y][0]; + } + + BM_elem_attrs_copy(bm, bm, l_tmp->f, f); + + + BM_face_as_array_loop_quad(f, l_quad); + + l_tmp = BM_FACE_FIRST_LOOP(f); + + if (use_flip) { + l_quad[0] = l_tmp; l_tmp = l_tmp->next; + l_quad[1] = l_tmp; l_tmp = l_tmp->next; + l_quad[3] = l_tmp; l_tmp = l_tmp->next; + l_quad[2] = l_tmp; + } + else { + l_quad[2] = l_tmp; l_tmp = l_tmp->next; + l_quad[3] = l_tmp; l_tmp = l_tmp->next; + l_quad[1] = l_tmp; l_tmp = l_tmp->next; + l_quad[0] = l_tmp; + } + + i = 0; + + for (x_side = 0; x_side < 2; x_side++) { + for (y_side = 0; y_side < 2; y_side++) { + + uv[0] = (float)(x + x_side) / (xtot - 1); + uv[1] = (float)(y + y_side) / (ytot - 1); + + if (interp_from == 'B') { + l_bound[0] = larr_x_a[x][x_side]; /* B */ + l_bound[1] = larr_y_a[y][y_side]; /* L */ + l_bound[2] = larr_x_b[x][x_side]; /* T */ + l_bound[3] = larr_y_b[y][y_side]; /* R */ + + bm_loop_interp_from_grid_boundary_4(bm, l_quad[i++], l_bound, uv); + } + else if (interp_from == 'X') { + l_bound[0] = larr_x_a[x][x_side]; /* B */ + l_bound[1] = larr_x_b[x][x_side]; /* T */ + + bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, uv[1]); + } + else if (interp_from == 'Y') { + l_bound[0] = larr_y_a[y][y_side]; /* L */ + l_bound[1] = larr_y_b[y][y_side]; /* R */ + + bm_loop_interp_from_grid_boundary_2(bm, l_quad[i++], l_bound, uv[0]); + } + else { + BLI_assert(0); + } + } + } } + /* end interp */ + + BMO_elem_flag_enable(bm, f, FACE_OUT); f->mat_nr = mat_nr; if (use_smooth) { @@ -237,6 +436,14 @@ static void bm_grid_fill_array(BMesh *bm, BMVert **v_grid, const int xtot, const } } } + + if (use_loop_interp) { + MEM_freeN(larr_x_a); + MEM_freeN(larr_y_a); + MEM_freeN(larr_x_b); + MEM_freeN(larr_y_b); + } + #undef XY } diff --git a/source/blender/bmesh/operators/bmo_fill_holes.c b/source/blender/bmesh/operators/bmo_fill_holes.c index 40a682e790d..8160d28d7a7 100644 --- a/source/blender/bmesh/operators/bmo_fill_holes.c +++ b/source/blender/bmesh/operators/bmo_fill_holes.c @@ -28,110 +28,58 @@ #include "MEM_guardedalloc.h" -#include "BLI_listbase.h" -#include "BLI_alloca.h" -#include "BLI_math.h" +#include "BLI_utildefines.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "intern/bmesh_operators_private.h" /* own include */ -#define EDGE_MARK 2 -#define ELE_OUT 4 - -/** - * Clone of BM_face_find_longest_loop that ensures the loop has an adjacent face - */ -static BMLoop *bm_face_find_longest_loop_manifold(BMFace *f) -{ - BMLoop *longest_loop = NULL; - float longest_len = 0.0f; - BMLoop *l_iter, *l_first; - - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - - do { - if (BM_edge_is_wire(l_iter->e) == false) { - const float len = len_squared_v3v3(l_iter->v->co, l_iter->next->v->co); - if (len >= longest_len) { - longest_loop = l_iter; - longest_len = len; - } - } - } while ((l_iter = l_iter->next) != l_first); - - return longest_loop; -} - -static BMFace *bm_face_from_eloop(BMesh *bm, struct BMEdgeLoopStore *el_store) -{ - LinkData *node = BM_edgeloop_verts_get(el_store)->first; - const int len = BM_edgeloop_length_get(el_store); - BMVert **f_verts = BLI_array_alloca(f_verts, len); - BMFace *f; - BMLoop *l; - unsigned int i = 0; - - do { - f_verts[i++] = node->data; - } while ((node = node->next)); - - f = BM_face_create_ngon_verts(bm, f_verts, len, 0, true, false); - BM_face_copy_shared(bm, f); - - l = bm_face_find_longest_loop_manifold(f); - if (l) { - BMFace *f_other = l->radial_next->f; - BLI_assert(l->radial_next != l); - BM_elem_attrs_copy(bm, bm, f_other, f); - } - - return f; -} - -static bool bm_edge_test_cb(BMEdge *e, void *bm_v) -{ - return BMO_elem_flag_test((BMesh *)bm_v, e, EDGE_MARK); -} - void bmo_holes_fill_exec(BMesh *bm, BMOperator *op) { - ListBase eloops = {NULL, NULL}; - LinkData *el_store; + BMOperator op_attr; + const unsigned int sides = BMO_slot_int_get(op->slots_in, "sides"); - BMEdge *e; - int count; - BMOIter siter; + BM_mesh_elem_hflag_disable_all(bm, BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "edges", BM_EDGE, BM_ELEM_TAG, false); - const int sides = BMO_slot_int_get(op->slots_in, "sides"); + BM_mesh_edgenet(bm, true, true); // TODO, sides - /* clear tags */ - BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); + /* bad - remove faces after as a workaround */ + if (sides != 0) { + BMOIter siter; + BMFace *f; - /* tag edges that may be apart of loops */ - BMO_ITER (e, &siter, op->slots_in, "edges", BM_EDGE) { - BMO_elem_flag_set(bm, e, EDGE_MARK, BM_edge_is_boundary(e)); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); + BMO_ITER (f, &siter, op->slots_out, "faces.out", BM_FACE) { + if (f->len > sides) { + BM_face_kill(bm, f); + } + } } - count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_cb, (void *)bm); + BMO_slot_buffer_from_enabled_hflag(bm, op, op->slots_out, "faces.out", BM_FACE, BM_ELEM_TAG); - for (el_store = eloops.first; el_store; el_store = el_store->next) { - if (BM_edgeloop_is_closed((struct BMEdgeLoopStore *)el_store)) { - const int len = BM_edgeloop_length_get((struct BMEdgeLoopStore *)el_store); - if ((sides == 0) || (len <= sides)) { - BMFace *f; + /* --- Attribute Fill --- */ + /* may as well since we have the faces already in a buffer */ + BMO_op_initf(bm, &op_attr, op->flag, + "face_attribute_fill faces=%S use_normals=%b use_data=%b", + op, "faces.out", true, true); - f = bm_face_from_eloop(bm, (struct BMEdgeLoopStore *)el_store); - BMO_elem_flag_enable(bm, f, ELE_OUT); - } - } - } + BMO_op_exec(bm, &op_attr); - (void)count; + /* check if some faces couldn't be touched */ + if (BMO_slot_buffer_count(op_attr.slots_out, "faces_fail.out")) { + BMOIter siter; + BMFace *f; - BM_mesh_edgeloops_free(&eloops); + BMO_ITER (f, &siter, op_attr.slots_out, "faces_fail.out", BM_FACE) { + BM_face_normal_update(f); /* normals are zero'd */ + } - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_OUT); + BMO_op_callf(bm, op->flag, "recalc_face_normals faces=%S", &op_attr, "faces_fail.out"); + } + BMO_op_finish(bm, &op_attr); } diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 500e984f4c9..e3a8e67c427 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -67,7 +67,7 @@ typedef struct HullTriangle { /*************************** Hull Triangles ***************************/ -static void hull_add_triangle(BMesh *bm, GHash *hull_triangles, BLI_mempool *pool, +static void hull_add_triangle(BMesh *bm, GSet *hull_triangles, BLI_mempool *pool, BMVert *v1, BMVert *v2, BMVert *v3) { HullTriangle *t; @@ -82,7 +82,7 @@ static void hull_add_triangle(BMesh *bm, GHash *hull_triangles, BLI_mempool *poo for (i = 0; i < 3; i++) BMO_elem_flag_disable(bm, t->v[i], HULL_FLAG_INTERIOR_ELE); - BLI_ghash_insert(hull_triangles, t, NULL); + BLI_gset_insert(hull_triangles, t); normal_tri_v3(t->no, v1->co, v2->co, v3->co); } @@ -102,12 +102,12 @@ static BMFace *hull_find_example_face(BMesh *bm, BMEdge *e) return NULL; } -static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) +static void hull_output_triangles(BMesh *bm, GSet *hull_triangles) { - GHashIterator iter; + GSetIterator iter; - GHASH_ITER (iter, hull_triangles) { - HullTriangle *t = BLI_ghashIterator_getKey(&iter); + GSET_ITER (iter, hull_triangles) { + HullTriangle *t = BLI_gsetIterator_getKey(&iter); int i; if (!t->skip) { @@ -135,7 +135,7 @@ static void hull_output_triangles(BMesh *bm, GHash *hull_triangles) } /* Create new hull face */ - f = BM_face_create_quad_tri_v(bm, t->v, 3, example, true); + f = BM_face_create_verts(bm, t->v, 3, example, BM_CREATE_NO_DOUBLE, true); BM_face_copy_shared(bm, f); } /* Mark face for 'geom.out' slot and select */ @@ -206,22 +206,22 @@ static int hull_final_edges_lookup(HullFinalEdges *final_edges, } /* Used for checking whether a pre-existing edge lies on the hull */ -static HullFinalEdges *hull_final_edges(GHash *hull_triangles) +static HullFinalEdges *hull_final_edges(GSet *hull_triangles) { HullFinalEdges *final_edges; - GHashIterator iter; + GSetIterator iter; final_edges = MEM_callocN(sizeof(HullFinalEdges), "HullFinalEdges"); final_edges->edges = BLI_ghash_ptr_new("final edges ghash"); final_edges->base_pool = BLI_mempool_create(sizeof(ListBase), 128, 128, 0); final_edges->link_pool = BLI_mempool_create(sizeof(LinkData), 128, 128, 0); - GHASH_ITER (iter, hull_triangles) { + GSET_ITER (iter, hull_triangles) { LinkData *link; int i; for (i = 0; i < 3; i++) { - HullTriangle *t = BLI_ghashIterator_getKey(&iter); + HullTriangle *t = BLI_gsetIterator_getKey(&iter); BMVert *v1 = t->v[i]; BMVert *v2 = t->v[(i + 1) % 3]; ListBase *adj; @@ -259,13 +259,13 @@ static void hull_final_edges_free(HullFinalEdges *final_edges) /**************************** Final Output ****************************/ -static void hull_remove_overlapping(BMesh *bm, GHash *hull_triangles, +static void hull_remove_overlapping(BMesh *bm, GSet *hull_triangles, HullFinalEdges *final_edges) { - GHashIterator hull_iter; + GSetIterator hull_iter; - GHASH_ITER (hull_iter, hull_triangles) { - HullTriangle *t = BLI_ghashIterator_getKey(&hull_iter); + GSET_ITER (hull_iter, hull_triangles) { + HullTriangle *t = BLI_gsetIterator_getKey(&hull_iter); BMIter bm_iter1, bm_iter2; BMFace *f; bool f_on_hull; @@ -479,7 +479,7 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull, } static void hull_from_bullet(BMesh *bm, BMOperator *op, - GHash *hull_triangles, + GSet *hull_triangles, BLI_mempool *pool) { int *fvi = NULL; @@ -556,7 +556,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) BLI_mempool *hull_pool; BMElemF *ele; BMOIter oiter; - GHash *hull_triangles; + GSet *hull_triangles; /* Verify that at least three verts in the input */ if (!hull_num_input_verts_is_ok(op)) { @@ -575,7 +575,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) } hull_pool = BLI_mempool_create(sizeof(HullTriangle), 128, 128, 0); - hull_triangles = BLI_ghash_ptr_new("hull_triangles"); + hull_triangles = BLI_gset_ptr_new("hull_triangles"); hull_from_bullet(bm, op, hull_triangles, hull_pool); @@ -597,7 +597,7 @@ void bmo_convex_hull_exec(BMesh *bm, BMOperator *op) hull_output_triangles(bm, hull_triangles); BLI_mempool_destroy(hull_pool); - BLI_ghash_free(hull_triangles, NULL, NULL); + BLI_gset_free(hull_triangles, NULL); hull_tag_unused(bm, op); diff --git a/source/blender/bmesh/operators/bmo_inset.c b/source/blender/bmesh/operators/bmo_inset.c index cffca91eabd..2063e458550 100644 --- a/source/blender/bmesh/operators/bmo_inset.c +++ b/source/blender/bmesh/operators/bmo_inset.c @@ -32,6 +32,7 @@ #include "BLI_math.h" #include "BLI_array.h" +#include "BLI_alloca.h" #include "BLI_memarena.h" #include "BKE_customdata.h" @@ -42,199 +43,263 @@ #define ELE_NEW 1 - /* -------------------------------------------------------------------- */ -/* Inset Individual */ - - -/* Holds Per-Face Inset Edge Data */ -typedef struct EdgeInsetInfo { - float no[3]; - BMEdge *e_old; - BMEdge *e_new; -} EdgeInsetInfo; +/* Generic Interp Face (use for both types of inset) */ /** - * Individual Face Inset. - * Find all tagged faces (f), duplicate edges around faces, inset verts of - * created edges, create new faces between old and new edges, fill face - * between connected new edges, kill old face (f). - */ -void bmo_inset_individual_exec(BMesh *bm, BMOperator *op) -{ - BMEdge **f_edges = NULL; - BMVert **f_verts = NULL; + * Interpolation, this is more complex for regions since we're not creating new faces + * and throwing away old ones, so instead, store face data needed for interpolation. + * + * \note This uses CustomData functions in quite a low-level way which should be + * avoided, but in this case its hard to do without storing a duplicate mesh. */ + +/* just enough of a face to store interpolation data we can use once the inset is done */ +typedef struct InterpFace { BMFace *f; + void **blocks_l; + void **blocks_v; + float (*cos_2d)[2]; + float axis_mat[3][3]; +} InterpFace; - BMOIter oiter; - EdgeInsetInfo *eiinfo_arr = NULL; +/* basically a clone of #BM_vert_interp_from_face */ +static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena) +{ + BMLoop *l_iter, *l_first; + void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len); + void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len); + float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len); + void *axis_mat = iface->axis_mat; + int i; - BLI_array_declare(eiinfo_arr); - BLI_array_declare(f_edges); - BLI_array_declare(f_verts); + BLI_assert(BM_face_is_normal_valid(f)); - const float thickness = BMO_slot_float_get(op->slots_in, "thickness"); - const float depth = BMO_slot_float_get(op->slots_in, "depth"); - const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); - const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); - const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate"); + axis_dominant_v3_to_m3(axis_mat, f->no); - /* Only tag faces in slot */ - BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); + iface->f = f; - BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); + i = 0; + l_iter = l_first = BM_FACE_FIRST_LOOP(f); + do { + mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); + blocks_l[i] = NULL; + CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]); + /* if we were not modifying the loops later we would do... */ + // blocks[i] = l_iter->head.data; - BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { - BMFace *f_new_inner; - BMLoop *l_iter, *l_first; - BMLoop *l_iter_inner = NULL; - int i; - - BLI_array_empty(f_verts); - BLI_array_empty(f_edges); - BLI_array_empty(eiinfo_arr); - BLI_array_grow_items(f_verts, f->len); - BLI_array_grow_items(f_edges, f->len); - BLI_array_grow_items(eiinfo_arr, f->len); - - /* create verts */ - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - f_verts[i] = BM_vert_create(bm, l_iter->v->co, l_iter->v, 0); - i++; - } while ((l_iter = l_iter->next) != l_first); + blocks_v[i] = NULL; + CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]); - /* make edges */ - i = 0; - l_iter = l_first; - do { - f_edges[i] = BM_edge_create(bm, f_verts[i], f_verts[(i + 1) % f->len], l_iter->e, 0); + /* use later for index lookups */ + BM_elem_index_set(l_iter, i); /* set_ok */ + } while (i++, (l_iter = l_iter->next) != l_first); +} +static void bm_interp_face_free(InterpFace *iface, BMesh *bm) +{ + void **blocks_l = iface->blocks_l; + void **blocks_v = iface->blocks_v; + int i; - eiinfo_arr[i].e_new = f_edges[i]; - eiinfo_arr[i].e_old = l_iter->e; - BM_edge_calc_face_tangent(l_iter->e, l_iter, eiinfo_arr[i].no); + for (i = 0; i < iface->f->len; i++) { + CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]); + CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]); + } +} - /* Tagging (old elements) required when iterating over edges - * connected to verts for translation vector calculation */ - BM_elem_flag_enable(l_iter->e, BM_ELEM_TAG); - BM_elem_index_set(l_iter->e, i); /* set_dirty! */ - i++; - } while ((l_iter = l_iter->next) != l_first); - /* done with edges */ - bm->elem_index_dirty |= BM_EDGE; +/* -------------------------------------------------------------------- */ +/* Inset Individual */ - /* Calculate translation vector for new */ - l_iter = l_first; - do { - EdgeInsetInfo *ei_prev = &eiinfo_arr[BM_elem_index_get(l_iter->prev->e)]; - EdgeInsetInfo *ei_next = &eiinfo_arr[BM_elem_index_get(l_iter->e)]; - float tvec[3]; - float v_new_co[3]; - int index = 0; +static void bmo_face_inset_individual( + BMesh *bm, BMFace *f, MemArena *interp_arena, + const float thickness, const float depth, + const bool use_even_offset, const bool use_relative_offset, const bool use_interpolate) +{ + InterpFace *iface = NULL; - add_v3_v3v3(tvec, ei_prev->no, ei_next->no); - normalize_v3(tvec); + /* stores verts split away from the face (aligned with face verts) */ + BMVert **verts = BLI_array_alloca(verts, f->len); + /* store edge normals (aligned with face-loop-edges) */ + float (*edge_nors)[3] = BLI_array_alloca(edge_nors, f->len); + float (*coords)[3] = BLI_array_alloca(coords, f->len); - /* l->e is traversed in order */ - index = BM_elem_index_get(l_iter->e); + BMLoop *l_iter, *l_first; + BMLoop *l_other; + unsigned int i; + float e_length_prev; - copy_v3_v3(v_new_co, eiinfo_arr[index].e_new->v1->co); + l_first = BM_FACE_FIRST_LOOP(f); - if (use_even_offset) { - mul_v3_fl(tvec, shell_angle_to_dist(angle_normalized_v3v3(ei_prev->no, ei_next->no) / 2.0f)); - } + /* split off all loops */ + l_iter = l_first; + i = 0; + do { + BMVert *v_other = l_iter->v; + BMVert *v_sep = BM_face_loop_separate(bm, l_iter); + if (v_sep == v_other) { + v_other = BM_vert_create(bm, l_iter->v->co, l_iter->v, BM_CREATE_NOP); + } + verts[i] = v_other; - /* Modify vertices and their normals */ - if (use_relative_offset) { - mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f); - } + /* unrelated to splitting, but calc here */ + BM_edge_calc_face_tangent(l_iter->e, l_iter, edge_nors[i]); + } while (i++, ((l_iter = l_iter->next) != l_first)); - madd_v3_v3fl(v_new_co, tvec, thickness); - /* Set normal, add depth and write new vertex position*/ - copy_v3_v3(eiinfo_arr[index].e_new->v1->no, f->no); + /* build rim faces */ + l_iter = l_first; + i = 0; + do { + BMFace *f_new_outer; + BMVert *v_other = verts[i]; + BMVert *v_other_next = verts[(i + 1) % f->len]; + + BMEdge *e_other = BM_edge_create(bm, v_other, v_other_next, l_iter->e, BM_CREATE_NO_DOUBLE); + (void)e_other; + + f_new_outer = BM_face_create_quad_tri(bm, + v_other, + v_other_next, + l_iter->next->v, + l_iter->v, + f, BM_CREATE_NOP); + BMO_elem_flag_enable(bm, f_new_outer, ELE_NEW); + + /* copy loop data */ + l_other = l_iter->radial_next; + BM_elem_attrs_copy(bm, bm, l_iter->next, l_other->prev); + BM_elem_attrs_copy(bm, bm, l_iter, l_other->next->next); + + if (use_interpolate == false) { + BM_elem_attrs_copy(bm, bm, l_iter->next, l_other); + BM_elem_attrs_copy(bm, bm, l_iter, l_other->next); + } + } while (i++, ((l_iter = l_iter->next) != l_first)); - madd_v3_v3fl(v_new_co, f->no, depth); + /* hold interpolation values */ + if (use_interpolate) { + iface = BLI_memarena_alloc(interp_arena, sizeof(*iface)); + bm_interp_face_store(iface, bm, f, interp_arena); + } - copy_v3_v3(eiinfo_arr[index].e_new->v1->co, v_new_co); - } while ((l_iter = l_iter->next) != l_first); + /* Calculate translation vector for new */ + l_iter = l_first; + i = 0; + if (depth != 0.0f) { + e_length_prev = BM_edge_calc_length(l_iter->prev->e); + } - /* Create New Inset Faces */ - f_new_inner = BM_face_create(bm, f_verts, f_edges, f->len, 0); - BLI_assert(f_new_inner != NULL); /* no reason it should fail */ + do { + const float *eno_prev = edge_nors[(i ? i : f->len) - 1]; + const float *eno_next = edge_nors[i]; + float tvec[3]; + float v_new_co[3]; + add_v3_v3v3(tvec, eno_prev, eno_next); + normalize_v3(tvec); - // Don't tag, gives more useful inner/outer select option - // BMO_elem_flag_enable(bm, f_new_inner, ELE_NEW); + copy_v3_v3(v_new_co, l_iter->v->co); + if (use_even_offset) { + mul_v3_fl(tvec, shell_angle_to_dist(angle_normalized_v3v3(eno_prev, eno_next) / 2.0f)); + } - /* Copy Face Data */ - /* interpolate loop data or just stretch */ - if (use_interpolate) { - BM_face_interp_from_face(bm, f_new_inner, f, true); + /* Modify vertices and their normals */ + if (use_relative_offset) { + mul_v3_fl(tvec, (BM_edge_calc_length(l_iter->e) + BM_edge_calc_length(l_iter->prev->e)) / 2.0f); } - else { - BM_elem_attrs_copy(bm, bm, f, f_new_inner); + + madd_v3_v3fl(v_new_co, tvec, thickness); + + /* Set normal, add depth and write new vertex position*/ + copy_v3_v3(l_iter->v->no, f->no); + + if (depth != 0.0f) { + const float e_length = BM_edge_calc_length(l_iter->e); + const float fac = depth * (use_relative_offset ? ((e_length_prev + e_length) * 0.5f) : 1.0f); + e_length_prev = e_length; + + madd_v3_v3fl(v_new_co, f->no, fac); } - l_iter_inner = BM_FACE_FIRST_LOOP(f_new_inner); + + + copy_v3_v3(coords[i], v_new_co); + } while (i++, ((l_iter = l_iter->next) != l_first)); + + /* update the coords */ + l_iter = l_first; + i = 0; + do { + copy_v3_v3(l_iter->v->co, coords[i]); + } while (i++, ((l_iter = l_iter->next) != l_first)); + + + if (use_interpolate) { + BM_face_interp_from_face_ex(bm, iface->f, iface->f, true, + iface->blocks_l, iface->blocks_v, iface->cos_2d, iface->axis_mat); + + /* build rim faces */ l_iter = l_first; do { - BMFace *f_new_outer; - - BMLoop *l_a; - BMLoop *l_b; + /* copy loop data */ + l_other = l_iter->radial_next; - if (use_interpolate == false) { - BM_elem_attrs_copy(bm, bm, l_iter, l_iter_inner); - } + BM_elem_attrs_copy(bm, bm, l_iter->next, l_other); + BM_elem_attrs_copy(bm, bm, l_iter, l_other->next); + } while ((l_iter = l_iter->next) != l_first); - f_new_outer = BM_face_create_quad_tri(bm, - l_iter->v, - l_iter->next->v, - l_iter_inner->next->v, - l_iter_inner->v, - f, false); + bm_interp_face_free(iface, bm); + } +} - BLI_assert(f_new_outer != NULL); /* no reason it should fail */ - BM_elem_attrs_copy(bm, bm, f, f_new_outer); - BMO_elem_flag_enable(bm, f_new_outer, ELE_NEW); - BM_elem_flag_enable(f_new_outer, BM_ELEM_TAG); +/** + * Individual Face Inset. + * Find all tagged faces (f), duplicate edges around faces, inset verts of + * created edges, create new faces between old and new edges, fill face + * between connected new edges, kill old face (f). + */ +void bmo_inset_individual_exec(BMesh *bm, BMOperator *op) +{ + BMFace *f; - /* Copy Loop Data */ - l_a = BM_FACE_FIRST_LOOP(f_new_outer); - l_b = l_a->next; + BMOIter oiter; + MemArena *interp_arena = NULL; - /* first pair */ - BM_elem_attrs_copy(bm, bm, l_iter, l_a); - BM_elem_attrs_copy(bm, bm, l_iter->next, l_b); + const float thickness = BMO_slot_float_get(op->slots_in, "thickness"); + const float depth = BMO_slot_float_get(op->slots_in, "depth"); + const bool use_even_offset = BMO_slot_bool_get(op->slots_in, "use_even_offset"); + const bool use_relative_offset = BMO_slot_bool_get(op->slots_in, "use_relative_offset"); + const bool use_interpolate = BMO_slot_bool_get(op->slots_in, "use_interpolate"); + /* Only tag faces in slot */ + BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false); - /* Move to the last two loops in new face */ - l_a = l_b->next; - l_b = l_a->next; + BMO_slot_buffer_hflag_enable(bm, op->slots_in, "faces", BM_FACE, BM_ELEM_TAG, false); - /* This loop should always have >1 radials - * (associated edge connects new and old face) */ - BM_elem_attrs_copy(bm, bm, l_iter_inner, l_b); - BM_elem_attrs_copy(bm, bm, use_interpolate ? l_iter_inner->next : l_iter->next, l_a); + if (use_interpolate) { + interp_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + } - } while ((l_iter_inner = l_iter_inner->next), - (l_iter = l_iter->next) != l_first); + BMO_ITER (f, &oiter, op->slots_in, "faces", BM_FACE) { + bmo_face_inset_individual( + bm, f, interp_arena, + thickness, depth, + use_even_offset, use_relative_offset, use_interpolate); - BM_face_kill(bm, f); + if (use_interpolate) { + BLI_memarena_clear(interp_arena); + } } /* we could flag new edges/verts too, is it useful? */ BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "faces.out", BM_FACE, ELE_NEW); - BLI_array_free(f_verts); - BLI_array_free(f_edges); - BLI_array_free(eiinfo_arr); + if (use_interpolate) { + BLI_memarena_free(interp_arena); + } } @@ -250,68 +315,6 @@ typedef struct SplitEdgeInfo { BMLoop *l; } SplitEdgeInfo; - -/** - * Interpolation, this is more complex for regions since we're not creating new faces - * and throwing away old ones, so instead, store face data needed for interpolation. - * - * \note This uses CustomData functions in quite a low-level way which should be - * avoided, but in this case its hard to do without storing a duplicate mesh. */ - -/* just enough of a face to store interpolation data we can use once the inset is done */ -typedef struct InterpFace { - BMFace *f; - void **blocks_l; - void **blocks_v; - float (*cos_2d)[2]; - float axis_mat[3][3]; -} InterpFace; - -/* basically a clone of #BM_vert_interp_from_face */ -static void bm_interp_face_store(InterpFace *iface, BMesh *bm, BMFace *f, MemArena *interp_arena) -{ - BMLoop *l_iter, *l_first; - void **blocks_l = iface->blocks_l = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_l) * f->len); - void **blocks_v = iface->blocks_v = BLI_memarena_alloc(interp_arena, sizeof(*iface->blocks_v) * f->len); - float (*cos_2d)[2] = iface->cos_2d = BLI_memarena_alloc(interp_arena, sizeof(*iface->cos_2d) * f->len); - void *axis_mat = iface->axis_mat; - int i; - - BLI_assert(BM_face_is_normal_valid(f)); - - axis_dominant_v3_to_m3(axis_mat, f->no); - - iface->f = f; - - i = 0; - l_iter = l_first = BM_FACE_FIRST_LOOP(f); - do { - mul_v2_m3v3(cos_2d[i], axis_mat, l_iter->v->co); - blocks_l[i] = NULL; - CustomData_bmesh_copy_data(&bm->ldata, &bm->ldata, l_iter->head.data, &blocks_l[i]); - /* if we were not modifying the loops later we would do... */ - // blocks[i] = l_iter->head.data; - - blocks_v[i] = NULL; - CustomData_bmesh_copy_data(&bm->vdata, &bm->vdata, l_iter->v->head.data, &blocks_v[i]); - - /* use later for index lookups */ - BM_elem_index_set(l_iter, i); /* set_ok */ - } while (i++, (l_iter = l_iter->next) != l_first); -} -static void bm_interp_face_free(InterpFace *iface, BMesh *bm) -{ - void **blocks_l = iface->blocks_l; - void **blocks_v = iface->blocks_v; - int i; - - for (i = 0; i < iface->f->len; i++) { - CustomData_bmesh_free_block(&bm->ldata, &blocks_l[i]); - CustomData_bmesh_free_block(&bm->vdata, &blocks_v[i]); - } -} - - /** * return the tag loop where there is... * - only 1 tagged face attached to this edge. @@ -350,6 +353,27 @@ static BMLoop *bm_edge_is_mixed_face_tag(BMLoop *l) } } +static float bm_edge_info_average_length(BMVert *v, SplitEdgeInfo *edge_info) +{ + BMIter iter; + BMEdge *e; + + float len = 0.0f; + int tot = 0; + + + BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { + const int i = BM_elem_index_get(e); + if (i != -1) { + len += edge_info[i].length; + tot++; + } + } + + BLI_assert(tot != 0); + return len / (float)tot; +} + /** * implementation is as follows... * @@ -465,7 +489,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) if (es->e_new == es->e_old) { /* happens on boundary edges */ /* take care here, we're creating this double edge which _must_ have its verts replaced later on */ - es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, 0); + es->e_old = BM_edge_create(bm, es->e_new->v1, es->e_new->v2, es->e_new, BM_CREATE_NOP); } /* store index back to original in 'edge_info' */ @@ -508,8 +532,8 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) mid_v3_v3v3(tvec, es->e_new->v1->co, es->e_new->v2->co); - v1 = BM_vert_create(bm, tvec, NULL); - v2 = BM_vert_create(bm, tvec, NULL); + v1 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP); + v2 = BM_vert_create(bm, tvec, NULL, BM_CREATE_NOP); madd_v3_v3fl(v2->co, es->no, 0.1f); BM_edge_create(bm, v1, v2, NULL, 0); } @@ -787,7 +811,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) #endif /* no need to check doubles, we KNOW there won't be any */ /* yes - reverse face is correct in this case */ - f = BM_face_create_quad_tri_v(bm, varr, j, es->l->f, false); + f = BM_face_create_verts(bm, varr, j, es->l->f, BM_CREATE_NOP, true); BMO_elem_flag_enable(bm, f, ELE_NEW); /* copy for loop data, otherwise UV's and vcols are no good. @@ -894,7 +918,7 @@ void bmo_inset_region_exec(BMesh *bm, BMOperator *op) BM_ITER_MESH_INDEX (v, &iter, bm, BM_VERTS_OF_MESH, i) { if (BM_elem_flag_test(v, BM_ELEM_TAG)) { const float fac = (depth * - (use_relative_offset ? BM_vert_calc_mean_tagged_edge_length(v) : 1.0f) * + (use_relative_offset ? bm_edge_info_average_length(v, edge_info) : 1.0f) * (use_even_boundry ? BM_vert_calc_shell_factor(v) : 1.0f)); madd_v3_v3v3fl(varr_co[i], v->co, v->no, fac); } diff --git a/source/blender/bmesh/operators/bmo_join_triangles.c b/source/blender/bmesh/operators/bmo_join_triangles.c index 12065743136..6d4f257909c 100644 --- a/source/blender/bmesh/operators/bmo_join_triangles.c +++ b/source/blender/bmesh/operators/bmo_join_triangles.c @@ -34,6 +34,7 @@ #include "DNA_meshdata_types.h" #include "BLI_math.h" +#include "BLI_sort_utils.h" #include "BKE_customdata.h" @@ -181,10 +182,6 @@ static bool bm_edge_faces_cmp(BMesh *bm, BMEdge *e, const bool do_uv, const bool return true; } -typedef struct JoinEdge { - float weight; - BMEdge *e; -} JoinEdge; #define EDGE_MARK 1 #define EDGE_CHOSEN 2 @@ -192,14 +189,7 @@ typedef struct JoinEdge { #define FACE_MARK 1 #define FACE_INPUT 2 -static int fplcmp(const void *v1, const void *v2) -{ - const JoinEdge *e1 = (JoinEdge *)v1, *e2 = (JoinEdge *)v2; - if (e1->weight > e2->weight) return 1; - else if (e1->weight < e2->weight) return -1; - else return 0; -} void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) { @@ -214,7 +204,8 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) BMOIter siter; BMFace *f; BMEdge *e; - JoinEdge *jedges = NULL; + /* data: edge-to-join, sort_value: error weight */ + struct SortPointerByFloat *jedges; unsigned i, totedge; unsigned int totedge_tag = 0; @@ -271,19 +262,19 @@ void bmo_join_triangles_exec(BMesh *bm, BMOperator *op) measure = measure_facepair(v1->co, v2->co, v3->co, v4->co, limit); if (measure < limit) { - jedges[i].e = e; - jedges[i].weight = measure; + jedges[i].data = e; + jedges[i].sort_value = measure; i++; } } totedge = i; - qsort(jedges, totedge, sizeof(JoinEdge), fplcmp); + qsort(jedges, totedge, sizeof(*jedges), BLI_sortutil_cmp_float); for (i = 0; i < totedge; i++) { BMFace *f_a, *f_b; - e = jedges[i].e; + e = jedges[i].data; f_a = e->l->f; f_b = e->l->radial_next->f; diff --git a/source/blender/bmesh/operators/bmo_poke.c b/source/blender/bmesh/operators/bmo_poke.c index 690a8a5176f..de65f4767ff 100644 --- a/source/blender/bmesh/operators/bmo_poke.c +++ b/source/blender/bmesh/operators/bmo_poke.c @@ -83,7 +83,7 @@ void bmo_poke_exec(BMesh *bm, BMOperator *op) int i; bm_face_calc_center_fn(f, f_center); - v_center = BM_vert_create(bm, f_center, NULL, 0); + v_center = BM_vert_create(bm, f_center, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v_center, ELE_NEW); /* handled by BM_loop_interp_from_face */ diff --git a/source/blender/bmesh/operators/bmo_primitive.c b/source/blender/bmesh/operators/bmo_primitive.c index 9f17c1dd8e3..45653f3411f 100644 --- a/source/blender/bmesh/operators/bmo_primitive.c +++ b/source/blender/bmesh/operators/bmo_primitive.c @@ -249,7 +249,7 @@ void bmo_create_grid_exec(BMesh *bm, BMOperator *op) vec[2] = 0.0f; mul_m4_v3(mat, vec); - eve = BM_vert_create(bm, vec, NULL, 0); + eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, eve, VERT_MARK); if (a != 0) { @@ -318,11 +318,11 @@ void bmo_create_uvsphere_exec(BMesh *bm, BMOperator *op) vec[0] = -dia * sinf(phi); vec[1] = 0.0; vec[2] = dia * cosf(phi); - eve = BM_vert_create(bm, vec, NULL, 0); + eve = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, eve, VERT_MARK); if (a != 0) { - e = BM_edge_create(bm, preveve, eve, NULL, 0); + e = BM_edge_create(bm, preveve, eve, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, e, EDGE_ORIG); } @@ -408,7 +408,7 @@ void bmo_create_icosphere_exec(BMesh *bm, BMOperator *op) vec[0] = dia_div * icovert[a][0]; vec[1] = dia_div * icovert[a][1]; vec[2] = dia_div * icovert[a][2]; - eva[a] = BM_vert_create(bm, vec, NULL, 0); + eva[a] = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, eva[a], VERT_MARK); } @@ -471,12 +471,12 @@ void bmo_create_monkey_exec(BMesh *bm, BMOperator *op) v[0] = (monkeyv[i][0] + 127) / 128.0, v[1] = monkeyv[i][1] / 128.0, v[2] = monkeyv[i][2] / 128.0; - tv[i] = BM_vert_create(bm, v, NULL, 0); + tv[i] = BM_vert_create(bm, v, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, tv[i], VERT_MARK); tv[monkeynv + i] = (fabsf(v[0] = -v[0]) < 0.001f) ? tv[i] : - (eve = BM_vert_create(bm, v, NULL, 0), mul_m4_v3(mat, eve->co), eve); + (eve = BM_vert_create(bm, v, NULL, BM_CREATE_NOP), mul_m4_v3(mat, eve->co), eve); BMO_elem_flag_enable(bm, tv[monkeynv + i], VERT_MARK); @@ -528,7 +528,7 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) zero_v3(vec); mul_m4_v3(mat, vec); - cent1 = BM_vert_create(bm, vec, NULL, 0); + cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, cent1, VERT_MARK); } @@ -538,12 +538,12 @@ void bmo_create_circle_exec(BMesh *bm, BMOperator *op) vec[1] = dia * cosf(phi); vec[2] = 0.0f; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL, 0); + v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v1, VERT_MARK); if (lastv1) - BM_edge_create(bm, v1, lastv1, NULL, 0); + BM_edge_create(bm, v1, lastv1, NULL, BM_CREATE_NOP); if (a && cap_ends) { BMFace *f; @@ -603,13 +603,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) vec[2] = -depth; mul_m4_v3(mat, vec); - cent1 = BM_vert_create(bm, vec, NULL, 0); + cent1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); vec[0] = vec[1] = 0.0f; vec[2] = depth; mul_m4_v3(mat, vec); - cent2 = BM_vert_create(bm, vec, NULL, 0); + cent2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, cent1, VERT_MARK); BMO_elem_flag_enable(bm, cent2, VERT_MARK); @@ -620,13 +620,13 @@ void bmo_create_cone_exec(BMesh *bm, BMOperator *op) vec[1] = dia1 * cosf(phi); vec[2] = -depth; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL, 0); + v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); vec[0] = dia2 * sinf(phi); vec[1] = dia2 * cosf(phi); vec[2] = depth; mul_m4_v3(mat, vec); - v2 = BM_vert_create(bm, vec, NULL, 0); + v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v1, VERT_MARK); BMO_elem_flag_enable(bm, v2, VERT_MARK); @@ -686,56 +686,56 @@ void bmo_create_cube_exec(BMesh *bm, BMOperator *op) vec[1] = -off; vec[2] = -off; mul_m4_v3(mat, vec); - v1 = BM_vert_create(bm, vec, NULL, 0); + v1 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v1, VERT_MARK); vec[0] = -off; vec[1] = off; vec[2] = -off; mul_m4_v3(mat, vec); - v2 = BM_vert_create(bm, vec, NULL, 0); + v2 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v2, VERT_MARK); vec[0] = off; vec[1] = off; vec[2] = -off; mul_m4_v3(mat, vec); - v3 = BM_vert_create(bm, vec, NULL, 0); + v3 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v3, VERT_MARK); vec[0] = off; vec[1] = -off; vec[2] = -off; mul_m4_v3(mat, vec); - v4 = BM_vert_create(bm, vec, NULL, 0); + v4 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v4, VERT_MARK); vec[0] = -off; vec[1] = -off; vec[2] = off; mul_m4_v3(mat, vec); - v5 = BM_vert_create(bm, vec, NULL, 0); + v5 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v5, VERT_MARK); vec[0] = -off; vec[1] = off; vec[2] = off; mul_m4_v3(mat, vec); - v6 = BM_vert_create(bm, vec, NULL, 0); + v6 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v6, VERT_MARK); vec[0] = off; vec[1] = off; vec[2] = off; mul_m4_v3(mat, vec); - v7 = BM_vert_create(bm, vec, NULL, 0); + v7 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v7, VERT_MARK); vec[0] = off; vec[1] = -off; vec[2] = off; mul_m4_v3(mat, vec); - v8 = BM_vert_create(bm, vec, NULL, 0); + v8 = BM_vert_create(bm, vec, NULL, BM_CREATE_NOP); BMO_elem_flag_enable(bm, v8, VERT_MARK); /* the four sides */ diff --git a/source/blender/bmesh/operators/bmo_removedoubles.c b/source/blender/bmesh/operators/bmo_removedoubles.c index 4ee4979fdcd..5ab909ffb0c 100644 --- a/source/blender/bmesh/operators/bmo_removedoubles.c +++ b/source/blender/bmesh/operators/bmo_removedoubles.c @@ -71,6 +71,11 @@ static void remdoubles_splitface(BMFace *f, BMesh *bm, BMOperator *op, BMOpSlot #define EDGE_COL 2 #define FACE_MARK 2 +/** + * \note with 'targetmap', multiple 'keys' are currently supported, though no callers should be using. + * (because slot maps currently use GHash without the GHASH_FLAG_ALLOW_DUPES flag set) + * + */ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) { BMIter iter, liter; @@ -189,10 +194,8 @@ void bmo_weld_verts_exec(BMesh *bm, BMOperator *op) v2 = BMO_slot_map_elem_get(slot_targetmap, v2); } - f_new = BM_face_create_ngon(bm, v, v2, edges, a, BM_CREATE_NO_DOUBLE); + f_new = BM_face_create_ngon(bm, v, v2, edges, a, f, BM_CREATE_NO_DOUBLE); if (f_new && (f_new != f)) { - BM_elem_attrs_copy(bm, bm, f, f_new); - a = 0; BM_ITER_ELEM (l, &liter, f_new, BM_LOOPS_OF_FACE) { l_new = loops[a]; @@ -495,13 +498,18 @@ static void bmesh_find_doubles_common(BMesh *bm, BMOperator *op, for (i = 0; i < verts_len; i++) { BMVert *v_check = verts[i]; - if (BMO_elem_flag_test(bm, v_check, VERT_DOUBLE)) { + if (BMO_elem_flag_test(bm, v_check, VERT_DOUBLE | VERT_TARGET)) { continue; } for (j = i + 1; j < verts_len; j++) { BMVert *v_other = verts[j]; + /* a match has already been found, (we could check which is best, for now don't) */ + if (BMO_elem_flag_test(bm, v_other, VERT_DOUBLE | VERT_TARGET)) { + continue; + } + /* Compare sort values of the verts using 3x tolerance (allowing for the tolerance * on each of the three axes). This avoids the more expensive length comparison * for most vertex pairs. */ diff --git a/source/blender/bmesh/operators/bmo_split_edges.c b/source/blender/bmesh/operators/bmo_split_edges.c index 7eea4c4878d..eb7946caff0 100644 --- a/source/blender/bmesh/operators/bmo_split_edges.c +++ b/source/blender/bmesh/operators/bmo_split_edges.c @@ -29,6 +29,7 @@ #include "BLI_utildefines.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "intern/bmesh_operators_private.h" /* own include */ diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index e669585a857..b3b9cecf389 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -921,7 +921,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } if (BMO_elem_flag_test(bm, face, FACE_CUSTOMFILL)) { - pat = BMO_slot_map_data_get(params.slot_custom_patterns, face); + pat = *BMO_slot_map_data_get(params.slot_custom_patterns, face); for (i = 0; i < pat->len; i++) { matched = 1; for (j = 0; j < pat->len; j++) { diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index fa39ae68cdf..13a7aa09335 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -203,7 +203,7 @@ finally: /* -------------------------------------------------------------------- */ /* Edge Loop Pairs */ /* key (ordered loop pointers) */ -static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim) +static GSet *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim) { /** * Method for for finding pairs: @@ -219,7 +219,7 @@ static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim) * could sort and optimize this but not really so important. */ - GHash *eloop_pair_gh = BLI_ghash_pair_new(__func__); + GSet *eloop_pair_gs = BLI_gset_pair_new(__func__); GHash *vert_eloop_gh = BLI_ghash_ptr_new(__func__); struct BMEdgeLoopStore *el_store; @@ -256,9 +256,9 @@ static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim) if (pair_test.first > pair_test.second) SWAP(const void *, pair_test.first, pair_test.second); - if (!BLI_ghash_haskey(eloop_pair_gh, &pair_test)) { + if (!BLI_gset_haskey(eloop_pair_gs, &pair_test)) { GHashPair *pair = BLI_ghashutil_pairalloc(pair_test.first, pair_test.second); - BLI_ghash_insert(eloop_pair_gh, pair, NULL); + BLI_gset_insert(eloop_pair_gs, pair); } } @@ -268,12 +268,12 @@ static GHash *bm_edgering_pair_calc(BMesh *bm, ListBase *eloops_rim) BLI_ghash_free(vert_eloop_gh, NULL, NULL); - if (BLI_ghash_size(eloop_pair_gh) == 0) { - BLI_ghash_free(eloop_pair_gh, NULL, NULL); - eloop_pair_gh = NULL; + if (BLI_gset_size(eloop_pair_gs) == 0) { + BLI_gset_free(eloop_pair_gs, NULL); + eloop_pair_gs = NULL; } - return eloop_pair_gh; + return eloop_pair_gs; } @@ -919,13 +919,13 @@ static void bm_edgering_pair_order(BMesh *bm, } BLI_assert(node != NULL); - BLI_rotatelist(lb_b, node); + BLI_rotatelist_first(lb_b, node); /* now check we are winding the same way */ if (bm_edgering_pair_order_is_flipped(bm, el_store_a, el_store_b)) { BM_edgeloop_flip(bm, el_store_b); /* re-ensure the first node */ - BLI_rotatelist(lb_b, node); + BLI_rotatelist_first(lb_b, node); } /* sanity checks that we are aligned & winding now */ @@ -1175,23 +1175,23 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) } } else { - GHashIterator gh_iter; + GSetIterator gs_iter; int i; - GHash *eloop_pairs_gh = bm_edgering_pair_calc(bm, &eloops_rim); + GSet *eloop_pairs_gs = bm_edgering_pair_calc(bm, &eloops_rim); LoopPairStore **lpair_arr; - if (eloop_pairs_gh == NULL) { + if (eloop_pairs_gs == NULL) { BMO_error_raise(bm, op, BMERR_INVALID_SELECTION, "Edge-rings are not connected"); goto cleanup; } - lpair_arr = BLI_array_alloca(lpair_arr, BLI_ghash_size(eloop_pairs_gh)); + lpair_arr = BLI_array_alloca(lpair_arr, BLI_gset_size(eloop_pairs_gs)); /* first cache pairs */ - GHASH_ITER_INDEX (gh_iter, eloop_pairs_gh, i) { - GHashPair *eloop_pair = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) { + GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter); struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first; struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second; LoopPairStore *lpair; @@ -1207,8 +1207,8 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) BLI_assert(bm_verts_tag_count(bm) == 0); } - GHASH_ITER_INDEX (gh_iter, eloop_pairs_gh, i) { - GHashPair *eloop_pair = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER_INDEX (gs_iter, eloop_pairs_gs, i) { + GHashPair *eloop_pair = BLI_gsetIterator_getKey(&gs_iter); struct BMEdgeLoopStore *el_store_a = (void *)eloop_pair->first; struct BMEdgeLoopStore *el_store_b = (void *)eloop_pair->second; LoopPairStore *lpair = lpair_arr[i]; @@ -1222,7 +1222,7 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) BLI_assert(bm_verts_tag_count(bm) == 0); } - BLI_ghash_free(eloop_pairs_gh, MEM_freeN, NULL); + BLI_gset_free(eloop_pairs_gs, MEM_freeN); } cleanup: diff --git a/source/blender/bmesh/operators/bmo_symmetrize.c b/source/blender/bmesh/operators/bmo_symmetrize.c index dd720c9cc0f..4b538dccb4e 100644 --- a/source/blender/bmesh/operators/bmo_symmetrize.c +++ b/source/blender/bmesh/operators/bmo_symmetrize.c @@ -15,7 +15,7 @@ * 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): Nicholas Bishop + * Contributor(s): Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ @@ -29,656 +29,81 @@ #include "MEM_guardedalloc.h" -#include "BLI_array.h" -#include "BLI_math.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "bmesh.h" #include "intern/bmesh_operators_private.h" -enum { - SYMM_OUTPUT_GEOM = (1 << 0) -}; - -/* Note: don't think there's much need to make these user-adjustable? */ -#define SYMM_AXIS_THRESHOLD 0.00002f -#define SYMM_VERT_THRESHOLD 0.00002f - -typedef enum { - /* Coordinate lies on the side being copied from */ - SYMM_SIDE_KEEP, - /* Coordinate lies on the side being copied from and within the - * axis threshold */ - SYMM_SIDE_AXIS, - /* Coordinate lies on the side being copied to */ - SYMM_SIDE_KILL -} SymmSide; - -typedef struct { - BMesh *bm; - BMOperator *op; - - int axis; - BMO_SymmDirection direction; - - /* Maps from input vertices to their mirrors. If the vertex - * doesn't have a mirror, it's not in this map. If the vertex is - * within the axis threshold, it's mapped to itself. */ - GHash *vert_symm_map; - - /* Edges that cross the symmetry plane and are asymmetric get - * split. This map goes from input edges to output vertices. If an - * edge is not split, it's not in this map. */ - GHash *edge_split_map; -} Symm; - -/* Return which side the coordinate lies on */ -static SymmSide symm_co_side(const Symm *symm, - const float *co) -{ - float comp = co[symm->axis]; - if (ELEM3(symm->direction, - BMO_SYMMETRIZE_NEGATIVE_X, - BMO_SYMMETRIZE_NEGATIVE_Y, - BMO_SYMMETRIZE_NEGATIVE_Z)) - { - comp = -comp; - } - - if (comp >= 0) { - if (comp < SYMM_AXIS_THRESHOLD) - return SYMM_SIDE_AXIS; - else - return SYMM_SIDE_KEEP; - } - else - return SYMM_SIDE_KILL; -} - -/* Output vertices and the vert_map array */ -static void symm_verts_mirror(Symm *symm) -{ - BMOIter oiter; - BMVert *src_v, *dst_v; - - symm->vert_symm_map = BLI_ghash_ptr_new(__func__); - - BMO_ITER (src_v, &oiter, symm->op->slots_in, "input", BM_VERT) { - SymmSide side = symm_co_side(symm, src_v->co); - float co[3]; - - switch (side) { - case SYMM_SIDE_KEEP: - /* The vertex is outside the axis area; output its mirror */ - copy_v3_v3(co, src_v->co); - co[symm->axis] = -co[symm->axis]; - - dst_v = BM_vert_create(symm->bm, co, src_v, 0); - BMO_elem_flag_enable(symm->bm, dst_v, SYMM_OUTPUT_GEOM); - BLI_ghash_insert(symm->vert_symm_map, src_v, dst_v); - break; - - case SYMM_SIDE_AXIS: - /* The vertex is within the axis area, snap to center */ - src_v->co[symm->axis] = 0; - /* Vertex isn't copied, map to itself */ - BLI_ghash_insert(symm->vert_symm_map, src_v, src_v); - break; - - case SYMM_SIDE_KILL: - /* The vertex does not lie in the half-space being - * copied from, nothing to do */ - break; - } - } -} - -static int symm_edge_crosses_axis(const Symm *symm, const BMEdge *e) -{ - const int sides[2] = {symm_co_side(symm, e->v1->co), - symm_co_side(symm, e->v2->co)}; - - return ((sides[0] != SYMM_SIDE_AXIS) && - (sides[1] != SYMM_SIDE_AXIS) && - (sides[0] != sides[1])); -} - -/* Output edge split vertices for asymmetric edges and the edge_splits - * mapping array */ -static void symm_split_asymmetric_edges(Symm *symm) -{ - BMOIter oiter; - BMEdge *e; - - symm->edge_split_map = BLI_ghash_ptr_new(__func__); - - BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { - float flipped[3]; - - copy_v3_v3(flipped, e->v1->co); - flipped[symm->axis] = -flipped[symm->axis]; - - if (symm_edge_crosses_axis(symm, e) && - (!compare_v3v3(e->v2->co, flipped, SYMM_VERT_THRESHOLD))) - { - /* Endpoints lie on opposite sides and are asymmetric */ - - BMVert *v; - float lambda = 0, edge_dir[3], co[3]; - float plane_co[3][3][3] = { - /* axis == 0 */ - {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}}, - /* axis == 1 */ - {{0, 0, 0}, {1, 0, 0}, {0, 0, 1}}, - /* axis == 2 */ - {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}}, - }; - int r; - - /* Find intersection of edge with symmetry plane */ - sub_v3_v3v3(edge_dir, e->v2->co, e->v1->co); - normalize_v3(edge_dir); - r = isect_ray_plane_v3(e->v1->co, - edge_dir, - plane_co[symm->axis][0], - plane_co[symm->axis][1], - plane_co[symm->axis][2], - &lambda, true); - BLI_assert(r); +#define ELE_OUT 1 - madd_v3_v3v3fl(co, e->v1->co, edge_dir, lambda); - co[symm->axis] = 0; - - /* Edge is asymmetric, split it with a new vertex */ - v = BM_vert_create(symm->bm, co, e->v1, 0); - BMO_elem_flag_enable(symm->bm, v, SYMM_OUTPUT_GEOM); - BLI_ghash_insert(symm->edge_split_map, e, v); - } - } -} - -static void symm_mirror_edges(Symm *symm) -{ - BMOIter oiter; - BMEdge *e; - - BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { - BMVert *v1 = NULL, *v2 = NULL; - BMEdge *e_new; - - v1 = BLI_ghash_lookup(symm->vert_symm_map, e->v1); - v2 = BLI_ghash_lookup(symm->vert_symm_map, e->v2); - - if (v1 && v2) { - e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE); - BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); - } - else if (v1 || v2) { - BMVert *v_split = BLI_ghash_lookup(symm->edge_split_map, e); - if (v_split) { - /* Output the keep side of the split edge */ - if (!v1) { - e_new = BM_edge_create(symm->bm, v_split, e->v2, e, BM_CREATE_NO_DOUBLE); - BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); - v1 = v_split; - } - else { - e_new = BM_edge_create(symm->bm, e->v1, v_split, e, BM_CREATE_NO_DOUBLE); - BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); - v2 = v_split; - } - - /* Output the kill side of the split edge */ - e_new = BM_edge_create(symm->bm, v1, v2, e, BM_CREATE_NO_DOUBLE); - BMO_elem_flag_enable(symm->bm, e_new, SYMM_OUTPUT_GEOM); - } - } - } -} - -/****************************** SymmPoly ******************************/ - -typedef struct { - /* Indices into the source mvert array (or -1 if not in that array) */ - BMVert **src_verts; - /* Indices into the destination mvert array, these are vertices - * created by an edge split (-1 for vertices not created by edge - * split) */ - BMVert **edge_verts; - - /* Number of vertices in the polygon */ - int len; - - /* True only if none of the polygon's edges were split */ - bool already_symmetric; - - BMFace *src_face; -} SymmPoly; - -static void symm_poly_with_splits(const Symm *symm, - BMFace *f, - SymmPoly *out) -{ - BMIter iter; - BMLoop *l; - int i; - - out->src_face = f; - - /* Count vertices and check for edge splits */ - out->len = f->len; - out->already_symmetric = true; - BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { - if (BLI_ghash_haskey(symm->edge_split_map, l->e)) { - out->len++; - out->already_symmetric = false; - } - } - - i = 0; - BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { - BMVert *split = BLI_ghash_lookup(symm->edge_split_map, l->e); - - out->src_verts[i] = l->v; - out->edge_verts[i] = NULL; - i++; - - if (split) { - out->src_verts[i] = NULL; - out->edge_verts[i] = split; - i++; - } - } -} - -static const float *symm_poly_co(const SymmPoly *sp, int v) -{ - if (sp->src_verts[v]) - return sp->src_verts[v]->co; - else if (sp->edge_verts[v]) - return sp->edge_verts[v]->co; - else - return NULL; -} - -static SymmSide symm_poly_co_side(const Symm *symm, - const SymmPoly *sp, - int v) -{ - return symm_co_side(symm, symm_poly_co(sp, v)); -} - -/* Return the index of the vertex in the destination array at corner - * 'v' of the polygon, or -1 if not in that array */ -static BMVert *symm_poly_dst(const SymmPoly *sp, int v) -{ - if (sp->edge_verts[v]) - return sp->edge_verts[v]; - else if (sp->src_verts[v]) - return sp->src_verts[v]; - else - return NULL; -} - -/* Same as above, but returns the index of the mirror if available, or - * the same index if on the axis, or -1 otherwise */ -static BMVert *symm_poly_mirror_dst(const Symm *symm, - const SymmPoly *sp, - int v) -{ - if (sp->edge_verts[v]) - return sp->edge_verts[v]; - else if (sp->src_verts[v]) { - BMVert *v_src = BLI_ghash_lookup(symm->vert_symm_map, sp->src_verts[v]); - if (v_src) - return v_src; - else - return sp->src_verts[v]; - } - else - return NULL; -} - -static bool symm_poly_next_crossing(const Symm *symm, - const SymmPoly *sp, - int start, - int *l1, - int *l2) -{ - int i; - - for (i = 0; i < sp->len; i++) { - (*l1) = (start + i) % sp->len; - (*l2) = ((*l1) + 1) % sp->len; - - if ((symm_poly_co_side(symm, sp, *l1) == SYMM_SIDE_KILL) ^ - (symm_poly_co_side(symm, sp, *l2) == SYMM_SIDE_KILL)) - { - return true; - } - } - - BLI_assert(!"symm_poly_next_crossing failed"); - return false; -} - -static BMFace *symm_face_create_v(BMesh *bm, BMFace *example, - BMVert **fv, BMEdge **fe, int len) -{ - BMFace *f_new; - int i; - - /* TODO: calling symmetrize in dynamic-topology sculpt mode - * frequently tries to create faces of length less than two, - * should investigate further */ - if (len < 3) - return NULL; - - for (i = 0; i < len; i++) { - int j = (i + 1) % len; - fe[i] = BM_edge_exists(fv[i], fv[j]); - if (!fe[i]) { - fe[i] = BM_edge_create(bm, fv[i], fv[j], NULL, 0); - BMO_elem_flag_enable(bm, fe[i], SYMM_OUTPUT_GEOM); - } - } - f_new = BM_face_create(bm, fv, fe, len, BM_CREATE_NO_DOUBLE); - if (example) - BM_elem_attrs_copy(bm, bm, example, f_new); - BM_face_select_set(bm, f_new, true); - BMO_elem_flag_enable(bm, f_new, SYMM_OUTPUT_GEOM); - - return f_new; -} - -static void symm_mesh_output_poly_zero_splits(Symm *symm, - SymmPoly *sp, - BMVert **fv, - BMEdge **fe, - int segment_len, - int start) -{ - int i, j; - - j = 0; - - /* Output the keep side of the input polygon */ - for (i = 0; i < segment_len; i++) { - const int offset = (start + i) % sp->len; - BLI_assert(sp->src_verts[offset]); - fv[j++] = sp->src_verts[offset]; - } - - /* Output the kill side of the polygon */ - for (i = segment_len - 1; i >= 0; i--) { - const int offset = (start + i) % sp->len; - - if (symm_poly_co_side(symm, sp, offset) == SYMM_SIDE_KEEP) { - BLI_assert(sp->src_verts[offset]); - fv[j++] = BLI_ghash_lookup(symm->vert_symm_map, - sp->src_verts[offset]); - } - } - - symm_face_create_v(symm->bm, sp->src_face, fv, fe, j); -} - -static void symm_mesh_output_poly_with_splits(Symm *symm, - SymmPoly *sp, - BMVert **fv, - BMEdge **fe, - int segment_len, - int start) -{ - int i; - - /* Output the keep side of the input polygon */ - - for (i = 0; i < segment_len; i++) { - const int offset = (start + i) % sp->len; - BMVert *v = symm_poly_dst(sp, offset); - - BLI_assert(v); - - fv[i] = v; - } - - symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len); - - /* Output the kill side of the input polygon */ - - for (i = 0; i < segment_len; i++) { - const int offset = (start + i) % sp->len; - BMVert *v = symm_poly_mirror_dst(symm, sp, offset); - - fv[segment_len - i - 1] = v; - - } - - symm_face_create_v(symm->bm, sp->src_face, fv, fe, segment_len); -} - -static void symm_mirror_polygons(Symm *symm) +void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) { - BMOIter oiter; - BMFace *f; - BMVert **pv = NULL; - BMVert **fv = NULL; - BMEdge **fe = NULL; - BLI_array_declare(pv); - BLI_array_declare(fv); - BLI_array_declare(fe); - - BMO_ITER (f, &oiter, symm->op->slots_in, "input", BM_FACE) { - BMIter iter; - BMLoop *l; - bool mirror_all = true, ignore_all = true; - - /* Check if entire polygon can be mirrored or ignored */ - BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { - const SymmSide side = symm_co_side(symm, l->v->co); - if (side == SYMM_SIDE_KILL) - mirror_all = false; - else if (side == SYMM_SIDE_KEEP) - ignore_all = false; - } - - if (mirror_all) { - int i; - - /* Make a mirrored copy of the polygon */ - - BLI_array_empty(fv); - BLI_array_empty(fe); - BLI_array_grow_items(fv, f->len); - BLI_array_grow_items(fe, f->len); - - i = f->len; - BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { - i--; - - if (symm_co_side(symm, l->v->co) == SYMM_SIDE_KEEP) - fv[i] = BLI_ghash_lookup(symm->vert_symm_map, l->v); - else - fv[i] = l->v; - } - - symm_face_create_v(symm->bm, f, fv, fe, f->len); - } - else if (ignore_all) { - BM_face_kill(symm->bm, f); - } - else { - SymmPoly sp; - int l1, l2, l3, l4; - int double_l2, double_l3; - int segment_len; + const float dist = BMO_slot_float_get(op->slots_in, "dist"); + const int direction = BMO_slot_int_get(op->slots_in, "direction"); + const int axis = direction % 3; - BLI_array_empty(pv); - BLI_array_grow_items(pv, f->len * 4); - sp.src_verts = pv; - sp.edge_verts = pv + f->len * 2; - symm_poly_with_splits(symm, f, &sp); + BMOperator op_bisect; + BMOperator op_dupe; + BMOperator op_weld; - /* Find first loop edge crossing the axis */ - symm_poly_next_crossing(symm, &sp, 0, &l1, &l2); + BMOpSlot *slot_vertmap; + BMOpSlot *slot_targetmap; - /* If crossing isn't kill to keep, find the next one */ - if (symm_poly_co_side(symm, &sp, l1) != SYMM_SIDE_KILL) { - symm_poly_next_crossing(symm, &sp, l2, &l1, &l2); - } + float plane_no[3]; + float scale[3]; - /* Find next crossing (keep to kill) */ - symm_poly_next_crossing(symm, &sp, l2, &l3, &l4); - - if (l2 == l3) - segment_len = 0; - else if (l2 < l3) - segment_len = l3 - l2 + 1; - else - segment_len = (sp.len - l2 + 1) + l3; - - double_l2 = symm_poly_co_side(symm, &sp, l2) == SYMM_SIDE_KEEP; - double_l3 = symm_poly_co_side(symm, &sp, l3) == SYMM_SIDE_KEEP; + BMOIter siter; + BMVert *v; - /* Calculate number of new polygons/loops */ - if (segment_len == 0) { - } - else if (sp.already_symmetric) { - int new_loops; + copy_v3_fl(plane_no, 0.0f); + copy_v3_fl(scale, 1.0f); - if (double_l2 && double_l3) - new_loops = segment_len * 2; - else if (!double_l2 && !double_l3) - new_loops = segment_len * 2 - 2; - else - new_loops = segment_len * 2 - 1; + plane_no[axis] = direction > 2 ? 1.0f : -1.0f; + scale[axis] *= -1.0f; - BLI_array_empty(fv); - BLI_array_empty(fe); - BLI_array_grow_items(fv, new_loops); - BLI_array_grow_items(fe, new_loops); + /* Cut in half */ + BMO_op_initf(bm, &op_bisect, op->flag, + "bisect_plane geom=%s plane_no=%v dist=%f clear_outer=%b use_snap_center=%b", + op, "input", plane_no, dist, true, true); - symm_mesh_output_poly_zero_splits(symm, &sp, - fv, fe, - segment_len, l2); - BM_face_kill(symm->bm, f); - } - else if (!double_l2 && !double_l3) { - BLI_array_empty(fv); - BLI_array_empty(fe); - BLI_array_grow_items(fv, segment_len); - BLI_array_grow_items(fe, segment_len); + BMO_op_exec(bm, &op_bisect); - symm_mesh_output_poly_with_splits(symm, &sp, - fv, fe, - segment_len, - l2); + /* Duplicate */ + BMO_op_initf(bm, &op_dupe, op->flag, + "duplicate geom=%S", + &op_bisect, "geom.out"); - BM_face_kill(symm->bm, f); - } - else { - BLI_array_empty(fv); - BLI_array_empty(fe); - BLI_array_grow_items(fv, segment_len); - BLI_array_grow_items(fe, segment_len); + BMO_op_exec(bm, &op_dupe); - symm_mesh_output_poly_with_splits(symm, &sp, - fv, fe, - segment_len, - l2); + /* Flag for output (some will be merged) */ + BMO_slot_buffer_flag_enable(bm, op_bisect.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT); + BMO_slot_buffer_flag_enable(bm, op_dupe.slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT); - BM_face_kill(symm->bm, f); - /* Output bridge triangle */ + BMO_op_callf(bm, op->flag, "scale verts=%S vec=%v", &op_dupe, "geom.out", scale); + BMO_op_callf(bm, op->flag, "reverse_faces faces=%S", &op_dupe, "geom.out"); - BLI_array_empty(fv); - BLI_array_empty(fe); - BLI_array_grow_items(fv, 3); - BLI_array_grow_items(fe, 3); - if (double_l2) { - fv[0] = symm_poly_dst(&sp, l2); - fv[1] = symm_poly_mirror_dst(symm, &sp, l2); - fv[2] = symm_poly_dst(&sp, l3); - } - else if (double_l3) { - fv[0] = symm_poly_dst(&sp, l3); - fv[1] = symm_poly_mirror_dst(symm, &sp, l3); - fv[2] = symm_poly_dst(&sp, l2); - } + /* Weld verts */ + BMO_op_init(bm, &op_weld, op->flag, "weld_verts"); - BLI_assert(fv[0] && fv[1] && fv[2]); + slot_vertmap = BMO_slot_get(op_dupe.slots_out, "vert_map.out"); + slot_targetmap = BMO_slot_get(op_weld.slots_in, "targetmap"); - symm_face_create_v(symm->bm, NULL, fv, fe, 3); - } - } + BMO_ITER (v, &siter, op_bisect.slots_out, "geom_cut.out", BM_VERT) { + BMVert *v_dupe = BMO_slot_map_elem_get(slot_vertmap, v); + BMO_slot_map_elem_insert(&op_weld, slot_targetmap, v_dupe, v); } - BLI_array_free(pv); - BLI_array_free(fv); - BLI_array_free(fe); -} - -/* Remove unused edges and vertices from the side being copied to */ -static void symm_kill_unused(Symm *symm) -{ - BMOIter oiter; - BMEdge *e; - BMVert *v; - - /* Kill unused edges */ - BMO_ITER (e, &oiter, symm->op->slots_in, "input", BM_EDGE) { - const int crosses = symm_edge_crosses_axis(symm, e); - const int symmetric = (crosses && - (!BLI_ghash_haskey(symm->edge_split_map, e))); - - if (((symm_co_side(symm, e->v1->co) == SYMM_SIDE_KILL) || - (symm_co_side(symm, e->v2->co) == SYMM_SIDE_KILL)) && - !symmetric) - { - /* The edge might be used by a face outside the input set */ - if (BM_edge_is_wire(e)) - BM_edge_kill(symm->bm, e); - } - } - - /* Kill unused vertices */ - BMO_ITER (v, &oiter, symm->op->slots_in, "input", BM_VERT) { - if (symm_co_side(symm, v->co) == SYMM_SIDE_KILL) { - if (BM_vert_edge_count(v) == 0) - BM_vert_kill(symm->bm, v); - } - } -} - -void bmo_symmetrize_exec(BMesh *bm, BMOperator *op) -{ - Symm symm; - BMO_SymmDirection direction = BMO_slot_int_get(op->slots_in, "direction"); - - symm.bm = bm; - symm.op = op; - symm.axis = (ELEM(direction, - BMO_SYMMETRIZE_NEGATIVE_X, - BMO_SYMMETRIZE_POSITIVE_X) ? 0 : - ELEM(direction, - BMO_SYMMETRIZE_NEGATIVE_Y, - BMO_SYMMETRIZE_POSITIVE_Y) ? 1 : - ELEM(direction, - BMO_SYMMETRIZE_NEGATIVE_Z, - BMO_SYMMETRIZE_POSITIVE_Z) ? 2 : 0); - symm.direction = direction; + BMO_op_exec(bm, &op_weld); - symm_verts_mirror(&symm); - symm_split_asymmetric_edges(&symm); - symm_mirror_edges(&symm); - symm_mirror_polygons(&symm); - symm_kill_unused(&symm); + /* Cleanup */ + BMO_op_finish(bm, &op_weld); - BLI_ghash_free(symm.vert_symm_map, NULL, NULL); - BLI_ghash_free(symm.edge_split_map, NULL, NULL); + BMO_op_finish(bm, &op_dupe); + BMO_op_finish(bm, &op_bisect); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", - BM_ALL_NOLOOP, SYMM_OUTPUT_GEOM); + /* Create output */ + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_ALL_NOLOOP, ELE_OUT); } diff --git a/source/blender/bmesh/operators/bmo_triangulate.c b/source/blender/bmesh/operators/bmo_triangulate.c index 754709b18c0..590b5ea97c4 100644 --- a/source/blender/bmesh/operators/bmo_triangulate.c +++ b/source/blender/bmesh/operators/bmo_triangulate.c @@ -34,6 +34,7 @@ #include "BLI_scanfill.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "intern/bmesh_operators_private.h" @@ -58,6 +59,7 @@ void bmo_triangulate_exec(BMesh *bm, BMOperator *op) void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) { const bool use_beauty = BMO_slot_bool_get(op->slots_in, "use_beauty"); + const bool use_dissolve = BMO_slot_bool_get(op->slots_in, "use_dissolve"); BMOIter siter; BMEdge *e; ScanFillContext sf_ctx; @@ -65,8 +67,11 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) ScanFillVert *sf_vert, *sf_vert_1, *sf_vert_2; ScanFillFace *sf_tri; SmallHash hash; + float normal[3], *normal_pt; BLI_smallhash_init(&hash); + + BMO_slot_vec_get(op->slots_in, "normal", normal); BLI_scanfill_begin(&sf_ctx); @@ -91,7 +96,15 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) /* sf_edge->tmp.p = e; */ /* UNUSED */ } - BLI_scanfill_calc(&sf_ctx, BLI_SCANFILL_CALC_HOLES); + if (is_zero_v3(normal)) { + normal_pt = NULL; + } + else { + normalize_v3(normal); + normal_pt = normal; + } + + BLI_scanfill_calc_ex(&sf_ctx, BLI_SCANFILL_CALC_HOLES, normal_pt); for (sf_tri = sf_ctx.fillfacebase.first; sf_tri; sf_tri = sf_tri->next) { BMFace *f = BM_face_create_quad_tri(bm, @@ -121,4 +134,27 @@ void bmo_triangle_fill_exec(BMesh *bm, BMOperator *op) } BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); + + if (use_dissolve) { + BMO_ITER (e, &siter, op->slots_out, "geom.out", BM_EDGE) { + if (LIKELY(e->l)) { /* in rare cases the edges face will have already been removed from the edge */ + BMFace *f_new; + f_new = BM_faces_join_pair(bm, e->l->f, + e->l->radial_next->f, e, + false); /* join faces */ + if (f_new) { + BMO_elem_flag_enable(bm, f_new, ELE_NEW); + BM_edge_kill(bm, e); + } + else { + BMO_error_clear(bm); + } + } + else { + BM_edge_kill(bm, e); + } + } + + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "geom.out", BM_EDGE | BM_FACE, ELE_NEW); + } } diff --git a/source/blender/bmesh/operators/bmo_unsubdivide.c b/source/blender/bmesh/operators/bmo_unsubdivide.c index c1cfb1866f4..ec222b48751 100644 --- a/source/blender/bmesh/operators/bmo_unsubdivide.c +++ b/source/blender/bmesh/operators/bmo_unsubdivide.c @@ -31,6 +31,7 @@ #include "BLI_utildefines.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "intern/bmesh_operators_private.h" /* own include */ diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index 8b8cab9d881..e23358bf4ff 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -41,14 +41,16 @@ #include "intern/bmesh_operators_private.h" /* own include */ +#define ELE_NEW 1 + void bmo_create_vert_exec(BMesh *bm, BMOperator *op) { float vec[3]; BMO_slot_vec_get(op->slots_in, "co", vec); - BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL, 0), 1); - BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, 1); + BMO_elem_flag_enable(bm, BM_vert_create(bm, vec, NULL, BM_CREATE_NOP), ELE_NEW); + BMO_slot_buffer_from_enabled_flag(bm, op, op->slots_out, "vert.out", BM_VERT, ELE_NEW); } void bmo_transform_exec(BMesh *UNUSED(bm), BMOperator *op) diff --git a/source/blender/bmesh/operators/bmo_wireframe.c b/source/blender/bmesh/operators/bmo_wireframe.c index c07e2c3bbf2..e87dd29b153 100644 --- a/source/blender/bmesh/operators/bmo_wireframe.c +++ b/source/blender/bmesh/operators/bmo_wireframe.c @@ -229,9 +229,9 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } madd_v3_v3v3fl(tvec, v_src->co, v_src->no, -fac); - verts_neg[i] = BM_vert_create(bm, tvec, v_src, 0); + verts_neg[i] = BM_vert_create(bm, tvec, v_src, BM_CREATE_NOP); madd_v3_v3v3fl(tvec, v_src->co, v_src->no, fac); - verts_pos[i] = BM_vert_create(bm, tvec, v_src, 0); + verts_pos[i] = BM_vert_create(bm, tvec, v_src, BM_CREATE_NOP); } else { /* could skip this */ @@ -269,7 +269,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) } madd_v3_v3v3fl(tvec, l->v->co, tvec, fac); - verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, 0); + verts_loop[verts_loop_tot] = BM_vert_create(bm, tvec, l->v, BM_CREATE_NOP); if (use_boundary) { @@ -303,7 +303,7 @@ void bmo_wireframe_exec(BMesh *bm, BMOperator *op) fac *= verts_relfac[BM_elem_index_get(l_pair[i]->v)]; } madd_v3_v3v3fl(tvec, l_pair[i]->v->co, tvec, fac); - verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v, 0); + verts_boundary[BM_elem_index_get(l_pair[i]->v)] = BM_vert_create(bm, tvec, l_pair[i]->v, BM_CREATE_NOP); } } } diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 27ca8c6ccc0..adeb3fdc630 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -42,6 +42,8 @@ #include "BKE_deform.h" #include "bmesh.h" +#include "bmesh_bevel.h" /* own include */ + #include "./intern/bmesh_private.h" #define BEVEL_EPSILON_D 1e-6 @@ -177,7 +179,7 @@ static NewVert *mesh_vert(VMesh *vm, int i, int j, int k) static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg) { NewVert *nv = mesh_vert(vm, i, j, k); - nv->v = BM_vert_create(bm, nv->co, eg, 0); + nv->v = BM_vert_create(bm, nv->co, eg, BM_CREATE_NOP); BM_elem_flag_disable(nv->v, BM_ELEM_TAG); } @@ -255,20 +257,8 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, const int totv, BMFace *f, *interp_f; int i; - if (totv == 3) { - f = BM_face_create_quad_tri_v(bm, vert_arr, 3, facerep, FALSE); - } - else if (totv == 4) { - f = BM_face_create_quad_tri_v(bm, vert_arr, 4, facerep, FALSE); - } - else { - BMEdge **ee = BLI_array_alloca(ee, totv); + f = BM_face_create_verts(bm, vert_arr, totv, facerep, BM_CREATE_NOP, true); - for (i = 0; i < totv; i++) { - ee[i] = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, BM_CREATE_NO_DOUBLE); - } - f = BM_face_create(bm, vert_arr, ee, totv, 0); - } if ((facerep || (face_arr && face_arr[0])) && f) { BM_elem_attrs_copy(bm, bm, facerep ? facerep : face_arr[0], f); if (do_interp) { @@ -744,14 +734,14 @@ static void snap_to_edge_profile(EdgeHalf *e, const float va[3], const float vb[ float co[3]) { float m[4][4], minv[4][4]; - float edir[3], va0[3], vb0[3], vmid0[3], p[3], snap[3]; + float edir[3], va0[3], vb0[3], vmid0[3], p[3], snap[3], plane[4]; sub_v3_v3v3(edir, e->e->v1->co, e->e->v2->co); - normalize_v3(edir); /* project va and vb onto plane P, with normal edir and containing co */ - closest_to_plane_v3(va0, co, edir, va); - closest_to_plane_v3(vb0, co, edir, vb); + plane_from_point_normal_v3(plane, co, edir); + closest_to_plane_v3(va0, plane, va); + closest_to_plane_v3(vb0, plane, vb); project_to_edge(e->e, va0, vb0, vmid0); if (make_unit_square_map(va0, vmid0, vb0, m)) { /* Transform co and project it onto the unit circle. @@ -1143,7 +1133,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) mul_v3_fl(midco, 1.0f / nn); if (epipe) snap_to_edge_profile(epipe, va_pipe, vb_pipe, midco); - bmv = BM_vert_create(bm, midco, NULL, 0); + bmv = BM_vert_create(bm, midco, NULL, BM_CREATE_NOP); v = vm->boundstart; do { i = v->index; diff --git a/source/blender/bmesh/tools/bmesh_bisect_plane.c b/source/blender/bmesh/tools/bmesh_bisect_plane.c new file mode 100644 index 00000000000..3baf8675a0d --- /dev/null +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.c @@ -0,0 +1,412 @@ +/* + * ***** 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/bmesh/tools/bmesh_bisect_plane.c + * \ingroup bmesh + * + * Cut the geometry in half using a plane. + * + * \par Implementation + * This simply works by splitting tagged edges whos verts span either side of + * the plane, then splitting faces along their dividing verts. + * The only complex case is when a ngon spans the axis multiple times, + * in this case we need to do some extra checks to correctly bisect the ngon. + * see: #bm_face_bisect_verts + */ + +#include <limits.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_alloca.h" +#include "BLI_mempool.h" +#include "BLI_linklist.h" +#include "BLI_linklist_stack.h" +#include "BLI_math.h" + +#include "bmesh.h" +#include "bmesh_bisect_plane.h" /* own include */ + +#include "BLI_strict_flags.h" /* keep last */ + + +/* -------------------------------------------------------------------- */ +/* Math utils */ + +static int plane_point_test_v3(const float plane[4], const float co[3], const float eps, float *r_depth) +{ + const float f = plane_point_side_v3(plane, co); + *r_depth = f; + + if (f <= -eps) return -1; + else if (f >= eps) return 1; + else return 0; +} + + +/* -------------------------------------------------------------------- */ +/* Wrappers to hide internal data-structure abuse, + * later we may want to move this into some hash lookup + * to a separate struct, but for now we can store in BMesh data */ + +#define BM_VERT_DIR(v) ((v)->head.index) /* Direction -1/0/1 */ +#define BM_VERT_DIST(v) ((v)->no[0]) /* Distance from the plane. */ +#define BM_VERT_SORTVAL(v) ((v)->no[1]) /* Temp value for sorting. */ +#define BM_VERT_LOOPINDEX(v) /* The verts index within a face (temp var) */ \ + (*((unsigned int *)(&(v)->no[2]))) + +/** + * Hide flag access + * (for more readable code since same flag is used differently for vert/edgeface)... + */ + +/* enable when vertex is in the center and its faces have been added to the stack */ +BLI_INLINE void vert_is_center_enable(BMVert *v) { BM_elem_flag_enable(v, BM_ELEM_TAG); } +BLI_INLINE void vert_is_center_disable(BMVert *v) { BM_elem_flag_disable(v, BM_ELEM_TAG); } +BLI_INLINE bool vert_is_center_test(BMVert *v) { return (BM_elem_flag_test(v, BM_ELEM_TAG) != 0); } + +/* enable when the edge can be cut */ +BLI_INLINE void edge_is_cut_enable(BMEdge *e) { BM_elem_flag_enable(e, BM_ELEM_TAG); } +BLI_INLINE void edge_is_cut_disable(BMEdge *e) { BM_elem_flag_disable(e, BM_ELEM_TAG); } +BLI_INLINE bool edge_is_cut_test(BMEdge *e) { return (BM_elem_flag_test(e, BM_ELEM_TAG) != 0); } + +/* enable when the faces are added to the stack */ +BLI_INLINE void face_in_stack_enable(BMFace *f) { BM_elem_flag_disable(f, BM_ELEM_TAG); } +BLI_INLINE void face_in_stack_disable(BMFace *f) { BM_elem_flag_enable(f, BM_ELEM_TAG); } +BLI_INLINE bool face_in_stack_test(BMFace *f) { return (BM_elem_flag_test(f, BM_ELEM_TAG) == 0); } + +/* -------------------------------------------------------------------- */ +/* BMesh utils */ + +static int bm_vert_sortval_cb(const void *v_a_v, const void *v_b_v) +{ + const float val_a = BM_VERT_SORTVAL(*((BMVert **)v_a_v)); + const float val_b = BM_VERT_SORTVAL(*((BMVert **)v_b_v)); + + if (val_a > val_b) return 1; + else if (val_a < val_b) return -1; + return 0; +} + + +static void bm_face_bisect_verts(BMesh *bm, BMFace *f, const float plane[4], const short oflag_center) +{ + /* unlikely more then 2 verts are needed */ + const unsigned int f_len_orig = (unsigned int)f->len; + BMVert **vert_split_arr = BLI_array_alloca(vert_split_arr, f_len_orig); + STACK_DECLARE(vert_split_arr); + BMLoop *l_iter, *l_first; + bool use_dirs[3] = {false, false, false}; + + STACK_INIT(vert_split_arr); + + l_first = BM_FACE_FIRST_LOOP(f); + + (void)bm; + (void)plane; + + /* add plane-aligned verts to the stack + * and check we have verts from both sides in this face, + * ... that the face doesn't only have boundry verts on the plane for eg. */ + l_iter = l_first; + do { + if (vert_is_center_test(l_iter->v)) { + BLI_assert(BM_VERT_DIR(l_iter->v) == 0); + STACK_PUSH(vert_split_arr, l_iter->v); + } + use_dirs[BM_VERT_DIR(l_iter->v) + 1] = true; + } while ((l_iter = l_iter->next) != l_first); + + if ((STACK_SIZE(vert_split_arr) > 1) && + (use_dirs[0] && use_dirs[2])) + { + BMLoop *l_new; + + if (LIKELY(STACK_SIZE(vert_split_arr) == 2)) { + /* common case, just cut the face once */ + l_new = NULL; + BM_face_split(bm, f, vert_split_arr[0], vert_split_arr[1], &l_new, NULL, true); + if (l_new) { + if (oflag_center) { + BMO_elem_flag_enable(bm, l_new->e, oflag_center); + BMO_elem_flag_enable(bm, l_new->f, oflag_center); + BMO_elem_flag_enable(bm, f, oflag_center); + } + } + } + else { + /* less common case, _complicated_ we need to calculate how to do multiple cuts */ + float (*face_verts_proj_2d)[2] = BLI_array_alloca(face_verts_proj_2d, f_len_orig); + float axis_mat[3][3]; + + BMFace **face_split_arr = BLI_array_alloca(face_split_arr, STACK_SIZE(vert_split_arr)); + STACK_DECLARE(face_split_arr); + + float sort_dir[3]; + unsigned int i; + + + /* ---- */ + /* Calculate the direction to sort verts in the face intersecting the plane */ + + /* exact dir isn't so important, + * just need a dir for sorting verts across face, + * 'sort_dir' could be flipped either way, it not important, we only need to order the array + */ + cross_v3_v3v3(sort_dir, f->no, plane); + if (UNLIKELY(normalize_v3(sort_dir) == 0.0f)) { + /* find any 2 verts and get their direction */ + for (i = 0; i < STACK_SIZE(vert_split_arr); i++) { + if (!equals_v3v3(vert_split_arr[0]->co, vert_split_arr[i]->co)) { + sub_v3_v3v3(sort_dir, vert_split_arr[0]->co, vert_split_arr[i]->co); + normalize_v3(sort_dir); + } + } + if (UNLIKELY(i == STACK_SIZE(vert_split_arr))) { + /* ok, we can't do anything useful here, + * face has no area or so, bail out, this is highly unlikely but not impossible */ + goto finally; + } + } + + + /* ---- */ + /* Calculate 2d coords to use for intersection checks */ + + /* get the faces 2d coords */ + BLI_assert(BM_face_is_normal_valid(f)); + axis_dominant_v3_to_m3(axis_mat, f->no); + + l_iter = l_first; + i = 0; + do { + BM_VERT_LOOPINDEX(l_iter->v) = i; + mul_v2_m3v3(face_verts_proj_2d[i], axis_mat, l_iter->v->co); + i++; + } while ((l_iter = l_iter->next) != l_first); + + + /* ---- */ + /* Sort the verts across the face from one side to another */ + for (i = 0; i < STACK_SIZE(vert_split_arr); i++) { + BMVert *v = vert_split_arr[i]; + BM_VERT_SORTVAL(v) = dot_v3v3(sort_dir, v->co); + } + + qsort(vert_split_arr, STACK_SIZE(vert_split_arr), sizeof(*vert_split_arr), bm_vert_sortval_cb); + + + /* ---- */ + /* Split the face across sorted splits */ + + /* note: we don't know which face gets which splits, + * so at the moment we have to search all faces for the vert pair, + * while not all that nice, typically there are < 5 resulting faces, + * so its not _that_ bad. */ + + STACK_INIT(face_split_arr); + STACK_PUSH(face_split_arr, f); + + for (i = 0; i < STACK_SIZE(vert_split_arr) - 1; i++) { + BMVert *v_a = vert_split_arr[i]; + BMVert *v_b = vert_split_arr[i + 1]; + float co_mid[2]; + + /* geometric test before doing face lookups, + * find if the split spans a filled region of the polygon. */ + mid_v2_v2v2(co_mid, + face_verts_proj_2d[BM_VERT_LOOPINDEX(v_a)], + face_verts_proj_2d[BM_VERT_LOOPINDEX(v_b)]); + + if (isect_point_poly_v2(co_mid, (const float (*)[2])face_verts_proj_2d, f_len_orig)) { + BMLoop *l_a, *l_b; + bool found = false; + unsigned int j; + + for (j = 0; j < STACK_SIZE(face_split_arr); j++) { + /* would be nice to avoid loop lookup here, + * but we need to know which face the verts are in */ + if ((l_a = BM_face_vert_share_loop(face_split_arr[j], v_a)) && + (l_b = BM_face_vert_share_loop(face_split_arr[j], v_b))) + { + found = true; + break; + } + } + + BLI_assert(found == true); + + /* in fact this simple test is good enough, + * test if the loops are adjacent */ + if (found && (l_a->next != l_b && l_a->prev != l_b)) { + BMFace *f_tmp; + f_tmp = BM_face_split(bm, face_split_arr[j], l_a->v, l_b->v, NULL, NULL, true); + if (f_tmp) { + if (f_tmp != face_split_arr[j]) { + STACK_PUSH(face_split_arr, f_tmp); + BLI_assert(STACK_SIZE(face_split_arr) <= STACK_SIZE(vert_split_arr)); + } + } + } + } + else { + // printf("no intersect\n"); + } + } + } + } + +finally: + STACK_FREE(vert_split_arr); + +} + +/* -------------------------------------------------------------------- */ +/* Main logic */ + +/** + * \param use_tag Only bisect tagged edges and faces. + * \param use_snap Snap verts onto the plane. + * \param oflag_center Operator flag, enabled for geometry on the axis (existing and created) + */ +void BM_mesh_bisect_plane(BMesh *bm, float plane[4], + const bool use_snap_center, const bool use_tag, + const short oflag_center, const float eps) +{ + unsigned int einput_len; + unsigned int i; + BMEdge **edges_arr = MEM_mallocN(sizeof(*edges_arr) * (size_t)bm->totedge, __func__); + + BLI_LINKSTACK_DECLARE(face_stack, BMFace *); + + BMVert *v; + BMFace *f; + + BMIter iter; + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + vert_is_center_disable(v); + + BM_VERT_DIR(v) = plane_point_test_v3(plane, v->co, eps, &(BM_VERT_DIST(v))); + if (BM_VERT_DIR(v) == 0) { + if (oflag_center) { + BMO_elem_flag_enable(bm, v, oflag_center); + } + if (use_snap_center) { + closest_to_plane_v3(v->co, plane, v->co); + } + } + } + + if (use_tag) { + /* build tagged edge array */ + BMEdge *e; + einput_len = 0; + /* keep face tags as is */ + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + if (edge_is_cut_test(e)) { + edges_arr[einput_len++] = e; + } + } + + } + else { + BMEdge *e; + einput_len = (unsigned int)bm->totedge; + BM_ITER_MESH_INDEX (e, &iter, bm, BM_EDGES_OF_MESH, i) { + edge_is_cut_enable(e); + edges_arr[i] = e; + } + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + face_in_stack_disable(f); + } + } + + /* store a stack of faces to be evaluated for splitting */ + BLI_LINKSTACK_INIT(face_stack); + + for (i = 0; i < einput_len; i++) { + /* we could check edge_is_cut_test(e) but there is no point */ + BMEdge *e = edges_arr[i]; + const int side[2] = {BM_VERT_DIR(e->v1), BM_VERT_DIR(e->v2)}; + const float dist[2] = {BM_VERT_DIST(e->v1), BM_VERT_DIST(e->v2)}; + + if (side[0] && side[1] && (side[0] != side[1])) { + const float e_fac = fabsf(dist[0]) / fabsf(dist[0] - dist[1]); + BMVert *v_new; + + if (e->l) { + BMLoop *l_iter, *l_first; + l_iter = l_first = e->l; + do { + if (!face_in_stack_test(l_iter->f)) { + face_in_stack_enable(l_iter->f); + BLI_LINKSTACK_PUSH(face_stack, l_iter->f); + } + } while ((l_iter = l_iter->radial_next) != l_first); + } + + v_new = BM_edge_split(bm, e, e->v1, NULL, e_fac); + vert_is_center_enable(v_new); + if (oflag_center) { + BMO_elem_flag_enable(bm, v_new, oflag_center); + } + + BM_VERT_DIR(v_new) = 0; + BM_VERT_DIST(v_new) = 0.0f; + } + else { + /* check if either edge verts are aligned, + * if so - tag and push all faces that use it into the stack */ + unsigned int j; + BM_ITER_ELEM_INDEX (v, &iter, e, BM_VERTS_OF_EDGE, j) { + if (side[j] == 0) { + if (vert_is_center_test(v) == 0) { + BMIter itersub; + BMLoop *l_iter; + + vert_is_center_enable(v); + + BM_ITER_ELEM (l_iter, &itersub, v, BM_LOOPS_OF_VERT) { + if (!face_in_stack_test(l_iter->f)) { + face_in_stack_enable(l_iter->f); + BLI_LINKSTACK_PUSH(face_stack, l_iter->f); + } + } + + } + } + } + } + } + + MEM_freeN(edges_arr); + + while ((f = BLI_LINKSTACK_POP(face_stack))) { + bm_face_bisect_verts(bm, f, plane, oflag_center); + } + + /* now we have all faces to split in the stack */ + BLI_LINKSTACK_FREE(face_stack); +} diff --git a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.h b/source/blender/bmesh/tools/bmesh_bisect_plane.h index 36668bc9338..15f902642c8 100644 --- a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.h +++ b/source/blender/bmesh/tools/bmesh_bisect_plane.h @@ -1,5 +1,5 @@ /* - * Copyright 2011, Blender Foundation. + * ***** 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 @@ -15,21 +15,20 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor: - * Jeroen Bakker - * Monique Dewanchand + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** */ -#ifndef _COM_RenderLayersAlphaProg_h -#define _COM_RenderLayersAlphaProg_h - -#include "COM_RenderLayersBaseProg.h" +#ifndef __BMESH_BISECT_PLANE_H__ +#define __BMESH_BISECT_PLANE_H__ -class RenderLayersAlphaProg : public RenderLayersBaseProg { -public: - RenderLayersAlphaProg(); - void executePixel(float output[4], float x, float y, PixelSampler sampler); +/** \file blender/bmesh/tools/bmesh_bisect_plane.h + * \ingroup bmesh + */ -}; +void BM_mesh_bisect_plane(BMesh *bm, float plane[4], + const bool use_snap_center, const bool use_tag, + const short oflag_center, const float eps); -#endif +#endif /* __BMESH_BISECT_PLANE_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c index 0667d560615..bc9288f98f6 100644 --- a/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/tools/bmesh_decimate_unsubdivide.c @@ -32,8 +32,7 @@ #include "BLI_math.h" #include "bmesh.h" - -#include "intern/bmesh_operators_private.h" /* own include */ +#include "bmesh_decimate.h" /* own include */ static bool bm_vert_dissolve_fan_test(BMVert *v) diff --git a/source/blender/bmesh/tools/bmesh_edgenet.c b/source/blender/bmesh/tools/bmesh_edgenet.c index ed5d47e9391..14d474fed61 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.c +++ b/source/blender/bmesh/tools/bmesh_edgenet.c @@ -37,14 +37,10 @@ #include "BLI_linklist.h" #include "bmesh.h" +#include "bmesh_edgenet.h" /* own include */ + +#include "BLI_strict_flags.h" /* keep last */ -#ifdef __GNUC__ -# pragma GCC diagnostic error "-Wsign-conversion" -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 /* gcc4.6+ only */ -# pragma GCC diagnostic error "-Wsign-compare" -# pragma GCC diagnostic error "-Wconversion" -# endif -#endif /* Data for one end of an edge involved in a bevel */ typedef struct VertNetInfo { @@ -117,7 +113,7 @@ static unsigned int bm_edgenet_path_from_pass( v_ls_tot += 1; v = vn->prev; vn = &vnet_info[BM_elem_index_get(v)]; - } while ((vn->pass == pass)); + } while (vn->pass == pass); return v_ls_tot; } @@ -132,7 +128,7 @@ static bool bm_edgenet_path_check_overlap( { /* vert order doesn't matter */ unsigned int v_ls_tot = 0; - LinkNode *v_ls; + LinkNode *v_ls = NULL; BMVert *v_pair[2] = {v1, v2}; unsigned int i; @@ -145,7 +141,7 @@ static bool bm_edgenet_path_check_overlap( v_ls_tot += 1; v = vn->prev; vn = &vnet_info[BM_elem_index_get(v)]; - } while ((vn->pass == pass)); + } while (vn->pass == pass); } if (v_ls_tot) { @@ -193,7 +189,7 @@ static BMFace *bm_edgenet_face_from_path( } #endif - f = BM_face_create(bm, vert_arr, edge_arr, (int)path_len, 0); + f = BM_face_create(bm, vert_arr, edge_arr, (int)path_len, NULL, BM_CREATE_NOP); return f; } @@ -443,7 +439,8 @@ static LinkNode *bm_edgenet_path_calc_best( * \param use_edge_tag Only fill tagged edges. * \param face_oflag if nonzero, apply all new faces with this bmo flag. */ -void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const short face_oflag) +void BM_mesh_edgenet(BMesh *bm, + const bool use_edge_tag, const bool use_new_face_tag) { VertNetInfo *vnet_info = MEM_callocN(sizeof(*vnet_info) * (size_t)bm->totvert, __func__); BLI_mempool *edge_queue_pool = BLI_mempool_create(sizeof(LinkNode), 1, 512, 0); @@ -491,8 +488,8 @@ void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const short face_oflag) } } while ((l_iter = l_iter->next) != l_first); - if (face_oflag) { - BMO_elem_flag_enable(bm, f, face_oflag); + if (use_new_face_tag) { + BM_elem_flag_enable(f, BM_ELEM_TAG); } /* the face index only needs to be unique, not kept valid */ diff --git a/source/blender/bmesh/tools/bmesh_edgenet.h b/source/blender/bmesh/tools/bmesh_edgenet.h index ffb3fa133da..327a7f5aa23 100644 --- a/source/blender/bmesh/tools/bmesh_edgenet.h +++ b/source/blender/bmesh/tools/bmesh_edgenet.h @@ -27,6 +27,7 @@ * \ingroup bmesh */ -void BM_mesh_edgenet(BMesh *bm, const bool use_edge_tag, const short face_oflag); +void BM_mesh_edgenet(BMesh *bm, + const bool use_edge_tag, const bool use_new_face_tag); #endif /* __BMESH_EDGENET_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_edgesplit.c b/source/blender/bmesh/tools/bmesh_edgesplit.c index aad600d13fa..412253aafe9 100644 --- a/source/blender/bmesh/tools/bmesh_edgesplit.c +++ b/source/blender/bmesh/tools/bmesh_edgesplit.c @@ -193,11 +193,13 @@ void BM_mesh_edgesplit(BMesh *bm, const bool use_verts, const bool tag_only, con bmesh_vert_separate(bm, v, &vtar, &vtar_len, copy_select); - if (vtar_len) { + /* first value is always in 'v' */ + if (vtar_len > 1) { BMEditSelection *ese = BLI_ghash_lookup(ese_gh, v); + BLI_assert(v == vtar[0]); if (UNLIKELY(ese)) { int j; - for (j = 0; j < vtar_len; j++) { + for (j = 1; j < vtar_len; j++) { BLI_assert(v != vtar[j]); BM_select_history_store_after_notest(bm, ese, vtar[j]); } diff --git a/source/blender/collada/CameraExporter.cpp b/source/blender/collada/CameraExporter.cpp index fc56ff8c63c..649288c2db4 100644 --- a/source/blender/collada/CameraExporter.cpp +++ b/source/blender/collada/CameraExporter.cpp @@ -63,7 +63,6 @@ void CamerasExporter::exportCameras(Scene *sce) } void CamerasExporter::operator()(Object *ob, Scene *sce) { - // TODO: shiftx, shifty, YF_dofdist Camera *cam = (Camera *)ob->data; std::string cam_id(get_camera_id(ob)); std::string cam_name(id_name(cam)); @@ -78,7 +77,9 @@ void CamerasExporter::operator()(Object *ob, Scene *sce) persp.setZFar(cam->clipend, false, "zfar"); persp.setZNear(cam->clipsta, false, "znear"); COLLADASW::Camera ccam(mSW, &persp, cam_id, cam_name); + exportBlenderProfile(ccam, cam); addCamera(ccam); + break; } case CAM_ORTHO: @@ -90,8 +91,17 @@ void CamerasExporter::operator()(Object *ob, Scene *sce) ortho.setZFar(cam->clipend, false, "zfar"); ortho.setZNear(cam->clipsta, false, "znear"); COLLADASW::Camera ccam(mSW, &ortho, cam_id, cam_name); + exportBlenderProfile(ccam, cam); addCamera(ccam); break; } } } +bool CamerasExporter::exportBlenderProfile(COLLADASW::Camera &cm,Camera *cam) +{ + cm.addExtraTechniqueParameter("blender","shiftx",cam->shiftx); + cm.addExtraTechniqueParameter("blender","shifty",cam->shifty); + cm.addExtraTechniqueParameter("blender","YF_dofdist",cam->YF_dofdist); + return true; + +} diff --git a/source/blender/collada/CameraExporter.h b/source/blender/collada/CameraExporter.h index 5405df8ab9e..a0c2d5790c8 100644 --- a/source/blender/collada/CameraExporter.h +++ b/source/blender/collada/CameraExporter.h @@ -37,6 +37,7 @@ extern "C" { } #include "ExportSettings.h" +#include "DNA_camera_types.h" class CamerasExporter: COLLADASW::LibraryCameras { @@ -45,6 +46,7 @@ public: void exportCameras(Scene *sce); void operator()(Object *ob, Scene *sce); private: + bool exportBlenderProfile(COLLADASW::Camera &cla,Camera *cam); const ExportSettings *export_settings; }; diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index c6337e27218..5592be6e872 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -933,6 +933,7 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) Camera *cam = NULL; std::string cam_id, cam_name; + ExtraTags *et=getExtraTags(camera->getUniqueId()); cam_id = camera->getOriginalId(); cam_name = camera->getName(); if (cam_name.size()) cam = (Camera *)BKE_camera_add(G.main, (char *)cam_name.c_str()); @@ -942,6 +943,12 @@ bool DocumentImporter::writeCamera(const COLLADAFW::Camera *camera) fprintf(stderr, "Cannot create camera.\n"); return true; } + + if(et && et->isProfile("blender")) { + et->setData("shiftx",&(cam->shiftx)); + et->setData("shifty",&(cam->shifty)); + et->setData("YF_dofdist",&(cam->YF_dofdist)); + } cam->clipsta = camera->getNearClippingPlane().getValue(); cam->clipend = camera->getFarClippingPlane().getValue(); diff --git a/source/blender/collada/MeshImporter.cpp b/source/blender/collada/MeshImporter.cpp index 8aa68ed9d04..0c46a2bd858 100644 --- a/source/blender/collada/MeshImporter.cpp +++ b/source/blender/collada/MeshImporter.cpp @@ -857,7 +857,7 @@ std::vector<Object *> MeshImporter::get_all_users_of(Mesh *reference_mesh) * * During import all materials have been assigned to Object. * Now we iterate over the imported objects and optimize - * the assignements as follows: + * the assignments as follows: * * for each imported geometry: * if number of users is 1: diff --git a/source/blender/collada/collada.cpp b/source/blender/collada/collada.cpp index 1eb5ac6ca4d..85bbaf4748f 100644 --- a/source/blender/collada/collada.cpp +++ b/source/blender/collada/collada.cpp @@ -83,16 +83,6 @@ int collada_export(Scene *sce, { ExportSettings export_settings; - /* 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)) { - fprintf(stdout, "Collada export: Can not create: %s\n", filepath); - return 0; - } - } - /* end! */ - export_settings.filepath = (char *)filepath; export_settings.apply_modifiers = apply_modifiers != 0; diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 3e17472e9c2..146aff5ca5b 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -56,7 +56,9 @@ extern "C" { #include "WM_api.h" // XXX hrm, see if we can do without this #include "WM_types.h" + #include "bmesh.h" +#include "bmesh_tools.h" } float bc_get_float_value(const COLLADAFW::FloatOrDoubleArray& array, unsigned int index) diff --git a/source/blender/compositor/CMakeLists.txt b/source/blender/compositor/CMakeLists.txt index a119a89c842..29049511321 100644 --- a/source/blender/compositor/CMakeLists.txt +++ b/source/blender/compositor/CMakeLists.txt @@ -368,48 +368,8 @@ set(SRC operations/COM_ColorSpillOperation.cpp operations/COM_ColorSpillOperation.h - operations/COM_RenderLayersBaseProg.cpp - operations/COM_RenderLayersBaseProg.h - operations/COM_RenderLayersImageProg.cpp - operations/COM_RenderLayersImageProg.h - operations/COM_RenderLayersAlphaProg.cpp - operations/COM_RenderLayersAlphaProg.h - operations/COM_RenderLayersDepthProg.cpp - operations/COM_RenderLayersDepthProg.h - operations/COM_RenderLayersNormalOperation.cpp - operations/COM_RenderLayersNormalOperation.h - operations/COM_RenderLayersSpeedOperation.cpp - operations/COM_RenderLayersSpeedOperation.h - operations/COM_RenderLayersColorOperation.cpp - operations/COM_RenderLayersColorOperation.h - operations/COM_RenderLayersUVOperation.cpp - operations/COM_RenderLayersUVOperation.h - operations/COM_RenderLayersMistOperation.cpp - operations/COM_RenderLayersMistOperation.h - operations/COM_RenderLayersObjectIndexOperation.cpp - operations/COM_RenderLayersObjectIndexOperation.h - operations/COM_RenderLayersMaterialIndexOperation.cpp - operations/COM_RenderLayersMaterialIndexOperation.h - operations/COM_RenderLayersDiffuseOperation.cpp - operations/COM_RenderLayersDiffuseOperation.h - operations/COM_RenderLayersSpecularOperation.cpp - operations/COM_RenderLayersSpecularOperation.h - operations/COM_RenderLayersShadowOperation.cpp - operations/COM_RenderLayersShadowOperation.h - operations/COM_RenderLayersAOOperation.cpp - operations/COM_RenderLayersAOOperation.h - operations/COM_RenderLayersEmitOperation.cpp - operations/COM_RenderLayersEmitOperation.h - operations/COM_RenderLayersReflectionOperation.cpp - operations/COM_RenderLayersReflectionOperation.h - operations/COM_RenderLayersRefractionOperation.cpp - operations/COM_RenderLayersRefractionOperation.h - operations/COM_RenderLayersEnvironmentOperation.cpp - operations/COM_RenderLayersEnvironmentOperation.h - operations/COM_RenderLayersIndirectOperation.cpp - operations/COM_RenderLayersIndirectOperation.h - operations/COM_RenderLayersCyclesOperation.cpp - operations/COM_RenderLayersCyclesOperation.h + operations/COM_RenderLayersProg.cpp + operations/COM_RenderLayersProg.h operations/COM_ImageOperation.cpp operations/COM_ImageOperation.h @@ -434,37 +394,11 @@ set(SRC operations/COM_PreviewOperation.cpp operations/COM_SplitOperation.h operations/COM_SplitOperation.cpp - operations/COM_ConvertValueToColorProg.h - operations/COM_ConvertValueToColorProg.cpp - operations/COM_ConvertColorToValueProg.h - operations/COM_ConvertColorToValueProg.cpp - operations/COM_ConvertColorToBWOperation.h - operations/COM_ConvertColorToBWOperation.cpp - operations/COM_ConvertColorToVectorOperation.h - operations/COM_ConvertColorToVectorOperation.cpp - operations/COM_ConvertValueToVectorOperation.h - operations/COM_ConvertValueToVectorOperation.cpp - operations/COM_ConvertVectorToColorOperation.h - operations/COM_ConvertVectorToColorOperation.cpp - operations/COM_ConvertVectorToValueOperation.h - operations/COM_ConvertVectorToValueOperation.cpp operations/COM_ConvertDepthToRadiusOperation.h operations/COM_ConvertDepthToRadiusOperation.cpp operations/COM_ZCombineOperation.cpp operations/COM_ZCombineOperation.h - operations/COM_ConvertRGBToYCCOperation.h - operations/COM_ConvertRGBToYCCOperation.cpp - operations/COM_ConvertYCCToRGBOperation.h - operations/COM_ConvertYCCToRGBOperation.cpp - operations/COM_ConvertRGBToYUVOperation.h - operations/COM_ConvertRGBToYUVOperation.cpp - operations/COM_ConvertYUVToRGBOperation.h - operations/COM_ConvertYUVToRGBOperation.cpp - operations/COM_ConvertRGBToHSVOperation.h - operations/COM_ConvertRGBToHSVOperation.cpp - operations/COM_ConvertHSVToRGBOperation.h - operations/COM_ConvertHSVToRGBOperation.cpp operations/COM_ChangeHSVOperation.h operations/COM_ChangeHSVOperation.cpp operations/COM_ColorCurveOperation.h @@ -491,25 +425,13 @@ set(SRC operations/COM_ColorMatteOperation.h operations/COM_ChannelMatteOperation.cpp operations/COM_ChannelMatteOperation.h - operations/COM_ConvertPremulToStraightOperation.cpp - operations/COM_ConvertPremulToStraightOperation.h - operations/COM_ConvertStraightToPremulOperation.cpp - operations/COM_ConvertStraightToPremulOperation.h operations/COM_ReadBufferOperation.cpp operations/COM_ReadBufferOperation.h operations/COM_WriteBufferOperation.cpp operations/COM_WriteBufferOperation.h - operations/COM_MixBaseOperation.h - operations/COM_MixBaseOperation.cpp - operations/COM_MixBlendOperation.cpp - operations/COM_MixBlendOperation.h - operations/COM_MixGlareOperation.cpp - operations/COM_MixGlareOperation.h - operations/COM_MixAddOperation.h - operations/COM_MixAddOperation.cpp - operations/COM_MixMultiplyOperation.h - operations/COM_MixMultiplyOperation.cpp + operations/COM_MixOperation.h + operations/COM_MixOperation.cpp operations/COM_BrightnessOperation.cpp operations/COM_BrightnessOperation.h operations/COM_GammaOperation.cpp @@ -523,37 +445,6 @@ set(SRC operations/COM_SetVectorOperation.h operations/COM_SetVectorOperation.cpp - operations/COM_MixBurnOperation.h - operations/COM_MixBurnOperation.cpp - operations/COM_MixColorOperation.h - operations/COM_MixColorOperation.cpp - operations/COM_MixDarkenOperation.h - operations/COM_MixDarkenOperation.cpp - operations/COM_MixDodgeOperation.h - operations/COM_MixDodgeOperation.cpp - operations/COM_MixDifferenceOperation.h - operations/COM_MixDifferenceOperation.cpp - operations/COM_MixDivideOperation.h - operations/COM_MixDivideOperation.cpp - operations/COM_MixHueOperation.h - operations/COM_MixHueOperation.cpp - operations/COM_MixLightenOperation.h - operations/COM_MixLightenOperation.cpp - operations/COM_MixLinearLightOperation.h - operations/COM_MixLinearLightOperation.cpp - operations/COM_MixOverlayOperation.h - operations/COM_MixOverlayOperation.cpp - operations/COM_MixSaturationOperation.h - operations/COM_MixSaturationOperation.cpp - operations/COM_MixScreenOperation.h - operations/COM_MixScreenOperation.cpp - operations/COM_MixSoftLightOperation.h - operations/COM_MixSoftLightOperation.cpp - operations/COM_MixValueOperation.h - operations/COM_MixValueOperation.cpp - operations/COM_MixSubtractOperation.h - operations/COM_MixSubtractOperation.cpp - operations/COM_MathBaseOperation.h operations/COM_MathBaseOperation.cpp @@ -635,11 +526,8 @@ set(SRC #Convert operations operations/COM_IDMaskOperation.cpp operations/COM_IDMaskOperation.h - - operations/COM_SeparateChannelOperation.cpp - operations/COM_SeparateChannelOperation.h - operations/COM_CombineChannelsOperation.cpp - operations/COM_CombineChannelsOperation.h + operations/COM_ConvertOperation.cpp + operations/COM_ConvertOperation.h operations/COM_DotproductOperation.cpp operations/COM_DotproductOperation.h diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index db0cdd1692e..384cfbe47fa 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -47,12 +47,7 @@ #include "COM_CombineYUVANode.h" #include "COM_CompositorNode.h" #include "COM_ConvertAlphaNode.h" -#include "COM_ConvertColorToVectorOperation.h" -#include "COM_ConvertColorToValueProg.h" -#include "COM_ConvertValueToColorProg.h" -#include "COM_ConvertValueToVectorOperation.h" -#include "COM_ConvertVectorToColorOperation.h" -#include "COM_ConvertVectorToValueOperation.h" +#include "COM_ConvertOperation.h" #include "COM_Converter.h" #include "COM_CropNode.h" #include "COM_DefocusNode.h" @@ -420,13 +415,13 @@ void Converter::convertDataType(SocketConnection *connection, ExecutionSystem *s DataType toDatatype = inputSocket->getDataType(); NodeOperation *converter = NULL; if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_COLOR) { - converter = new ConvertValueToColorProg(); + converter = new ConvertValueToColorOperation(); } else if (fromDatatype == COM_DT_VALUE && toDatatype == COM_DT_VECTOR) { converter = new ConvertValueToVectorOperation(); } else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VALUE) { - converter = new ConvertColorToValueProg(); + converter = new ConvertColorToValueOperation(); } else if (fromDatatype == COM_DT_COLOR && toDatatype == COM_DT_VECTOR) { converter = new ConvertColorToVectorOperation(); diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.cpp b/source/blender/compositor/intern/COM_MemoryBuffer.cpp index 357a4c1d4c0..4bebf004a89 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.cpp +++ b/source/blender/compositor/intern/COM_MemoryBuffer.cpp @@ -335,8 +335,7 @@ void MemoryBuffer::readEWA(float result[4], float fx, float fy, float dx, float float tc[4]; const float wt = EWA_WTS[(Q < 0.f) ? 0 : (unsigned int)Q]; read(tc, clipuv(u, width), clipuv(v, height)); - madd_v3_v3fl(result, tc, wt); - result[3] += result[3] ? tc[3] * wt : 0.f; + madd_v4_v4fl(result, tc, wt); d += wt; } Q += DQ; @@ -346,9 +345,5 @@ void MemoryBuffer::readEWA(float result[4], float fx, float fy, float dx, float // d should hopefully never be zero anymore d = 1.f / d; - result[0] *= d; - result[1] *= d; - result[2] *= d; - // clipping can be ignored if alpha used, texr->ta already includes filtered edge - result[3] = result[3] ? result[3] * d : 1.f; + mul_v4_fl(result, d); } diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index d176298578f..548744f6660 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -46,6 +46,12 @@ typedef enum MemoryBufferState { COM_MB_TEMPORARILY = 6 } MemoryBufferState; +typedef enum MemoryBufferExtend { + COM_MB_CLIP, + COM_MB_EXTEND, + COM_MB_REPEAT +} MemoryBufferExtend; + class MemoryProxy; /** @@ -125,31 +131,66 @@ public: this->m_state = COM_MB_AVAILABLE; } - inline void read(float result[4], int x, int y) + inline void wrap_pixel(int &x, int &y, MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) { - if (x >= this->m_rect.xmin && x < this->m_rect.xmax && - y >= this->m_rect.ymin && y < this->m_rect.ymax) - { - const int dx = x - this->m_rect.xmin; - const int dy = y - this->m_rect.ymin; - const int offset = (this->m_chunkWidth * dy + dx) * COM_NUMBER_OF_CHANNELS; - copy_v4_v4(result, &this->m_buffer[offset]); + int w = m_rect.xmax - m_rect.xmin; + int h = m_rect.ymax - m_rect.ymin; + x = x - m_rect.xmin; + y = y - m_rect.ymin; + + switch (extend_x) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (x < 0) x = 0; + if (x >= w) x = w; + break; + case COM_MB_REPEAT: + x = (x >= 0.0f ? (x % w) : (x % w) + w); + break; } - else { + + switch (extend_y) { + case COM_MB_CLIP: + break; + case COM_MB_EXTEND: + if (y < 0) y = 0; + if (y >= h) y = h; + break; + case COM_MB_REPEAT: + y = (y >= 0.0f ? (y % h) : (y % h) + h); + break; + } + } + + inline void read(float result[4], int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) + { + bool clip_x = (extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)); + bool clip_y = (extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax)); + if (clip_x || clip_y) { + /* clip result outside rect is zero */ zero_v4(result); } + else { + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS; + copy_v4_v4(result, &this->m_buffer[offset]); + } } - inline void readNoCheck(float result[4], int x, int y) + inline void readNoCheck(float result[4], int x, int y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) { - const int dx = x - this->m_rect.xmin; - const int dy = y - this->m_rect.ymin; - const int offset = (this->m_chunkWidth * dy + dx) * COM_NUMBER_OF_CHANNELS; + wrap_pixel(x, y, extend_x, extend_y); + const int offset = (this->m_chunkWidth * y + x) * COM_NUMBER_OF_CHANNELS; BLI_assert(offset >= 0); BLI_assert(offset < this->determineBufferSize() * COM_NUMBER_OF_CHANNELS); - BLI_assert(x >= this->m_rect.xmin && x < this->m_rect.xmax && - y >= this->m_rect.ymin && y < this->m_rect.ymax); + BLI_assert(!(extend_x == COM_MB_CLIP && (x < m_rect.xmin || x >= m_rect.xmax)) && + !(extend_y == COM_MB_CLIP && (y < m_rect.ymin || y >= m_rect.ymax))); #if 0 /* always true */ @@ -162,12 +203,16 @@ public: void writePixel(int x, int y, const float color[4]); void addPixel(int x, int y, const float color[4]); - inline void readCubic(float result[4], float x, float y) + inline void readBilinear(float result[4], float x, float y, + MemoryBufferExtend extend_x = COM_MB_CLIP, + MemoryBufferExtend extend_y = COM_MB_CLIP) { int x1 = floor(x); - int x2 = x1 + 1; int y1 = floor(y); + int x2 = x1 + 1; int y2 = y1 + 1; + wrap_pixel(x1, y1, extend_x, extend_y); + wrap_pixel(x2, y2, extend_x, extend_y); float valuex = x - x1; float valuey = y - y1; @@ -199,8 +244,6 @@ public: result[2] = color1[2] * mvaluex + color3[2] * valuex; result[3] = color1[3] * mvaluex + color3[3] * valuex; } - - void readEWA(float result[4], float fx, float fy, float dx, float dy, PixelSampler sampler); diff --git a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp index 4f3ed36aadb..bf081cae097 100644 --- a/source/blender/compositor/nodes/COM_AlphaOverNode.cpp +++ b/source/blender/compositor/nodes/COM_AlphaOverNode.cpp @@ -22,7 +22,7 @@ #include "COM_AlphaOverNode.h" -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" #include "COM_AlphaOverKeyOperation.h" #include "COM_AlphaOverMixedOperation.h" #include "COM_AlphaOverPremultiplyOperation.h" diff --git a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp index c1511ee611b..4c136583936 100644 --- a/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChannelMatteNode.cpp @@ -22,9 +22,7 @@ #include "COM_ChannelMatteNode.h" #include "BKE_node.h" #include "COM_ChannelMatteOperation.h" -#include "COM_ConvertRGBToHSVOperation.h" -#include "COM_ConvertRGBToYCCOperation.h" -#include "COM_ConvertRGBToYUVOperation.h" +#include "COM_ConvertOperation.h" #include "COM_SetAlphaOperation.h" ChannelMatteNode::ChannelMatteNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp index d2598e661a9..c23f242ca5c 100644 --- a/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ChromaMatteNode.cpp @@ -22,7 +22,7 @@ #include "COM_ChromaMatteNode.h" #include "BKE_node.h" #include "COM_ChromaMatteOperation.h" -#include "COM_ConvertRGBToYCCOperation.h" +#include "COM_ConvertOperation.h" #include "COM_SetAlphaOperation.h" ChromaMatteNode::ChromaMatteNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp index aeed859b350..5578fdae54e 100644 --- a/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorBalanceNode.cpp @@ -25,7 +25,7 @@ #include "COM_ColorBalanceASCCDLOperation.h" #include "COM_ExecutionSystem.h" #include "BKE_node.h" -#include "COM_MixBlendOperation.h" +#include "COM_MixOperation.h" ColorBalanceNode::ColorBalanceNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp index 54e6762961b..8ab93a58a1d 100644 --- a/source/blender/compositor/nodes/COM_ColorMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorMatteNode.cpp @@ -22,7 +22,7 @@ #include "COM_ColorMatteNode.h" #include "BKE_node.h" #include "COM_ColorMatteOperation.h" -#include "COM_ConvertRGBToHSVOperation.h" +#include "COM_ConvertOperation.h" #include "COM_SetAlphaOperation.h" ColorMatteNode::ColorMatteNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_ColorRampNode.cpp b/source/blender/compositor/nodes/COM_ColorRampNode.cpp index a79c7885ae4..6f715a8f278 100644 --- a/source/blender/compositor/nodes/COM_ColorRampNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorRampNode.cpp @@ -24,7 +24,7 @@ #include "COM_ExecutionSystem.h" #include "BKE_node.h" #include "COM_ColorRampOperation.h" -#include "COM_SeparateChannelOperation.h" +#include "COM_ConvertOperation.h" #include "DNA_texture_types.h" ColorRampNode::ColorRampNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp index 511fdf09f41..07be93dab86 100644 --- a/source/blender/compositor/nodes/COM_ColorToBWNode.cpp +++ b/source/blender/compositor/nodes/COM_ColorToBWNode.cpp @@ -22,7 +22,7 @@ #include "COM_ColorToBWNode.h" -#include "COM_ConvertColorToBWOperation.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" ColorToBWNode::ColorToBWNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_CombineHSVANode.cpp b/source/blender/compositor/nodes/COM_CombineHSVANode.cpp index beba41fade9..9f6614ed8c3 100644 --- a/source/blender/compositor/nodes/COM_CombineHSVANode.cpp +++ b/source/blender/compositor/nodes/COM_CombineHSVANode.cpp @@ -22,11 +22,11 @@ #include "COM_CombineHSVANode.h" -#include "COM_CombineChannelsOperation.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" -#include "COM_ConvertHSVToRGBOperation.h" +#include "COM_ConvertOperation.h" CombineHSVANode::CombineHSVANode(bNode *editorNode) : CombineRGBANode(editorNode) { diff --git a/source/blender/compositor/nodes/COM_CombineRGBANode.cpp b/source/blender/compositor/nodes/COM_CombineRGBANode.cpp index a8cdd8c2950..8dfded049e5 100644 --- a/source/blender/compositor/nodes/COM_CombineRGBANode.cpp +++ b/source/blender/compositor/nodes/COM_CombineRGBANode.cpp @@ -22,7 +22,7 @@ #include "COM_CombineRGBANode.h" -#include "COM_CombineChannelsOperation.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" diff --git a/source/blender/compositor/nodes/COM_CombineYCCANode.cpp b/source/blender/compositor/nodes/COM_CombineYCCANode.cpp index 5319eb84184..ee787a4f9c1 100644 --- a/source/blender/compositor/nodes/COM_CombineYCCANode.cpp +++ b/source/blender/compositor/nodes/COM_CombineYCCANode.cpp @@ -20,7 +20,7 @@ */ #include "COM_CombineYCCANode.h" -#include "COM_ConvertYCCToRGBOperation.h" +#include "COM_ConvertOperation.h" CombineYCCANode::CombineYCCANode(bNode *editorNode) : CombineRGBANode(editorNode) { diff --git a/source/blender/compositor/nodes/COM_CombineYUVANode.cpp b/source/blender/compositor/nodes/COM_CombineYUVANode.cpp index 48c2c6ca649..feee443cf05 100644 --- a/source/blender/compositor/nodes/COM_CombineYUVANode.cpp +++ b/source/blender/compositor/nodes/COM_CombineYUVANode.cpp @@ -20,7 +20,7 @@ */ #include "COM_CombineYUVANode.h" -#include "COM_ConvertYUVToRGBOperation.h" +#include "COM_ConvertOperation.h" CombineYUVANode::CombineYUVANode(bNode *editorNode) : CombineRGBANode(editorNode) { diff --git a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp index a7149cc63b2..72f3ed07fd5 100644 --- a/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp +++ b/source/blender/compositor/nodes/COM_ConvertAlphaNode.cpp @@ -20,8 +20,7 @@ */ #include "COM_ConvertAlphaNode.h" -#include "COM_ConvertPremulToStraightOperation.h" -#include "COM_ConvertStraightToPremulOperation.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" void ConvertAlphaNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) diff --git a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp index 782c897f6fb..3c532fe0b1d 100644 --- a/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_DistanceMatteNode.cpp @@ -24,7 +24,7 @@ #include "COM_DistanceRGBMatteOperation.h" #include "COM_DistanceYCCMatteOperation.h" #include "COM_SetAlphaOperation.h" -#include "COM_ConvertRGBToYCCOperation.h" +#include "COM_ConvertOperation.h" DistanceMatteNode::DistanceMatteNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_FilterNode.cpp b/source/blender/compositor/nodes/COM_FilterNode.cpp index 990cdb480ca..3b75e3e0a1a 100644 --- a/source/blender/compositor/nodes/COM_FilterNode.cpp +++ b/source/blender/compositor/nodes/COM_FilterNode.cpp @@ -25,7 +25,7 @@ #include "COM_ConvolutionEdgeFilterOperation.h" #include "COM_ExecutionSystem.h" #include "BKE_node.h" -#include "COM_MixBlendOperation.h" +#include "COM_MixOperation.h" FilterNode::FilterNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_GlareNode.cpp b/source/blender/compositor/nodes/COM_GlareNode.cpp index 8782e6bb6d9..a6a83846623 100644 --- a/source/blender/compositor/nodes/COM_GlareNode.cpp +++ b/source/blender/compositor/nodes/COM_GlareNode.cpp @@ -26,7 +26,7 @@ #include "COM_GlareSimpleStarOperation.h" #include "COM_GlareStreaksOperation.h" #include "COM_SetValueOperation.h" -#include "COM_MixGlareOperation.h" +#include "COM_MixOperation.h" #include "COM_FastGaussianBlurOperation.h" #include "COM_GlareGhostOperation.h" #include "COM_GlareFogGlowOperation.h" diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp index fd961030ebf..66b98b29d5e 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueCorrectNode.cpp @@ -22,11 +22,9 @@ #include "COM_HueSaturationValueCorrectNode.h" -#include "COM_ConvertColorToValueProg.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" -#include "COM_ConvertRGBToHSVOperation.h" -#include "COM_ConvertHSVToRGBOperation.h" -#include "COM_MixBlendOperation.h" +#include "COM_MixOperation.h" #include "COM_SetColorOperation.h" #include "COM_SetValueOperation.h" #include "COM_ChangeHSVOperation.h" diff --git a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp index 29e10db0758..5001433513c 100644 --- a/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp +++ b/source/blender/compositor/nodes/COM_HueSaturationValueNode.cpp @@ -22,11 +22,9 @@ #include "COM_HueSaturationValueNode.h" -#include "COM_ConvertColorToValueProg.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" -#include "COM_ConvertRGBToHSVOperation.h" -#include "COM_ConvertHSVToRGBOperation.h" -#include "COM_MixBlendOperation.h" +#include "COM_MixOperation.h" #include "COM_SetColorOperation.h" #include "COM_SetValueOperation.h" #include "COM_ChangeHSVOperation.h" diff --git a/source/blender/compositor/nodes/COM_ImageNode.cpp b/source/blender/compositor/nodes/COM_ImageNode.cpp index b8d9841c92a..c3aaf8358fe 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.cpp +++ b/source/blender/compositor/nodes/COM_ImageNode.cpp @@ -25,7 +25,7 @@ #include "COM_ExecutionSystem.h" #include "COM_ImageOperation.h" #include "COM_MultilayerImageOperation.h" -#include "COM_ConvertPremulToStraightOperation.h" +#include "COM_ConvertOperation.h" #include "BKE_node.h" #include "BLI_utildefines.h" diff --git a/source/blender/compositor/nodes/COM_KeyingNode.cpp b/source/blender/compositor/nodes/COM_KeyingNode.cpp index 51ea2913e65..786530bd3c4 100644 --- a/source/blender/compositor/nodes/COM_KeyingNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingNode.cpp @@ -32,10 +32,7 @@ #include "COM_MathBaseOperation.h" -#include "COM_SeparateChannelOperation.h" -#include "COM_CombineChannelsOperation.h" -#include "COM_ConvertRGBToYCCOperation.h" -#include "COM_ConvertYCCToRGBOperation.h" +#include "COM_ConvertOperation.h" #include "COM_SetValueOperation.h" #include "COM_DilateErodeOperation.h" diff --git a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp index 4656e00b006..b1e6967ba42 100644 --- a/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp +++ b/source/blender/compositor/nodes/COM_LuminanceMatteNode.cpp @@ -22,7 +22,7 @@ #include "COM_LuminanceMatteNode.h" #include "BKE_node.h" #include "COM_LuminanceMatteOperation.h" -#include "COM_ConvertRGBToYUVOperation.h" +#include "COM_ConvertOperation.h" #include "COM_SetAlphaOperation.h" LuminanceMatteNode::LuminanceMatteNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_MixNode.cpp b/source/blender/compositor/nodes/COM_MixNode.cpp index ab4e464327d..42217243fdf 100644 --- a/source/blender/compositor/nodes/COM_MixNode.cpp +++ b/source/blender/compositor/nodes/COM_MixNode.cpp @@ -22,24 +22,7 @@ #include "COM_MixNode.h" -#include "COM_MixBlendOperation.h" -#include "COM_MixAddOperation.h" -#include "COM_MixMultiplyOperation.h" -#include "COM_MixBurnOperation.h" -#include "COM_MixColorOperation.h" -#include "COM_MixDarkenOperation.h" -#include "COM_MixDifferenceOperation.h" -#include "COM_MixDivideOperation.h" -#include "COM_MixHueOperation.h" -#include "COM_MixLightenOperation.h" -#include "COM_MixLinearLightOperation.h" -#include "COM_MixOverlayOperation.h" -#include "COM_MixSaturationOperation.h" -#include "COM_MixScreenOperation.h" -#include "COM_MixSoftLightOperation.h" -#include "COM_MixSubtractOperation.h" -#include "COM_MixValueOperation.h" -#include "COM_MixDodgeOperation.h" +#include "COM_MixOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp index 74e557c77ce..512f8eec90f 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.cpp +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.cpp @@ -22,26 +22,7 @@ #include "COM_RenderLayersNode.h" #include "COM_ExecutionSystem.h" -#include "COM_RenderLayersImageProg.h" -#include "COM_RenderLayersAlphaProg.h" -#include "COM_RenderLayersDepthProg.h" -#include "COM_RenderLayersNormalOperation.h" -#include "COM_RenderLayersSpeedOperation.h" -#include "COM_RenderLayersColorOperation.h" -#include "COM_RenderLayersUVOperation.h" -#include "COM_RenderLayersMistOperation.h" -#include "COM_RenderLayersObjectIndexOperation.h" -#include "COM_RenderLayersDiffuseOperation.h" -#include "COM_RenderLayersSpecularOperation.h" -#include "COM_RenderLayersShadowOperation.h" -#include "COM_RenderLayersAOOperation.h" -#include "COM_RenderLayersEmitOperation.h" -#include "COM_RenderLayersReflectionOperation.h" -#include "COM_RenderLayersRefractionOperation.h" -#include "COM_RenderLayersEnvironmentOperation.h" -#include "COM_RenderLayersIndirectOperation.h" -#include "COM_RenderLayersMaterialIndexOperation.h" -#include "COM_RenderLayersCyclesOperation.h" +#include "COM_RenderLayersProg.h" #include "COM_TranslateOperation.h" #include "COM_RotateOperation.h" #include "COM_ScaleOperation.h" diff --git a/source/blender/compositor/nodes/COM_RenderLayersNode.h b/source/blender/compositor/nodes/COM_RenderLayersNode.h index 9bd74624b0c..0c769d32aea 100644 --- a/source/blender/compositor/nodes/COM_RenderLayersNode.h +++ b/source/blender/compositor/nodes/COM_RenderLayersNode.h @@ -22,7 +22,7 @@ #include "COM_Node.h" #include "DNA_node_types.h" -#include "COM_RenderLayersBaseProg.h" +#include "COM_RenderLayersProg.h" /** * @brief RenderLayersNode diff --git a/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp b/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp index 4f93b226fa1..4cd77d4bae6 100644 --- a/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp +++ b/source/blender/compositor/nodes/COM_SeparateHSVANode.cpp @@ -22,10 +22,9 @@ #include "COM_SeparateHSVANode.h" -#include "COM_SeparateChannelOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" -#include "COM_ConvertRGBToHSVOperation.h" +#include "COM_ConvertOperation.h" SeparateHSVANode::SeparateHSVANode(bNode *editorNode) : SeparateRGBANode(editorNode) { diff --git a/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp b/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp index 7fcdebadb46..7d9bff30a93 100644 --- a/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp +++ b/source/blender/compositor/nodes/COM_SeparateRGBANode.cpp @@ -22,7 +22,7 @@ #include "COM_SeparateRGBANode.h" -#include "COM_SeparateChannelOperation.h" +#include "COM_ConvertOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" #include "DNA_material_types.h" // the ramp types diff --git a/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp b/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp index 154e2bcd550..797cd49316a 100644 --- a/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp +++ b/source/blender/compositor/nodes/COM_SeparateYCCANode.cpp @@ -20,10 +20,9 @@ */ #include "COM_SeparateYCCANode.h" -#include "COM_SeparateChannelOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" -#include "COM_ConvertRGBToYCCOperation.h" +#include "COM_ConvertOperation.h" SeparateYCCANode::SeparateYCCANode(bNode *editorNode) : SeparateRGBANode(editorNode) { diff --git a/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp b/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp index 8a647b7f849..9a6ec20fa80 100644 --- a/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp +++ b/source/blender/compositor/nodes/COM_SeparateYUVANode.cpp @@ -20,10 +20,9 @@ */ #include "COM_SeparateYUVANode.h" -#include "COM_SeparateChannelOperation.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" -#include "COM_ConvertRGBToYUVOperation.h" +#include "COM_ConvertOperation.h" SeparateYUVANode::SeparateYUVANode(bNode *editorNode) : SeparateRGBANode(editorNode) { diff --git a/source/blender/compositor/nodes/COM_TranslateNode.cpp b/source/blender/compositor/nodes/COM_TranslateNode.cpp index 44d796c2911..d2cd009449c 100644 --- a/source/blender/compositor/nodes/COM_TranslateNode.cpp +++ b/source/blender/compositor/nodes/COM_TranslateNode.cpp @@ -24,6 +24,7 @@ #include "COM_TranslateOperation.h" #include "COM_WrapOperation.h" +#include "COM_WriteBufferOperation.h" #include "COM_ExecutionSystem.h" TranslateNode::TranslateNode(bNode *editorNode) : Node(editorNode) @@ -43,10 +44,15 @@ void TranslateNode::convertToOperations(ExecutionSystem *graph, CompositorContex NodeTranslateData *data = (NodeTranslateData *)bnode->storage; if (data->wrap_axis) { + WriteBufferOperation *writeOperation = new WriteBufferOperation(); WrapOperation *wrapOperation = new WrapOperation(); + wrapOperation->setMemoryProxy(writeOperation->getMemoryProxy()); wrapOperation->setWrapping(data->wrap_axis); - inputSocket->relinkConnections(wrapOperation->getInputSocket(0), 0, graph); + + inputSocket->relinkConnections(writeOperation->getInputSocket(0), 0, graph); addLink(graph, wrapOperation->getOutputSocket(), operation->getInputSocket(0)); + + graph->addOperation(writeOperation); graph->addOperation(wrapOperation); } else { diff --git a/source/blender/compositor/nodes/COM_ZCombineNode.cpp b/source/blender/compositor/nodes/COM_ZCombineNode.cpp index b48d974e893..b5fe4882f57 100644 --- a/source/blender/compositor/nodes/COM_ZCombineNode.cpp +++ b/source/blender/compositor/nodes/COM_ZCombineNode.cpp @@ -28,7 +28,7 @@ #include "COM_SetValueOperation.h" #include "COM_MathBaseOperation.h" #include "COM_AntiAliasOperation.h" -#include "COM_MixBlendOperation.h" +#include "COM_MixOperation.h" #include "DNA_material_types.h" // the ramp types diff --git a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h index fa884bacf49..31b0422918a 100644 --- a/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h +++ b/source/blender/compositor/operations/COM_AlphaOverKeyOperation.h @@ -22,7 +22,7 @@ #ifndef _COM_AlphaOverKeyOperation_h #define _COM_AlphaOverKeyOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h index 91128454783..14e7325ec1d 100644 --- a/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h +++ b/source/blender/compositor/operations/COM_AlphaOverMixedOperation.h @@ -22,7 +22,7 @@ #ifndef _COM_AlphaOverMixedOperation_h_ #define _COM_AlphaOverMixedOperation_h_ -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h index d6e9e31c35f..16bd2aeaeed 100644 --- a/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h +++ b/source/blender/compositor/operations/COM_AlphaOverPremultiplyOperation.h @@ -22,7 +22,7 @@ #ifndef _COM_AlphaOverPremultiplyOperation_h #define _COM_AlphaOverPremultiplyOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_ChangeHSVOperation.h b/source/blender/compositor/operations/COM_ChangeHSVOperation.h index 57e5dc991e9..01852084e41 100644 --- a/source/blender/compositor/operations/COM_ChangeHSVOperation.h +++ b/source/blender/compositor/operations/COM_ChangeHSVOperation.h @@ -22,7 +22,7 @@ #ifndef _COM_ChangeHSVOperation_h #define _COM_ChangeHSVOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_ChannelMatteOperation.h b/source/blender/compositor/operations/COM_ChannelMatteOperation.h index 17f84965f63..efb4f7427ca 100644 --- a/source/blender/compositor/operations/COM_ChannelMatteOperation.h +++ b/source/blender/compositor/operations/COM_ChannelMatteOperation.h @@ -21,7 +21,7 @@ #ifndef _COM_ChannelMatteOperation_h #define _COM_ChannelMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_ChromaMatteOperation.h b/source/blender/compositor/operations/COM_ChromaMatteOperation.h index adebb7a30c2..9557faec855 100644 --- a/source/blender/compositor/operations/COM_ChromaMatteOperation.h +++ b/source/blender/compositor/operations/COM_ChromaMatteOperation.h @@ -21,7 +21,7 @@ #ifndef _COM_ChromaMatteOperation_h #define _COM_ChromaMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_ColorMatteOperation.h b/source/blender/compositor/operations/COM_ColorMatteOperation.h index 582a94e1873..f065a5f7e89 100644 --- a/source/blender/compositor/operations/COM_ColorMatteOperation.h +++ b/source/blender/compositor/operations/COM_ColorMatteOperation.h @@ -21,7 +21,7 @@ #ifndef _COM_ColorMatteOperation_h #define _COM_ColorMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp b/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp deleted file mode 100644 index 3ced0548bb8..00000000000 --- a/source/blender/compositor/operations/COM_CombineChannelsOperation.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_CombineChannelsOperation.h" -#include "BLI_utildefines.h" - -CombineChannelsOperation::CombineChannelsOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputChannel1Operation = NULL; - this->m_inputChannel2Operation = NULL; - this->m_inputChannel3Operation = NULL; - this->m_inputChannel4Operation = NULL; -} - -void CombineChannelsOperation::initExecution() -{ - this->m_inputChannel1Operation = this->getInputSocketReader(0); - this->m_inputChannel2Operation = this->getInputSocketReader(1); - this->m_inputChannel3Operation = this->getInputSocketReader(2); - this->m_inputChannel4Operation = this->getInputSocketReader(3); -} - -void CombineChannelsOperation::deinitExecution() -{ - this->m_inputChannel1Operation = NULL; - this->m_inputChannel2Operation = NULL; - this->m_inputChannel3Operation = NULL; - this->m_inputChannel4Operation = NULL; -} - - -void CombineChannelsOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float input[4]; - if (this->m_inputChannel1Operation) { - this->m_inputChannel1Operation->read(input, x, y, sampler); - output[0] = input[0]; - } - if (this->m_inputChannel2Operation) { - this->m_inputChannel2Operation->read(input, x, y, sampler); - output[1] = input[0]; - } - if (this->m_inputChannel3Operation) { - this->m_inputChannel3Operation->read(input, x, y, sampler); - output[2] = input[0]; - } - if (this->m_inputChannel4Operation) { - this->m_inputChannel4Operation->read(input, x, y, sampler); - output[3] = input[0]; - } -} diff --git a/source/blender/compositor/operations/COM_CombineChannelsOperation.h b/source/blender/compositor/operations/COM_CombineChannelsOperation.h deleted file mode 100644 index 7c8742b1557..00000000000 --- a/source/blender/compositor/operations/COM_CombineChannelsOperation.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_CombineChannelsOperation_h_ -#define _COM_CombineChannelsOperation_h_ - -#include "COM_NodeOperation.h" - -class CombineChannelsOperation : public NodeOperation { -private: - SocketReader *m_inputChannel1Operation; - SocketReader *m_inputChannel2Operation; - SocketReader *m_inputChannel3Operation; - SocketReader *m_inputChannel4Operation; -public: - CombineChannelsOperation(); - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp deleted file mode 100644 index 3b5aa8cd755..00000000000 --- a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertColorToBWOperation.h" - -ConvertColorToBWOperation::ConvertColorToBWOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; -} - -void ConvertColorToBWOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertColorToBWOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - output[0] = rgb_to_bw(inputColor); -} - -void ConvertColorToBWOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.h b/source/blender/compositor/operations/COM_ConvertColorToBWOperation.h deleted file mode 100644 index 963bd32a2f6..00000000000 --- a/source/blender/compositor/operations/COM_ConvertColorToBWOperation.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertColorToBWOperation_h -#define _COM_ConvertColorToBWOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertColorToBWOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertColorToBWOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp b/source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp deleted file mode 100644 index 44e751d1cae..00000000000 --- a/source/blender/compositor/operations/COM_ConvertColorToValueProg.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertColorToValueProg.h" - -ConvertColorToValueProg::ConvertColorToValueProg() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; -} - -void ConvertColorToValueProg::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertColorToValueProg::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f; -} - -void ConvertColorToValueProg::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertColorToValueProg.h b/source/blender/compositor/operations/COM_ConvertColorToValueProg.h deleted file mode 100644 index 5c25d5d0540..00000000000 --- a/source/blender/compositor/operations/COM_ConvertColorToValueProg.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertColorToValueProg_h -#define _COM_ConvertColorToValueProg_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertColorToValueProg : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertColorToValueProg(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp deleted file mode 100644 index a9b8cbb4272..00000000000 --- a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertColorToVectorOperation.h" - -ConvertColorToVectorOperation::ConvertColorToVectorOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VECTOR); - this->m_inputOperation = NULL; -} - -void ConvertColorToVectorOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertColorToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - this->m_inputOperation->read(output, x, y, sampler); -} - -void ConvertColorToVectorOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h b/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h deleted file mode 100644 index 93644cb5d1c..00000000000 --- a/source/blender/compositor/operations/COM_ConvertColorToVectorOperation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertColorToVectorOperation_h -#define _COM_ConvertColorToVectorOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertColorToVectorOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertColorToVectorOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp b/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp deleted file mode 100644 index 65907a8e537..00000000000 --- a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertHSVToRGBOperation.h" -#include "BLI_math_color.h" - -ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertHSVToRGBOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertHSVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - hsv_to_rgb_v(inputColor, output); - output[3] = inputColor[3]; -} - -void ConvertHSVToRGBOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} - diff --git a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h b/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h deleted file mode 100644 index 17419ca2a05..00000000000 --- a/source/blender/compositor/operations/COM_ConvertHSVToRGBOperation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertHSVToRGBOperation_h -#define _COM_ConvertHSVToRGBOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertHSVToRGBOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertHSVToRGBOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp new file mode 100644 index 00000000000..d72aabb078e --- /dev/null +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -0,0 +1,429 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_ConvertOperation.h" + + +ConvertBaseOperation::ConvertBaseOperation() +{ + this->m_inputOperation = NULL; +} + +void ConvertBaseOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); +} + +void ConvertBaseOperation::deinitExecution() +{ + this->m_inputOperation = NULL; +} + + +/* ******** Value to Color ******** */ + +ConvertValueToColorOperation::ConvertValueToColorOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertValueToColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputValue[4]; + this->m_inputOperation->read(inputValue, x, y, sampler); + output[0] = output[1] = output[2] = inputValue[0]; + output[3] = 1.0f; +} + + +/* ******** Color to Value ******** */ + +ConvertColorToValueOperation::ConvertColorToValueOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); +} + +void ConvertColorToValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + output[0] = (inputColor[0] + inputColor[1] + inputColor[2]) / 3.0f; +} + + +/* ******** Color to BW ******** */ + +ConvertColorToBWOperation::ConvertColorToBWOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); +} + +void ConvertColorToBWOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + output[0] = rgb_to_bw(inputColor); +} + + +/* ******** Color to Vector ******** */ + +ConvertColorToVectorOperation::ConvertColorToVectorOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VECTOR); +} + +void ConvertColorToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + this->m_inputOperation->read(output, x, y, sampler); +} + + +/* ******** Value to Vector ******** */ + +ConvertValueToVectorOperation::ConvertValueToVectorOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_VECTOR); +} + +void ConvertValueToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float input[4]; + this->m_inputOperation->read(input, x, y, sampler); + output[0] = input[0]; + output[1] = input[0]; + output[2] = input[0]; + output[3] = 0.0f; +} + + +/* ******** Vector to Color ******** */ + +ConvertVectorToColorOperation::ConvertVectorToColorOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertVectorToColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + this->m_inputOperation->read(output, x, y, sampler); + output[3] = 1.0f; +} + + +/* ******** Vector to Value ******** */ + +ConvertVectorToValueOperation::ConvertVectorToValueOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_VECTOR); + this->addOutputSocket(COM_DT_VALUE); +} + +void ConvertVectorToValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float input[4]; + this->m_inputOperation->read(input, x, y, sampler); + output[0] = (input[0] + input[1] + input[2]) / 3.0f; +} + + +/* ******** RGB to YCC ******** */ + +ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertRGBToYCCOperation::setMode(int mode) +{ + switch (mode) { + case 1: + this->m_mode = BLI_YCC_ITU_BT709; + break; + case 2: + this->m_mode = BLI_YCC_JFIF_0_255; + break; + case 0: + default: + this->m_mode = BLI_YCC_ITU_BT601; + break; + } +} + +void ConvertRGBToYCCOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + float color[3]; + + this->m_inputOperation->read(inputColor, x, y, sampler); + rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode); + + /* divided by 255 to normalize for viewing in */ + /* R,G,B --> Y,Cb,Cr */ + mul_v3_v3fl(output, color, 1.0f / 255.0f); + output[3] = inputColor[3]; +} + +/* ******** YCC to RGB ******** */ + +ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertYCCToRGBOperation::setMode(int mode) +{ + switch (mode) { + case 1: + this->m_mode = BLI_YCC_ITU_BT709; + break; + case 2: + this->m_mode = BLI_YCC_JFIF_0_255; + break; + case 0: + default: + this->m_mode = BLI_YCC_ITU_BT601; + break; + } +} + +void ConvertYCCToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + + /* need to un-normalize the data */ + /* R,G,B --> Y,Cb,Cr */ + mul_v3_fl(inputColor, 255.0f); + + ycc_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], this->m_mode); + output[3] = inputColor[3]; +} + + +/* ******** RGB to YUV ******** */ + +ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertRGBToYUVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]); + output[3] = inputColor[3]; +} + + +/* ******** YUV to RGB ******** */ + +ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertYUVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]); + output[3] = inputColor[3]; +} + + +/* ******** RGB to HSV ******** */ + +ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertRGBToHSVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + rgb_to_hsv_v(inputColor, output); + output[3] = inputColor[3]; +} + + +/* ******** HSV to RGB ******** */ + +ConvertHSVToRGBOperation::ConvertHSVToRGBOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertHSVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor[4]; + this->m_inputOperation->read(inputColor, x, y, sampler); + hsv_to_rgb_v(inputColor, output); + output[3] = inputColor[3]; +} + + +/* ******** Premul to Straight ******** */ + +ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertPremulToStraightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputValue[4]; + float alpha; + + this->m_inputOperation->read(inputValue, x, y, sampler); + alpha = inputValue[3]; + + if (fabsf(alpha) < 1e-5f) { + zero_v3(output); + } + else { + mul_v3_v3fl(output, inputValue, 1.0f / alpha); + } + + /* never touches the alpha */ + output[3] = alpha; +} + + +/* ******** Straight to Premul ******** */ + +ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : ConvertBaseOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); +} + +void ConvertStraightToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputValue[4]; + float alpha; + + this->m_inputOperation->read(inputValue, x, y, sampler); + alpha = inputValue[3]; + + mul_v3_v3fl(output, inputValue, alpha); + + /* never touches the alpha */ + output[3] = alpha; +} + + +/* ******** Separate Channels ******** */ + +SeparateChannelOperation::SeparateChannelOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_VALUE); + this->m_inputOperation = NULL; +} +void SeparateChannelOperation::initExecution() +{ + this->m_inputOperation = this->getInputSocketReader(0); +} + +void SeparateChannelOperation::deinitExecution() +{ + this->m_inputOperation = NULL; +} + + +void SeparateChannelOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float input[4]; + this->m_inputOperation->read(input, x, y, sampler); + output[0] = input[this->m_channel]; +} + + +/* ******** Combine Channels ******** */ + +CombineChannelsOperation::CombineChannelsOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_VALUE); + this->addOutputSocket(COM_DT_COLOR); + this->setResolutionInputSocketIndex(0); + this->m_inputChannel1Operation = NULL; + this->m_inputChannel2Operation = NULL; + this->m_inputChannel3Operation = NULL; + this->m_inputChannel4Operation = NULL; +} + +void CombineChannelsOperation::initExecution() +{ + this->m_inputChannel1Operation = this->getInputSocketReader(0); + this->m_inputChannel2Operation = this->getInputSocketReader(1); + this->m_inputChannel3Operation = this->getInputSocketReader(2); + this->m_inputChannel4Operation = this->getInputSocketReader(3); +} + +void CombineChannelsOperation::deinitExecution() +{ + this->m_inputChannel1Operation = NULL; + this->m_inputChannel2Operation = NULL; + this->m_inputChannel3Operation = NULL; + this->m_inputChannel4Operation = NULL; +} + + +void CombineChannelsOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float input[4]; + if (this->m_inputChannel1Operation) { + this->m_inputChannel1Operation->read(input, x, y, sampler); + output[0] = input[0]; + } + if (this->m_inputChannel2Operation) { + this->m_inputChannel2Operation->read(input, x, y, sampler); + output[1] = input[0]; + } + if (this->m_inputChannel3Operation) { + this->m_inputChannel3Operation->read(input, x, y, sampler); + output[2] = input[0]; + } + if (this->m_inputChannel4Operation) { + this->m_inputChannel4Operation->read(input, x, y, sampler); + output[3] = input[0]; + } +} diff --git a/source/blender/compositor/operations/COM_ConvertOperation.h b/source/blender/compositor/operations/COM_ConvertOperation.h new file mode 100644 index 00000000000..06aeb2e52d7 --- /dev/null +++ b/source/blender/compositor/operations/COM_ConvertOperation.h @@ -0,0 +1,202 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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: + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_ConvertOperation_h +#define _COM_ConvertOperation_h + +#include "COM_NodeOperation.h" + + +class ConvertBaseOperation : public NodeOperation { +protected: + SocketReader *m_inputOperation; + +public: + ConvertBaseOperation(); + + void initExecution(); + void deinitExecution(); +}; + + +class ConvertValueToColorOperation : public ConvertBaseOperation { +public: + ConvertValueToColorOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertColorToValueOperation : public ConvertBaseOperation { +public: + ConvertColorToValueOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertColorToBWOperation : public ConvertBaseOperation { +public: + ConvertColorToBWOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertColorToVectorOperation : public ConvertBaseOperation { +public: + ConvertColorToVectorOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertValueToVectorOperation : public ConvertBaseOperation { +public: + ConvertValueToVectorOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertVectorToColorOperation : public ConvertBaseOperation { +public: + ConvertVectorToColorOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertVectorToValueOperation : public ConvertBaseOperation { +public: + ConvertVectorToValueOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertRGBToYCCOperation : public ConvertBaseOperation { +private: + /** YCbCr mode (Jpeg, ITU601, ITU709) */ + int m_mode; +public: + ConvertRGBToYCCOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + /** Set the YCC mode */ + void setMode(int mode); +}; + + +class ConvertYCCToRGBOperation : public ConvertBaseOperation { +private: + /** YCbCr mode (Jpeg, ITU601, ITU709) */ + int m_mode; +public: + ConvertYCCToRGBOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + /** Set the YCC mode */ + void setMode(int mode); +}; + + +class ConvertRGBToYUVOperation : public ConvertBaseOperation { +public: + ConvertRGBToYUVOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertYUVToRGBOperation : public ConvertBaseOperation { +public: + ConvertYUVToRGBOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertRGBToHSVOperation : public ConvertBaseOperation { +public: + ConvertRGBToHSVOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertHSVToRGBOperation : public ConvertBaseOperation { +public: + ConvertHSVToRGBOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertPremulToStraightOperation : public ConvertBaseOperation { +public: + ConvertPremulToStraightOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class ConvertStraightToPremulOperation : public ConvertBaseOperation { +public: + ConvertStraightToPremulOperation(); + + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + + +class SeparateChannelOperation : public NodeOperation { +private: + SocketReader *m_inputOperation; + int m_channel; +public: + SeparateChannelOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); + + void setChannel(int channel) { this->m_channel = channel; } +}; + + +class CombineChannelsOperation : public NodeOperation { +private: + SocketReader *m_inputChannel1Operation; + SocketReader *m_inputChannel2Operation; + SocketReader *m_inputChannel3Operation; + SocketReader *m_inputChannel4Operation; +public: + CombineChannelsOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + void initExecution(); + void deinitExecution(); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp b/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp deleted file mode 100644 index 2af4b55de1a..00000000000 --- a/source/blender/compositor/operations/COM_ConvertPremulToStraightOperation.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2012, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#include "COM_ConvertPremulToStraightOperation.h" -#include "BLI_math.h" - -ConvertPremulToStraightOperation::ConvertPremulToStraightOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - - this->m_inputColor = NULL; -} - -void ConvertPremulToStraightOperation::initExecution() -{ - this->m_inputColor = getInputSocketReader(0); -} - -void ConvertPremulToStraightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputValue[4]; - float alpha; - - this->m_inputColor->read(inputValue, x, y, sampler); - alpha = inputValue[3]; - - if (fabsf(alpha) < 1e-5f) { - zero_v3(output); - } - else { - mul_v3_v3fl(output, inputValue, 1.0f / alpha); - } - - /* never touches the alpha */ - output[3] = alpha; -} - -void ConvertPremulToStraightOperation::deinitExecution() -{ - this->m_inputColor = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp b/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp deleted file mode 100644 index 3c7a9d5fd50..00000000000 --- a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertRGBToHSVOperation.h" -#include "BLI_math_color.h" - -ConvertRGBToHSVOperation::ConvertRGBToHSVOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertRGBToHSVOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertRGBToHSVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - rgb_to_hsv_v(inputColor, output); - output[3] = inputColor[3]; -} - -void ConvertRGBToHSVOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h b/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h deleted file mode 100644 index fdc8dfed31b..00000000000 --- a/source/blender/compositor/operations/COM_ConvertRGBToHSVOperation.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertRGBToHSVOperation_h -#define _COM_ConvertRGBToHSVOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertRGBToHSVOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertRGBToHSVOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp b/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp deleted file mode 100644 index 6f6dffdc72b..00000000000 --- a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#include "COM_ConvertRGBToYCCOperation.h" -#include "BLI_math_color.h" - -ConvertRGBToYCCOperation::ConvertRGBToYCCOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertRGBToYCCOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertRGBToYCCOperation::setMode(int mode) -{ - switch (mode) { - case 1: - this->m_mode = BLI_YCC_ITU_BT709; - break; - case 2: - this->m_mode = BLI_YCC_JFIF_0_255; - break; - case 0: - default: - this->m_mode = BLI_YCC_ITU_BT601; - break; - } -} - -void ConvertRGBToYCCOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - float color[3]; - - this->m_inputOperation->read(inputColor, x, y, sampler); - rgb_to_ycc(inputColor[0], inputColor[1], inputColor[2], &color[0], &color[1], &color[2], this->m_mode); - - /* divided by 255 to normalize for viewing in */ - /* R,G,B --> Y,Cb,Cr */ - mul_v3_v3fl(output, color, 1.0f / 255.0f); - output[3] = inputColor[3]; -} - -void ConvertRGBToYCCOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h b/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h deleted file mode 100644 index 3f85555f3bb..00000000000 --- a/source/blender/compositor/operations/COM_ConvertRGBToYCCOperation.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#ifndef _COM_ConvertRGBToYCCOperation_h -#define _COM_ConvertRGBToYCCOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertRGBToYCCOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; - - /** - * YCbCr mode (Jpeg, ITU601, ITU709) - */ - int m_mode; -public: - /** - * Default constructor - */ - ConvertRGBToYCCOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - /** - * Set the YCC mode - */ - void setMode(int mode); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp b/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp deleted file mode 100644 index 8ce9e150080..00000000000 --- a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#include "COM_ConvertRGBToYUVOperation.h" -#include "BLI_math_color.h" - -ConvertRGBToYUVOperation::ConvertRGBToYUVOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertRGBToYUVOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertRGBToYUVOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - rgb_to_yuv(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]); - output[3] = inputColor[3]; -} - -void ConvertRGBToYUVOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h b/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h deleted file mode 100644 index 97d57f657ec..00000000000 --- a/source/blender/compositor/operations/COM_ConvertRGBToYUVOperation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#ifndef _COM_ConvertRGBToYUVOperation_h -#define _COM_ConvertRGBToYUVOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertRGBToYUVOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertRGBToYUVOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp deleted file mode 100644 index ae55d949ff2..00000000000 --- a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#include "COM_ConvertStraightToPremulOperation.h" -#include "BLI_math.h" - -ConvertStraightToPremulOperation::ConvertStraightToPremulOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - - this->m_inputColor = NULL; -} - -void ConvertStraightToPremulOperation::initExecution() -{ - this->m_inputColor = getInputSocketReader(0); -} - -void ConvertStraightToPremulOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputValue[4]; - float alpha; - - this->m_inputColor->read(inputValue, x, y, sampler); - alpha = inputValue[3]; - - mul_v3_v3fl(output, inputValue, alpha); - - /* never touches the alpha */ - output[3] = alpha; -} - -void ConvertStraightToPremulOperation::deinitExecution() -{ - this->m_inputColor = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h b/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h deleted file mode 100644 index d0191f292d2..00000000000 --- a/source/blender/compositor/operations/COM_ConvertStraightToPremulOperation.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2012, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#ifndef _COM_ConvertStraightToPremulOperation_h -#define _COM_ConvertStraightToPremulOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertStraightToPremulOperation : public NodeOperation { -private: - SocketReader *m_inputColor; -public: - /** - * Default constructor - */ - ConvertStraightToPremulOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp b/source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp deleted file mode 100644 index 98e7650aa56..00000000000 --- a/source/blender/compositor/operations/COM_ConvertValueToColorProg.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertValueToColorProg.h" - -ConvertValueToColorProg::ConvertValueToColorProg() : NodeOperation() -{ - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputProgram = NULL; -} -void ConvertValueToColorProg::initExecution() -{ - this->m_inputProgram = this->getInputSocketReader(0); -} - -void ConvertValueToColorProg::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputValue[4]; - this->m_inputProgram->read(inputValue, x, y, sampler); - output[0] = output[1] = output[2] = inputValue[0]; - output[3] = 1.0f; -} - -void ConvertValueToColorProg::deinitExecution() -{ - this->m_inputProgram = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertValueToColorProg.h b/source/blender/compositor/operations/COM_ConvertValueToColorProg.h deleted file mode 100644 index f0f6cfb8fd2..00000000000 --- a/source/blender/compositor/operations/COM_ConvertValueToColorProg.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertValueToColorProg_h -#define _COM_ConvertValueToColorProg_h -#include "COM_NodeOperation.h" - - -class ConvertValueToColorProg : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputProgram; -public: - ConvertValueToColorProg(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp b/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp deleted file mode 100644 index 411409d263c..00000000000 --- a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertValueToVectorOperation.h" - -ConvertValueToVectorOperation::ConvertValueToVectorOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_VALUE); - this->addOutputSocket(COM_DT_VECTOR); - this->m_inputOperation = NULL; -} - -void ConvertValueToVectorOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertValueToVectorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float input[4]; - this->m_inputOperation->read(input, x, y, sampler); - output[0] = input[0]; - output[1] = input[0]; - output[2] = input[0]; - output[3] = 0.0f; -} - -void ConvertValueToVectorOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h b/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h deleted file mode 100644 index da45848ca34..00000000000 --- a/source/blender/compositor/operations/COM_ConvertValueToVectorOperation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertValueToVectorOperation_h -#define _COM_ConvertValueToVectorOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertValueToVectorOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertValueToVectorOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp b/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp deleted file mode 100644 index 78cb706c32d..00000000000 --- a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertVectorToColorOperation.h" - -ConvertVectorToColorOperation::ConvertVectorToColorOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertVectorToColorOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertVectorToColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - this->m_inputOperation->read(output, x, y, sampler); - output[3] = 1.0f; -} - -void ConvertVectorToColorOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h b/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h deleted file mode 100644 index 9ef5f8fece3..00000000000 --- a/source/blender/compositor/operations/COM_ConvertVectorToColorOperation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertVectorToColorOperation_h -#define _COM_ConvertVectorToColorOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertVectorToColorOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertVectorToColorOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp b/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp deleted file mode 100644 index a3612414029..00000000000 --- a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_ConvertVectorToValueOperation.h" - -ConvertVectorToValueOperation::ConvertVectorToValueOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_VECTOR); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; -} - -void ConvertVectorToValueOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertVectorToValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float input[4]; - this->m_inputOperation->read(input, x, y, sampler); - output[0] = (input[0] + input[1] + input[2]) / 3.0f; -} - -void ConvertVectorToValueOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} diff --git a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h b/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h deleted file mode 100644 index e42f235a12b..00000000000 --- a/source/blender/compositor/operations/COM_ConvertVectorToValueOperation.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_ConvertVectorToValueOperation_h -#define _COM_ConvertVectorToValueOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertVectorToValueOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertVectorToValueOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp b/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp deleted file mode 100644 index 8f9eaf49ea4..00000000000 --- a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#include "COM_ConvertYCCToRGBOperation.h" -#include "BLI_math_color.h" - -ConvertYCCToRGBOperation::ConvertYCCToRGBOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertYCCToRGBOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertYCCToRGBOperation::setMode(int mode) -{ - switch (mode) { - case 1: - this->m_mode = BLI_YCC_ITU_BT709; - break; - case 2: - this->m_mode = BLI_YCC_JFIF_0_255; - break; - case 0: - default: - this->m_mode = BLI_YCC_ITU_BT601; - break; - } -} - -void ConvertYCCToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - - /* need to un-normalize the data */ - /* R,G,B --> Y,Cb,Cr */ - mul_v3_fl(inputColor, 255.0f); - - ycc_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2], this->m_mode); - output[3] = inputColor[3]; -} - -void ConvertYCCToRGBOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} - diff --git a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h b/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h deleted file mode 100644 index 0a8b67e0bee..00000000000 --- a/source/blender/compositor/operations/COM_ConvertYCCToRGBOperation.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#ifndef _COM_ConvertYCCToRGBOperation_h -#define _COM_ConvertYCCToRGBOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertYCCToRGBOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; - - /** - * YCbCr mode (Jpeg, ITU601, ITU709) - */ - int m_mode; -public: - /** - * Default constructor - */ - ConvertYCCToRGBOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); - - /** - * Set the YCC mode - */ - void setMode(int mode); -}; -#endif diff --git a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp b/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp deleted file mode 100644 index 197c7f9f043..00000000000 --- a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#include "COM_ConvertYUVToRGBOperation.h" -#include "BLI_math_color.h" - -ConvertYUVToRGBOperation::ConvertYUVToRGBOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputOperation = NULL; -} - -void ConvertYUVToRGBOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void ConvertYUVToRGBOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor[4]; - this->m_inputOperation->read(inputColor, x, y, sampler); - yuv_to_rgb(inputColor[0], inputColor[1], inputColor[2], &output[0], &output[1], &output[2]); - output[3] = inputColor[3]; -} - -void ConvertYUVToRGBOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} - diff --git a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h b/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h deleted file mode 100644 index ee11ef8df60..00000000000 --- a/source/blender/compositor/operations/COM_ConvertYUVToRGBOperation.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Dalai Felinto - */ - -#ifndef _COM_ConvertYUVToRGBOperation_h -#define _COM_ConvertYUVToRGBOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class ConvertYUVToRGBOperation : public NodeOperation { -private: - /** - * Cached reference to the inputProgram - */ - SocketReader *m_inputOperation; -public: - /** - * Default constructor - */ - ConvertYUVToRGBOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - void deinitExecution(); -}; -#endif diff --git a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h index e7d881cbbd5..e0a38f703ed 100644 --- a/source/blender/compositor/operations/COM_DifferenceMatteOperation.h +++ b/source/blender/compositor/operations/COM_DifferenceMatteOperation.h @@ -22,7 +22,7 @@ #ifndef _COM_DifferenceMatteOperation_h #define _COM_DifferenceMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h index 5a34135b1a4..43299486f60 100644 --- a/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h +++ b/source/blender/compositor/operations/COM_DistanceRGBMatteOperation.h @@ -21,7 +21,7 @@ #ifndef _COM_DistanceRGBMatteOperation_h #define _COM_DistanceRGBMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h index f4866a327f1..27025188d49 100644 --- a/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h +++ b/source/blender/compositor/operations/COM_DistanceYCCMatteOperation.h @@ -21,7 +21,7 @@ #ifndef _COM_DistanceYCCMatteOperation_h #define _COM_DistanceYCCMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" #include "COM_DistanceRGBMatteOperation.h" diff --git a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp index c4f8b3a0ddb..8854be52ded 100644 --- a/source/blender/compositor/operations/COM_GlareGhostOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareGhostOperation.cpp @@ -83,11 +83,11 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No for (x = 0; x < gbuf->getWidth(); x++) { u = ((float)x + 0.5f) / (float)gbuf->getWidth(); s = (u - 0.5f) * sc + 0.5f, t = (v - 0.5f) * sc + 0.5f; - tbuf1->readCubic(c, s * gbuf->getWidth(), t * gbuf->getHeight()); + tbuf1->readBilinear(c, s * gbuf->getWidth(), t * gbuf->getHeight()); sm = smoothMask(s, t); mul_v3_fl(c, sm); s = (u - 0.5f) * isc + 0.5f, t = (v - 0.5f) * isc + 0.5f; - tbuf2->readCubic(tc, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); + tbuf2->readBilinear(tc, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); sm = smoothMask(s, t); madd_v3_v3fl(c, tc, sm); @@ -108,7 +108,7 @@ void GlareGhostOperation::generateGlare(float *data, MemoryBuffer *inputTile, No np = (n << 2) + p; s = (u - 0.5f) * scalef[np] + 0.5f; t = (v - 0.5f) * scalef[np] + 0.5f; - gbuf->readCubic(c, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); + gbuf->readBilinear(c, s * gbuf->getWidth() - 0.5f, t * gbuf->getHeight() - 0.5f); mul_v3_v3(c, cm[np]); sm = smoothMask(s, t) * 0.25f; madd_v3_v3fl(tc, c, sm); diff --git a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp index 60d37fb8145..5644ff30ef3 100644 --- a/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareStreaksOperation.cpp @@ -54,9 +54,9 @@ void GlareStreaksOperation::generateGlare(float *data, MemoryBuffer *inputTile, // first pass no offset, always same for every pass, exact copy, // otherwise results in uneven brightness, only need once if (n == 0) tsrc->read(c1, x, y); else c1[0] = c1[1] = c1[2] = 0; - tsrc->readCubic(c2, x + vxp, y + vyp); - tsrc->readCubic(c3, x + vxp * 2.f, y + vyp * 2.f); - tsrc->readCubic(c4, x + vxp * 3.f, y + vyp * 3.f); + tsrc->readBilinear(c2, x + vxp, y + vyp); + tsrc->readBilinear(c3, x + vxp * 2.f, y + vyp * 2.f); + tsrc->readBilinear(c4, x + vxp * 3.f, y + vyp * 3.f); // modulate color to look vaguely similar to a color spectrum c2[1] *= cmo; c2[2] *= cmo; diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index 89a56af6b15..cface29fdca 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -141,7 +141,7 @@ static void sampleImageAtLocation(ImBuf *ibuf, float x, float y, PixelSampler sa } rgba_uchar_to_float(color, byte_color); if (make_linear_rgb) { - IMB_colormanagement_colorspace_to_scene_linear_v4(color, FALSE, ibuf->rect_colorspace); + IMB_colormanagement_colorspace_to_scene_linear_v4(color, false, ibuf->rect_colorspace); } } } diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h index 009a1e8825e..cb8cc01efea 100644 --- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.h +++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.h @@ -21,7 +21,7 @@ #ifndef _COM_LuminanceMatteOperation_h #define _COM_LuminanceMatteOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/compositor/operations/COM_MixAddOperation.cpp b/source/blender/compositor/operations/COM_MixAddOperation.cpp deleted file mode 100644 index 4e0876439c0..00000000000 --- a/source/blender/compositor/operations/COM_MixAddOperation.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixAddOperation.h" - -MixAddOperation::MixAddOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixAddOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - output[0] = inputColor1[0] + value * inputColor2[0]; - output[1] = inputColor1[1] + value * inputColor2[1]; - output[2] = inputColor1[2] + value * inputColor2[2]; - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixAddOperation.h b/source/blender/compositor/operations/COM_MixAddOperation.h deleted file mode 100644 index 5a52846e847..00000000000 --- a/source/blender/compositor/operations/COM_MixAddOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixAddOperation_h -#define _COM_MixAddOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixAddOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixAddOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.cpp b/source/blender/compositor/operations/COM_MixBaseOperation.cpp deleted file mode 100644 index 5b455338bb0..00000000000 --- a/source/blender/compositor/operations/COM_MixBaseOperation.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixBaseOperation.h" - -MixBaseOperation::MixBaseOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_VALUE); - this->addInputSocket(COM_DT_COLOR); - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->m_inputValueOperation = NULL; - this->m_inputColor1Operation = NULL; - this->m_inputColor2Operation = NULL; - this->setUseValueAlphaMultiply(false); - this->setUseClamp(false); -} - -void MixBaseOperation::initExecution() -{ - this->m_inputValueOperation = this->getInputSocketReader(0); - this->m_inputColor1Operation = this->getInputSocketReader(1); - this->m_inputColor2Operation = this->getInputSocketReader(2); -} - -void MixBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); - output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); - output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); - output[3] = inputColor1[3]; -} - -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); - socket->determineResolution(tempResolution, tempPreferredResolution); - if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { - this->setResolutionInputSocketIndex(2); - } - else { - this->setResolutionInputSocketIndex(0); - } - } - NodeOperation::determineResolution(resolution, preferredResolution); -} - -void MixBaseOperation::deinitExecution() -{ - this->m_inputValueOperation = NULL; - this->m_inputColor1Operation = NULL; - this->m_inputColor2Operation = NULL; -} diff --git a/source/blender/compositor/operations/COM_MixBaseOperation.h b/source/blender/compositor/operations/COM_MixBaseOperation.h deleted file mode 100644 index 3c0c0778190..00000000000 --- a/source/blender/compositor/operations/COM_MixBaseOperation.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixBaseOperation_h -#define _COM_MixBaseOperation_h -#include "COM_NodeOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixBaseOperation : public NodeOperation { -protected: - /** - * Prefetched reference to the inputProgram - */ - SocketReader *m_inputValueOperation; - SocketReader *m_inputColor1Operation; - SocketReader *m_inputColor2Operation; - bool m_valueAlphaMultiply; - bool m_useClamp; - - inline void clampIfNeeded(float color[4]) - { - if (m_useClamp) { - CLAMP(color[0], 0.0f, 1.0f); - CLAMP(color[1], 0.0f, 1.0f); - CLAMP(color[2], 0.0f, 1.0f); - CLAMP(color[3], 0.0f, 1.0f); - } - } - -public: - /** - * Default constructor - */ - MixBaseOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - /** - * Initialize the execution - */ - void initExecution(); - - /** - * Deinitialize the execution - */ - 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; } -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixBlendOperation.cpp b/source/blender/compositor/operations/COM_MixBlendOperation.cpp deleted file mode 100644 index 0ca7d460064..00000000000 --- a/source/blender/compositor/operations/COM_MixBlendOperation.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixBlendOperation.h" - -MixBlendOperation::MixBlendOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixBlendOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float value; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - value = inputValue[0]; - - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); - output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); - output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} diff --git a/source/blender/compositor/operations/COM_MixBurnOperation.cpp b/source/blender/compositor/operations/COM_MixBurnOperation.cpp deleted file mode 100644 index d4422c6cc6a..00000000000 --- a/source/blender/compositor/operations/COM_MixBurnOperation.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixBurnOperation.h" - -MixBurnOperation::MixBurnOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixBurnOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float tmp; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - tmp = valuem + value * inputColor2[0]; - if (tmp <= 0.0f) - output[0] = 0.0f; - else { - tmp = 1.0f - (1.0f - inputColor1[0]) / tmp; - if (tmp < 0.0f) - output[0] = 0.0f; - else if (tmp > 1.0f) - output[0] = 1.0f; - else - output[0] = tmp; - } - - tmp = valuem + value * inputColor2[1]; - if (tmp <= 0.0f) - output[1] = 0.0f; - else { - tmp = 1.0f - (1.0f - inputColor1[1]) / tmp; - if (tmp < 0.0f) - output[1] = 0.0f; - else if (tmp > 1.0f) - output[1] = 1.0f; - else - output[1] = tmp; - } - - tmp = valuem + value * inputColor2[2]; - if (tmp <= 0.0f) - output[2] = 0.0f; - else { - tmp = 1.0f - (1.0f - inputColor1[2]) / tmp; - if (tmp < 0.0f) - output[2] = 0.0f; - else if (tmp > 1.0f) - output[2] = 1.0f; - else - output[2] = tmp; - } - - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixColorOperation.cpp b/source/blender/compositor/operations/COM_MixColorOperation.cpp deleted file mode 100644 index 6919a636aeb..00000000000 --- a/source/blender/compositor/operations/COM_MixColorOperation.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixColorOperation.h" - -extern "C" { - #include "BLI_math.h" -} - -MixColorOperation::MixColorOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - float colH, colS, colV; - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - if (colS != 0.0f) { - float rH, rS, rV; - float tmpr, tmpg, tmpb; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); - output[0] = (valuem * inputColor1[0]) + (value * tmpr); - output[1] = (valuem * inputColor1[1]) + (value * tmpg); - output[2] = (valuem * inputColor1[2]) + (value * tmpb); - } - else { - copy_v3_v3(output, inputColor1); - } - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixColorOperation.h b/source/blender/compositor/operations/COM_MixColorOperation.h deleted file mode 100644 index 1409d726f03..00000000000 --- a/source/blender/compositor/operations/COM_MixColorOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixColorOperation_h -#define _COM_MixColorOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixColorOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixColorOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixDarkenOperation.cpp b/source/blender/compositor/operations/COM_MixDarkenOperation.cpp deleted file mode 100644 index d56d9fdf122..00000000000 --- a/source/blender/compositor/operations/COM_MixDarkenOperation.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixDarkenOperation.h" - -MixDarkenOperation::MixDarkenOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixDarkenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - float tmp; - tmp = inputColor2[0] + ((1.0f - inputColor2[0]) * valuem); - if (tmp < inputColor1[0]) output[0] = tmp; - else output[0] = inputColor1[0]; - tmp = inputColor2[1] + ((1.0f - inputColor2[1]) * valuem); - if (tmp < inputColor1[1]) output[1] = tmp; - else output[1] = inputColor1[1]; - tmp = inputColor2[2] + ((1.0f - inputColor2[2]) * valuem); - if (tmp < inputColor1[2]) output[2] = tmp; - else output[2] = inputColor1[2]; - - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixDarkenOperation.h b/source/blender/compositor/operations/COM_MixDarkenOperation.h deleted file mode 100644 index f9c35fa364b..00000000000 --- a/source/blender/compositor/operations/COM_MixDarkenOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixDarkenOperation_h -#define _COM_MixDarkenOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixDarkenOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixDarkenOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixDifferenceOperation.cpp b/source/blender/compositor/operations/COM_MixDifferenceOperation.cpp deleted file mode 100644 index 13494401c60..00000000000 --- a/source/blender/compositor/operations/COM_MixDifferenceOperation.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixDifferenceOperation.h" -#include "BLI_math.h" - -MixDifferenceOperation::MixDifferenceOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixDifferenceOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = valuem * inputColor1[0] + value *fabsf(inputColor1[0] - inputColor2[0]); - output[1] = valuem * inputColor1[1] + value *fabsf(inputColor1[1] - inputColor2[1]); - output[2] = valuem * inputColor1[2] + value *fabsf(inputColor1[2] - inputColor2[2]); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixDifferenceOperation.h b/source/blender/compositor/operations/COM_MixDifferenceOperation.h deleted file mode 100644 index 7e4bf3c675c..00000000000 --- a/source/blender/compositor/operations/COM_MixDifferenceOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixDifferenceOperation_h -#define _COM_MixDifferenceOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixDifferenceOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixDifferenceOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixDivideOperation.cpp b/source/blender/compositor/operations/COM_MixDivideOperation.cpp deleted file mode 100644 index 3e0eb66565c..00000000000 --- a/source/blender/compositor/operations/COM_MixDivideOperation.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixDivideOperation.h" - -MixDivideOperation::MixDivideOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixDivideOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - if (inputColor2[0] != 0.0f) - output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0]; - else - output[0] = 0.0f; - if (inputColor2[1] != 0.0f) - output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1]; - else - output[1] = 0.0f; - if (inputColor2[2] != 0.0f) - output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2]; - else - output[2] = 0.0f; - - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixDivideOperation.h b/source/blender/compositor/operations/COM_MixDivideOperation.h deleted file mode 100644 index f543265075b..00000000000 --- a/source/blender/compositor/operations/COM_MixDivideOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixDivideOperation_h -#define _COM_MixDivideOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixDivideOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixDivideOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixDodgeOperation.cpp b/source/blender/compositor/operations/COM_MixDodgeOperation.cpp deleted file mode 100644 index acb39f665ff..00000000000 --- a/source/blender/compositor/operations/COM_MixDodgeOperation.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixDodgeOperation.h" - -MixDodgeOperation::MixDodgeOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixDodgeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float tmp; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - - if (inputColor1[0] != 0.0f) { - tmp = 1.0f - value * inputColor2[0]; - if (tmp <= 0.0f) - output[0] = 1.0f; - else { - tmp = inputColor1[0] / tmp; - if (tmp > 1.0f) - output[0] = 1.0f; - else - output[0] = tmp; - } - } - else - output[0] = 0.0f; - - if (inputColor1[1] != 0.0f) { - tmp = 1.0f - value * inputColor2[1]; - if (tmp <= 0.0f) - output[1] = 1.0f; - else { - tmp = inputColor1[1] / tmp; - if (tmp > 1.0f) - output[1] = 1.0f; - else - output[1] = tmp; - } - } - else - output[1] = 0.0f; - - if (inputColor1[2] != 0.0f) { - tmp = 1.0f - value * inputColor2[2]; - if (tmp <= 0.0f) - output[2] = 1.0f; - else { - tmp = inputColor1[2] / tmp; - if (tmp > 1.0f) - output[2] = 1.0f; - else - output[2] = tmp; - } - } - else - output[2] = 0.0f; - - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixDodgeOperation.h b/source/blender/compositor/operations/COM_MixDodgeOperation.h deleted file mode 100644 index 9a285c675c5..00000000000 --- a/source/blender/compositor/operations/COM_MixDodgeOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixDodgeOperation_h -#define _COM_MixDodgeOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixDodgeOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixDodgeOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixGlareOperation.cpp b/source/blender/compositor/operations/COM_MixGlareOperation.cpp deleted file mode 100644 index 1c6555206da..00000000000 --- a/source/blender/compositor/operations/COM_MixGlareOperation.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011, Glareer Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixGlareOperation.h" - -MixGlareOperation::MixGlareOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixGlareOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - float value; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - value = inputValue[0]; - float mf = 2.f - 2.f * fabsf(value - 0.5f); - - if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f; - if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f; - if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f; - - output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f); - output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f); - output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} diff --git a/source/blender/compositor/operations/COM_MixGlareOperation.h b/source/blender/compositor/operations/COM_MixGlareOperation.h deleted file mode 100644 index 99d478e347d..00000000000 --- a/source/blender/compositor/operations/COM_MixGlareOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Glareer Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixGlareOperation_h -#define _COM_MixGlareOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixGlareOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixGlareOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixHueOperation.cpp b/source/blender/compositor/operations/COM_MixHueOperation.cpp deleted file mode 100644 index 64c88592b93..00000000000 --- a/source/blender/compositor/operations/COM_MixHueOperation.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixHueOperation.h" - -extern "C" { - #include "BLI_math.h" -} - -MixHueOperation::MixHueOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixHueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - float colH, colS, colV; - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - if (colS != 0.0f) { - float rH, rS, rV; - float tmpr, tmpg, tmpb; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb); - output[0] = valuem * (inputColor1[0]) + value * tmpr; - output[1] = valuem * (inputColor1[1]) + value * tmpg; - output[2] = valuem * (inputColor1[2]) + value * tmpb; - } - else { - copy_v3_v3(output, inputColor1); - } - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} diff --git a/source/blender/compositor/operations/COM_MixHueOperation.h b/source/blender/compositor/operations/COM_MixHueOperation.h deleted file mode 100644 index d9864bbe3dc..00000000000 --- a/source/blender/compositor/operations/COM_MixHueOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixHueOperation_h -#define _COM_MixHueOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixHueOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixHueOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixLightenOperation.cpp b/source/blender/compositor/operations/COM_MixLightenOperation.cpp deleted file mode 100644 index a468fb39442..00000000000 --- a/source/blender/compositor/operations/COM_MixLightenOperation.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixLightenOperation.h" - -MixLightenOperation::MixLightenOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixLightenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float tmp; - tmp = value * inputColor2[0]; - if (tmp > inputColor1[0]) output[0] = tmp; - else output[0] = inputColor1[0]; - tmp = value * inputColor2[1]; - if (tmp > inputColor1[1]) output[1] = tmp; - else output[1] = inputColor1[1]; - tmp = value * inputColor2[2]; - if (tmp > inputColor1[2]) output[2] = tmp; - else output[2] = inputColor1[2]; - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixLightenOperation.h b/source/blender/compositor/operations/COM_MixLightenOperation.h deleted file mode 100644 index 5f08a067e11..00000000000 --- a/source/blender/compositor/operations/COM_MixLightenOperation.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixLightenOperation_h -#define _COM_MixLightenOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixLightenOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixLightenOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixLinearLightOperation.cpp b/source/blender/compositor/operations/COM_MixLinearLightOperation.cpp deleted file mode 100644 index e1b5e040f0f..00000000000 --- a/source/blender/compositor/operations/COM_MixLinearLightOperation.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixLinearLightOperation.h" - -MixLinearLightOperation::MixLinearLightOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixLinearLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - if (inputColor2[0] > 0.5f) - output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f)); - else - output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f); - if (inputColor2[1] > 0.5f) - output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f)); - else - output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f); - if (inputColor2[2] > 0.5f) - output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f)); - else - output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f); - - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} diff --git a/source/blender/compositor/operations/COM_MixLinearLightOperation.h b/source/blender/compositor/operations/COM_MixLinearLightOperation.h deleted file mode 100644 index 35451a9f3db..00000000000 --- a/source/blender/compositor/operations/COM_MixLinearLightOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixLinearLightOperation_h -#define _COM_MixLinearLightOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixLinearLightOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixLinearLightOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixMultiplyOperation.cpp b/source/blender/compositor/operations/COM_MixMultiplyOperation.cpp deleted file mode 100644 index e53addb7041..00000000000 --- a/source/blender/compositor/operations/COM_MixMultiplyOperation.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixMultiplyOperation.h" - -MixMultiplyOperation::MixMultiplyOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixMultiplyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - output[0] = inputColor1[0] * (valuem + value * inputColor2[0]); - output[1] = inputColor1[1] * (valuem + value * inputColor2[1]); - output[2] = inputColor1[2] * (valuem + value * inputColor2[2]); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixMultiplyOperation.h b/source/blender/compositor/operations/COM_MixMultiplyOperation.h deleted file mode 100644 index cdd56bd2f39..00000000000 --- a/source/blender/compositor/operations/COM_MixMultiplyOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixMultiplyOperation_h -#define _COM_MixMultiplyOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixMultiplyOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixMultiplyOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp new file mode 100644 index 00000000000..f094e93f147 --- /dev/null +++ b/source/blender/compositor/operations/COM_MixOperation.cpp @@ -0,0 +1,848 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_MixOperation.h" + +extern "C" { + #include "BLI_math.h" +} + +/* ******** Mix Base Operation ******** */ + +MixBaseOperation::MixBaseOperation() : NodeOperation() +{ + this->addInputSocket(COM_DT_VALUE); + this->addInputSocket(COM_DT_COLOR); + this->addInputSocket(COM_DT_COLOR); + this->addOutputSocket(COM_DT_COLOR); + this->m_inputValueOperation = NULL; + this->m_inputColor1Operation = NULL; + this->m_inputColor2Operation = NULL; + this->setUseValueAlphaMultiply(false); + this->setUseClamp(false); +} + +void MixBaseOperation::initExecution() +{ + this->m_inputValueOperation = this->getInputSocketReader(0); + this->m_inputColor1Operation = this->getInputSocketReader(1); + this->m_inputColor2Operation = this->getInputSocketReader(2); +} + +void MixBaseOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); + output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); + output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); + output[3] = inputColor1[3]; +} + +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); + socket->determineResolution(tempResolution, tempPreferredResolution); + if ((tempResolution[0] != 0) && (tempResolution[1] != 0)) { + this->setResolutionInputSocketIndex(2); + } + else { + this->setResolutionInputSocketIndex(0); + } + } + NodeOperation::determineResolution(resolution, preferredResolution); +} + +void MixBaseOperation::deinitExecution() +{ + this->m_inputValueOperation = NULL; + this->m_inputColor1Operation = NULL; + this->m_inputColor2Operation = NULL; +} + +/* ******** Mix Add Operation ******** */ + +MixAddOperation::MixAddOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixAddOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + output[0] = inputColor1[0] + value * inputColor2[0]; + output[1] = inputColor1[1] + value * inputColor2[1]; + output[2] = inputColor1[2] + value * inputColor2[2]; + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Blend Operation ******** */ + +MixBlendOperation::MixBlendOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixBlendOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float value; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + value = inputValue[0]; + + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = valuem * (inputColor1[0]) + value * (inputColor2[0]); + output[1] = valuem * (inputColor1[1]) + value * (inputColor2[1]); + output[2] = valuem * (inputColor1[2]) + value * (inputColor2[2]); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Burn Operation ******** */ + +MixBurnOperation::MixBurnOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixBurnOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float tmp; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + tmp = valuem + value * inputColor2[0]; + if (tmp <= 0.0f) + output[0] = 0.0f; + else { + tmp = 1.0f - (1.0f - inputColor1[0]) / tmp; + if (tmp < 0.0f) + output[0] = 0.0f; + else if (tmp > 1.0f) + output[0] = 1.0f; + else + output[0] = tmp; + } + + tmp = valuem + value * inputColor2[1]; + if (tmp <= 0.0f) + output[1] = 0.0f; + else { + tmp = 1.0f - (1.0f - inputColor1[1]) / tmp; + if (tmp < 0.0f) + output[1] = 0.0f; + else if (tmp > 1.0f) + output[1] = 1.0f; + else + output[1] = tmp; + } + + tmp = valuem + value * inputColor2[2]; + if (tmp <= 0.0f) + output[2] = 0.0f; + else { + tmp = 1.0f - (1.0f - inputColor1[2]) / tmp; + if (tmp < 0.0f) + output[2] = 0.0f; + else if (tmp > 1.0f) + output[2] = 1.0f; + else + output[2] = tmp; + } + + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Color Operation ******** */ + +MixColorOperation::MixColorOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixColorOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, colS, rV, &tmpr, &tmpg, &tmpb); + output[0] = (valuem * inputColor1[0]) + (value * tmpr); + output[1] = (valuem * inputColor1[1]) + (value * tmpg); + output[2] = (valuem * inputColor1[2]) + (value * tmpb); + } + else { + copy_v3_v3(output, inputColor1); + } + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Darken Operation ******** */ + +MixDarkenOperation::MixDarkenOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixDarkenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + float tmp; + tmp = inputColor2[0] + ((1.0f - inputColor2[0]) * valuem); + if (tmp < inputColor1[0]) output[0] = tmp; + else output[0] = inputColor1[0]; + tmp = inputColor2[1] + ((1.0f - inputColor2[1]) * valuem); + if (tmp < inputColor1[1]) output[1] = tmp; + else output[1] = inputColor1[1]; + tmp = inputColor2[2] + ((1.0f - inputColor2[2]) * valuem); + if (tmp < inputColor1[2]) output[2] = tmp; + else output[2] = inputColor1[2]; + + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Difference Operation ******** */ + +MixDifferenceOperation::MixDifferenceOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixDifferenceOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = valuem * inputColor1[0] + value *fabsf(inputColor1[0] - inputColor2[0]); + output[1] = valuem * inputColor1[1] + value *fabsf(inputColor1[1] - inputColor2[1]); + output[2] = valuem * inputColor1[2] + value *fabsf(inputColor1[2] - inputColor2[2]); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Difference Operation ******** */ + +MixDivideOperation::MixDivideOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixDivideOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + if (inputColor2[0] != 0.0f) + output[0] = valuem * (inputColor1[0]) + value * (inputColor1[0]) / inputColor2[0]; + else + output[0] = 0.0f; + if (inputColor2[1] != 0.0f) + output[1] = valuem * (inputColor1[1]) + value * (inputColor1[1]) / inputColor2[1]; + else + output[1] = 0.0f; + if (inputColor2[2] != 0.0f) + output[2] = valuem * (inputColor1[2]) + value * (inputColor1[2]) / inputColor2[2]; + else + output[2] = 0.0f; + + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Dodge Operation ******** */ + +MixDodgeOperation::MixDodgeOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixDodgeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float tmp; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + + if (inputColor1[0] != 0.0f) { + tmp = 1.0f - value * inputColor2[0]; + if (tmp <= 0.0f) + output[0] = 1.0f; + else { + tmp = inputColor1[0] / tmp; + if (tmp > 1.0f) + output[0] = 1.0f; + else + output[0] = tmp; + } + } + else + output[0] = 0.0f; + + if (inputColor1[1] != 0.0f) { + tmp = 1.0f - value * inputColor2[1]; + if (tmp <= 0.0f) + output[1] = 1.0f; + else { + tmp = inputColor1[1] / tmp; + if (tmp > 1.0f) + output[1] = 1.0f; + else + output[1] = tmp; + } + } + else + output[1] = 0.0f; + + if (inputColor1[2] != 0.0f) { + tmp = 1.0f - value * inputColor2[2]; + if (tmp <= 0.0f) + output[2] = 1.0f; + else { + tmp = inputColor1[2] / tmp; + if (tmp > 1.0f) + output[2] = 1.0f; + else + output[2] = tmp; + } + } + else + output[2] = 0.0f; + + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Glare Operation ******** */ + +MixGlareOperation::MixGlareOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixGlareOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + float value; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + value = inputValue[0]; + float mf = 2.f - 2.f * fabsf(value - 0.5f); + + if (inputColor1[0] < 0.0f) inputColor1[0] = 0.0f; + if (inputColor1[1] < 0.0f) inputColor1[1] = 0.0f; + if (inputColor1[2] < 0.0f) inputColor1[2] = 0.0f; + + output[0] = mf * max(inputColor1[0] + value * (inputColor2[0] - inputColor1[0]), 0.0f); + output[1] = mf * max(inputColor1[1] + value * (inputColor2[1] - inputColor1[1]), 0.0f); + output[2] = mf * max(inputColor1[2] + value * (inputColor2[2] - inputColor1[2]), 0.0f); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Hue Operation ******** */ + +MixHueOperation::MixHueOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixHueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + float colH, colS, colV; + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + if (colS != 0.0f) { + float rH, rS, rV; + float tmpr, tmpg, tmpb; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + hsv_to_rgb(colH, rS, rV, &tmpr, &tmpg, &tmpb); + output[0] = valuem * (inputColor1[0]) + value * tmpr; + output[1] = valuem * (inputColor1[1]) + value * tmpg; + output[2] = valuem * (inputColor1[2]) + value * tmpb; + } + else { + copy_v3_v3(output, inputColor1); + } + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Lighten Operation ******** */ + +MixLightenOperation::MixLightenOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixLightenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float tmp; + tmp = value * inputColor2[0]; + if (tmp > inputColor1[0]) output[0] = tmp; + else output[0] = inputColor1[0]; + tmp = value * inputColor2[1]; + if (tmp > inputColor1[1]) output[1] = tmp; + else output[1] = inputColor1[1]; + tmp = value * inputColor2[2]; + if (tmp > inputColor1[2]) output[2] = tmp; + else output[2] = inputColor1[2]; + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Linear Light Operation ******** */ + +MixLinearLightOperation::MixLinearLightOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixLinearLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + if (inputColor2[0] > 0.5f) + output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0] - 0.5f)); + else + output[0] = inputColor1[0] + value * (2.0f * (inputColor2[0]) - 1.0f); + if (inputColor2[1] > 0.5f) + output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1] - 0.5f)); + else + output[1] = inputColor1[1] + value * (2.0f * (inputColor2[1]) - 1.0f); + if (inputColor2[2] > 0.5f) + output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2] - 0.5f)); + else + output[2] = inputColor1[2] + value * (2.0f * (inputColor2[2]) - 1.0f); + + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Multiply Operation ******** */ + +MixMultiplyOperation::MixMultiplyOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixMultiplyOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + output[0] = inputColor1[0] * (valuem + value * inputColor2[0]); + output[1] = inputColor1[1] * (valuem + value * inputColor2[1]); + output[2] = inputColor1[2] * (valuem + value * inputColor2[2]); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Ovelray Operation ******** */ + +MixOverlayOperation::MixOverlayOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixOverlayOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + + float valuem = 1.0f - value; + + if (inputColor1[0] < 0.5f) { + output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]); + } + else { + output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); + } + if (inputColor1[1] < 0.5f) { + output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]); + } + else { + output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); + } + if (inputColor1[2] < 0.5f) { + output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]); + } + else { + output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); + } + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Saturation Operation ******** */ + +MixSaturationOperation::MixSaturationOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixSaturationOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + float rH, rS, rV; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + if (rS != 0.0f) { + float colH, colS, colV; + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]); + } + else { + copy_v3_v3(output, inputColor1); + } + + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Screen Operation ******** */ + +MixScreenOperation::MixScreenOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixScreenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); + output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); + output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Soft Light Operation ******** */ + +MixSoftLightOperation::MixSoftLightOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixSoftLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) \ +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + float scr, scg, scb; + + /* first calculate non-fac based Screen mix */ + scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]); + scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]); + scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]); + + output[0] = valuem * (inputColor1[0]) + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + (inputColor1[0] * scr)); + output[1] = valuem * (inputColor1[1]) + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + (inputColor1[1] * scg)); + output[2] = valuem * (inputColor1[2]) + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + (inputColor1[2] * scb)); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Subtract Operation ******** */ + +MixSubtractOperation::MixSubtractOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixSubtractOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + output[0] = inputColor1[0] - value * (inputColor2[0]); + output[1] = inputColor1[1] - value * (inputColor2[1]); + output[2] = inputColor1[2] - value * (inputColor2[2]); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} + +/* ******** Mix Value Operation ******** */ + +MixValueOperation::MixValueOperation() : MixBaseOperation() +{ + /* pass */ +} + +void MixValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + float inputColor1[4]; + float inputColor2[4]; + float inputValue[4]; + + this->m_inputValueOperation->read(inputValue, x, y, sampler); + this->m_inputColor1Operation->read(inputColor1, x, y, sampler); + this->m_inputColor2Operation->read(inputColor2, x, y, sampler); + + float value = inputValue[0]; + if (this->useValueAlphaMultiply()) { + value *= inputColor2[3]; + } + float valuem = 1.0f - value; + + float rH, rS, rV; + float colH, colS, colV; + rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); + rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); + hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]); + output[3] = inputColor1[3]; + + clampIfNeeded(output); +} diff --git a/source/blender/compositor/operations/COM_MixOperation.h b/source/blender/compositor/operations/COM_MixOperation.h new file mode 100644 index 00000000000..93dbe6f36a6 --- /dev/null +++ b/source/blender/compositor/operations/COM_MixOperation.h @@ -0,0 +1,197 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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: + * Jeroen Bakker + * Monique Dewanchand + */ + +#ifndef _COM_MixBaseOperation_h +#define _COM_MixBaseOperation_h +#include "COM_NodeOperation.h" + + +/** + * All this programs converts an input color to an output value. + * it assumes we are in sRGB color space. + */ + +class MixBaseOperation : public NodeOperation { +protected: + /** + * Prefetched reference to the inputProgram + */ + SocketReader *m_inputValueOperation; + SocketReader *m_inputColor1Operation; + SocketReader *m_inputColor2Operation; + bool m_valueAlphaMultiply; + bool m_useClamp; + + inline void clampIfNeeded(float color[4]) + { + if (m_useClamp) { + CLAMP(color[0], 0.0f, 1.0f); + CLAMP(color[1], 0.0f, 1.0f); + CLAMP(color[2], 0.0f, 1.0f); + CLAMP(color[3], 0.0f, 1.0f); + } + } + +public: + /** + * Default constructor + */ + MixBaseOperation(); + + /** + * the inner loop of this program + */ + void executePixel(float output[4], float x, float y, PixelSampler sampler); + + /** + * Initialize the execution + */ + void initExecution(); + + /** + * Deinitialize the execution + */ + 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; } +}; + +class MixAddOperation : public MixBaseOperation { +public: + MixAddOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixBlendOperation : public MixBaseOperation { +public: + MixBlendOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixBurnOperation : public MixBaseOperation { +public: + MixBurnOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixColorOperation : public MixBaseOperation { +public: + MixColorOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixDarkenOperation : public MixBaseOperation { +public: + MixDarkenOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixDifferenceOperation : public MixBaseOperation { +public: + MixDifferenceOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixDivideOperation : public MixBaseOperation { +public: + MixDivideOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixDodgeOperation : public MixBaseOperation { +public: + MixDodgeOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixGlareOperation : public MixBaseOperation { +public: + MixGlareOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixHueOperation : public MixBaseOperation { +public: + MixHueOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixLightenOperation : public MixBaseOperation { +public: + MixLightenOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixLinearLightOperation : public MixBaseOperation { +public: + MixLinearLightOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixMultiplyOperation : public MixBaseOperation { +public: + MixMultiplyOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixOverlayOperation : public MixBaseOperation { +public: + MixOverlayOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixSaturationOperation : public MixBaseOperation { +public: + MixSaturationOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixScreenOperation : public MixBaseOperation { +public: + MixScreenOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixSoftLightOperation : public MixBaseOperation { +public: + MixSoftLightOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixSubtractOperation : public MixBaseOperation { +public: + MixSubtractOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +class MixValueOperation : public MixBaseOperation { +public: + MixValueOperation(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); +}; + +#endif diff --git a/source/blender/compositor/operations/COM_MixOverlayOperation.cpp b/source/blender/compositor/operations/COM_MixOverlayOperation.cpp deleted file mode 100644 index d5e1c6d1167..00000000000 --- a/source/blender/compositor/operations/COM_MixOverlayOperation.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixOverlayOperation.h" - -MixOverlayOperation::MixOverlayOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixOverlayOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - - float valuem = 1.0f - value; - - if (inputColor1[0] < 0.5f) { - output[0] = inputColor1[0] * (valuem + 2.0f * value * inputColor2[0]); - } - else { - output[0] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); - } - if (inputColor1[1] < 0.5f) { - output[1] = inputColor1[1] * (valuem + 2.0f * value * inputColor2[1]); - } - else { - output[1] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); - } - if (inputColor1[2] < 0.5f) { - output[2] = inputColor1[2] * (valuem + 2.0f * value * inputColor2[2]); - } - else { - output[2] = 1.0f - (valuem + 2.0f * value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); - } - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixOverlayOperation.h b/source/blender/compositor/operations/COM_MixOverlayOperation.h deleted file mode 100644 index 4f2c08ce95f..00000000000 --- a/source/blender/compositor/operations/COM_MixOverlayOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixOverlayOperation_h -#define _COM_MixOverlayOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixOverlayOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixOverlayOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixSaturationOperation.cpp b/source/blender/compositor/operations/COM_MixSaturationOperation.cpp deleted file mode 100644 index ca45a1c703a..00000000000 --- a/source/blender/compositor/operations/COM_MixSaturationOperation.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixSaturationOperation.h" - -extern "C" { - #include "BLI_math.h" -} - -MixSaturationOperation::MixSaturationOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixSaturationOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - float rH, rS, rV; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - if (rS != 0.0f) { - float colH, colS, colV; - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - hsv_to_rgb(rH, (valuem * rS + value * colS), rV, &output[0], &output[1], &output[2]); - } - else { - copy_v3_v3(output, inputColor1); - } - - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} diff --git a/source/blender/compositor/operations/COM_MixSaturationOperation.h b/source/blender/compositor/operations/COM_MixSaturationOperation.h deleted file mode 100644 index c690db38daf..00000000000 --- a/source/blender/compositor/operations/COM_MixSaturationOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixSaturationOperation_h -#define _COM_MixSaturationOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixSaturationOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixSaturationOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixScreenOperation.cpp b/source/blender/compositor/operations/COM_MixScreenOperation.cpp deleted file mode 100644 index 511768a49ad..00000000000 --- a/source/blender/compositor/operations/COM_MixScreenOperation.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixScreenOperation.h" - -MixScreenOperation::MixScreenOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixScreenOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - output[0] = 1.0f - (valuem + value * (1.0f - inputColor2[0])) * (1.0f - inputColor1[0]); - output[1] = 1.0f - (valuem + value * (1.0f - inputColor2[1])) * (1.0f - inputColor1[1]); - output[2] = 1.0f - (valuem + value * (1.0f - inputColor2[2])) * (1.0f - inputColor1[2]); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixScreenOperation.h b/source/blender/compositor/operations/COM_MixScreenOperation.h deleted file mode 100644 index 5ba3cf769bb..00000000000 --- a/source/blender/compositor/operations/COM_MixScreenOperation.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixScreenOperation_h -#define _COM_MixScreenOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixScreenOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixScreenOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixSoftLightOperation.cpp b/source/blender/compositor/operations/COM_MixSoftLightOperation.cpp deleted file mode 100644 index 71d83ce54ea..00000000000 --- a/source/blender/compositor/operations/COM_MixSoftLightOperation.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixSoftLightOperation.h" - -MixSoftLightOperation::MixSoftLightOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixSoftLightOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) \ -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - float scr, scg, scb; - - /* first calculate non-fac based Screen mix */ - scr = 1.0f - (1.0f - inputColor2[0]) * (1.0f - inputColor1[0]); - scg = 1.0f - (1.0f - inputColor2[1]) * (1.0f - inputColor1[1]); - scb = 1.0f - (1.0f - inputColor2[2]) * (1.0f - inputColor1[2]); - - output[0] = valuem * (inputColor1[0]) + value * (((1.0f - inputColor1[0]) * inputColor2[0] * (inputColor1[0])) + (inputColor1[0] * scr)); - output[1] = valuem * (inputColor1[1]) + value * (((1.0f - inputColor1[1]) * inputColor2[1] * (inputColor1[1])) + (inputColor1[1] * scg)); - output[2] = valuem * (inputColor1[2]) + value * (((1.0f - inputColor1[2]) * inputColor2[2] * (inputColor1[2])) + (inputColor1[2] * scb)); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixSoftLightOperation.h b/source/blender/compositor/operations/COM_MixSoftLightOperation.h deleted file mode 100644 index 55f6a70791a..00000000000 --- a/source/blender/compositor/operations/COM_MixSoftLightOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixSoftLightOperation_h -#define _COM_MixSoftLightOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixSoftLightOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixSoftLightOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixSubtractOperation.cpp b/source/blender/compositor/operations/COM_MixSubtractOperation.cpp deleted file mode 100644 index e6efe0f62f3..00000000000 --- a/source/blender/compositor/operations/COM_MixSubtractOperation.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixSubtractOperation.h" - -MixSubtractOperation::MixSubtractOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixSubtractOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - output[0] = inputColor1[0] - value * (inputColor2[0]); - output[1] = inputColor1[1] - value * (inputColor2[1]); - output[2] = inputColor1[2] - value * (inputColor2[2]); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} - diff --git a/source/blender/compositor/operations/COM_MixSubtractOperation.h b/source/blender/compositor/operations/COM_MixSubtractOperation.h deleted file mode 100644 index 046d8d4949b..00000000000 --- a/source/blender/compositor/operations/COM_MixSubtractOperation.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixSubtractOperation_h -#define _COM_MixSubtractOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixSubtractOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixSubtractOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); - -}; -#endif diff --git a/source/blender/compositor/operations/COM_MixValueOperation.cpp b/source/blender/compositor/operations/COM_MixValueOperation.cpp deleted file mode 100644 index 553041e39bf..00000000000 --- a/source/blender/compositor/operations/COM_MixValueOperation.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_MixValueOperation.h" - -extern "C" { - #include "BLI_math.h" -} - -MixValueOperation::MixValueOperation() : MixBaseOperation() -{ - /* pass */ -} - -void MixValueOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float inputColor1[4]; - float inputColor2[4]; - float inputValue[4]; - - this->m_inputValueOperation->read(inputValue, x, y, sampler); - this->m_inputColor1Operation->read(inputColor1, x, y, sampler); - this->m_inputColor2Operation->read(inputColor2, x, y, sampler); - - float value = inputValue[0]; - if (this->useValueAlphaMultiply()) { - value *= inputColor2[3]; - } - float valuem = 1.0f - value; - - float rH, rS, rV; - float colH, colS, colV; - rgb_to_hsv(inputColor1[0], inputColor1[1], inputColor1[2], &rH, &rS, &rV); - rgb_to_hsv(inputColor2[0], inputColor2[1], inputColor2[2], &colH, &colS, &colV); - hsv_to_rgb(rH, rS, (valuem * rV + value * colV), &output[0], &output[1], &output[2]); - output[3] = inputColor1[3]; - - clampIfNeeded(output); -} diff --git a/source/blender/compositor/operations/COM_MixValueOperation.h b/source/blender/compositor/operations/COM_MixValueOperation.h deleted file mode 100644 index 6c3f3ce8072..00000000000 --- a/source/blender/compositor/operations/COM_MixValueOperation.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_MixValueOperation_h -#define _COM_MixValueOperation_h -#include "COM_MixBaseOperation.h" - - -/** - * this program converts an input color to an output value. - * it assumes we are in sRGB color space. - */ -class MixValueOperation : public MixBaseOperation { -public: - /** - * Default constructor - */ - MixValueOperation(); - - /** - * the inner loop of this program - */ - void executePixel(float output[4], float x, float y, PixelSampler sampler); -}; -#endif diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index 15e5ab947d4..d0eadc5c4d1 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -138,7 +138,7 @@ void OutputSingleLayerOperation::deinitExecution() ibuf->mall |= IB_rectfloat; ibuf->dither = this->m_rd->dither_intensity; - IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, m_viewSettings, m_displaySettings, + IMB_colormanagement_imbuf_for_write(ibuf, true, false, m_viewSettings, m_displaySettings, this->m_format); BKE_makepicstring(filename, this->m_path, bmain->name, this->m_rd->cfra, this->m_format, diff --git a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp index fe794cb769f..8aa1324d8e2 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackMaskOperation.cpp @@ -38,15 +38,16 @@ extern "C" { PlaneTrackMaskOperation::PlaneTrackMaskOperation() : PlaneTrackCommonOperation() { this->addOutputSocket(COM_DT_VALUE); + + /* Currently hardcoded to 8 samples. */ + this->m_osa = 8; } void PlaneTrackMaskOperation::initExecution() { PlaneTrackCommonOperation::initExecution(); - const int osa = 8; - this->m_osa = osa; - BLI_jitter_init(this->m_jitter[0], osa); + BLI_jitter_init(this->m_jitter[0], this->m_osa); } void PlaneTrackMaskOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) diff --git a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp index c90e915fcd5..2385219c656 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp @@ -106,6 +106,9 @@ PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonO this->addOutputSocket(COM_DT_COLOR); this->m_pixelReader = NULL; this->setComplex(true); + + /* Currently hardcoded to 8 samples. */ + this->m_osa = 8; } void PlaneTrackWarpImageOperation::initExecution() @@ -114,9 +117,7 @@ void PlaneTrackWarpImageOperation::initExecution() this->m_pixelReader = this->getInputSocketReader(0); - const int osa = 8; - this->m_osa = osa; - BLI_jitter_init(this->m_jitter[0], osa); + BLI_jitter_init(this->m_jitter[0], this->m_osa); } void PlaneTrackWarpImageOperation::deinitExecution() diff --git a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp index 5cc02a1ed65..e8b900b9a85 100644 --- a/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ProjectorLensDistortionOperation.cpp @@ -55,11 +55,11 @@ void ProjectorLensDistortionOperation::executePixel(float output[4], int x, int const float v = (y + 0.5f) / height; const float u = (x + 0.5f) / width; MemoryBuffer *inputBuffer = (MemoryBuffer *)data; - inputBuffer->readCubic(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f); + inputBuffer->readBilinear(inputValue, (u * width + this->m_kr2) - 0.5f, v * height - 0.5f); output[0] = inputValue[0]; inputBuffer->read(inputValue, x, y); output[1] = inputValue[1]; - inputBuffer->readCubic(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f); + inputBuffer->readBilinear(inputValue, (u * width - this->m_kr2) - 0.5f, v * height - 0.5f); output[2] = inputValue[2]; output[3] = 1.0f; } diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp index 22820375831..3aeef6bf409 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.cpp +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.cpp @@ -62,7 +62,22 @@ void ReadBufferOperation::executePixel(float output[4], float x, float y, PixelS m_buffer->read(output, x, y); } else { - m_buffer->readCubic(output, x, y); + m_buffer->readBilinear(output, x, y); + } +} + +void ReadBufferOperation::executePixelExtend(float output[4], float x, float y, PixelSampler sampler, + MemoryBufferExtend extend_x, MemoryBufferExtend extend_y) +{ + if (m_single_value) { + /* write buffer has a single value stored at (0,0) */ + m_buffer->read(output, 0, 0); + } + else if (sampler == COM_PS_NEAREST) { + m_buffer->read(output, x, y, extend_x, extend_y); + } + else { + m_buffer->readBilinear(output, x, y, extend_x, extend_y); } } diff --git a/source/blender/compositor/operations/COM_ReadBufferOperation.h b/source/blender/compositor/operations/COM_ReadBufferOperation.h index c8dcfb7c33d..7a67056eda6 100644 --- a/source/blender/compositor/operations/COM_ReadBufferOperation.h +++ b/source/blender/compositor/operations/COM_ReadBufferOperation.h @@ -41,10 +41,12 @@ public: void *initializeTileData(rcti *rect); void executePixel(float output[4], float x, float y, PixelSampler sampler); + void executePixelExtend(float output[4], float x, float y, PixelSampler sampler, + MemoryBufferExtend extend_x, MemoryBufferExtend extend_y); void executePixel(float output[4], float x, float y, float dx, float dy, PixelSampler sampler); const bool isReadBufferOperation() const { return true; } void setOffset(unsigned int offset) { this->m_offset = offset; } - unsigned int getOffset() { return this->m_offset; } + unsigned int getOffset() const { return this->m_offset; } bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); MemoryBuffer *getInputMemoryBuffer(MemoryBuffer **memoryBuffers) { return memoryBuffers[this->m_offset]; } void readResolutionFromWriteBuffer(); diff --git a/source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp deleted file mode 100644 index bb165c2fe1c..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersAOOperation.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersAOOperation.h" - -RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} - diff --git a/source/blender/compositor/operations/COM_RenderLayersAOOperation.h b/source/blender/compositor/operations/COM_RenderLayersAOOperation.h deleted file mode 100644 index 71b0b885e81..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersAOOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersAOOperation_h -#define _COM_RenderLayersAOOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersAOOperation : public RenderLayersBaseProg { -public: - RenderLayersAOOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp b/source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp deleted file mode 100644 index 74cb506d264..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersAlphaProg.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersAlphaProg.h" - -RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) -{ - this->addOutputSocket(COM_DT_VALUE); -} - -void RenderLayersAlphaProg::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - int ix = x; - int iy = y; - float *inputBuffer = this->getInputBuffer(); - - if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { - output[0] = 0.0f; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } - else { - unsigned int offset = (iy * this->getWidth() + ix) * 4; - output[0] = inputBuffer[offset + 3]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } -} diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp deleted file mode 100644 index b50dca33f3b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersBaseProg.h" - -#include "BLI_listbase.h" -#include "DNA_scene_types.h" - -extern "C" { - #include "RE_pipeline.h" - #include "RE_shader_ext.h" - #include "RE_render_ext.h" -} - -RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation() -{ - this->m_renderpass = renderpass; - this->setScene(NULL); - this->m_inputBuffer = NULL; - this->m_elementsize = elementsize; - this->m_rd = NULL; -} - - -void RenderLayersBaseProg::initExecution() -{ - Scene *scene = this->getScene(); - Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; - RenderResult *rr = NULL; - - if (re) - rr = RE_AcquireResultRead(re); - - if (rr) { - SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, getLayerId()); - if (srl) { - - RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); - if (rl && rl->rectf) { - this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass); - - if (this->m_inputBuffer == NULL || this->m_renderpass == SCE_PASS_COMBINED) { - this->m_inputBuffer = rl->rectf; - } - } - } - } - if (re) { - RE_ReleaseResult(re); - re = NULL; - } -} - -void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) -{ - unsigned int offset; - int ix, iy; - int width = this->getWidth(), height = this->getHeight(); - - switch (sampler) { - case COM_PS_NEAREST: - ix = x; - iy = y; - offset = (iy * width + ix) * this->m_elementsize; - - if (this->m_elementsize == 1) - output[0] = this->m_inputBuffer[offset]; - else if (this->m_elementsize == 3) - copy_v3_v3(output, &this->m_inputBuffer[offset]); - else - copy_v4_v4(output, &this->m_inputBuffer[offset]); - - break; - - case COM_PS_BILINEAR: - BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); - break; - - case COM_PS_BICUBIC: - BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); - break; - } - - if (this->m_elementsize == 1) { - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } - else if (this->m_elementsize == 3) { - output[3] = 1.0f; - } -} - -void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ -#if 0 - const RenderData *rd = this->m_rd; - - int dx = 0, dy = 0; - - if (rd->mode & R_BORDER && rd->mode & R_CROP) { - /* see comment in executeRegion describing coordinate mapping, - * here it simply goes other way around - */ - int full_width = rd->xsch * rd->size / 100; - int full_height = rd->ysch * rd->size / 100; - - dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; - dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; - } - - int ix = x - dx; - int iy = y - dy; -#else - int ix = x; - int iy = y; -#endif - - if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { - zero_v4(output); - } - else { - doInterpolation(output, ix, iy, sampler); - } -} - -void RenderLayersBaseProg::deinitExecution() -{ - this->m_inputBuffer = NULL; -} - -void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) -{ - Scene *sce = this->getScene(); - Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL; - RenderResult *rr = NULL; - - resolution[0] = 0; - resolution[1] = 0; - - if (re) - rr = RE_AcquireResultRead(re); - - if (rr) { - SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId()); - if (srl) { - RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); - if (rl && rl->rectf) { - resolution[0] = rl->rectx; - resolution[1] = rl->recty; - } - } - } - - if (re) - RE_ReleaseResult(re); - -} - diff --git a/source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp deleted file mode 100644 index 3083c37c2bb..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersColorOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersColorOperation.h" - -RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersColorOperation.h b/source/blender/compositor/operations/COM_RenderLayersColorOperation.h deleted file mode 100644 index 4f4dfbfb6f3..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersColorOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersColorOperation_h -#define _COM_RenderLayersColorOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersColorOperation : public RenderLayersBaseProg { -public: - RenderLayersColorOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp deleted file mode 100644 index b056896994e..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersCyclesOperation.h" - -RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h b/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h deleted file mode 100644 index baa53c7388b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersCyclesOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersCyclesOperation_h -#define _COM_RenderLayersCyclesOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersCyclesOperation : public RenderLayersBaseProg { -public: - RenderLayersCyclesOperation(int pass); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp b/source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp deleted file mode 100644 index ae5fc3b2254..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersDepthProg.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersDepthProg.h" - -RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} - diff --git a/source/blender/compositor/operations/COM_RenderLayersDepthProg.h b/source/blender/compositor/operations/COM_RenderLayersDepthProg.h deleted file mode 100644 index fdbe25c818e..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersDepthProg.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersDepthProg_h -#define _COM_RenderLayersDepthProg_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersDepthProg : public RenderLayersBaseProg { -public: - RenderLayersDepthProg(); - -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp deleted file mode 100644 index 6baa25e5600..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersDiffuseOperation.h" - -RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h b/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h deleted file mode 100644 index 8c20d6f497d..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersDiffuseOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersDiffuseOperation_h -#define _COM_RenderLayersDiffuseOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersDiffuseOperation : public RenderLayersBaseProg { -public: - RenderLayersDiffuseOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp deleted file mode 100644 index 1b03a4e169f..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersEmitOperation.h" - -RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.h b/source/blender/compositor/operations/COM_RenderLayersEmitOperation.h deleted file mode 100644 index c003cb2f87b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersEmitOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersEmitOperation_h -#define _COM_RenderLayersEmitOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersEmitOperation : public RenderLayersBaseProg { -public: - RenderLayersEmitOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp deleted file mode 100644 index f4d6dc7353b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersEnvironmentOperation.h" - -RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h b/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h deleted file mode 100644 index b9310a1778b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersEnvironmentOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersEnvironmentOperation_h -#define _COM_RenderLayersEnvironmentOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersEnvironmentOperation : public RenderLayersBaseProg { -public: - RenderLayersEnvironmentOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersImageProg.cpp b/source/blender/compositor/operations/COM_RenderLayersImageProg.cpp deleted file mode 100644 index f21585844ff..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersImageProg.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersImageProg.h" - -RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersImageProg.h b/source/blender/compositor/operations/COM_RenderLayersImageProg.h deleted file mode 100644 index 5fa74c8b21f..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersImageProg.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersColorProg_h -#define _COM_RenderLayersColorProg_h - -#include "COM_RenderLayersBaseProg.h" - -/// @todo rename to image operation -class RenderLayersColorProg : public RenderLayersBaseProg { -public: - RenderLayersColorProg(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp deleted file mode 100644 index 4258cb94a26..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersIndirectOperation.h" - -RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h b/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h deleted file mode 100644 index d64207a4355..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersIndirectOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersIndirectOperation_h -#define _COM_RenderLayersIndirectOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersIndirectOperation : public RenderLayersBaseProg { -public: - RenderLayersIndirectOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp deleted file mode 100644 index aab7e0089e4..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersMaterialIndexOperation.h" - -RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h b/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h deleted file mode 100644 index d06568f5a10..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersMaterialIndexOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersMaterialIndexOperation_h -#define _COM_RenderLayersMaterialIndexOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg { -public: - RenderLayersMaterialIndexOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp deleted file mode 100644 index c64ddc6e9d8..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersMistOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersMistOperation.h" - -RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersMistOperation.h b/source/blender/compositor/operations/COM_RenderLayersMistOperation.h deleted file mode 100644 index ad838c9e340..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersMistOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersMistOperation_h -#define _COM_RenderLayersMistOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersMistOperation : public RenderLayersBaseProg { -public: - RenderLayersMistOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp deleted file mode 100644 index 9d8e7d6272c..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersNormalOperation.h" - -RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.h b/source/blender/compositor/operations/COM_RenderLayersNormalOperation.h deleted file mode 100644 index 39b2040863a..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersNormalOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersNormalOperation_h -#define _COM_RenderLayersNormalOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersNormalOperation : public RenderLayersBaseProg { -public: - RenderLayersNormalOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp deleted file mode 100644 index 430ea698263..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersObjectIndexOperation.h" - -RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1) -{ - this->addOutputSocket(COM_DT_VALUE); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h b/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h deleted file mode 100644 index e8a1602cbfc..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersObjectIndexOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersObjectIndexOperation_h -#define _COM_RenderLayersObjectIndexOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersObjectIndexOperation : public RenderLayersBaseProg { -public: - RenderLayersObjectIndexOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp new file mode 100644 index 00000000000..8a32502982c --- /dev/null +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -0,0 +1,340 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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: + * Jeroen Bakker + * Monique Dewanchand + */ + +#include "COM_RenderLayersProg.h" + +#include "BLI_listbase.h" +#include "DNA_scene_types.h" + +extern "C" { + #include "RE_pipeline.h" + #include "RE_shader_ext.h" + #include "RE_render_ext.h" +} + +/* ******** Render Layers Base Prog ******** */ + +RenderLayersBaseProg::RenderLayersBaseProg(int renderpass, int elementsize) : NodeOperation() +{ + this->m_renderpass = renderpass; + this->setScene(NULL); + this->m_inputBuffer = NULL; + this->m_elementsize = elementsize; + this->m_rd = NULL; +} + + +void RenderLayersBaseProg::initExecution() +{ + Scene *scene = this->getScene(); + Render *re = (scene) ? RE_GetRender(scene->id.name) : NULL; + RenderResult *rr = NULL; + + if (re) + rr = RE_AcquireResultRead(re); + + if (rr) { + SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&scene->r.layers, getLayerId()); + if (srl) { + + RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); + if (rl && rl->rectf) { + this->m_inputBuffer = RE_RenderLayerGetPass(rl, this->m_renderpass); + + if (this->m_inputBuffer == NULL || this->m_renderpass == SCE_PASS_COMBINED) { + this->m_inputBuffer = rl->rectf; + } + } + } + } + if (re) { + RE_ReleaseResult(re); + re = NULL; + } +} + +void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) +{ + unsigned int offset; + int ix, iy; + int width = this->getWidth(), height = this->getHeight(); + + switch (sampler) { + case COM_PS_NEAREST: + ix = x; + iy = y; + offset = (iy * width + ix) * this->m_elementsize; + + if (this->m_elementsize == 1) + output[0] = this->m_inputBuffer[offset]; + else if (this->m_elementsize == 3) + copy_v3_v3(output, &this->m_inputBuffer[offset]); + else + copy_v4_v4(output, &this->m_inputBuffer[offset]); + + break; + + case COM_PS_BILINEAR: + BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + + case COM_PS_BICUBIC: + BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + } + + if (this->m_elementsize == 1) { + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 0.0f; + } + else if (this->m_elementsize == 3) { + output[3] = 1.0f; + } +} + +void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ +#if 0 + const RenderData *rd = this->m_rd; + + int dx = 0, dy = 0; + + if (rd->mode & R_BORDER && rd->mode & R_CROP) { + /* see comment in executeRegion describing coordinate mapping, + * here it simply goes other way around + */ + int full_width = rd->xsch * rd->size / 100; + int full_height = rd->ysch * rd->size / 100; + + dx = rd->border.xmin * full_width - (full_width - this->getWidth()) / 2.0f; + dy = rd->border.ymin * full_height - (full_height - this->getHeight()) / 2.0f; + } + + int ix = x - dx; + int iy = y - dy; +#else + int ix = x; + int iy = y; +#endif + + if (this->m_inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { + zero_v4(output); + } + else { + doInterpolation(output, ix, iy, sampler); + } +} + +void RenderLayersBaseProg::deinitExecution() +{ + this->m_inputBuffer = NULL; +} + +void RenderLayersBaseProg::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) +{ + Scene *sce = this->getScene(); + Render *re = (sce) ? RE_GetRender(sce->id.name) : NULL; + RenderResult *rr = NULL; + + resolution[0] = 0; + resolution[1] = 0; + + if (re) + rr = RE_AcquireResultRead(re); + + if (rr) { + SceneRenderLayer *srl = (SceneRenderLayer *)BLI_findlink(&sce->r.layers, getLayerId()); + if (srl) { + RenderLayer *rl = RE_GetRenderLayer(rr, srl->name); + if (rl && rl->rectf) { + resolution[0] = rl->rectx; + resolution[1] = rl->recty; + } + } + } + + if (re) + RE_ReleaseResult(re); + +} + +/* ******** Render Layers AO Operation ******** */ + +RenderLayersAOOperation::RenderLayersAOOperation() : RenderLayersBaseProg(SCE_PASS_AO, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Alpha Operation ******** */ + +RenderLayersAlphaProg::RenderLayersAlphaProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) +{ + this->addOutputSocket(COM_DT_VALUE); +} + +void RenderLayersAlphaProg::executePixel(float output[4], float x, float y, PixelSampler sampler) +{ + int ix = x; + int iy = y; + float *inputBuffer = this->getInputBuffer(); + + if (inputBuffer == NULL || ix < 0 || iy < 0 || ix >= (int)this->getWidth() || iy >= (int)this->getHeight() ) { + output[0] = 0.0f; + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 0.0f; + } + else { + unsigned int offset = (iy * this->getWidth() + ix) * 4; + output[0] = inputBuffer[offset + 3]; + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 0.0f; + } +} + +/* ******** Render Layers Color Operation ******** */ + +RenderLayersColorOperation::RenderLayersColorOperation() : RenderLayersBaseProg(SCE_PASS_RGBA, 4) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Cycles Operation ******** */ + +RenderLayersCyclesOperation::RenderLayersCyclesOperation(int pass) : RenderLayersBaseProg(pass, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Depth Operation ******** */ + +RenderLayersDepthProg::RenderLayersDepthProg() : RenderLayersBaseProg(SCE_PASS_Z, 1) +{ + this->addOutputSocket(COM_DT_VALUE); +} + +/* ******** Render Layers Diffuse Operation ******** */ + +RenderLayersDiffuseOperation::RenderLayersDiffuseOperation() : RenderLayersBaseProg(SCE_PASS_DIFFUSE, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Emit Operation ******** */ + +RenderLayersEmitOperation::RenderLayersEmitOperation() : RenderLayersBaseProg(SCE_PASS_EMIT, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Environment Operation ******** */ + +RenderLayersEnvironmentOperation::RenderLayersEnvironmentOperation() : RenderLayersBaseProg(SCE_PASS_ENVIRONMENT, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Image Operation ******** */ + +RenderLayersColorProg::RenderLayersColorProg() : RenderLayersBaseProg(SCE_PASS_COMBINED, 4) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Indirect Operation ******** */ + +RenderLayersIndirectOperation::RenderLayersIndirectOperation() : RenderLayersBaseProg(SCE_PASS_INDIRECT, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Material Index Operation ******** */ + +RenderLayersMaterialIndexOperation::RenderLayersMaterialIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXMA, 1) +{ + this->addOutputSocket(COM_DT_VALUE); +} + +/* ******** Render Layers Mist Operation ******** */ + +RenderLayersMistOperation::RenderLayersMistOperation() : RenderLayersBaseProg(SCE_PASS_MIST, 1) +{ + this->addOutputSocket(COM_DT_VALUE); +} + +/* ******** Render Layers Normal Operation ******** */ + +RenderLayersNormalOperation::RenderLayersNormalOperation() : RenderLayersBaseProg(SCE_PASS_NORMAL, 3) +{ + this->addOutputSocket(COM_DT_VECTOR); +} + +/* ******** Render Layers Object Index Operation ******** */ + +RenderLayersObjectIndexOperation::RenderLayersObjectIndexOperation() : RenderLayersBaseProg(SCE_PASS_INDEXOB, 1) +{ + this->addOutputSocket(COM_DT_VALUE); +} + +/* ******** Render Layers Reflection Operation ******** */ + +RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Refraction Operation ******** */ + +RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Shadow Operation ******** */ + +RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Specular Operation ******** */ + +RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers Speed Operation ******** */ + +RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4) +{ + this->addOutputSocket(COM_DT_COLOR); +} + +/* ******** Render Layers UV Operation ******** */ + +RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3) +{ + this->addOutputSocket(COM_DT_VECTOR); +} diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index 84d6c1ee188..48aaa47cc50 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -102,4 +102,107 @@ public: void executePixel(float output[4], float x, float y, PixelSampler sampler); }; +class RenderLayersAOOperation : public RenderLayersBaseProg { +public: + RenderLayersAOOperation(); +}; + +class RenderLayersAlphaProg : public RenderLayersBaseProg { +public: + RenderLayersAlphaProg(); + void executePixel(float output[4], float x, float y, PixelSampler sampler); + +}; + +class RenderLayersColorOperation : public RenderLayersBaseProg { +public: + RenderLayersColorOperation(); +}; + +class RenderLayersCyclesOperation : public RenderLayersBaseProg { +public: + RenderLayersCyclesOperation(int pass); +}; + +class RenderLayersDepthProg : public RenderLayersBaseProg { +public: + RenderLayersDepthProg(); +}; + +class RenderLayersDiffuseOperation : public RenderLayersBaseProg { +public: + RenderLayersDiffuseOperation(); +}; + +class RenderLayersEmitOperation : public RenderLayersBaseProg { +public: + RenderLayersEmitOperation(); +}; + +class RenderLayersEnvironmentOperation : public RenderLayersBaseProg { +public: + RenderLayersEnvironmentOperation(); +}; + +/// @todo rename to image operation +class RenderLayersColorProg : public RenderLayersBaseProg { +public: + RenderLayersColorProg(); +}; + +class RenderLayersIndirectOperation : public RenderLayersBaseProg { +public: + RenderLayersIndirectOperation(); +}; + +class RenderLayersMaterialIndexOperation : public RenderLayersBaseProg { +public: + RenderLayersMaterialIndexOperation(); +}; + +class RenderLayersMistOperation : public RenderLayersBaseProg { +public: + RenderLayersMistOperation(); +}; + +class RenderLayersNormalOperation : public RenderLayersBaseProg { +public: + RenderLayersNormalOperation(); +}; + +class RenderLayersObjectIndexOperation : public RenderLayersBaseProg { +public: + RenderLayersObjectIndexOperation(); +}; + +class RenderLayersReflectionOperation : public RenderLayersBaseProg { +public: + RenderLayersReflectionOperation(); +}; + +class RenderLayersRefractionOperation : public RenderLayersBaseProg { +public: + RenderLayersRefractionOperation(); +}; + +class RenderLayersShadowOperation : public RenderLayersBaseProg { +public: + RenderLayersShadowOperation(); +}; + +class RenderLayersSpecularOperation : public RenderLayersBaseProg { +public: + RenderLayersSpecularOperation(); +}; + +class RenderLayersSpeedOperation : public RenderLayersBaseProg { +public: + RenderLayersSpeedOperation(); +}; + +class RenderLayersUVOperation : public RenderLayersBaseProg { +public: + RenderLayersUVOperation(); +}; + #endif diff --git a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp deleted file mode 100644 index 1fbd599235b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersReflectionOperation.h" - -RenderLayersReflectionOperation::RenderLayersReflectionOperation() : RenderLayersBaseProg(SCE_PASS_REFLECT, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h b/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h deleted file mode 100644 index 3dc7148930b..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersReflectionOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersReflectionOperation_h -#define _COM_RenderLayersReflectionOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersReflectionOperation : public RenderLayersBaseProg { -public: - RenderLayersReflectionOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp deleted file mode 100644 index 2ec9be46059..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersRefractionOperation.h" - -RenderLayersRefractionOperation::RenderLayersRefractionOperation() : RenderLayersBaseProg(SCE_PASS_REFRACT, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h b/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h deleted file mode 100644 index 02ac7aa14f4..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersRefractionOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersRefractionOperation_h -#define _COM_RenderLayersRefractionOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersRefractionOperation : public RenderLayersBaseProg { -public: - RenderLayersRefractionOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp deleted file mode 100644 index 7582e010e2c..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersShadowOperation.h" - -RenderLayersShadowOperation::RenderLayersShadowOperation() : RenderLayersBaseProg(SCE_PASS_SHADOW, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.h b/source/blender/compositor/operations/COM_RenderLayersShadowOperation.h deleted file mode 100644 index af35915c2ee..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersShadowOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersShadowOperation_h -#define _COM_RenderLayersShadowOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersShadowOperation : public RenderLayersBaseProg { -public: - RenderLayersShadowOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp deleted file mode 100644 index 60c1636dcda..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersSpecularOperation.h" - -RenderLayersSpecularOperation::RenderLayersSpecularOperation() : RenderLayersBaseProg(SCE_PASS_SPEC, 3) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h b/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h deleted file mode 100644 index fc7d77976a3..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersSpecularOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersSpecularOperation_h -#define _COM_RenderLayersSpecularOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersSpecularOperation : public RenderLayersBaseProg { -public: - RenderLayersSpecularOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp deleted file mode 100644 index 5a0662d13eb..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersSpeedOperation.h" - -RenderLayersSpeedOperation::RenderLayersSpeedOperation() : RenderLayersBaseProg(SCE_PASS_VECTOR, 4) -{ - this->addOutputSocket(COM_DT_COLOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h b/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h deleted file mode 100644 index d341aa43950..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersSpeedOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersSpeedOperation_h -#define _COM_RenderLayersSpeedOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersSpeedOperation : public RenderLayersBaseProg { -public: - RenderLayersSpeedOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp b/source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp deleted file mode 100644 index b966f98632c..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersUVOperation.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_RenderLayersUVOperation.h" - -RenderLayersUVOperation::RenderLayersUVOperation() : RenderLayersBaseProg(SCE_PASS_UV, 3) -{ - this->addOutputSocket(COM_DT_VECTOR); -} diff --git a/source/blender/compositor/operations/COM_RenderLayersUVOperation.h b/source/blender/compositor/operations/COM_RenderLayersUVOperation.h deleted file mode 100644 index 3068372a66c..00000000000 --- a/source/blender/compositor/operations/COM_RenderLayersUVOperation.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_RenderLayersUVOperation_h -#define _COM_RenderLayersUVOperation_h - -#include "COM_RenderLayersBaseProg.h" - -class RenderLayersUVOperation : public RenderLayersBaseProg { -public: - RenderLayersUVOperation(); -}; - -#endif diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index fb996f2abaf..d1060224444 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -103,7 +103,7 @@ void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, d = 1.0f / (1.0f + sqrtf(t)); const float nx = (u * d + 0.5f) * width - 0.5f; const float ny = (v * d + 0.5f) * height - 0.5f; - buffer->readCubic(color, nx, ny); + buffer->readBilinear(color, nx, ny); tc[0] += (1.0f - tz) * color[0], tc[1] += tz * color[1]; dr++, dg++; } @@ -121,7 +121,7 @@ void ScreenLensDistortionOperation::executePixel(float output[4], int x, int y, d = 1.0f / (1.0f + sqrtf(t)); const float nx = (u * d + 0.5f) * width - 0.5f; const float ny = (v * d + 0.5f) * height - 0.5f; - buffer->readCubic(color, nx, ny); + buffer->readBilinear(color, nx, ny); tc[1] += (1.0f - tz) * color[1], tc[2] += tz * color[2]; dg++, db++; } diff --git a/source/blender/compositor/operations/COM_SeparateChannelOperation.cpp b/source/blender/compositor/operations/COM_SeparateChannelOperation.cpp deleted file mode 100644 index 9fc266cce86..00000000000 --- a/source/blender/compositor/operations/COM_SeparateChannelOperation.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#include "COM_SeparateChannelOperation.h" - -SeparateChannelOperation::SeparateChannelOperation() : NodeOperation() -{ - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_VALUE); - this->m_inputOperation = NULL; -} -void SeparateChannelOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void SeparateChannelOperation::deinitExecution() -{ - this->m_inputOperation = NULL; -} - - -void SeparateChannelOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) -{ - float input[4]; - this->m_inputOperation->read(input, x, y, sampler); - output[0] = input[this->m_channel]; -} diff --git a/source/blender/compositor/operations/COM_SeparateChannelOperation.h b/source/blender/compositor/operations/COM_SeparateChannelOperation.h deleted file mode 100644 index f964df5df02..00000000000 --- a/source/blender/compositor/operations/COM_SeparateChannelOperation.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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: - * Jeroen Bakker - * Monique Dewanchand - */ - -#ifndef _COM_SeparateChannelOperation_h_ -#define _COM_SeparateChannelOperation_h_ - -#include "COM_NodeOperation.h" - -class SeparateChannelOperation : public NodeOperation { -private: - SocketReader *m_inputOperation; - int m_channel; -public: - SeparateChannelOperation(); - void executePixel(float output[4], float x, float y, PixelSampler sampler); - - void initExecution(); - void deinitExecution(); - - void setChannel(int channel) { this->m_channel = channel; } -}; - -#endif diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index e9f083178e4..468aec64a56 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -173,7 +173,7 @@ void ViewerOperation::updateImage(rcti *rect) { IMB_partial_display_buffer_update(this->m_ibuf, this->m_outputBuffer, NULL, getWidth(), 0, 0, this->m_viewSettings, this->m_displaySettings, - rect->xmin, rect->ymin, rect->xmax, rect->ymax, FALSE); + rect->xmin, rect->ymin, rect->xmax, rect->ymax, false); this->updateDraw(); } diff --git a/source/blender/compositor/operations/COM_WrapOperation.cpp b/source/blender/compositor/operations/COM_WrapOperation.cpp index 68c3e74a237..ea19952f60c 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.cpp +++ b/source/blender/compositor/operations/COM_WrapOperation.cpp @@ -23,21 +23,9 @@ #include "COM_WrapOperation.h" -WrapOperation::WrapOperation() : NodeOperation() +WrapOperation::WrapOperation() : ReadBufferOperation() { - this->addInputSocket(COM_DT_COLOR); - this->addOutputSocket(COM_DT_COLOR); - this->setResolutionInputSocketIndex(0); - this->m_inputOperation = NULL; -} -void WrapOperation::initExecution() -{ - this->m_inputOperation = this->getInputSocketReader(0); -} - -void WrapOperation::deinitExecution() -{ - this->m_inputOperation = NULL; + this->m_wrappingType = CMP_NODE_WRAP_NONE; } inline float WrapOperation::getWrappedOriginalXPos(float x) @@ -59,6 +47,7 @@ void WrapOperation::executePixel(float output[4], float x, float y, PixelSampler float nx, ny; nx = x; ny = y; + MemoryBufferExtend extend_x = COM_MB_CLIP, extend_y = COM_MB_CLIP; switch (m_wrappingType) { case CMP_NODE_WRAP_NONE: //Intentionally empty, originalXPos and originalYPos have been set before @@ -66,20 +55,23 @@ void WrapOperation::executePixel(float output[4], float x, float y, PixelSampler case CMP_NODE_WRAP_X: // wrap only on the x-axis nx = this->getWrappedOriginalXPos(x); + extend_x = COM_MB_REPEAT; break; case CMP_NODE_WRAP_Y: // wrap only on the y-axis ny = this->getWrappedOriginalYPos(y); + extend_y = COM_MB_REPEAT; break; case CMP_NODE_WRAP_XY: // wrap on both nx = this->getWrappedOriginalXPos(x); ny = this->getWrappedOriginalYPos(y); + extend_x = COM_MB_REPEAT; + extend_y = COM_MB_REPEAT; break; } - this->m_inputOperation->read(output, nx, ny, sampler); - + executePixelExtend(output, nx, ny, sampler, extend_x, extend_y); } bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -110,7 +102,7 @@ bool WrapOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOper } } - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return ReadBufferOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void WrapOperation::setWrapping(int wrapping_type) diff --git a/source/blender/compositor/operations/COM_WrapOperation.h b/source/blender/compositor/operations/COM_WrapOperation.h index b84d85e7b5d..ddd5fa8032d 100644 --- a/source/blender/compositor/operations/COM_WrapOperation.h +++ b/source/blender/compositor/operations/COM_WrapOperation.h @@ -23,20 +23,16 @@ #ifndef _COM_WrapOperation_h_ #define _COM_WrapOperation_h_ -#include "COM_NodeOperation.h" +#include "COM_ReadBufferOperation.h" -class WrapOperation : public NodeOperation { +class WrapOperation : public ReadBufferOperation { private: - SocketReader *m_inputOperation; int m_wrappingType; public: WrapOperation(); bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void executePixel(float output[4], float x, float y, PixelSampler sampler); - void initExecution(); - void deinitExecution(); - void setWrapping(int wrapping_type); float getWrappedOriginalXPos(float x); float getWrappedOriginalYPos(float y); diff --git a/source/blender/compositor/operations/COM_ZCombineOperation.h b/source/blender/compositor/operations/COM_ZCombineOperation.h index 4545775f26f..eeeb29d330f 100644 --- a/source/blender/compositor/operations/COM_ZCombineOperation.h +++ b/source/blender/compositor/operations/COM_ZCombineOperation.h @@ -22,7 +22,7 @@ #ifndef _COM_ZCombineOperation_h #define _COM_ZCombineOperation_h -#include "COM_MixBaseOperation.h" +#include "COM_MixOperation.h" /** diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index 845ad72d7aa..142342997be 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -1828,7 +1828,7 @@ static void *acf_dsmball_setting_ptr(bAnimListElem *ale, int setting, short *typ switch (setting) { case ACHANNEL_SETTING_EXPAND: /* expanded */ - return GET_ACF_FLAG_PTR(mb->flag, type); + return GET_ACF_FLAG_PTR(mb->flag2, type); case ACHANNEL_SETTING_SELECT: /* selected */ case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ @@ -2781,6 +2781,9 @@ static void ANIM_init_channel_typeinfo_data(void) if (ACF_INIT) { ACF_INIT = 0; + /* NOTE: need to keep the order of these synchronized with the definition of + * channel types (eAnim_ChannelType) in ED_anim_api.h + */ animchannelTypeInfo[type++] = NULL; /* None */ animchannelTypeInfo[type++] = NULL; /* AnimData */ animchannelTypeInfo[type++] = NULL; /* Special */ @@ -2808,8 +2811,8 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_DSMESH; /* Mesh Channel */ animchannelTypeInfo[type++] = &ACF_DSTEX; /* Texture Channel */ animchannelTypeInfo[type++] = &ACF_DSLAT; /* Lattice Channel */ - animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */ animchannelTypeInfo[type++] = &ACF_DSLINESTYLE; /* LineStyle Channel */ + animchannelTypeInfo[type++] = &ACF_DSSPK; /* Speaker Channel */ animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 91003674524..041a2c2216e 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -1541,10 +1541,16 @@ static size_t animdata_filter_ds_nodetree(bAnimContext *ac, ListBase *anim_data, static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data, bDopeSheet *ads, Scene *sce, int filter_mode) { SceneRenderLayer *srl; + FreestyleLineSet *lineset; size_t items = 0; for (srl = sce->r.layers.first; srl; srl = srl->next) { - FreestyleLineSet *lineset; + for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + lineset->linestyle->id.flag |= LIB_DOIT; + } + } + + for (srl = sce->r.layers.first; srl; srl = srl->next) { /* skip render layers without Freestyle enabled */ if (!(srl->layflag & SCE_LAY_FRS)) @@ -1555,6 +1561,10 @@ static size_t animdata_filter_ds_linestyle(bAnimContext *ac, ListBase *anim_data FreestyleLineStyle *linestyle = lineset->linestyle; ListBase tmp_data = {NULL, NULL}; size_t tmp_items = 0; + + if (!(linestyle->id.flag & LIB_DOIT)) + continue; + linestyle->id.flag &= ~LIB_DOIT; /* add scene-level animation channels */ BEGIN_ANIMFILTER_SUBCHANNELS(FILTER_LS_SCED(linestyle)) @@ -2533,13 +2543,13 @@ static size_t animdata_filter_remove_invalid(ListBase *anim_data) static size_t animdata_filter_remove_duplis(ListBase *anim_data) { bAnimListElem *ale, *next; - GHash *gh; + GSet *gs; size_t items = 0; /* build new hashtable to efficiently store and retrieve which entries have been * encountered already while searching */ - gh = BLI_ghash_ptr_new("animdata_filter_duplis_remove gh"); + gs = BLI_gset_ptr_new(__func__); /* loop through items, removing them from the list if a similar item occurs already */ for (ale = anim_data->first; ale; ale = next) { @@ -2549,9 +2559,8 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data) * - just use ale->data for now, though it would be nicer to involve * ale->type in combination too to capture corner cases (where same data performs differently) */ - if (BLI_ghash_haskey(gh, ale->data) == 0) { + if (BLI_gset_reinsert(gs, ale->data, NULL)) { /* this entry is 'unique' and can be kept */ - BLI_ghash_insert(gh, ale->data, NULL); items++; } else { @@ -2561,7 +2570,7 @@ static size_t animdata_filter_remove_duplis(ListBase *anim_data) } /* free the hash... */ - BLI_ghash_free(gh, NULL, NULL); + BLI_gset_free(gs, NULL); /* return the number of items still in the list */ return items; diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index df93da8b7c1..826e204d981 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -75,7 +75,8 @@ void free_anim_drivers_copybuf(void); * for the given Animation Data block. This assumes that all the destinations are valid. * * - add: 0 - don't add anything if not found, - * 1 - add new Driver FCurve, + * 1 - add new Driver FCurve (with keyframes for visual tweaking), + * 2 - add new Driver FCurve (with generator, for script backwards compatability) * -1 - add new Driver FCurve without driver stuff (for pasting) */ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_index, short add) @@ -114,11 +115,38 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde /* if add is negative, don't init this data yet, since it will be filled in by the pasted driver */ if (add > 0) { + BezTriple *bezt; + size_t i; + /* add some new driver data */ fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver"); + fcu->driver->flag |= DRIVER_FLAG_SHOWDEBUG; - /* add simple generator modifier for driver so that there is some visible representation */ - add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + /* F-Modifier or Keyframes? */ + // FIXME: replace these magic numbers with defines + if (add == 2) { + /* Python API Backwards compatability hack: + * Create FModifier so that old scripts won't break + * for now before 2.7 series -- (September 4, 2013) + */ + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR); + } + else { + /* add 2 keyframes so that user has something to work with + * - These are configured to 0,0 and 1,1 to give a 1-1 mapping + * which can be easily tweaked from there. + */ + insert_vert_fcurve(fcu, 0.0f, 0.0f, INSERTKEY_FAST); + insert_vert_fcurve(fcu, 1.0f, 1.0f, INSERTKEY_FAST); + + /* configure this curve to extrapolate */ + for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) { + bezt->h1 = bezt->h2 = HD_VECT; + } + + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + calchandles_fcurve(fcu); + } } /* just add F-Curve to end of driver list */ @@ -166,8 +194,10 @@ short ANIM_add_driver(ReportList *reports, ID *id, const char rna_path[], int ar /* will only loop once unless the array index was -1 */ for (; array_index < array_index_max; array_index++) { + short add_mode = (flag & CREATEDRIVER_WITH_FMODIFIER) ? 2 : 1; + /* create F-Curve with Driver */ - fcu = verify_driver_fcurve(id, rna_path, array_index, 1); + fcu = verify_driver_fcurve(id, rna_path, array_index, add_mode); if (fcu && fcu->driver) { ChannelDriver *driver = fcu->driver; diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 63acc5a943c..cfc03050a9e 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -256,7 +256,7 @@ int insert_bezt_fcurve(FCurve *fcu, BezTriple *bezt, short flag) dst->f1 = bezt->f1; dst->f2 = bezt->f2; dst->f3 = bezt->f3; - + /* TODO: perform some other operations? */ } } diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index 22bd22c8561..0301db4b4cf 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -255,7 +255,7 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, bDeformGroup *dgroup; bPoseChannel *pchan; Mesh *mesh; - Mat4 *bbone = NULL; + Mat4 bbone_array[MAX_BBONE_SUBDIV], *bbone = NULL; float (*root)[3], (*tip)[3], (*verts)[3]; int *selected; int numbones, vertsfilled = 0, i, j, segments = 0; @@ -309,7 +309,8 @@ static void add_verts_to_dgroups(ReportList *reports, Scene *scene, Object *ob, if ((par->pose) && (pchan = BKE_pose_channel_find_name(par->pose, bone->name))) { if (bone->segments > 1) { segments = bone->segments; - bbone = b_bone_spline_setup(pchan, 1); + b_bone_spline_setup(pchan, 1, bbone_array); + bbone = bbone_array; } } } diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 76068c122bf..16d7f9c9420 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -281,7 +281,7 @@ static void laplacian_system_construct_end(LaplacianSystem *sys) sys->varea = MEM_callocN(sizeof(float) * totvert, "LaplacianSystemVarea"); - sys->edgehash = BLI_edgehash_new(); + sys->edgehash = BLI_edgehash_new_ex(__func__, BLI_EDGEHASH_SIZE_GUESS_FROM_POLYS(sys->totface)); for (a = 0, face = sys->faces; a < sys->totface; a++, face++) { laplacian_increase_edge_count(sys->edgehash, (*face)[0], (*face)[1]); laplacian_increase_edge_count(sys->edgehash, (*face)[1], (*face)[2]); diff --git a/source/blender/editors/armature/reeb.c b/source/blender/editors/armature/reeb.c index f66fb38a2a6..3a09f531d44 100644 --- a/source/blender/editors/armature/reeb.c +++ b/source/blender/editors/armature/reeb.c @@ -198,7 +198,7 @@ ReebGraph *newReebGraph(void) rg = MEM_callocN(sizeof(ReebGraph), "reeb graph"); rg->totnodes = 0; - rg->emap = BLI_edgehash_new(); + rg->emap = BLI_edgehash_new(__func__); rg->free_arc = REEB_freeArc; diff --git a/source/blender/editors/curve/curve_intern.h b/source/blender/editors/curve/curve_intern.h index d197697e60b..8a5e4b338d3 100644 --- a/source/blender/editors/curve/curve_intern.h +++ b/source/blender/editors/curve/curve_intern.h @@ -76,6 +76,7 @@ void CURVE_OT_hide(struct wmOperatorType *ot); void CURVE_OT_reveal(struct wmOperatorType *ot); void CURVE_OT_separate(struct wmOperatorType *ot); +void CURVE_OT_split(struct wmOperatorType *ot); void CURVE_OT_duplicate(struct wmOperatorType *ot); void CURVE_OT_delete(struct wmOperatorType *ot); diff --git a/source/blender/editors/curve/curve_ops.c b/source/blender/editors/curve/curve_ops.c index 2452a5d1a4b..1cf194e02c4 100644 --- a/source/blender/editors/curve/curve_ops.c +++ b/source/blender/editors/curve/curve_ops.c @@ -87,6 +87,7 @@ void ED_operatortypes_curve(void) WM_operatortype_append(CURVE_OT_reveal); WM_operatortype_append(CURVE_OT_separate); + WM_operatortype_append(CURVE_OT_split); WM_operatortype_append(CURVE_OT_duplicate); WM_operatortype_append(CURVE_OT_delete); @@ -244,6 +245,7 @@ void ED_keymap_curve(wmKeyConfig *keyconf) RNA_boolean_set(kmi->ptr, "deselect", TRUE); WM_keymap_add_item(keymap, "CURVE_OT_separate", PKEY, KM_PRESS, 0, 0); + WM_keymap_add_item(keymap, "CURVE_OT_split", YKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CURVE_OT_extrude_move", EKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "CURVE_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "CURVE_OT_make_segment", FKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 660f8098a38..ce0881b2e11 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -106,11 +106,25 @@ typedef struct { Nurb *orig_nu; } CVKeyIndex; -void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus); -static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus); - -/* still need to eradicate a few :( */ -#define CALLOC_STRUCT_N(x, y, name) (x *)MEM_callocN((y) * sizeof(x), name) +typedef enum eVisible_Types { + HIDDEN = true, + VISIBLE = false, +} eVisible_Types; + +typedef enum eEndPoint_Types { + FIRST = true, + LAST = false, +} eEndPoint_Types; + +typedef enum eCurveElem_Types { + CURVE_VERTEX = 0, + CURVE_SEGMENT, +} eCurveElem_Types; + +void selectend_nurb(Object *obedit, enum eEndPoint_Types selfirst, bool doswap, bool selstatus); +static void select_adjacent_cp(ListBase *editnurb, short next, const bool cont, const bool selstatus); +static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, const short flag, const bool split); +static int curve_delete_selected(Object *obedit, const eCurveElem_Types type, const bool split); static float nurbcircle[8][2] = { {0.0, -1.0}, {-1.0, -1.0}, {-1.0, 0.0}, {-1.0, 1.0}, @@ -149,69 +163,59 @@ static Nurb *get_actNurb(Object *obedit) /* ******************* SELECTION FUNCTIONS ********************* */ -#define HIDDEN 1 -#define VISIBLE 0 - -#define FIRST 1 -#define LAST 0 - /* returns 1 in case (de)selection was successful */ -static short select_beztriple(BezTriple *bezt, short selstatus, short flag, short hidden) +static bool select_beztriple(BezTriple *bezt, bool selstatus, short flag, eVisible_Types hidden) { - if (bezt) { - if ((bezt->hide == 0) || (hidden == 1)) { - if (selstatus == 1) { /* selects */ - bezt->f1 |= flag; - bezt->f2 |= flag; - bezt->f3 |= flag; - return 1; - } - else { /* deselects */ - bezt->f1 &= ~flag; - bezt->f2 &= ~flag; - bezt->f3 &= ~flag; - return 1; - } + if ((bezt->hide == 0) || (hidden == HIDDEN)) { + if (selstatus == SELECT) { /* selects */ + bezt->f1 |= flag; + bezt->f2 |= flag; + bezt->f3 |= flag; + return true; + } + else { /* deselects */ + bezt->f1 &= ~flag; + bezt->f2 &= ~flag; + bezt->f3 &= ~flag; + return true; } } - return 0; + return false; } /* returns 1 in case (de)selection was successful */ -static short select_bpoint(BPoint *bp, short selstatus, short flag, short hidden) +static bool select_bpoint(BPoint *bp, bool selstatus, short flag, bool hidden) { - if (bp) { - if ((bp->hide == 0) || (hidden == 1)) { - if (selstatus == 1) { - bp->f1 |= flag; - return 1; - } - else { - bp->f1 &= ~flag; - return 1; - } + if ((bp->hide == 0) || (hidden == 1)) { + if (selstatus == SELECT) { + bp->f1 |= flag; + return true; + } + else { + bp->f1 &= ~flag; + return true; } } - return 0; + return false; } -static short swap_selection_beztriple(BezTriple *bezt) +static bool swap_selection_beztriple(BezTriple *bezt) { if (bezt->f2 & SELECT) - return select_beztriple(bezt, DESELECT, 1, VISIBLE); + return select_beztriple(bezt, DESELECT, SELECT, VISIBLE); else - return select_beztriple(bezt, SELECT, 1, VISIBLE); + return select_beztriple(bezt, SELECT, SELECT, VISIBLE); } -static short swap_selection_bpoint(BPoint *bp) +static bool swap_selection_bpoint(BPoint *bp) { if (bp->f1 & SELECT) - return select_bpoint(bp, DESELECT, 1, VISIBLE); + return select_bpoint(bp, DESELECT, SELECT, VISIBLE); else - return select_bpoint(bp, SELECT, 1, VISIBLE); + return select_bpoint(bp, SELECT, SELECT, VISIBLE); } int isNurbsel(Nurb *nu) @@ -361,7 +365,7 @@ static CVKeyIndex *getCVKeyIndex(EditNurb *editnurb, void *cv) static CVKeyIndex *popCVKeyIndex(EditNurb *editnurb, void *cv) { - return BLI_ghash_pop(editnurb->keyindex, cv, NULL); + return BLI_ghash_popkey(editnurb->keyindex, cv, NULL); } static BezTriple *getKeyIndexOrig_bezt(EditNurb *editnurb, BezTriple *bezt) @@ -674,7 +678,7 @@ static GHash *dupli_keyIndexHash(GHash *keyindex) GHash *gh; GHashIterator *hashIter; - gh = BLI_ghash_ptr_new("dupli_keyIndex gh"); + gh = BLI_ghash_ptr_new_ex("dupli_keyIndex gh", BLI_ghash_size(keyindex)); for (hashIter = BLI_ghashIterator_new(keyindex); BLI_ghashIterator_done(hashIter) == false; @@ -1463,6 +1467,49 @@ void CURVE_OT_separate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/******************** split operator ***********************/ + +static int curve_split_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + ListBase *editnurb = object_editcurve_get(obedit); + ListBase newnurb = {NULL, NULL}; + + adduplicateflagNurb(obedit, &newnurb, SELECT, true); + + if (newnurb.first != NULL) { + curve_delete_selected(obedit, CURVE_SEGMENT, true); + BLI_movelisttolist(editnurb, &newnurb); + + if (ED_curve_updateAnimPaths(obedit->data)) + WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DAG_id_tag_update(obedit->data, 0); + } + else { + BKE_report(op->reports, RPT_ERROR, "Cannot split current selection"); + return OPERATOR_CANCELLED; + } + + return OPERATOR_FINISHED; +} + +void CURVE_OT_split(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Split"; + ot->idname = "CURVE_OT_split"; + ot->description = "Split off selected points from connected unselected points"; + + /* api callbacks */ + ot->exec = curve_split_exec; + ot->poll = ED_operator_editcurve; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /* ******************* FLAGS ********************* */ static short isNurbselUV(Nurb *nu, int *u, int *v, int flag) @@ -1614,9 +1661,8 @@ static void weightflagNurb(ListBase *editnurb, short flag, float w) } } -static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag) +static int deleteflagNurb(Object *obedit, short flag) { - Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu, *next; @@ -1744,9 +1790,6 @@ static int deleteflagNurb(bContext *C, wmOperator *UNUSED(op), int flag) nu = next; } - if (ED_curve_updateAnimPaths(obedit->data)) - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - return OPERATOR_FINISHED; } @@ -1869,40 +1912,54 @@ static short extrudeflagNurb(EditNurb *editnurb, int flag) return ok; } -static void adduplicateflagNurb(Object *obedit, short flag) +static void adduplicateflagNurb(Object *obedit, ListBase *newnurb, + const short flag, const bool split) { ListBase *editnurb = object_editcurve_get(obedit); - Nurb *nu, *newnu; + Nurb *nu, *newnu, *startnu; BezTriple *bezt, *bezt1; BPoint *bp, *bp1; Curve *cu = (Curve *)obedit->data; - int a, b, starta, enda, newu, newv; + int a, b, starta, enda, diffa, newu, newv; char *usel; cu->lastsel = NULL; nu = editnurb->last; while (nu) { + startnu = NULL; if (nu->type == CU_BEZIER) { bezt = nu->bezt; for (a = 0; a < nu->pntsu; a++) { enda = -1; starta = a; while ((bezt->f1 & flag) || (bezt->f2 & flag) || (bezt->f3 & flag)) { - select_beztriple(bezt, DESELECT, flag, HIDDEN); + if (!split) select_beztriple(bezt, DESELECT, flag, HIDDEN); enda = a; if (a >= nu->pntsu - 1) break; a++; bezt++; } if (enda >= starta) { - newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN"); - memcpy(newnu, nu, sizeof(Nurb)); - BLI_addtail(editnurb, newnu); - set_actNurb(obedit, newnu); - newnu->pntsu = enda - starta + 1; - newnu->bezt = (BezTriple *)MEM_mallocN((enda - starta + 1) * sizeof(BezTriple), "adduplicateN"); - memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple)); + diffa = enda - starta + 1; + + if (startnu != NULL && enda == nu->pntsu - 1) { + /* end point of cyclic spline selected, so merge end points with start points */ + bezt1 = (BezTriple *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BezTriple), "adduplicateN"); + memcpy(bezt1, &nu->bezt[starta], diffa * sizeof(BezTriple)); + memcpy(&bezt1[diffa], startnu->bezt, startnu->pntsu * sizeof(BezTriple)); + + MEM_freeN(startnu->bezt); + startnu->bezt = bezt1; + startnu->pntsu += diffa; + newnu = startnu; + } + else { + newnu = ED_curve_nurbcpy(nu, diffa); + BLI_addtail(newnurb, newnu); + set_actNurb(obedit, newnu); + memcpy(newnu->bezt, &nu->bezt[starta], newnu->pntsu * sizeof(BezTriple)); + } b = newnu->pntsu; bezt1 = newnu->bezt; @@ -1914,6 +1971,7 @@ static void adduplicateflagNurb(Object *obedit, short flag) if (nu->flagu & CU_NURB_CYCLIC) { if (starta != 0 || enda != nu->pntsu - 1) { newnu->flagu &= ~CU_NURB_CYCLIC; + if (starta == 0) startnu = newnu; } } } @@ -1926,20 +1984,32 @@ static void adduplicateflagNurb(Object *obedit, short flag) enda = -1; starta = a; while (bp->f1 & flag) { - select_bpoint(bp, DESELECT, flag, HIDDEN); + if (!split) select_bpoint(bp, DESELECT, flag, HIDDEN); enda = a; if (a >= nu->pntsu - 1) break; a++; bp++; } if (enda >= starta) { - newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN3"); - memcpy(newnu, nu, sizeof(Nurb)); - set_actNurb(obedit, newnu); - BLI_addtail(editnurb, newnu); - newnu->pntsu = enda - starta + 1; - newnu->bp = (BPoint *)MEM_mallocN((enda - starta + 1) * sizeof(BPoint), "adduplicateN4"); - memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint)); + diffa = enda - starta + 1; + + if (startnu != NULL && enda == nu->pntsu - 1) { + /* end point of cyclic spline selected, so merge end points with start points */ + bp1 = (BPoint *)MEM_mallocN((startnu->pntsu + diffa) * sizeof(BPoint), "adduplicateN2"); + memcpy(bp1, &nu->bp[starta], diffa * sizeof(BPoint)); + memcpy(&bp1[diffa], startnu->bp, startnu->pntsu * sizeof(BPoint)); + + MEM_freeN(startnu->bp); + startnu->bp = bp1; + startnu->pntsu += diffa; + newnu = startnu; + } + else { + newnu = ED_curve_nurbcpy(nu, diffa); + BLI_addtail(newnurb, newnu); + set_actNurb(obedit, newnu); + memcpy(newnu->bp, &nu->bp[starta], newnu->pntsu * sizeof(BPoint)); + } b = newnu->pntsu; bp1 = newnu->bp; @@ -1951,12 +2021,9 @@ static void adduplicateflagNurb(Object *obedit, short flag) if (nu->flagu & CU_NURB_CYCLIC) { if (starta != 0 || enda != nu->pntsu - 1) { newnu->flagu &= ~CU_NURB_CYCLIC; + if (starta == 0) startnu = newnu; } } - - /* knots */ - newnu->knotsu = NULL; - BKE_nurb_knot_calc_u(newnu); } bp++; } @@ -1964,7 +2031,7 @@ static void adduplicateflagNurb(Object *obedit, short flag) else { /* a rectangular area in nurb has to be selected */ if (isNurbsel(nu)) { - usel = MEM_callocN(nu->pntsu, "adduplicateN4"); + usel = MEM_callocN(nu->pntsu, "adduplicateN3"); bp = nu->bp; for (a = 0; a < nu->pntsv; a++) { for (b = 0; b < nu->pntsu; b++, bp++) { @@ -1993,13 +2060,13 @@ static void adduplicateflagNurb(Object *obedit, short flag) if (newu == 1) SWAP(int, newu, newv); - newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN5"); + newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "adduplicateN4"); memcpy(newnu, nu, sizeof(Nurb)); - BLI_addtail(editnurb, newnu); + BLI_addtail(newnurb, newnu); set_actNurb(obedit, newnu); newnu->pntsu = newu; newnu->pntsv = newv; - newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN6"); + newnu->bp = (BPoint *)MEM_mallocN(newu * newv * sizeof(BPoint), "adduplicateN5"); BKE_nurb_order_clamp_u(newnu); BKE_nurb_order_clamp_v(newnu); @@ -2040,6 +2107,22 @@ static void adduplicateflagNurb(Object *obedit, short flag) nu = nu->prev; } + for (nu = newnurb->first; nu; nu = nu->next) { + /* knots done after duplicate as pntsu may change */ + if (nu->pntsv == 1) { + nu->knotsu = NULL; + BKE_nurb_knot_calc_u(nu); + } + + if (split) { + if (nu->type == CU_BEZIER) { + /* recalc first and last */ + BKE_nurb_handle_calc_simple(nu, &nu->bezt[0]); + BKE_nurb_handle_calc_simple(nu, &nu->bezt[nu->pntsu - 1]); + } + } + } + /* actnu changed */ } @@ -2513,7 +2596,8 @@ void CURVE_OT_smooth_tilt(wmOperatorType *ot) /* next == -1 -> select previous */ /* cont == 1 -> select continuously */ /* selstatus, inverts behavior */ -static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short selstatus) +static void select_adjacent_cp(ListBase *editnurb, short next, + const bool cont, const bool selstatus) { Nurb *nu; BezTriple *bezt; @@ -2531,10 +2615,10 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short if (next < 0) bezt = &nu->bezt[a - 1]; while (a--) { if (a - abs(next) < 0) break; - if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == 0))) { + if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { bezt += next; - if (!(bezt->f2 & SELECT) || (selstatus == 0)) { - short sel = select_beztriple(bezt, selstatus, 1, VISIBLE); + if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) { + short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); if ((sel == 1) && (cont == 0)) lastsel = true; } } @@ -2552,10 +2636,10 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short if (next < 0) bp = &nu->bp[a - 1]; while (a--) { if (a - abs(next) < 0) break; - if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == 0))) { + if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) { bp += next; - if (!(bp->f1 & SELECT) || (selstatus == 0)) { - short sel = select_bpoint(bp, selstatus, 1, VISIBLE); + if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) { + short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); if ((sel == 1) && (cont == 0)) lastsel = true; } } @@ -2577,7 +2661,7 @@ static void select_adjacent_cp(ListBase *editnurb, short next, short cont, short * doswap: defines if selection state of each first/last control point is swapped * selstatus: selection status in case doswap is false */ -void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatus) +void selectend_nurb(Object *obedit, eEndPoint_Types selfirst, bool doswap, bool selstatus) { ListBase *editnurb = object_editcurve_get(obedit); Nurb *nu; @@ -2596,7 +2680,7 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu a = nu->pntsu; /* which point? */ - if (selfirst == 0) { /* select last */ + if (selfirst == LAST) { /* select last */ bezt = &nu->bezt[a - 1]; } else { /* select first */ @@ -2604,18 +2688,18 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu } while (a--) { - short sel; + bool sel; if (doswap) sel = swap_selection_beztriple(bezt); - else sel = select_beztriple(bezt, selstatus, 1, VISIBLE); + else sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); - if (sel == 1) break; + if (sel == true) break; } } else { a = nu->pntsu * nu->pntsv; /* which point? */ - if (selfirst == 0) { /* select last */ + if (selfirst == LAST) { /* select last */ bp = &nu->bp[a - 1]; } else { /* select first */ @@ -2624,11 +2708,11 @@ void selectend_nurb(Object *obedit, short selfirst, short doswap, short selstatu while (a--) { if (bp->hide == 0) { - short sel; + bool sel; if (doswap) sel = swap_selection_bpoint(bp); - else sel = select_bpoint(bp, selstatus, 1, VISIBLE); + else sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); - if (sel == 1) break; + if (sel == true) break; } } } @@ -2639,7 +2723,7 @@ static int de_select_first_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); - selectend_nurb(obedit, FIRST, 1, DESELECT); + selectend_nurb(obedit, FIRST, true, DESELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -2664,7 +2748,7 @@ static int de_select_last_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); - selectend_nurb(obedit, LAST, 1, DESELECT); + selectend_nurb(obedit, LAST, true, DESELECT); WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); return OPERATOR_FINISHED; @@ -2789,11 +2873,11 @@ static int hide_exec(bContext *C, wmOperator *op) sel = 0; while (a--) { if (invert == 0 && BEZSELECTED_HIDDENHANDLES(cu, bezt)) { - select_beztriple(bezt, DESELECT, 1, HIDDEN); + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); bezt->hide = 1; } else if (invert && !BEZSELECTED_HIDDENHANDLES(cu, bezt)) { - select_beztriple(bezt, DESELECT, 1, HIDDEN); + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); bezt->hide = 1; } if (bezt->hide) sel++; @@ -2807,11 +2891,11 @@ static int hide_exec(bContext *C, wmOperator *op) sel = 0; while (a--) { if (invert == 0 && (bp->f1 & SELECT)) { - select_bpoint(bp, DESELECT, 1, HIDDEN); + select_bpoint(bp, DESELECT, SELECT, HIDDEN); bp->hide = 1; } else if (invert && (bp->f1 & SELECT) == 0) { - select_bpoint(bp, DESELECT, 1, HIDDEN); + select_bpoint(bp, DESELECT, SELECT, HIDDEN); bp->hide = 1; } if (bp->hide) sel++; @@ -2863,7 +2947,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu; while (a--) { if (bezt->hide) { - select_beztriple(bezt, SELECT, 1, HIDDEN); + select_beztriple(bezt, SELECT, SELECT, HIDDEN); bezt->hide = 0; } bezt++; @@ -2874,7 +2958,7 @@ static int reveal_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu * nu->pntsv; while (a--) { if (bp->hide) { - select_bpoint(bp, SELECT, 1, HIDDEN); + select_bpoint(bp, SELECT, SELECT, HIDDEN); bp->hide = 0; } bp++; @@ -3840,7 +3924,7 @@ static void merge_2_nurb(wmOperator *op, ListBase *editnurb, Nurb *nu1, Nurb *nu for (u = 0; u < nu1->pntsu; u++, bp++) { if (u < origu) { *bp = *bp1; bp1++; - select_bpoint(bp, SELECT, 1, HIDDEN); + select_bpoint(bp, SELECT, SELECT, HIDDEN); } else { *bp = *bp2; bp2++; @@ -4148,7 +4232,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool if (extend) { if (bezt) { if (hand == 1) { - select_beztriple(bezt, SELECT, 1, HIDDEN); + select_beztriple(bezt, SELECT, SELECT, HIDDEN); cu->lastsel = bezt; } else { @@ -4160,13 +4244,13 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool } else { cu->lastsel = bp; - select_bpoint(bp, SELECT, 1, HIDDEN); + select_bpoint(bp, SELECT, SELECT, HIDDEN); } } else if (deselect) { if (bezt) { if (hand == 1) { - select_beztriple(bezt, DESELECT, 1, HIDDEN); + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); if (bezt == cu->lastsel) cu->lastsel = NULL; } else if (hand == 0) { @@ -4177,7 +4261,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool } } else { - select_bpoint(bp, DESELECT, 1, HIDDEN); + select_bpoint(bp, DESELECT, SELECT, HIDDEN); if (cu->lastsel == bp) cu->lastsel = NULL; } } @@ -4185,11 +4269,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool if (bezt) { if (hand == 1) { if (bezt->f2 & SELECT) { - select_beztriple(bezt, DESELECT, 1, HIDDEN); + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); if (bezt == cu->lastsel) cu->lastsel = NULL; } else { - select_beztriple(bezt, SELECT, 1, HIDDEN); + select_beztriple(bezt, SELECT, SELECT, HIDDEN); cu->lastsel = bezt; } } @@ -4202,11 +4286,11 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool } else { if (bp->f1 & SELECT) { - select_bpoint(bp, DESELECT, 1, HIDDEN); + select_bpoint(bp, DESELECT, SELECT, HIDDEN); if (cu->lastsel == bp) cu->lastsel = NULL; } else { - select_bpoint(bp, SELECT, 1, HIDDEN); + select_bpoint(bp, SELECT, SELECT, HIDDEN); cu->lastsel = bp; } } @@ -4217,7 +4301,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool if (bezt) { if (hand == 1) { - select_beztriple(bezt, SELECT, 1, HIDDEN); + select_beztriple(bezt, SELECT, SELECT, HIDDEN); cu->lastsel = bezt; } else { @@ -4229,7 +4313,7 @@ bool mouse_nurb(bContext *C, const int mval[2], bool extend, bool deselect, bool } else { cu->lastsel = bp; - select_bpoint(bp, SELECT, 1, HIDDEN); + select_bpoint(bp, SELECT, SELECT, HIDDEN); } } @@ -4944,7 +5028,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu; bezt = nu->bezt; while (a--) { - select_beztriple(bezt, SELECT, 1, VISIBLE); + select_beztriple(bezt, SELECT, SELECT, VISIBLE); bezt++; } break; @@ -4960,7 +5044,7 @@ static int select_linked_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu * nu->pntsv; bp = nu->bp; while (a--) { - select_bpoint(bp, SELECT, 1, VISIBLE); + select_bpoint(bp, SELECT, SELECT, VISIBLE); bp++; } break; @@ -5021,8 +5105,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent a = nu->pntsu; bezt = nu->bezt; while (a--) { - if (deselect) select_beztriple(bezt, DESELECT, 1, VISIBLE); - else select_beztriple(bezt, SELECT, 1, VISIBLE); + if (deselect) select_beztriple(bezt, DESELECT, SELECT, VISIBLE); + else select_beztriple(bezt, SELECT, SELECT, VISIBLE); bezt++; } } @@ -5030,8 +5114,8 @@ static int select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent a = nu->pntsu * nu->pntsv; bp = nu->bp; while (a--) { - if (deselect) select_bpoint(bp, DESELECT, 1, VISIBLE); - else select_bpoint(bp, SELECT, 1, VISIBLE); + if (deselect) select_bpoint(bp, DESELECT, SELECT, VISIBLE); + else select_bpoint(bp, SELECT, SELECT, VISIBLE); bp++; } } @@ -5103,10 +5187,10 @@ static int select_row_exec(bContext *C, wmOperator *UNUSED(op)) for (a = 0; a < nu->pntsv; a++) { for (b = 0; b < nu->pntsu; b++, bp++) { if (direction) { - if (a == v) select_bpoint(bp, SELECT, 1, VISIBLE); + if (a == v) select_bpoint(bp, SELECT, SELECT, VISIBLE); } else { - if (b == u) select_bpoint(bp, SELECT, 1, VISIBLE); + if (b == u) select_bpoint(bp, SELECT, SELECT, VISIBLE); } } } @@ -5217,14 +5301,14 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) /* upper control point */ if (a % nu->pntsu != 0) { tempbp = bp - 1; - if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE); + if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE); } /* left control point. select only if it is not selected already */ if (a - nu->pntsu > 0) { sel = 0; tempbp = bp + nu->pntsu; - if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE); + if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); /* make sure selected bpoint is discarded */ if (sel == 1) BLI_BITMAP_SET(selbpoints, a - nu->pntsu); } @@ -5232,14 +5316,14 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op)) /* right control point */ if (a + nu->pntsu < nu->pntsu * nu->pntsv) { tempbp = bp - nu->pntsu; - if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, 1, VISIBLE); + if (!(tempbp->f1 & SELECT)) select_bpoint(tempbp, SELECT, SELECT, VISIBLE); } /* lower control point. skip next bp in case selection was made */ if (a % nu->pntsu != 1) { sel = 0; tempbp = bp + 1; - if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, 1, VISIBLE); + if (!(tempbp->f1 & SELECT)) sel = select_bpoint(tempbp, SELECT, SELECT, VISIBLE); if (sel) { bp++; a--; @@ -5341,7 +5425,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } if (sel != 4) { - select_bpoint(bp, DESELECT, 1, VISIBLE); + select_bpoint(bp, DESELECT, SELECT, VISIBLE); BLI_BITMAP_SET(selbpoints, a); } } @@ -5387,7 +5471,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } if (sel != 2) { - select_beztriple(bezt, DESELECT, 1, VISIBLE); + select_beztriple(bezt, DESELECT, SELECT, VISIBLE); lastsel = true; } else { @@ -5429,7 +5513,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) } if (sel != 2) { - select_bpoint(bp, DESELECT, 1, VISIBLE); + select_bpoint(bp, DESELECT, SELECT, VISIBLE); lastsel = true; } else { @@ -5481,7 +5565,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac) a = nu->pntsu; while (a--) { if (BLI_frand() < randfac) - select_beztriple(bezt, SELECT, 1, VISIBLE); + select_beztriple(bezt, SELECT, SELECT, VISIBLE); bezt++; } } @@ -5491,7 +5575,7 @@ static void selectrandom_curve(ListBase *editnurb, float randfac) while (a--) { if (BLI_frand() < randfac) - select_bpoint(bp, SELECT, 1, VISIBLE); + select_bpoint(bp, SELECT, SELECT, VISIBLE); bp++; } } @@ -5534,15 +5618,13 @@ void CURVE_OT_select_random(wmOperatorType *ot) /********************* every nth number of point *******************/ -static int point_on_nurb(Nurb *nu, void *point) +static bool point_in_nurb(Nurb *nu, void *point) { if (nu->bezt) { - BezTriple *bezt = (BezTriple *)point; - return bezt >= nu->bezt && bezt < &nu->bezt[nu->pntsu]; + return ARRAY_HAS_ITEM((BezTriple *)point, nu->bezt, nu->pntsu); } else { - BPoint *bp = (BPoint *)point; - return bp >= nu->bp && bp < &nu->bp[nu->pntsu * nu->pntsv]; + return ARRAY_HAS_ITEM((BPoint *)point, nu->bp, nu->pntsu); } } @@ -5555,7 +5637,7 @@ static Nurb *get_lastsel_nurb(Curve *cu) return NULL; while (nu) { - if (point_on_nurb(nu, cu->lastsel)) + if (point_in_nurb(nu, cu->lastsel)) return nu; nu = nu->next; @@ -5574,7 +5656,7 @@ static void select_nth_bezt(Nurb *nu, BezTriple *bezt, int nth) while (a--) { if (abs(start - a) % nth) { - select_beztriple(bezt, DESELECT, 1, HIDDEN); + select_beztriple(bezt, DESELECT, SELECT, HIDDEN); } bezt--; @@ -5597,7 +5679,7 @@ static void select_nth_bp(Nurb *nu, BPoint *bp, int nth) while (a--) { dist = abs(pnt - startpnt) + abs(row - startrow); if (dist % nth) { - select_bpoint(bp, DESELECT, 1, HIDDEN); + select_bpoint(bp, DESELECT, SELECT, HIDDEN); } pnt--; @@ -5672,9 +5754,14 @@ void CURVE_OT_select_nth(wmOperatorType *ot) static int duplicate_exec(bContext *C, wmOperator *UNUSED(op)) { Object *obedit = CTX_data_edit_object(C); + ListBase newnurb = {NULL, NULL}; - adduplicateflagNurb(obedit, 1); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + adduplicateflagNurb(obedit, &newnurb, SELECT, false); + + if (newnurb.first != NULL) { + BLI_movelisttolist(object_editcurve_get(obedit), &newnurb); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } return OPERATOR_FINISHED; } @@ -5696,37 +5783,31 @@ void CURVE_OT_duplicate(wmOperatorType *ot) /********************** delete operator *********************/ -static int delete_exec(bContext *C, wmOperator *op) +static int curve_delete_selected(Object *obedit, eCurveElem_Types type, const bool split) { - Object *obedit = CTX_data_edit_object(C); Curve *cu = obedit->data; EditNurb *editnurb = cu->editnurb; ListBase *nubase = &editnurb->nurbs; - Nurb *nu, *nu1; + Nurb *nu, *nu1, *startnu; BezTriple *bezt, *bezt1, *bezt2; BPoint *bp, *bp1, *bp2; - int a, cut = 0, type = RNA_enum_get(op->ptr, "type"); + int a, b, starta, enda, cut = 0; int nuindex = 0; + ListBase newnurb = {NULL, NULL}; if (obedit->type == OB_SURF) { - if (type == 0) { - deleteflagNurb(C, op, 1); + if (type == CURVE_VERTEX) { + return deleteflagNurb(obedit, SELECT); } else { keyIndex_delNurbList(editnurb, nubase); BKE_nurbList_free(nubase); - if (ED_curve_updateAnimPaths(obedit->data)) - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + return OPERATOR_FINISHED; } - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); - - return OPERATOR_FINISHED; } - if (type == 0) { + if (type == CURVE_VERTEX) { /* first loop, can we remove entire pieces? */ Nurb *next; nu = nubase->first; @@ -5861,204 +5942,343 @@ static int delete_exec(bContext *C, wmOperator *op) nu = next; } } - else if (type == 1) { /* erase segment */ - /* find the 2 selected points */ - bezt1 = bezt2 = NULL; - bp1 = bp2 = NULL; - nu1 = NULL; - nuindex = 0; + else if (type == CURVE_SEGMENT) { for (nu = nubase->first; nu; nu = nu->next) { + startnu = nu1 = NULL; + starta = enda = cut = -1; + if (nu->type == CU_BEZIER) { - bezt = nu->bezt; - for (a = 0; a < nu->pntsu - 1; a++) { - if (BEZSELECTED_HIDDENHANDLES(cu, bezt)) { - bezt1 = bezt; - bezt2 = bezt + 1; - if ((bezt2->f1 & SELECT) || (bezt2->f2 & SELECT) || (bezt2->f3 & SELECT)) { - /* pass */ + for (a = 0, bezt = nu->bezt; a < nu->pntsu; a++, bezt++) { + if (!BEZSELECTED_HIDDENHANDLES(cu, bezt)) { + enda = a; + if (starta == -1) starta = a; + if (a < nu->pntsu - 1) continue; + } + else if (a < nu->pntsu - 1 && !BEZSELECTED_HIDDENHANDLES(cu, bezt + 1)) { + /* if just single selected point then continue */ + continue; + } + + if (starta >= 0) { + /* got selected segment, now check where and copy */ + if (starta <= 1 && a == nu->pntsu - 1) { + /* copying all points in spline */ + if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC; + + starta = 0; + enda = a; + cut = enda - starta + 1; + + nu1 = ED_curve_nurbcpy(nu, cut); + } + else if (starta == 0) { + /* if start of curve copy next end point */ + enda++; + cut = enda - starta + 1; + + bezt1 = &nu->bezt[nu->pntsu - 1]; + bezt2 = &nu->bezt[nu->pntsu - 2]; + + if ((nu->flagu & CU_NURB_CYCLIC) && + BEZSELECTED_HIDDENHANDLES(cu, bezt1) && + BEZSELECTED_HIDDENHANDLES(cu, bezt2)) + { + /* check if need to join start of spline to end */ + nu1 = ED_curve_nurbcpy(nu, cut + 1); + ED_curve_beztcpy(editnurb, &nu1->bezt[1], nu->bezt, cut); + starta = nu->pntsu - 1; + cut = 1; + } + else { + nu1 = ED_curve_nurbcpy(nu, cut); + + if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1; + } + } + else if (enda == nu->pntsu - 1) { + /* if end of curve copy previous start point */ + starta--; + cut = enda - starta + 1; + + bezt1 = nu->bezt; + bezt2 = &nu->bezt[1]; + + if ((nu->flagu & CU_NURB_CYCLIC) && + BEZSELECTED_HIDDENHANDLES(cu, bezt1) && + BEZSELECTED_HIDDENHANDLES(cu, bezt2)) + { + /* check if need to join start of spline to end */ + nu1 = ED_curve_nurbcpy(nu, cut + 1); + ED_curve_beztcpy(editnurb, &nu1->bezt[cut], nu->bezt, 1); + } + else if (startnu != NULL) { + /* if startnu exists it is a cyclic spline, start and end should be connected */ + bezt1 = (BezTriple *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BezTriple), "delNurb3"); + ED_curve_beztcpy(editnurb, bezt1, &nu->bezt[starta], cut); + ED_curve_beztcpy(editnurb, &bezt1[cut], nu->bezt, startnu->pntsu); + + MEM_freeN(startnu->bezt); + startnu->bezt = bezt1; + startnu->pntsu += cut; + + if (split) { + for (b = 0; b < startnu->pntsu; b++, bezt1++) { + select_beztriple(bezt1, DESELECT, SELECT, true); + } + } + + BKE_nurb_handles_calc(startnu); + } + else { + nu1 = ED_curve_nurbcpy(nu, cut); + } } - else { /* maybe do not make cyclic */ - if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) { - bezt2 = bezt + (nu->pntsu - 1); - 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); - DAG_id_tag_update(obedit->data, 0); + else { + /* mid spline selection, copy adjacent start and end */ + starta--; + enda++; + cut = enda - starta + 1; + + nu1 = ED_curve_nurbcpy(nu, cut); + } + + if (nu1 != NULL) { + ED_curve_beztcpy(editnurb, nu1->bezt, &nu->bezt[starta], cut); + + if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC; + + if (split) { + /* deselect for split operator */ + for (b = 0, bezt1 = nu1->bezt; b < nu1->pntsu; b++, bezt1++) { + select_beztriple(bezt1, DESELECT, SELECT, true); } } - return OPERATOR_FINISHED; + BLI_addtail(&newnurb, nu1); + BKE_nurb_handles_calc(nu1); + nu1 = NULL; } - cut = a; - nu1 = nu; - break; + starta = enda = -1; + } + } + + if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { + /* start and points copied if connecting segment was deleted and not cylic spline */ + bezt1 = nu->bezt; + bezt2 = &nu->bezt[1]; + if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) { + nu1 = ED_curve_nurbcpy(nu, 1); + ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1); + BLI_addtail(&newnurb, nu1); + } + + bezt1 = &nu->bezt[nu->pntsu - 1]; + bezt2 = &nu->bezt[nu->pntsu - 2]; + if (BEZSELECTED_HIDDENHANDLES(cu, bezt1) && BEZSELECTED_HIDDENHANDLES(cu, bezt2)) { + nu1 = ED_curve_nurbcpy(nu, 1); + ED_curve_beztcpy(editnurb, nu1->bezt, bezt1, 1); + BLI_addtail(&newnurb, nu1); } - bezt++; } } else if (nu->pntsv == 1) { - bp = nu->bp; - for (a = 0; a < nu->pntsu - 1; a++) { - if (bp->f1 & SELECT) { - bp1 = bp; - bp2 = bp + 1; - if (bp2->f1 & SELECT) { - /* pass */ + for (a = 0, bp = nu->bp; a < nu->pntsu; a++, bp++) { + if (!(bp->f1 & SELECT)) { + enda = a; + if (starta == -1) starta = a; + if (a < nu->pntsu - 1) continue; + } + else if (a < nu->pntsu - 1 && !((bp + 1)->f1 & SELECT)) { + /* if just single selected point then continue */ + continue; + } + + if (starta >= 0) { + /* got selected segment, now check where and copy */ + if (starta <= 1 && a == nu->pntsu - 1) { + /* copying all points in spline */ + if (starta == 1 && enda != a) nu->flagu &= ~CU_NURB_CYCLIC; + + starta = 0; + enda = a; + cut = enda - starta + 1; + + nu1 = ED_curve_nurbcpy(nu, cut); } - else { /* maybe do not make cyclic */ - if (a == 0 && (nu->flagu & CU_NURB_CYCLIC)) { - bp2 = bp + (nu->pntsu - 1); - if (bp2->f1 & SELECT) { - nu->flagu &= ~CU_NURB_CYCLIC; - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); + else if (starta == 0) { + /* if start of curve copy next end point */ + enda++; + cut = enda - starta + 1; + + bp1 = &nu->bp[nu->pntsu - 1]; + bp2 = &nu->bp[nu->pntsu - 2]; + + if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + /* check if need to join start of spline to end */ + nu1 = ED_curve_nurbcpy(nu, cut + 1); + ED_curve_bpcpy(editnurb, &nu1->bp[1], nu->bp, cut); + starta = nu->pntsu - 1; + cut = 1; + } + else { + nu1 = ED_curve_nurbcpy(nu, cut); + + if (nu->flagu & CU_NURB_CYCLIC) startnu = nu1; + } + } + else if (enda == nu->pntsu - 1) { + /* if end of curve copy previous start point */ + starta--; + cut = enda - starta + 1; + + bp1 = nu->bp; + bp2 = &nu->bp[1]; + + if ((nu->flagu & CU_NURB_CYCLIC) && (bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + /* check if need to join start of spline to end */ + nu1 = ED_curve_nurbcpy(nu, cut + 1); + ED_curve_bpcpy(editnurb, &nu1->bp[cut], nu->bp, 1); + } + else if (startnu != NULL) { + /* if startnu exists it is a cyclic spline, start and end should be connected */ + bp1 = (BPoint *)MEM_mallocN((cut + startnu->pntsu) * sizeof(BPoint), "delNurb4"); + ED_curve_bpcpy(editnurb, bp1, &nu->bp[starta], cut); + ED_curve_bpcpy(editnurb, &bp1[cut], nu->bp, startnu->pntsu); + + MEM_freeN(startnu->bp); + startnu->bp = bp1; + startnu->pntsu += cut; + + if (split) { + for (b = 0; b < startnu->pntsu; b++, bp1++) { + select_bpoint(bp1, DESELECT, SELECT, HIDDEN); + } } + + BKE_nurb_order_clamp_u(startnu); + BKE_nurb_knot_calc_u(startnu); + } + else { + nu1 = ED_curve_nurbcpy(nu, cut); } + } + else { + /* mid spline selection, copy adjacent start and end */ + starta--; + enda++; + cut = enda - starta + 1; - return OPERATOR_FINISHED; + nu1 = ED_curve_nurbcpy(nu, cut); } - cut = a; - nu1 = nu; - break; - } - bp++; - } - } - if (nu1) break; - nuindex++; - } - if (nu1) { - if (bezt1) { - if (nu1->pntsu == 2) { /* remove completely */ - if (cu->actnu == nuindex) - cu->actnu = -1; - BLI_remlink(nubase, nu); - BKE_nurb_free(nu); nu = NULL; - } - else if (nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */ - bezt = (BezTriple *)MEM_mallocN((cut + 1) * sizeof(BezTriple), "delNurb1"); - ED_curve_beztcpy(editnurb, bezt, nu1->bezt, cut + 1); - a = nu1->pntsu - cut - 1; - ED_curve_beztcpy(editnurb, nu1->bezt, bezt2, a); - ED_curve_beztcpy(editnurb, &nu1->bezt[a], bezt, cut + 1); + if (nu1 != NULL) { + ED_curve_bpcpy(editnurb, nu1->bp, &nu->bp[starta], cut); - nu1->flagu &= ~CU_NURB_CYCLIC; - MEM_freeN(bezt); - BKE_nurb_handles_calc(nu); - } - else { /* add new curve */ + if (starta != 0 || enda != nu->pntsu - 1) nu1->flagu &= ~CU_NURB_CYCLIC; -/* seems to be an error here... but where? (a can become zero) */ + if (split) { + /* deselect for split operator */ + for (b = 0, bp1 = nu1->bp; b < nu1->pntsu; b++, bp1++) { + select_bpoint(bp1, DESELECT, SELECT, HIDDEN); + } + } - nu = (Nurb *)MEM_mallocN(sizeof(Nurb), "delNurb2"); - memcpy(nu, nu1, sizeof(Nurb)); - BLI_addtail(nubase, nu); - nu->bezt = (BezTriple *)MEM_mallocN((cut + 1) * sizeof(BezTriple), "delNurb3"); - ED_curve_beztcpy(editnurb, nu->bezt, nu1->bezt, cut + 1); - a = nu1->pntsu - cut - 1; + BLI_addtail(&newnurb, nu1); + nu1->knotsu = NULL; + BKE_nurb_order_clamp_u(nu1); + BKE_nurb_knot_calc_u(nu1); + nu1 = NULL; + } + starta = enda = -1; + } + } - bezt = (BezTriple *)MEM_mallocN(a * sizeof(BezTriple), "delNurb4"); - ED_curve_beztcpy(editnurb, bezt, &nu1->bezt[cut + 1], a); - MEM_freeN(nu1->bezt); - nu1->bezt = bezt; - nu1->pntsu = a; - nu->pntsu = cut + 1; - - - BKE_nurb_handles_calc(nu); - BKE_nurb_handles_calc(nu1); - } - } - else if (bp1) { - if (nu1->pntsu == 2) { /* remove completely */ - if (cu->actnu == nuindex) - cu->actnu = -1; - - BLI_remlink(nubase, nu); - BKE_nurb_free(nu); nu = NULL; - } - else if (nu1->flagu & CU_NURB_CYCLIC) { /* cyclic */ - bp = (BPoint *)MEM_mallocN((cut + 1) * sizeof(BPoint), "delNurb5"); - ED_curve_bpcpy(editnurb, bp, nu1->bp, cut + 1); - a = nu1->pntsu - cut - 1; - ED_curve_bpcpy(editnurb, nu1->bp, bp2, a); - ED_curve_bpcpy(editnurb, &nu1->bp[a], bp, cut + 1); - - nu1->flagu &= ~CU_NURB_CYCLIC; - MEM_freeN(bp); - } - else { /* add new curve */ - nu = (Nurb *)MEM_mallocN(sizeof(Nurb), "delNurb6"); - memcpy(nu, nu1, sizeof(Nurb)); - BLI_addtail(nubase, nu); - nu->bp = (BPoint *)MEM_mallocN((cut + 1) * sizeof(BPoint), "delNurb7"); - ED_curve_bpcpy(editnurb, nu->bp, nu1->bp, cut + 1); - a = nu1->pntsu - cut - 1; - bp = (BPoint *)MEM_mallocN(a * sizeof(BPoint), "delNurb8"); - ED_curve_bpcpy(editnurb, bp, &nu1->bp[cut + 1], a); - MEM_freeN(nu1->bp); - nu1->bp = bp; - nu1->pntsu = a; - nu1->knotsu = NULL; - nu->pntsu = cut + 1; - - BKE_nurb_order_clamp_u(nu); - BKE_nurb_knot_calc_u(nu); + if (!split && cut != -1 && nu->pntsu > 2 && !(nu->flagu & CU_NURB_CYCLIC)) { + /* start and points copied if connecting segment was deleted and not cylic spline */ + bp1 = nu->bp; + bp2 = &nu->bp[1]; + if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + nu1 = ED_curve_nurbcpy(nu, 1); + ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1); + BLI_addtail(&newnurb, nu1); + nu1->knotsu = NULL; + } - BKE_nurb_order_clamp_u(nu1); - BKE_nurb_knot_calc_u(nu1); + bp1 = &nu->bp[nu->pntsu - 1]; + bp2 = &nu->bp[nu->pntsu - 2]; + if ((bp1->f1 & SELECT) && (bp2->f1 & SELECT)) { + nu1 = ED_curve_nurbcpy(nu, 1); + ED_curve_bpcpy(editnurb, nu1->bp, bp1, 1); + BLI_addtail(&newnurb, nu1); + nu1->knotsu = NULL; + } } } } - } - else if (type == 2) { - cu->actnu = -1; - keyIndex_delNurbList(editnurb, nubase); + BKE_nurbList_free(nubase); + BLI_movelisttolist(nubase, &newnurb); + } + else { + BLI_assert(0); } - if (ED_curve_updateAnimPaths(obedit->data)) - WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); - - WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); - DAG_id_tag_update(obedit->data, 0); - return OPERATOR_FINISHED; } -static int delete_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +static int curve_delete_exec(bContext *C, wmOperator *op) { Object *obedit = CTX_data_edit_object(C); - uiPopupMenu *pup; - uiLayout *layout; + eCurveElem_Types type = RNA_enum_get(op->ptr, "type"); + int retval = curve_delete_selected(obedit, type, false); + + if (retval == OPERATOR_FINISHED) { + if (ED_curve_updateAnimPaths(obedit->data)) WM_event_add_notifier(C, NC_OBJECT | ND_KEYS, obedit); + + WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data); + DAG_id_tag_update(obedit->data, 0); + return retval; + } + + return retval; +} + +static EnumPropertyItem curve_delete_type_items[] = { + {CURVE_VERTEX, "VERTICES", 0, "Vertices", ""}, + {CURVE_SEGMENT, "SEGMENT", 0, "Segments", ""}, + {0, NULL, 0, NULL, NULL} +}; + +static EnumPropertyItem *rna_curve_delete_type_itemf(bContext *C, PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), int *free) +{ + Object *obedit; + EnumPropertyItem *item = NULL; + int totitem = 0; + + + if (!C) /* needed for docs and i18n tools */ + return curve_delete_type_items; + + obedit = CTX_data_edit_object(C); if (obedit->type == OB_SURF) { - pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE); - layout = uiPupMenuLayout(pup); - uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 0); - uiItemEnumO_ptr(layout, op->type, NULL, 0, "type", 2); - uiPupMenuEnd(C, pup); + RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX); } else { - pup = uiPupMenuBegin(C, IFACE_("Delete"), ICON_NONE); - layout = uiPupMenuLayout(pup); - uiItemsEnumO(layout, op->type->idname, "type"); - uiPupMenuEnd(C, pup); + RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_VERTEX); + RNA_enum_items_add_value(&item, &totitem, curve_delete_type_items, CURVE_SEGMENT); } - return OPERATOR_CANCELLED; + RNA_enum_item_end(&item, &totitem); + *free = true; + + return item; } void CURVE_OT_delete(wmOperatorType *ot) { - static EnumPropertyItem type_items[] = { - {0, "SELECTED", 0, "Select", ""}, - {1, "SEGMENT", 0, "Segment", ""}, - {2, "ALL", 0, "All", ""}, - {0, NULL, 0, NULL, NULL} - }; + PropertyRNA *prop; /* identifiers */ ot->name = "Delete"; @@ -6066,15 +6286,18 @@ void CURVE_OT_delete(wmOperatorType *ot) ot->idname = "CURVE_OT_delete"; /* api callbacks */ - ot->exec = delete_exec; - ot->invoke = delete_invoke; + ot->exec = curve_delete_exec; + ot->invoke = WM_menu_invoke; ot->poll = ED_operator_editsurfcurve; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - RNA_def_enum(ot->srna, "type", type_items, 0, "Type", "Which elements to delete"); + prop = RNA_def_enum(ot->srna, "type", curve_delete_type_items, 0, "Type", "Which elements to delete"); + RNA_def_enum_funcs(prop, rna_curve_delete_type_itemf); + + ot->prop = prop; } /********************** shade smooth/flat operator *********************/ @@ -6345,7 +6568,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type nu->pntsu = 4; nu->pntsv = 1; nu->orderu = 4; - nu->bp = CALLOC_STRUCT_N(BPoint, 4, "addNurbprim3"); + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 4, "addNurbprim3"); bp = nu->bp; for (a = 0; a < 4; a++, bp++) { @@ -6381,7 +6604,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type nu->orderu = 5; nu->flagu = CU_NURB_ENDPOINT; /* endpoint */ nu->resolu = cu->resolu; - nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim3"); + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim3"); bp = nu->bp; for (a = 0; a < 5; a++, bp++) { @@ -6414,7 +6637,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type if (cutype == CU_BEZIER) { if (!force_3d) nu->flag |= CU_2D; nu->pntsu = 4; - nu->bezt = CALLOC_STRUCT_N(BezTriple, 4, "addNurbprim1"); + nu->bezt = (BezTriple *)MEM_callocN(sizeof(BezTriple) * 4, "addNurbprim1"); nu->flagu = CU_NURB_CYCLIC; bezt = nu->bezt; @@ -6451,7 +6674,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type nu->pntsu = 8; nu->pntsv = 1; nu->orderu = 4; - nu->bp = CALLOC_STRUCT_N(BPoint, 8, "addNurbprim6"); + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 8, "addNurbprim6"); nu->flagu = CU_NURB_CYCLIC; bp = nu->bp; @@ -6484,7 +6707,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type nu->orderu = 4; nu->orderv = 4; nu->flag = CU_SMOOTH; - nu->bp = CALLOC_STRUCT_N(BPoint, 4 * 4, "addNurbprim6"); + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * (4 * 4), "addNurbprim6"); nu->flagu = 0; nu->flagv = 0; bp = nu->bp; @@ -6546,7 +6769,7 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type nu->resolu = cu->resolu; nu->resolv = cu->resolv; nu->flag = CU_SMOOTH; - nu->bp = CALLOC_STRUCT_N(BPoint, 5, "addNurbprim6"); + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * 5, "addNurbprim6"); nu->flagu = 0; bp = nu->bp; @@ -7158,6 +7381,22 @@ void ED_curve_bpcpy(EditNurb *editnurb, BPoint *dst, BPoint *src, int count) keyIndex_updateBP(editnurb, src, dst, count); } +Nurb *ED_curve_nurbcpy(Nurb *src, int count) +{ + Nurb *newnu = (Nurb *)MEM_mallocN(sizeof(Nurb), "copyNurb"); + memcpy(newnu, src, sizeof(Nurb)); + newnu->pntsu = count; + + if (src->bezt) { + newnu->bezt = (BezTriple *)MEM_mallocN(count * sizeof(BezTriple), "copyNurb2"); + } + else { + newnu->bp = (BPoint *)MEM_mallocN(count * sizeof(BPoint), "copyNurb3"); + } + + return newnu; +} + int ED_curve_actSelection(Curve *cu, float center[3]) { Nurb *nu = get_lastsel_nurb(cu); diff --git a/source/blender/editors/datafiles/CMakeLists.txt b/source/blender/editors/datafiles/CMakeLists.txt index 8d108644470..6adc500baa4 100644 --- a/source/blender/editors/datafiles/CMakeLists.txt +++ b/source/blender/editors/datafiles/CMakeLists.txt @@ -47,8 +47,18 @@ if(WITH_BLENDER) # images data_to_c_simple(../../../../release/datafiles/splash.png SRC) + # XXX These are handy, but give nasty "false changes" in svn :/ + #svg_to_png(../../../../release/datafiles/blender_icons.svg + #../../../../release/datafiles/blender_icons16.png + #90 SRC) data_to_c_simple(../../../../release/datafiles/blender_icons16.png SRC) + #svg_to_png(../../../../release/datafiles/blender_icons.svg + #../../../../release/datafiles/blender_icons32.png + #180 SRC) data_to_c_simple(../../../../release/datafiles/blender_icons32.png SRC) + #svg_to_png(../../../../release/datafiles/prvicons.svg + #../../../../release/datafiles/prvicons.png + #90 SRC) data_to_c_simple(../../../../release/datafiles/prvicons.png SRC) # brushes diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 99157b074fd..c5dc8654e9d 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -106,8 +106,8 @@ bGPdata **gpencil_data_get_pointers(const bContext *C, PointerRNA *ptr) /* TODO: we can include other data-types such as bones later if need be... */ - /* just in case no active object */ - if (ob) { + /* just in case no active/selected object */ + if (ob && (ob->flag & SELECT)) { /* for now, as long as there's an object, default to using that in 3D-View */ if (ptr) RNA_id_pointer_create(&ob->id, ptr); return &ob->gpd; @@ -192,7 +192,14 @@ bGPdata *gpencil_data_get_active(const bContext *C) /* needed for offscreen rendering */ bGPdata *gpencil_data_get_active_v3d(Scene *scene) { - bGPdata *gpd = scene->basact ? scene->basact->object->gpd : NULL; + Base *base = scene->basact; + bGPdata *gpd = NULL; + /* We have to make sure active object is actually visible and selected, else we must use default scene gpd, + * to be consistent with gpencil_data_get_active's behavior. + */ + if (base && (scene->lay & base->lay) && (base->object->flag & SELECT)) { + gpd = base->object->gpd; + } return gpd ? gpd : scene->gpd; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 4c5727f16ed..da832554443 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1679,7 +1679,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), * setting the relevant values in context at each step, then applying */ - RNA_BEGIN(op->ptr, itemptr, "stroke") + RNA_BEGIN (op->ptr, itemptr, "stroke") { float mousef[2]; diff --git a/source/blender/editors/include/ED_clip.h b/source/blender/editors/include/ED_clip.h index 541956136bd..27e62928f1b 100644 --- a/source/blender/editors/include/ED_clip.h +++ b/source/blender/editors/include/ED_clip.h @@ -63,18 +63,18 @@ int ED_space_clip_get_clip_frame_number(struct SpaceClip *sc); struct ImBuf *ED_space_clip_get_buffer(struct SpaceClip *sc); struct ImBuf *ED_space_clip_get_stable_buffer(struct SpaceClip *sc, float loc[2], float *scale, float *angle); -int ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]); +bool ED_space_clip_color_sample(struct SpaceClip *sc, struct ARegion *ar, int mval[2], float r_col[3]); void ED_clip_update_frame(const struct Main *mainp, int cfra); -int ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, int fit); +bool ED_clip_view_selection(const struct bContext *C, struct ARegion *ar, bool fit); void ED_clip_point_undistorted_pos(struct SpaceClip *sc, const float co[2], float r_co[2]); void ED_clip_point_stable_pos(struct SpaceClip *sc, struct ARegion *ar, float x, float y, float *xr, float *yr); void ED_clip_point_stable_pos__reverse(struct SpaceClip *sc, struct ARegion *ar, const float co[2], float r_co[2]); void ED_clip_mouse_pos(struct SpaceClip *sc, struct ARegion *ar, const int mval[2], float co[2]); -int ED_space_clip_check_show_trackedit(struct SpaceClip *sc); -int ED_space_clip_check_show_maskedit(struct SpaceClip *sc); +bool ED_space_clip_check_show_trackedit(struct SpaceClip *sc); +bool ED_space_clip_check_show_maskedit(struct SpaceClip *sc); struct MovieClip *ED_space_clip_get_clip(struct SpaceClip *sc); void ED_space_clip_set_clip(struct bContext *C, struct bScreen *screen, struct SpaceClip *sc, struct MovieClip *clip); diff --git a/source/blender/editors/include/ED_curve.h b/source/blender/editors/include/ED_curve.h index 1d26204095c..571788f4f8f 100644 --- a/source/blender/editors/include/ED_curve.h +++ b/source/blender/editors/include/ED_curve.h @@ -83,6 +83,7 @@ int CU_select_nth(struct Object *obedit, int nth); void ED_curve_beztcpy(struct EditNurb *editnurb, struct BezTriple *dst, struct BezTriple *src, int count); void ED_curve_bpcpy(struct EditNurb *editnurb, struct BPoint *dst, struct BPoint *src, int count); +struct Nurb *ED_curve_nurbcpy(struct Nurb *src, int count); int ED_curve_updateAnimPaths(struct Curve *cu); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 95fad17274e..dc40efc748b 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -222,6 +222,7 @@ short ANIM_keyingset_context_ok_poll(struct bContext *C, struct KeyingSet *ks); /* Flags for use by driver creation calls */ typedef enum eCreateDriverFlags { CREATEDRIVER_WITH_DEFAULT_DVAR = (1 << 0), /* create drivers with a default variable for nicer UI */ + CREATEDRIVER_WITH_FMODIFIER = (1 << 1), /* create drivers with Generator FModifier (for backwards compat) */ } eCreateDriverFlags; /* -------- */ diff --git a/source/blender/editors/include/ED_mask.h b/source/blender/editors/include/ED_mask.h index 420ab24e5e9..3e2dbe255df 100644 --- a/source/blender/editors/include/ED_mask.h +++ b/source/blender/editors/include/ED_mask.h @@ -48,6 +48,8 @@ void ED_mask_point_pos(struct ScrArea *sa, struct ARegion *ar, float x, float y, void ED_mask_point_pos__reverse(struct ScrArea *sa, struct ARegion *ar, float x, float y, float *xr, float *yr); +void ED_mask_cursor_location_get(struct ScrArea *sa, float cursor[2]); + void ED_operatortypes_mask(void); void ED_keymap_mask(struct wmKeyConfig *keyconf); void ED_operatormacros_mask(void); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 90b131e5acc..7553cb3699c 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -92,7 +92,7 @@ typedef enum eParentType { PAR_PATH_CONST, PAR_LATTICE, PAR_VERTEX, - PAR_TRIA + PAR_VERTEX_TRI } eParentType; #ifdef __RNA_TYPES_H__ @@ -101,7 +101,7 @@ extern struct EnumPropertyItem prop_make_parent_types[]; #endif int ED_object_parent_set(struct ReportList *reports, struct Main *bmain, struct Scene *scene, struct Object *ob, - struct Object *par, int partype, int xmirror, int keep_transform); + struct Object *par, int partype, bool xmirror, bool keep_transform, const int vert_par[3]); void ED_object_parent_clear(struct Object *ob, int type); struct Base *ED_object_scene_link(struct Scene *scene, struct Object *ob); @@ -123,6 +123,7 @@ struct Base *ED_object_add_duplicate(struct Main *bmain, struct Scene *scene, st void ED_object_parent(struct Object *ob, struct Object *parent, int type, const char *substr); +bool ED_object_mode_compat_set(struct bContext *C, struct Object *ob, int mode, struct ReportList *reports); void ED_object_toggle_modes(struct bContext *C, int mode); /* bitflags for enter/exit editmode */ diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 9f42fd042c3..2b02606c6d9 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -79,7 +79,7 @@ typedef enum { AE_RIGHT_TO_TOPLEFT, /* Region located on the left, _right_ edge is action zone. Region minimized to the top left */ AE_LEFT_TO_TOPRIGHT, /* Region located on the right, _left_ edge is action zone. Region minimized to the top right */ AE_TOP_TO_BOTTOMRIGHT, /* Region located at the bottom, _top_ edge is action zone. Region minimized to the bottom right */ - AE_BOTTOM_TO_TOPLEFT /* Region located at the top, _bottom_edge is action zone. Region minimized to the top left */ + AE_BOTTOM_TO_TOPLEFT /* Region located at the top, _bottom_ edge is action zone. Region minimized to the top left */ } AZEdge; /* for editing areas/regions */ @@ -87,10 +87,8 @@ typedef struct AZone { struct AZone *next, *prev; ARegion *ar; int type; - /* region-azone, which of the edges */ + /* region-azone, which of the edges (only for AZONE_REGION) */ AZEdge edge; - /* internal */ - short do_draw; /* for draw */ short x1, y1, x2, y2; /* for clip */ diff --git a/source/blender/editors/include/ED_uvedit.h b/source/blender/editors/include/ED_uvedit.h index ffc9e6651bc..735227ae9b5 100644 --- a/source/blender/editors/include/ED_uvedit.h +++ b/source/blender/editors/include/ED_uvedit.h @@ -102,7 +102,7 @@ void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit); void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel); /* uvedit_draw.c */ -void draw_image_cursor(struct SpaceImage *sima, struct ARegion *ar); +void draw_image_cursor(struct ARegion *ar, const float cursor[2]); void draw_uvedit_main(struct SpaceImage *sima, struct ARegion *ar, struct Scene *scene, struct Object *obedit, struct Object *obact); /* uvedit_buttons.c */ diff --git a/source/blender/editors/include/UI_icons.h b/source/blender/editors/include/UI_icons.h index 3929cf9788c..f8e1bbb2413 100644 --- a/source/blender/editors/include/UI_icons.h +++ b/source/blender/editors/include/UI_icons.h @@ -49,9 +49,7 @@ DEF_ICON(RADIOBUT_OFF) DEF_ICON(RADIOBUT_ON) DEF_ICON(MENU_PANEL) DEF_ICON(BLENDER) -#ifndef DEF_ICON_BLANK_SKIP - DEF_ICON(BLANK003) -#endif +DEF_ICON(GRIP) DEF_ICON(DOT) #ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK004) @@ -75,9 +73,9 @@ DEF_ICON(VIEWZOOM) DEF_ICON(ZOOMIN) DEF_ICON(ZOOMOUT) DEF_ICON(PANEL_CLOSE) -DEF_ICON(COPY_ID) //ICON_BLANK009 +DEF_ICON(COPY_ID) DEF_ICON(EYEDROPPER) -DEF_ICON(LINK_AREA) //ICON_BLANK010 +DEF_ICON(LINK_AREA) DEF_ICON(AUTO) DEF_ICON(CHECKBOX_DEHLT) DEF_ICON(CHECKBOX_HLT) @@ -138,7 +136,7 @@ DEF_ICON(SCRIPT) DEF_ICON(PARTICLES) DEF_ICON(PHYSICS) DEF_ICON(SPEAKER) -DEF_ICON(TEXTURE_SHADED) //ICON_BLANK041 +DEF_ICON(TEXTURE_SHADED) #ifndef DEF_ICON_BLANK_SKIP DEF_ICON(BLANK042) DEF_ICON(BLANK043) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 9a9cab9b46c..8b395505623 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -32,6 +32,7 @@ #ifndef __UI_INTERFACE_H__ #define __UI_INTERFACE_H__ +#include "BLI_compiler_attrs.h" #include "BLI_sys_types.h" /* size_t */ #include "RNA_types.h" #include "DNA_userdef_types.h" @@ -327,30 +328,14 @@ typedef void (*uiMenuHandleFunc)(struct bContext *C, void *arg, int event); typedef struct uiPopupMenu uiPopupMenu; -struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) -#ifdef __GNUC__ -__attribute__((nonnull)) -#endif -; +struct uiPopupMenu *uiPupMenuBegin(struct bContext *C, const char *title, int icon) ATTR_NONNULL(); void uiPupMenuEnd(struct bContext *C, struct uiPopupMenu *head); struct uiLayout *uiPupMenuLayout(uiPopupMenu *head); -void uiPupMenuOkee(struct bContext *C, const char *opname, const char *str, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 3, 4))) -#endif -; +void uiPupMenuOkee(struct bContext *C, const char *opname, const char *str, ...) ATTR_PRINTF_FORMAT(3, 4); void uiPupMenuSaveOver(struct bContext *C, struct wmOperator *op, const char *filename); -void uiPupMenuNotice(struct bContext *C, const char *str, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 2, 3))) -#endif -; -void uiPupMenuError(struct bContext *C, const char *str, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 2, 3))) -#endif -; +void uiPupMenuNotice(struct bContext *C, const char *str, ...) ATTR_PRINTF_FORMAT(2, 3); +void uiPupMenuError(struct bContext *C, const char *str, ...) ATTR_PRINTF_FORMAT(2, 3); void uiPupMenuReports(struct bContext *C, struct ReportList *reports); void uiPupMenuInvoke(struct bContext *C, const char *idname); /* popup registered menu */ @@ -550,11 +535,7 @@ typedef struct uiStringInfo { /* Note: Expects pointers to uiStringInfo structs as parameters. * Will fill them with translated strings, when possible. * Strings in uiStringInfo must be MEM_freeN'ed by caller. */ -void uiButGetStrInfo(struct bContext *C, uiBut *but, ...) -#ifdef __GNUC__ -__attribute__((sentinel)) -#endif -; +void uiButGetStrInfo(struct bContext *C, uiBut *but, ...) ATTR_SENTINEL(0); /* Edit i18n stuff. */ /* Name of the main py op from i18n addon. */ @@ -845,7 +826,7 @@ void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color); #define UI_UL_DEFAULT_CLASS_NAME "UI_UL_list" void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id, struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr, - const char *active_propname, int rows, int maxrows, int layout_type); + const char *active_propname, int rows, int maxrows, int layout_type, int columns); void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); void uiTemplateTextureUser(uiLayout *layout, struct bContext *C); diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index 42e9d892871..0c8a39a6714 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -210,6 +210,9 @@ enum { TH_STITCH_PREVIEW_UNSTITCHABLE, TH_STITCH_PREVIEW_ACTIVE, + TH_UV_SHADOW, + TH_UV_OTHERS, + TH_FREESTYLE_EDGE_MARK, TH_FREESTYLE_FACE_MARK, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index e46334b06e7..fb70ad50b5d 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -192,6 +192,7 @@ void UI_view2d_listview_visible_cells(struct View2D *v2d, float columnwidth, flo void UI_view2d_region_to_view(struct View2D *v2d, float x, float y, float *viewx, float *viewy); void UI_view2d_view_to_region(struct View2D *v2d, float x, float y, int *regionx, int *regiony); void UI_view2d_to_region_no_clip(struct View2D *v2d, float x, float y, int *regionx, int *region_y); +void UI_view2d_to_region_float(struct View2D *v2d, float x, float y, float *regionx, float *regiony); /* utilities */ struct View2D *UI_view2d_fromcontext(const struct bContext *C); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 21a63183c1a..ec5a4d0027d 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -985,7 +985,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but, IDPropertyTemplate val = {0}; prop_path = IDP_New(IDP_GROUP, &val, __func__); - prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1); /* len + 1, or else will be truncated */ + prop_path_value = IDP_NewString(data_path, "data_path", strlen(data_path) + 1); IDP_AddToGroup(prop_path, prop_path_value); /* check each until one works... */ @@ -1807,12 +1807,14 @@ static void ui_get_but_string_unit(uiBut *but, char *str, int len_max, double va static float ui_get_but_step_unit(uiBut *but, float step_default) { int unit_type = RNA_SUBTYPE_UNIT_VALUE(uiButGetUnitType(but)); - float step; + double step; step = bUnit_ClosestScalar(ui_get_but_scale_unit(but, step_default), but->block->unit->system, unit_type); - if (step > 0.0f) { /* -1 is an error value */ - return (float)((double)step / ui_get_but_scale_unit(but, 1.0)) * 100.0f; + /* -1 is an error value */ + if (step != -1.0) { + BLI_assert(step > 0.0); + return (float)(step / ui_get_but_scale_unit(but, 1.0)) * 100.0f; } else { return step_default; @@ -2047,13 +2049,14 @@ bool ui_set_but_string(bContext *C, uiBut *but, const char *str) return false; } -void ui_set_but_default(bContext *C, short all) +void ui_set_but_default(bContext *C, const bool all) { + const char *opstring = "UI_OT_reset_default_button"; PointerRNA ptr; - WM_operator_properties_create(&ptr, "UI_OT_reset_default_button"); + WM_operator_properties_create(&ptr, opstring); RNA_boolean_set(&ptr, "all", all); - WM_operator_name_call(C, "UI_OT_reset_default_button", WM_OP_EXEC_DEFAULT, &ptr); + WM_operator_name_call(C, opstring, WM_OP_EXEC_DEFAULT, &ptr); WM_operator_properties_free(&ptr); } @@ -2230,8 +2233,7 @@ void uiFreeBlock(const bContext *C, uiBlock *block) { uiBut *but; - while ( (but = block->buttons.first) ) { - BLI_remlink(&block->buttons, but); + while ((but = BLI_pophead(&block->buttons))) { ui_free_but(C, but); } @@ -2255,8 +2257,7 @@ void uiFreeBlocks(const bContext *C, ListBase *lb) { uiBlock *block; - while ( (block = lb->first) ) { - BLI_remlink(lb, block); + while ((block = BLI_pophead(lb))) { uiFreeBlock(C, block); } } diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index f9ee2b67e6b..dc7813510ec 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -152,7 +152,9 @@ typedef struct uiHandleButtonData { char *str, *origstr; double value, origvalue, startvalue; float vec[3], origvec[3]; +#if 0 /* UNUSED */ int togdual, togonly; +#endif ColorBand *coba; /* tooltip */ @@ -170,6 +172,7 @@ typedef struct uiHandleButtonData { /* coords are Window/uiBlock relative (depends on the button) */ int draglastx, draglasty; int dragstartx, dragstarty; + int draglastvalue; bool dragchange, draglock; int dragsel; float dragf, dragfstart; @@ -2660,8 +2663,10 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons #ifdef USE_DRAG_TOGGLE if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE && event->val == KM_PRESS && ui_is_but_bool(but)) { +#if 0 /* UNUSED */ data->togdual = event->ctrl; data->togonly = !event->shift; +#endif ui_apply_button(C, but->block, but, data, true); button_activate_state(C, but, BUTTON_STATE_WAIT_DRAG); data->dragstartx = event->x; @@ -2677,8 +2682,10 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons #endif if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM3(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { +#if 0 /* UNUSED */ data->togdual = event->ctrl; data->togonly = !event->shift; +#endif button_activate_state(C, but, BUTTON_STATE_EXIT); return WM_UI_HANDLER_BREAK; } @@ -3406,6 +3413,100 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return retval; } +static int ui_do_but_LISTBOX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +{ + uiList *ui_list = but->custom_data; + int *size = (int *)but->poin; + int mx, my, raw_dir_sign; + int retval = WM_UI_HANDLER_CONTINUE; + + mx = event->x; + my = event->y; + + /* We find the direction of the mouse since last time, before converting coordinates into block's space. + * We'll use it to avoid flickering in case some rows are higher than UI_UNIT_Y. + */ + raw_dir_sign = (data->draglasty - my < 0) ? -1 : 1; + data->draglasty = my; + + ui_window_to_block(data->region, block, &mx, &my); + + if (data->state == BUTTON_STATE_NUM_EDITING) { + if (event->type == ESCKEY) { + data->cancel = true; + data->escapecancel = true; + *size = (int)data->origvalue; + button_activate_state(C, but, BUTTON_STATE_EXIT); + ui_list->flag &= ~UILST_RESIZING; + ED_region_tag_redraw(data->region); + } + else if (event->type == LEFTMOUSE && event->val != KM_PRESS) { + button_activate_state(C, but, BUTTON_STATE_EXIT); + ui_list->flag &= ~UILST_RESIZING; + ED_region_tag_redraw(data->region); + } + else if (event->type == MOUSEMOVE) { + /* If we switched from dragged to auto size, suspend shrinking dragging and set dragstarty to a temp + * refpoint. + */ + if (data->draglastvalue > 0 && *size == 0) { + data->draglastvalue = *size; + data->dragstartx = data->dragstarty; /* draglasty already used... */ + data->dragstarty = my; + } + else { + int delta = data->dragstarty - my; + /* We only actually do something if the real mousemouve direction matches the "virtual" + * mousemove direction in current block's space. This avoids flickering when drag-resizing lists with + * items drawing higher that UI_UNIT_Y. + */ + if (delta * raw_dir_sign > 0) { + /* Number of rows to show/hide, UI_UNIT_Y should work nice in most cases. */ + delta = (int)floorf(((float)delta / (float)UI_UNIT_Y) + 0.5f); + + /* If we are not in autosize mode, default behavior... */ + if (*size > 0 && delta != 0) { + /* This prevents some instability in case some items draw more/less than UI_UNIT_Y height. */ + delta = (delta < -5) ? -5 : (delta > 5) ? 5 : delta; + /* We can't use ui_numedit_apply()... */ + /* list template will clamp, but we do not want to reach 0 aka autosize mode! */ + *size = max_ii(*size + delta, 1); + + /* Used to detect switch to/from autosize mode. */ + data->draglastvalue = *size; + + data->dragchange = true; + data->applied = data->applied_interactive = true; + + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ED_region_tag_redraw(data->region); + } + /* If we are leaving autosize mode (growing dragging), restore to minimal size. */ + else if (delta > 0) { + /* We can't use ui_numedit_apply()... */ + *size = ui_list->dyn_data->visual_height_min; + + /* Restore real dragstarty value! */ + data->dragstarty = data->dragstartx; + + /* Used to detect switch to/from autosize mode. */ + data->draglastvalue = *size; + + data->dragchange = true; + data->applied = data->applied_interactive = true; + + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ED_region_tag_redraw(data->region); + } + } + } + } + + retval = WM_UI_HANDLER_BREAK; + } + + return retval; +} static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { @@ -5161,13 +5262,12 @@ static bool ui_but_menu(bContext *C, uiBut *but) } /* Show header tools for header buttons. */ - if (CTX_wm_region(C)) { + { ARegion *ar = CTX_wm_region(C); - if (ar->regiontype == RGN_TYPE_HEADER) { - - uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); - uiItemS(layout); - } + if (ar && (ar->regiontype == RGN_TYPE_HEADER)) { + uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); + uiItemS(layout); + } } { /* Docs */ @@ -5273,7 +5373,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * ui_but_anim_insert_keyframe(C); } - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(data->region); return WM_UI_HANDLER_BREAK; } @@ -5287,7 +5387,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * else ui_but_anim_add_driver(C); - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(data->region); return WM_UI_HANDLER_BREAK; } @@ -5301,17 +5401,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * else ui_but_anim_add_keyingset(C); - ED_region_tag_redraw(CTX_wm_region(C)); + ED_region_tag_redraw(data->region); return WM_UI_HANDLER_BREAK; } - /* reset to default */ - /* XXX hardcoded keymap check.... */ - else if (event->type == BACKSPACEKEY && event->val == KM_PRESS) { - /* ctrl+backspace = reset active button; backspace = reset a whole array*/ - if (!(ELEM3(but->type, HSVCIRCLE, HSVCUBE, HISTOGRAM))) - ui_set_but_default(C, !event->ctrl); - } /* handle menu */ else if (event->type == RIGHTMOUSE && event->val == KM_PRESS) { /* RMB has two options now */ @@ -5367,8 +5460,10 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case NUMSLI: retval = ui_do_but_SLI(C, block, but, data, event); break; - case ROUNDBOX: case LISTBOX: + retval = ui_do_but_LISTBOX(C, block, but, data, event); + break; + case ROUNDBOX: case LABEL: case LISTLABEL: case ROW: @@ -5436,7 +5531,22 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * case BUT_EXTRA: break; } - + + + /* reset to default (generic function, only use if not handled by switch above) */ + /* XXX hardcoded keymap check.... */ + if (data->state == BUTTON_STATE_HIGHLIGHT) { + if ((retval == WM_UI_HANDLER_CONTINUE) && + (event->type == BACKSPACEKEY && event->val == KM_PRESS)) + { + /* ctrl+backspace = reset active button; backspace = reset a whole array*/ + ui_set_but_default(C, !event->ctrl); + ED_region_tag_redraw(data->region); + retval = WM_UI_HANDLER_BREAK; + } + } + + return retval; } @@ -5622,8 +5732,6 @@ static uiBut *ui_list_find_mouse_over(ARegion *ar, int x, int y) uiBut *but; int mx, my; -// if (!win->active) -// return NULL; if (!ui_mouse_inside_region(ar, x, y)) return NULL; @@ -5768,7 +5876,7 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s WM_cursor_grab_disable(data->window, NULL); } #else - WM_cursor_grab_disable(data->window, ); + WM_cursor_grab_disable(data->window, NULL); #endif } } @@ -6423,90 +6531,166 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar) { - uiBut *but = ui_list_find_mouse_over(ar, event->x, event->y); + uiBut *but, *dragbut; + uiList *ui_list; + uiListDyn *dyn_data; int retval = WM_UI_HANDLER_CONTINUE; int type = event->type, val = event->val; + int mx, my; + bool is_over_dragbut = false; - if (but) { - uiList *ui_list = but->custom_data; + but = ui_list_find_mouse_over(ar, event->x, event->y); + if (!but) { + return retval; + } - if (ui_list) { - - /* convert pan to scrollwheel */ - if (type == MOUSEPAN) { - ui_pan_to_scroll(event, &type, &val); - - /* if type still is mousepan, we call it handled, since delta-y accumulate */ - /* also see wm_event_system.c do_wheel_ui hack */ - if (type == MOUSEPAN) - retval = WM_UI_HANDLER_BREAK; - } - - if (val == KM_PRESS) { - - if (ELEM(type, UPARROWKEY, DOWNARROWKEY) || - ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt))) - { - const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop); - int value, min, max; + ui_list = but->custom_data; + if (!ui_list || !ui_list->dyn_data) { + return retval; + } + dyn_data = ui_list->dyn_data; - /* activate up/down the list */ - value = value_orig; + mx = event->x; + my = event->y; + ui_window_to_block(ar, but->block, &mx, &my); - if (ELEM(type, UPARROWKEY, WHEELUPMOUSE)) - value--; - else - value++; + /* Find our "dragging" button. */ + for (dragbut = but->block->buttons.first; dragbut; dragbut = dragbut->next) { + if (dragbut->poin == (void *)ui_list) { + break; + } + } + if (dragbut && dragbut == ui_but_find_mouse_over(ar, event->x, event->y)) { + is_over_dragbut = true; + } - CLAMP(value, 0, ui_list->list_last_len - 1); + if (is_over_dragbut && type == LEFTMOUSE && val == KM_PRESS) { + uiHandleButtonData *data; + int *size = (int *)but->poin; - if (value < ui_list->list_scroll) - ui_list->list_scroll = value; - else if (value >= ui_list->list_scroll + ui_list->list_size) - ui_list->list_scroll = value - ui_list->list_size + 1; + ui_handle_button_activate(C, ar, but, BUTTON_ACTIVATE); + button_activate_state(C, but, BUTTON_STATE_INIT); + + data = but->active; + data->dragstarty = my; - RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max); - value = CLAMPIS(value, min, max); + button_activate_state(C, but, BUTTON_STATE_NUM_EDITING); - if (value != value_orig) { - RNA_property_int_set(&but->rnapoin, but->rnaprop, value); - RNA_property_update(C, &but->rnapoin, but->rnaprop); + /* Again, have to override values set by ui_numedit_begin, because our listbox button also has a rnapoin... */ + *size = data->origvalue = (double)dyn_data->visual_height; + ui_list->flag |= UILST_RESIZING; - ui_apply_undo(but); - ED_region_tag_redraw(ar); + retval = WM_UI_HANDLER_BREAK; + } + else { + /* convert pan to scrollwheel */ + if (type == MOUSEPAN) { + ui_pan_to_scroll(event, &type, &val); + + /* if type still is mousepan, we call it handled, since delta-y accumulate */ + /* also see wm_event_system.c do_wheel_ui hack */ + if (type == MOUSEPAN) + retval = WM_UI_HANDLER_BREAK; + } + + if (val == KM_PRESS) { + if (ELEM(type, UPARROWKEY, DOWNARROWKEY) || + ((ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt))) + { + const int value_orig = RNA_property_int_get(&but->rnapoin, but->rnaprop); + int value, min, max, inc; + + /* activate up/down the list */ + value = value_orig; + if ((ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0) { + inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? 1 : -1; + } + else { + inc = ELEM(type, UPARROWKEY, WHEELUPMOUSE) ? -1 : 1; + } + + if (dyn_data->items_filter_neworder || dyn_data->items_filter_flags) { + /* If we have a display order different from collection order, we have some work! */ + int *org_order = MEM_mallocN(dyn_data->items_shown * sizeof(int), AT); + int *new_order = dyn_data->items_filter_neworder; + int i, org_idx = -1, len = dyn_data->items_len; + int current_idx = -1; + int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; + + for (i = 0; i < len; i++) { + if (!dyn_data->items_filter_flags || + ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) + { + org_order[new_order ? new_order[++org_idx] : ++org_idx] = i; + if (i == value) { + current_idx = new_order ? new_order[org_idx] : org_idx; + } + } + else if (i == value && org_idx >= 0) { + current_idx = -(new_order ? new_order[org_idx] : org_idx) - 1; + } + } + /* Now, org_order maps displayed indices to real indices, + * and current_idx either contains the displayed index of active value (positive), + * or its more-nearest one (negated). + */ + if (current_idx < 0) { + current_idx = (current_idx * -1) + (inc < 0 ? inc : inc - 1); + } + else { + current_idx += inc; } + CLAMP(current_idx, 0, dyn_data->items_shown - 1); + value = org_order[current_idx]; + MEM_freeN(org_order); + } + else { + value += inc; + } - retval = WM_UI_HANDLER_BREAK; + CLAMP(value, 0, dyn_data->items_len - 1); + + RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max); + CLAMP(value, min, max); + + if (value != value_orig) { + RNA_property_int_set(&but->rnapoin, but->rnaprop, value); + RNA_property_update(C, &but->rnapoin, but->rnaprop); + + ui_apply_undo(but); + + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ED_region_tag_redraw(ar); } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) { - /* silly replacement for proper grip */ - if (ui_list->list_grip_size == 0) - ui_list->list_grip_size = ui_list->list_size; + retval = WM_UI_HANDLER_BREAK; + } + else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) { + /* We now have proper grip, but keep this anyway! */ + if (ui_list->list_grip == 0) + ui_list->list_grip = dyn_data->visual_height; + /* list template will clamp */ + if (type == WHEELUPMOUSE) + ui_list->list_grip--; + else + ui_list->list_grip++; + + ui_list->flag |= UILST_SCROLL_TO_ACTIVE_ITEM; + ED_region_tag_redraw(ar); + retval = WM_UI_HANDLER_BREAK; + } + else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { + if (dyn_data->height > dyn_data->visual_height) { + /* list template will clamp */ if (type == WHEELUPMOUSE) - ui_list->list_grip_size--; + ui_list->list_scroll--; else - ui_list->list_grip_size++; - - ui_list->list_grip_size = MAX2(ui_list->list_grip_size, 1); + ui_list->list_scroll++; ED_region_tag_redraw(ar); retval = WM_UI_HANDLER_BREAK; } - else if (ELEM(type, WHEELUPMOUSE, WHEELDOWNMOUSE)) { - if (ui_list->list_last_len > ui_list->list_size) { - /* list template will clamp */ - if (type == WHEELUPMOUSE) - ui_list->list_scroll--; - else - ui_list->list_scroll++; - - ED_region_tag_redraw(ar); - - retval = WM_UI_HANDLER_BREAK; - } - } } } } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index d2a8c47b347..0b02a1a5db4 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -393,7 +393,7 @@ extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str); extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value); extern int ui_get_but_string_max_length(uiBut *but); -extern void ui_set_but_default(struct bContext *C, short all); +extern void ui_set_but_default(struct bContext *C, const bool all); extern void ui_check_but(uiBut *but); extern bool ui_is_but_float(uiBut *but); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 079ba97aa9d..424d2231a03 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -471,6 +471,8 @@ static void ui_item_array(uiLayout *layout, uiBlock *block, const char *name, in but->type = NUMSLI; if (toggle && but->type == OPTION) but->type = TOG; + if ((a == 0) && (subtype == PROP_AXISANGLE)) + uiButSetUnitType(but, PROP_UNIT_ROTATION); } if (boolarr) { @@ -568,7 +570,7 @@ static uiBut *ui_item_with_label(uiLayout *layout, uiBlock *block, const char *n PropertySubType subtype; int labelw; - sub = uiLayoutRow(layout, FALSE); + sub = uiLayoutRow(layout, layout->align); uiBlockSetCurLayout(block, sub); if (name[0]) { @@ -1465,6 +1467,7 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna uiBlock *block; StructRNA *icontype; int w, h; + char namestr[UI_MAX_NAME_STR]; /* validate arguments */ prop = RNA_struct_find_property(ptr, propname); @@ -1507,6 +1510,8 @@ void uiItemPointerR(uiLayout *layout, struct PointerRNA *ptr, const char *propna if (!name) name = RNA_property_ui_name(prop); + name = ui_item_name_add_colon(name, namestr); + /* create button */ block = uiLayoutGetBlock(layout); @@ -2429,6 +2434,15 @@ uiLayout *uiLayoutListBox(uiLayout *layout, uiList *ui_list, PointerRNA *ptr, Pr but->rnapoin = *actptr; but->rnaprop = actprop; + /* Resizing data. */ + /* Note: we can't use usual "num button" value handling, as it only tries rnapoin when it is non-NULL... :/ + * So just setting but->poin, not but->pointype. + */ + but->poin = (void *)&ui_list->list_grip; + but->hardmin = but->softmin = 0.0f; + but->hardmax = but->softmax = 1000.0f; /* Should be more than enough! */ + but->a1 = 0.0f; + /* only for the undo string */ if (but->flag & UI_BUT_UNDO) { but->tip = RNA_property_description(actprop); @@ -2678,8 +2692,9 @@ static void ui_item_align(uiLayout *litem, short nr) BLI_remlink(&litem->root->block->buttons, box->roundbox); BLI_addhead(&litem->root->block->buttons, box->roundbox); } - else + else if (((uiLayout *)item)->align) { ui_item_align((uiLayout *)item, nr); + } } } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 95f47be0b70..832dd4d23ce 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2605,12 +2605,10 @@ static void confirm_cancel_operator(bContext *UNUSED(C), void *opv) WM_operator_free(opv); } -static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap) -#ifdef __GNUC__ -__attribute__ ((format(printf, 4, 0))) -#endif -; -static void vconfirm_opname(bContext *C, const char *opname, const char *title, const char *itemfmt, va_list ap) +static void vconfirm_opname(bContext *C, const char *opname, const char *title, + const char *itemfmt, va_list ap) ATTR_PRINTF_FORMAT(4, 0); +static void vconfirm_opname(bContext *C, const char *opname, const char *title, + const char *itemfmt, va_list ap) { uiPopupBlockHandle *handle; char *s, buf[512]; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 61cc021800e..4e79fd19f24 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1,4 +1,5 @@ /* + * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -43,6 +44,7 @@ #include "BLI_rect.h" #include "BLI_math.h" #include "BLI_listbase.h" +#include "BLI_fnmatch.h" #include "BLF_api.h" #include "BLF_translation.h" @@ -1017,6 +1019,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) Scene *scene = CTX_data_scene(C); Object *ob; ModifierData *md, *vmd; + VirtualModifierData virtualModifierData; int i, lastCageIndex, cageIndex; /* verify we have valid data */ @@ -1039,7 +1042,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0); /* XXX virtual modifiers are not accesible for python */ - vmd = modifiers_getVirtualModifierList(ob); + vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); for (i = 0; vmd; i++, vmd = vmd->next) { if (md == vmd) @@ -1145,9 +1148,10 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) uiBlockSetEmboss(block, UI_EMBOSSN); uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); uiBlockSetEmboss(block, UI_EMBOSS); - + /* name */ - uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco + 0.5f*UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f*UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, ""); + uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, + xco + 0.5f * UI_UNIT_X, yco, 5 * UI_UNIT_X, 0.9f * UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, ""); if (con->flag & CONSTRAINT_DISABLE) uiLayoutSetRedAlert(row, TRUE); @@ -2468,7 +2472,7 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout, struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon, struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname), - int UNUSED(index)) + int UNUSED(index), int UNUSED(flt_flag)) { char *namebuf; const char *name; @@ -2494,30 +2498,245 @@ static void uilist_draw_item_default(struct uiList *ui_list, struct bContext *UN } } +static void uilist_draw_filter_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct uiLayout *layout) +{ + PointerRNA listptr; + uiLayout *row, *subrow; + + RNA_pointer_create(NULL, &RNA_UIList, ui_list, &listptr); + + row = uiLayoutRow(layout, FALSE); + + subrow = uiLayoutRow(row, TRUE); + uiItemR(subrow, &listptr, "filter_name", 0, "", ICON_NONE); + uiItemR(subrow, &listptr, "use_filter_invert", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", + (ui_list->filter_flag & UILST_FLT_EXCLUDE) ? ICON_ZOOM_OUT : ICON_ZOOM_IN); + + subrow = uiLayoutRow(row, TRUE); + uiItemR(subrow, &listptr, "use_filter_sort_alpha", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", ICON_NONE); + uiItemR(subrow, &listptr, "use_filter_sort_reverse", UI_ITEM_R_TOGGLE | UI_ITEM_R_ICON_ONLY, "", + (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) ? ICON_TRIA_UP : ICON_TRIA_DOWN); +} + +typedef struct { + char name[MAX_IDPROP_NAME]; + int org_idx; +} StringCmp; + +static int cmpstringp(const void *p1, const void *p2) +{ + /* Case-insensitive comparison. */ + return BLI_strcasecmp(((StringCmp *) p1)->name, ((StringCmp *) p2)->name); +} + +static void uilist_filter_items_default(struct uiList *ui_list, struct bContext *UNUSED(C), struct PointerRNA *dataptr, + const char *propname) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + PropertyRNA *prop = RNA_struct_find_property(dataptr, propname); + + const char *filter_raw = ui_list->filter_byname; + char *filter = (char *)filter_raw, filter_buff[32], *filter_dyn = NULL; + bool filter_exclude = (ui_list->filter_flag & UILST_FLT_EXCLUDE) != 0; + bool order_by_name = (ui_list->filter_sort_flag & UILST_FLT_SORT_ALPHA) != 0; + int len = RNA_property_collection_length(dataptr, prop); + + dyn_data->items_shown = dyn_data->items_len = len; + + if (len && (order_by_name || filter_raw[0])) { + StringCmp *names = NULL; + int order_idx = 0, i = 0; + + if (order_by_name) { + names = MEM_callocN(sizeof(StringCmp) * len, AT); + } + if (filter_raw[0]) { + size_t idx = 0, slen = strlen(filter_raw); + + dyn_data->items_filter_flags = MEM_callocN(sizeof(int) * len, AT); + dyn_data->items_shown = 0; + + /* Implicitly add heading/trailing wildcards if needed. */ + if (len + 3 <= 32) { + filter = filter_buff; + } + else { + filter = filter_dyn = MEM_mallocN((slen + 3) * sizeof(char), AT); + } + if (filter_raw[idx] != '*') { + filter[idx++] = '*'; + } + memcpy(filter + idx, filter_raw, slen); + idx += slen; + if (filter[idx - 1] != '*') { + filter[idx++] = '*'; + } + filter[idx] = '\0'; + } + + RNA_PROP_BEGIN (dataptr, itemptr, prop) + { + char *namebuf; + const char *name; + bool do_order = false; + + namebuf = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); + name = namebuf ? namebuf : ""; + + if (filter[0]) { + /* Case-insensitive! */ + if (fnmatch(filter, name, FNM_CASEFOLD) == 0) { + dyn_data->items_filter_flags[i] = UILST_FLT_ITEM; + if (!filter_exclude) { + dyn_data->items_shown++; + do_order = order_by_name; + } + //printf("%s: '%s' matches '%s'\n", __func__, name, filter); + } + else if (filter_exclude) { + dyn_data->items_shown++; + do_order = order_by_name; + } + } + else { + do_order = order_by_name; + } + + if (do_order) { + names[order_idx].org_idx = order_idx; + BLI_strncpy(names[order_idx++].name, name, MAX_IDPROP_NAME); + } + + /* free name */ + if (namebuf) { + MEM_freeN(namebuf); + } + i++; + } + RNA_PROP_END; + + if (order_by_name) { + int new_idx; + /* note: order_idx equals either to ui_list->items_len if no filtering done, + * or to ui_list->items_shown if filter is enabled, + * or to (ui_list->items_len - ui_list->items_shown) if filtered items are excluded. + * This way, we only sort items we actually intend to draw! + */ + qsort(names, order_idx, sizeof(StringCmp), cmpstringp); + + dyn_data->items_filter_neworder = MEM_mallocN(sizeof(int) * order_idx, AT); + for (new_idx = 0; new_idx < order_idx; new_idx++) { + dyn_data->items_filter_neworder[names[new_idx].org_idx] = new_idx; + } + } + + if (filter_dyn) { + MEM_freeN(filter_dyn); + } + if (names) { + MEM_freeN(names); + } + } +} + +typedef struct { + PointerRNA item; + int org_idx; + int flt_flag; +} _uilist_item; + +typedef struct { + int visual_items; /* Visual number of items (i.e. number of items we have room to display). */ + int start_idx; /* Index of first item to display. */ + int end_idx; /* Index of last item to display + 1. */ +} uiListLayoutdata; + +static void prepare_list(uiList *ui_list, int len, int activei, int rows, int maxrows, int columns, + uiListLayoutdata *layoutdata) +{ + uiListDyn *dyn_data = ui_list->dyn_data; + int activei_row, max_scroll; + + /* default rows */ + if (rows == 0) + rows = 5; + dyn_data->visual_height_min = rows; + if (maxrows == 0) + maxrows = 5; + if (columns == 0) + columns = 9; + + if (ui_list->list_grip >= rows) { + maxrows = rows = ui_list->list_grip; + } + else { + ui_list->list_grip = 0; /* Reset to auto-size mode. */ + /* Prevent auto-size mode to take effect while grab-resizing! */ + if (ui_list->flag & UILST_RESIZING) { + maxrows = rows; + } + } + + if (columns > 1) { + dyn_data->height = (int)ceil((double)len / (double)columns); + activei_row = (int)floor((double)activei / (double)columns); + } + else { + dyn_data->height = len; + activei_row = activei; + } + + /* Expand size if needed and possible. */ + if ((ui_list->list_grip == 0) && (rows != maxrows) && (dyn_data->height > rows)) { + rows = min_ii(dyn_data->height, maxrows); + } + + /* If list length changes or list is tagged to check this, and active is out of view, scroll to it .*/ + if (ui_list->list_last_len != len || ui_list->flag & UILST_SCROLL_TO_ACTIVE_ITEM) { + if (activei_row < ui_list->list_scroll) { + ui_list->list_scroll = activei_row; + } + else if (activei_row >= ui_list->list_scroll + rows) { + ui_list->list_scroll = activei_row - rows + 1; + } + ui_list->flag &= ~UILST_SCROLL_TO_ACTIVE_ITEM; + } + + max_scroll = max_ii(0, dyn_data->height - rows); + CLAMP(ui_list->list_scroll, 0, max_scroll); + ui_list->list_last_len = len; + dyn_data->visual_height = rows; + layoutdata->visual_items = rows * columns; + layoutdata->start_idx = ui_list->list_scroll * columns; + layoutdata->end_idx = min_ii(layoutdata->start_idx + rows * columns, len); +} + void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id, PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr, - const char *active_propname, int rows, int maxrows, int layout_type) + const char *active_propname, int rows, int maxrows, int layout_type, int columns) { uiListType *ui_list_type; uiList *ui_list = NULL; + uiListDyn *dyn_data; ARegion *ar; uiListDrawItemFunc draw_item; + uiListDrawFilterFunc draw_filter; + uiListFilterItemsFunc filter_items; PropertyRNA *prop = NULL, *activeprop; PropertyType type, activetype; + _uilist_item *items_ptr = NULL; StructRNA *ptype; - uiLayout *box, *row, *col, *sub, *overlap; + uiLayout *glob = NULL, *box, *row, *col, *subrow, *sub, *overlap; uiBlock *block, *subblock; uiBut *but; + uiListLayoutdata layoutdata; char ui_list_id[UI_MAX_NAME_STR]; char numstr[32]; int rnaicon = ICON_NONE, icon = ICON_NONE; int i = 0, activei = 0; int len = 0; - int items; - int found; - int min, max; /* validate arguments */ /* Forbid default UI_UL_DEFAULT_CLASS_NAME list class without a custom list_id! */ @@ -2580,6 +2799,8 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co } draw_item = ui_list_type->draw_item ? ui_list_type->draw_item : uilist_draw_item_default; + draw_filter = ui_list_type->draw_filter ? ui_list_type->draw_filter : uilist_draw_filter_default; + filter_items = ui_list_type->filter_items ? ui_list_type->filter_items : uilist_filter_items_default; /* Find or add the uiList to the current Region. */ /* We tag the list id with the list type... */ @@ -2589,146 +2810,211 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co ui_list = BLI_findstring(&ar->ui_lists, ui_list_id, offsetof(uiList, list_id)); if (!ui_list) { - ui_list = MEM_callocN(sizeof(uiList), __func__); + ui_list = MEM_callocN(sizeof(uiList), AT); BLI_strncpy(ui_list->list_id, ui_list_id, sizeof(ui_list->list_id)); BLI_addtail(&ar->ui_lists, ui_list); } + if (!ui_list->dyn_data) { + ui_list->dyn_data = MEM_callocN(sizeof(uiListDyn), AT); + } + dyn_data = ui_list->dyn_data; + /* Because we can't actually pass type across save&load... */ ui_list->type = ui_list_type; ui_list->layout_type = layout_type; + /* Reset filtering data. */ + if (dyn_data->items_filter_flags) { + MEM_freeN(dyn_data->items_filter_flags); + dyn_data->items_filter_flags = NULL; + } + if (dyn_data->items_filter_neworder) { + MEM_freeN(dyn_data->items_filter_neworder); + dyn_data->items_filter_neworder = NULL; + } + dyn_data->items_len = dyn_data->items_shown = -1; + + /* Filter list items! (not for compact layout, though) */ + if (dataptr->data && prop) { + int filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; + bool order_reverse = (ui_list->filter_sort_flag & UILST_FLT_SORT_REVERSE) != 0; + int items_shown, idx = 0; +#if 0 + int prev_ii = -1, prev_i; +#endif + + if (layout_type == UILST_LAYOUT_COMPACT) { + dyn_data->items_len = dyn_data->items_shown = RNA_property_collection_length(dataptr, prop); + } + else { + //printf("%s: filtering...\n", __func__); + filter_items(ui_list, C, dataptr, propname); + //printf("%s: filtering done.\n", __func__); + } + + items_shown = dyn_data->items_shown; + if (items_shown >= 0) { + items_ptr = MEM_mallocN(sizeof(_uilist_item) * items_shown, AT); + //printf("%s: items shown: %d.\n", __func__, items_shown); + RNA_PROP_BEGIN (dataptr, itemptr, prop) + { + if (!dyn_data->items_filter_flags || + ((dyn_data->items_filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude)) + { + int ii; + if (dyn_data->items_filter_neworder) { + ii = dyn_data->items_filter_neworder[idx++]; + ii = order_reverse ? items_shown - ii - 1 : ii; + } + else { + ii = order_reverse ? items_shown - ++idx : idx++; + } + //printf("%s: ii: %d\n", __func__, ii); + items_ptr[ii].item = itemptr; + items_ptr[ii].org_idx = i; + items_ptr[ii].flt_flag = dyn_data->items_filter_flags ? dyn_data->items_filter_flags[i] : 0; + + if (activei == i) { + activei = ii; + } +# if 0 /* For now, do not alter active element, even if it will be hidden... */ + else if (activei < i) { + /* We do not want an active but invisible item! + * Only exception is when all items are filtered out... + */ + if (prev_ii >= 0) { + activei = prev_ii; + RNA_property_int_set(active_dataptr, activeprop, prev_i); + } + else { + activei = ii; + RNA_property_int_set(active_dataptr, activeprop, i); + } + } + prev_i = i; + prev_ii = ii; +#endif + } + i++; + } + RNA_PROP_END; + } + if (dyn_data->items_shown >= 0) { + len = dyn_data->items_shown; + } + else { + len = dyn_data->items_len; + } + } + switch (layout_type) { case UILST_LAYOUT_DEFAULT: - /* default rows */ - if (rows == 0) - rows = 5; - if (maxrows == 0) - maxrows = 5; - if (ui_list->list_grip_size != 0) - rows = ui_list->list_grip_size; - /* layout */ box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop); - row = uiLayoutRow(box, FALSE); + glob = uiLayoutColumn(box, TRUE); + row = uiLayoutRow(glob, FALSE); col = uiLayoutColumn(row, TRUE); /* init numbers */ - RNA_property_int_range(active_dataptr, activeprop, &min, &max); - - if (prop) - len = RNA_property_collection_length(dataptr, prop); - items = CLAMPIS(len, rows, MAX2(rows, maxrows)); - - /* if list length changes and active is out of view, scroll to it */ - if ((ui_list->list_last_len != len) && - (activei < ui_list->list_scroll || activei >= ui_list->list_scroll + items)) - { - ui_list->list_scroll = activei; - } - - ui_list->list_scroll = min_ii(ui_list->list_scroll, len - items); - ui_list->list_scroll = max_ii(ui_list->list_scroll, 0); - ui_list->list_size = items; - ui_list->list_last_len = len; + prepare_list(ui_list, len, activei, rows, maxrows, 1, &layoutdata); if (dataptr->data && prop) { /* create list items */ - RNA_PROP_BEGIN (dataptr, itemptr, prop) - { - if (i >= ui_list->list_scroll && i < ui_list->list_scroll + items) { - subblock = uiLayoutGetBlock(col); - overlap = uiLayoutOverlap(col); + for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) { + PointerRNA *itemptr = &items_ptr[i].item; + int org_i = items_ptr[i].org_idx; + int flt_flag = items_ptr[i].flt_flag; + subblock = uiLayoutGetBlock(col); + + overlap = uiLayoutOverlap(col); - uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM); + uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM); - /* list item behind label & other buttons */ - sub = uiLayoutRow(overlap, FALSE); + /* list item behind label & other buttons */ + sub = uiLayoutRow(overlap, FALSE); - but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, - active_dataptr, activeprop, 0, 0, i, 0, 0, NULL); - uiButSetFlag(but, UI_BUT_NO_TOOLTIP); + but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, + active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL); + uiButSetFlag(but, UI_BUT_NO_TOOLTIP); - sub = uiLayoutRow(overlap, FALSE); + sub = uiLayoutRow(overlap, FALSE); - icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false); - if (icon == ICON_DOT) - icon = ICON_NONE; - draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i); + icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false); + if (icon == ICON_DOT) + icon = ICON_NONE; + draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname, + org_i, flt_flag); - /* If we are "drawing" active item, set all labels as active. */ - if (i == activei) { - ui_layout_list_set_labels_active(sub); - } - uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM); + /* If we are "drawing" active item, set all labels as active. */ + if (i == activei) { + ui_layout_list_set_labels_active(sub); } - i++; + + uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM); } - RNA_PROP_END; } /* add dummy buttons to fill space */ - while (i < ui_list->list_scroll + items) { - if (i >= ui_list->list_scroll) - uiItemL(col, "", ICON_NONE); - i++; + for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) { + uiItemL(col, "", ICON_NONE); } /* add scrollbar */ - if (len > items) { + if (len > layoutdata.visual_items) { col = uiLayoutColumn(row, FALSE); - uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &ui_list->list_scroll, - 0, len - items, items, 0, ""); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, + &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, 0, ""); } break; case UILST_LAYOUT_COMPACT: row = uiLayoutRow(layout, TRUE); - if (dataptr->data && prop) { - /* create list items */ - RNA_PROP_BEGIN (dataptr, itemptr, prop) - { - found = (activei == i); - - if (found) { - icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false); - if (icon == ICON_DOT) - icon = ICON_NONE; - draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i); - } + if (dataptr->data && prop && dyn_data->items_shown > 0) { + PointerRNA *itemptr = &items_ptr[activei].item; + int org_i = items_ptr[activei].org_idx; - i++; - } - RNA_PROP_END; + icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false); + if (icon == ICON_DOT) + icon = ICON_NONE; + draw_item(ui_list, C, row, dataptr, itemptr, icon, active_dataptr, active_propname, org_i, 0); } - /* if list is empty, add in dummy button */ - if (i == 0) + else { uiItemL(row, "", ICON_NONE); + } /* next/prev button */ - BLI_snprintf(numstr, sizeof(numstr), "%d :", i); + BLI_snprintf(numstr, sizeof(numstr), "%d :", dyn_data->items_shown); but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, active_dataptr, activeprop, 0, 0, 0, 0, 0, ""); - if (i == 0) + if (dyn_data->items_shown == 0) uiButSetFlag(but, UI_BUT_DISABLED); break; case UILST_LAYOUT_GRID: box = uiLayoutListBox(layout, ui_list, dataptr, prop, active_dataptr, activeprop); - col = uiLayoutColumn(box, TRUE); - row = uiLayoutRow(col, FALSE); + glob = uiLayoutColumn(box, TRUE); + row = uiLayoutRow(glob, FALSE); + col = uiLayoutColumn(row, TRUE); + subrow = NULL; /* Quite gcc warning! */ + + prepare_list(ui_list, len, activei, rows, maxrows, columns, &layoutdata); if (dataptr->data && prop) { /* create list items */ - RNA_PROP_BEGIN (dataptr, itemptr, prop) - { + for (i = layoutdata.start_idx; i < layoutdata.end_idx; i++) { + PointerRNA *itemptr = &items_ptr[i].item; + int org_i = items_ptr[i].org_idx; + int flt_flag = items_ptr[i].flt_flag; + /* create button */ - if (!(i % 9)) - row = uiLayoutRow(col, FALSE); + if (!(i % columns)) + subrow = uiLayoutRow(col, FALSE); - subblock = uiLayoutGetBlock(row); - overlap = uiLayoutOverlap(row); + subblock = uiLayoutGetBlock(subrow); + overlap = uiLayoutOverlap(subrow); uiBlockSetFlag(subblock, UI_BLOCK_LIST_ITEM); @@ -2736,13 +3022,14 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co sub = uiLayoutRow(overlap, FALSE); but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, - active_dataptr, activeprop, 0, 0, i, 0, 0, NULL); + active_dataptr, activeprop, 0, 0, org_i, 0, 0, NULL); uiButSetFlag(but, UI_BUT_NO_TOOLTIP); sub = uiLayoutRow(overlap, FALSE); - icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false); - draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i); + icon = UI_rnaptr_icon_get(C, itemptr, rnaicon, false); + draw_item(ui_list, C, sub, dataptr, itemptr, icon, active_dataptr, active_propname, + org_i, flt_flag); /* If we are "drawing" active item, set all labels as active. */ if (i == activei) { @@ -2750,13 +3037,67 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co } uiBlockClearFlag(subblock, UI_BLOCK_LIST_ITEM); + } + } - i++; + /* add dummy buttons to fill space */ + for (; i < layoutdata.start_idx + layoutdata.visual_items; i++) { + if (!(i % columns)) { + subrow = uiLayoutRow(col, FALSE); } - RNA_PROP_END; + uiItemL(subrow, "", ICON_NONE); + } + + /* add scrollbar */ + if (len > layoutdata.visual_items) { + col = uiLayoutColumn(row, FALSE); + uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * dyn_data->visual_height, + &ui_list->list_scroll, 0, dyn_data->height - dyn_data->visual_height, + dyn_data->visual_height, 0, ""); } break; } + + if (glob) { + row = uiLayoutRow(glob, TRUE); + subblock = uiLayoutGetBlock(row); + uiBlockSetEmboss(subblock, UI_EMBOSSN); + + if (ui_list->filter_flag & UILST_FLT_SHOW) { + but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_DOWN, 0, 0, + UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0, + TIP_("Hide filtering options")); + uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list, + 0.0, 0.0, 0, -1, ""); + uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + uiBlockSetEmboss(subblock, UI_EMBOSS); + + col = uiLayoutColumn(glob, FALSE); + subblock = uiLayoutGetBlock(col); + uiDefBut(subblock, SEPR, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y * 0.05f, NULL, 0.0, 0.0, 0, 0, ""); + + draw_filter(ui_list, C, col); + } + else { + but = uiDefIconButBitI(subblock, TOG, UILST_FLT_SHOW, 0, ICON_DISCLOSURE_TRI_RIGHT, 0, 0, + UI_UNIT_X, UI_UNIT_Y * 0.6f, &(ui_list->filter_flag), 0, 0, 0, 0, + TIP_("Show filtering options")); + uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + but = uiDefIconBut(subblock, BUT, 0, ICON_GRIP, 0, 0, UI_UNIT_X * 10.0f, UI_UNIT_Y * 0.6f, ui_list, + 0.0, 0.0, 0, -1, ""); + uiButClearFlag(but, UI_BUT_UNDO); /* skip undo on screen buttons */ + + uiBlockSetEmboss(subblock, UI_EMBOSS); + } + } + + if (items_ptr) { + MEM_freeN(items_ptr); + } } /************************* Operator Search Template **************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 594d3e40dcd..b469dc994bc 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2850,6 +2850,16 @@ static void widget_optionbut(uiWidgetColors *wcol, rcti *rect, int state, int UN rect->xmin += BLI_rcti_size_y(rect) * 0.7 + delta; } +/* labels use Editor theme colors for text */ +static void widget_state_label(uiWidgetType *wt, int state) +{ + /* call this for option button */ + widget_state(wt, state); + if (state & UI_SELECT) + UI_GetThemeColor3ubv(TH_TEXT_HI, (unsigned char *)wt->wcol.text); + else + UI_GetThemeColor3ubv(TH_TEXT, (unsigned char *)wt->wcol.text); +} static void widget_radiobut(uiWidgetColors *wcol, rcti *rect, int UNUSED(state), int roundboxalign) { @@ -2970,9 +2980,12 @@ static uiWidgetType *widget_type(uiWidgetTypeEnum type) case UI_WTYPE_LISTLABEL: wt.wcol_theme = &btheme->tui.wcol_list_item; - /* fall-through */ /* we use usual label code too. */ + wt.draw = NULL; + /* Can't use usual label code. */ + break; case UI_WTYPE_LABEL: wt.draw = NULL; + wt.state = widget_state_label; break; case UI_WTYPE_TOGGLE: diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 1ef4d43c9f3..ace35f0276e 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -484,6 +484,14 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_STITCH_PREVIEW_ACTIVE: cp = ts->preview_stitch_active; break; + + case TH_UV_OTHERS: + cp = ts->uv_others; + break; + case TH_UV_SHADOW: + cp = ts->uv_shadow; + break; + case TH_MARKER_OUTLINE: cp = ts->marker_outline; break; case TH_MARKER: @@ -918,6 +926,9 @@ void ui_theme_init_default(void) rgba_char_args_set_fl(btheme->tima.preview_stitch_unstitchable, 1.0, 0.0, 0.0, 1.0); rgba_char_args_set_fl(btheme->tima.preview_stitch_active, 0.886, 0.824, 0.765, 0.140); + rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255); + rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255); + /* space text */ btheme->text = btheme->tv3d; rgba_char_args_set(btheme->text.back, 153, 153, 153, 255); @@ -2205,7 +2216,15 @@ void init_userdef_do_versions(void) } /* NOTE!! from now on use U.versionfile and U.subversionfile */ - + + if (U.versionfile < 269 || (U.versionfile == 268 && U.subversionfile < 3)) { + bTheme *btheme; + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_test_set(btheme->tima.uv_others, 96, 96, 96, 255); + rgba_char_args_test_set(btheme->tima.uv_shadow, 112, 112, 112, 255); + } + } + if (U.pixelsize == 0.0f) U.pixelsize = 1.0f; diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index f656d22fc64..037fa7c6a94 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -2029,6 +2029,17 @@ void UI_view2d_to_region_no_clip(View2D *v2d, float x, float y, int *regionx, in } } +void UI_view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony) +{ + /* express given coordinates as proportional values */ + x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur); + y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur); + + /* convert proportional distances to screen coordinates */ + *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask); + *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask); +} + /* *********************************************************************** */ /* Utilities */ diff --git a/source/blender/editors/interface/view2d_ops.c b/source/blender/editors/interface/view2d_ops.c index 929b7ae2a5d..3e9e16b285c 100644 --- a/source/blender/editors/interface/view2d_ops.c +++ b/source/blender/editors/interface/view2d_ops.c @@ -128,7 +128,7 @@ static int view_pan_init(bContext *C, wmOperator *op) } /* apply transform to view (i.e. adjust 'cur' rect) */ -static void view_pan_apply(wmOperator *op) +static void view_pan_apply(bContext *C, wmOperator *op) { v2dViewPanData *vpd = op->customdata; View2D *v2d = vpd->v2d; @@ -153,6 +153,7 @@ static void view_pan_apply(wmOperator *op) /* request updates to be done... */ ED_region_tag_redraw(vpd->ar); + WM_event_add_mousemove(C); UI_view2d_sync(vpd->sc, vpd->sa, v2d, V2D_LOCK_COPY); @@ -181,7 +182,7 @@ static int view_pan_exec(bContext *C, wmOperator *op) if (!view_pan_init(C, op)) return OPERATOR_CANCELLED; - view_pan_apply(op); + view_pan_apply(C, op); view_pan_exit(op); return OPERATOR_FINISHED; } @@ -209,7 +210,7 @@ static int view_pan_invoke(bContext *C, wmOperator *op, const wmEvent *event) RNA_int_set(op->ptr, "deltax", event->prevx - event->x); RNA_int_set(op->ptr, "deltay", event->prevy - event->y); - view_pan_apply(op); + view_pan_apply(C, op); view_pan_exit(op); return OPERATOR_FINISHED; } @@ -246,7 +247,7 @@ static int view_pan_modal(bContext *C, wmOperator *op, const wmEvent *event) vpd->lastx = event->x; vpd->lasty = event->y; - view_pan_apply(op); + view_pan_apply(C, op); break; } /* XXX - Mode switching isn't implemented. See comments in 36818. @@ -333,7 +334,7 @@ static int view_scrollright_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltay", 0); /* apply movement, then we're done */ - view_pan_apply(op); + view_pan_apply(C, op); view_pan_exit(op); return OPERATOR_FINISHED; @@ -377,7 +378,7 @@ static int view_scrollleft_exec(bContext *C, wmOperator *op) RNA_int_set(op->ptr, "deltay", 0); /* apply movement, then we're done */ - view_pan_apply(op); + view_pan_apply(C, op); view_pan_exit(op); return OPERATOR_FINISHED; @@ -425,7 +426,7 @@ static int view_scrolldown_exec(bContext *C, wmOperator *op) } /* apply movement, then we're done */ - view_pan_apply(op); + view_pan_apply(C, op); view_pan_exit(op); return OPERATOR_FINISHED; @@ -475,7 +476,7 @@ static int view_scrollup_exec(bContext *C, wmOperator *op) } /* apply movement, then we're done */ - view_pan_apply(op); + view_pan_apply(C, op); view_pan_exit(op); return OPERATOR_FINISHED; diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index a1bb7a8ae88..70fa97bebc1 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -106,6 +106,24 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "filepath", filepath); BLI_ensure_extension(filepath, sizeof(filepath), ".dae"); + + /* Avoid File write exceptions in Collada */ + if (!BLI_exists(filepath)) { + BLI_make_existing_file(filepath); + if (!BLI_file_touch(filepath)) { + BKE_report(op->reports, RPT_ERROR, "Can't create export file"); + fprintf(stdout, "Collada export: Can not create: %s\n", filepath); + return OPERATOR_CANCELLED; + } + } + else if (!BLI_file_is_writable(filepath)) { + BKE_report(op->reports, RPT_ERROR, "Can't overwrite export file"); + fprintf(stdout, "Collada export: Can not modify: %s\n", filepath); + return OPERATOR_CANCELLED; + } + + /* Now the exporter can create and write the export file */ + /* Options panel */ apply_modifiers = RNA_boolean_get(op->ptr, "apply_modifiers"); export_mesh_type = RNA_enum_get(op->ptr, "export_mesh_type_selection"); @@ -129,6 +147,8 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) /* get editmode results */ ED_object_editmode_load(CTX_data_edit_object(C)); + + if (collada_export(CTX_data_scene(C), filepath, apply_modifiers, diff --git a/source/blender/editors/mask/mask_add.c b/source/blender/editors/mask/mask_add.c index 9c270144a0a..4cc9d3b59b1 100644 --- a/source/blender/editors/mask/mask_add.c +++ b/source/blender/editors/mask/mask_add.c @@ -737,3 +737,159 @@ void MASK_OT_add_feather_vertex(wmOperatorType *ot) RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", "Location of vertex in normalized space", -1.0f, 1.0f); } + +/******************** common primitive functions *********************/ + +static int create_primitive_from_points(bContext *C, wmOperator *op, const float (*points)[2], + int num_points, char handle_type) +{ + ScrArea *sa = CTX_wm_area(C); + Scene *scene = CTX_data_scene(C); + Mask *mask; + MaskLayer *mask_layer; + MaskSpline *new_spline; + float scale, location[2], frame_size[2]; + int i, width, height; + int size = RNA_float_get(op->ptr, "size"); + + ED_mask_get_size(sa, &width, &height); + scale = (float)size / max_ii(width, height); + + /* Get location in mask space. */ + frame_size[0] = width; + frame_size[1] = height; + RNA_float_get_array(op->ptr, "location", location); + location[0] /= width; + location[1] /= height; + BKE_mask_coord_from_frame(location, location, frame_size); + + /* Make it so new primitive is centered to mouse location. */ + location[0] -= 0.5f * scale; + location[1] -= 0.5f * scale; + + mask_layer = ED_mask_layer_ensure(C); + mask = CTX_data_edit_mask(C); + + ED_mask_select_toggle_all(mask, SEL_DESELECT); + + new_spline = BKE_mask_spline_add(mask_layer); + new_spline->flag = MASK_SPLINE_CYCLIC | SELECT; + new_spline->tot_point = num_points; + new_spline->points = MEM_recallocN(new_spline->points, + sizeof(MaskSplinePoint) * new_spline->tot_point); + + mask_layer->act_spline = new_spline; + mask_layer->act_point = NULL; + + for (i = 0; i < num_points; i++) { + MaskSplinePoint *new_point = &new_spline->points[i]; + + copy_v2_v2(new_point->bezt.vec[1], points[i]); + mul_v2_fl(new_point->bezt.vec[1], scale); + add_v2_v2(new_point->bezt.vec[1], location); + + new_point->bezt.h1 = handle_type; + new_point->bezt.h2 = handle_type; + BKE_mask_point_select_set(new_point, true); + } + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + /* TODO: only update this spline */ + BKE_mask_update_display(mask, CFRA); + + return OPERATOR_FINISHED; +} + +static int primitive_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + ScrArea *sa = CTX_wm_area(C); + float cursor[2]; + int width, height; + + ED_mask_get_size(sa, &width, &height); + ED_mask_cursor_location_get(sa, cursor); + + cursor[0] *= width; + cursor[1] *= height; + + RNA_float_set_array(op->ptr, "location", cursor); + + return op->type->exec(C, op); +} + +static void define_prinitive_add_properties(wmOperatorType *ot) +{ + RNA_def_float(ot->srna, "size", 100, -FLT_MAX, FLT_MAX, + "Size", "Size of new circle", -FLT_MAX, FLT_MAX); + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, + "Location", "Location of new circle", -FLT_MAX, FLT_MAX); +} + +/******************** primitive add circle *********************/ + +static int primitive_circle_add_exec(bContext *C, wmOperator *op) +{ + const float points[4][2] = {{0.0f, 0.5f}, + {0.5f, 1.0f}, + {1.0f, 0.5f}, + {0.5f, 0.0f}}; + int num_points = sizeof(points) / (2 * sizeof(float)); + + create_primitive_from_points(C, op, points, num_points, HD_AUTO); + + return OPERATOR_FINISHED; +} + +void MASK_OT_primitive_circle_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Circle"; + ot->description = "Add new circle-shaped spline"; + ot->idname = "MASK_OT_primitive_circle_add"; + + /* api callbacks */ + ot->exec = primitive_circle_add_exec; + ot->invoke = primitive_add_invoke; + ot->poll = ED_operator_mask; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + define_prinitive_add_properties(ot); +} + +/******************** primitive add suqare *********************/ + +static int primitive_square_add_exec(bContext *C, wmOperator *op) +{ + const float points[4][2] = {{0.0f, 0.0f}, + {0.0f, 1.0f}, + {1.0f, 1.0f}, + {1.0f, 0.0f}}; + int num_points = sizeof(points) / (2 * sizeof(float)); + + create_primitive_from_points(C, op, points, num_points, HD_VECT); + + return OPERATOR_FINISHED; +} + +void MASK_OT_primitive_square_add(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add Square"; + ot->description = "Add new square-shaped spline"; + ot->idname = "MASK_OT_primitive_square_add"; + + /* api callbacks */ + ot->exec = primitive_square_add_exec; + ot->invoke = primitive_add_invoke; + ot->poll = ED_operator_mask; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + define_prinitive_add_properties(ot); +} diff --git a/source/blender/editors/mask/mask_edit.c b/source/blender/editors/mask/mask_edit.c index 9ae5b436fb3..62eb9cc240a 100644 --- a/source/blender/editors/mask/mask_edit.c +++ b/source/blender/editors/mask/mask_edit.c @@ -363,6 +363,40 @@ void ED_mask_pixelspace_factor(ScrArea *sa, ARegion *ar, float *scalex, float *s } } +void ED_mask_cursor_location_get(ScrArea *sa, float cursor[2]) +{ + if (sa) { + switch (sa->spacetype) { + case SPACE_CLIP: + { + SpaceClip *space_clip = sa->spacedata.first; + copy_v2_v2(cursor, space_clip->cursor); + break; + } + case SPACE_SEQ: + { + zero_v2(cursor); + break; + } + case SPACE_IMAGE: + { + SpaceImage *space_image = sa->spacedata.first; + copy_v2_v2(cursor, space_image->cursor); + break; + } + default: + /* possible other spaces from which mask editing is available */ + BLI_assert(0); + zero_v2(cursor); + break; + } + } + else { + BLI_assert(0); + zero_v2(cursor); + } +} + /********************** registration *********************/ void ED_operatortypes_mask(void) @@ -376,6 +410,8 @@ void ED_operatortypes_mask(void) /* add */ WM_operatortype_append(MASK_OT_add_vertex); WM_operatortype_append(MASK_OT_add_feather_vertex); + WM_operatortype_append(MASK_OT_primitive_circle_add); + WM_operatortype_append(MASK_OT_primitive_square_add); /* geometry */ WM_operatortype_append(MASK_OT_switch_direction); @@ -417,6 +453,9 @@ void ED_operatortypes_mask(void) /* layers */ WM_operatortype_append(MASK_OT_layer_move); + + /* duplicate */ + WM_operatortype_append(MASK_OT_duplicate); } void ED_keymap_mask(wmKeyConfig *keyconf) @@ -429,6 +468,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_new", NKEY, KM_PRESS, KM_ALT, 0); + /* add menu */ + WM_keymap_add_menu(keymap, "MASK_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0); + /* mask mode supports PET now */ ED_keymap_proportional_cycle(keyconf, keymap); ED_keymap_proportional_maskmode(keyconf, keymap); @@ -500,6 +542,9 @@ void ED_keymap_mask(wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "MASK_OT_shape_key_insert", IKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "MASK_OT_shape_key_clear", IKEY, KM_PRESS, KM_ALT, 0); + /* duplicate */ + WM_keymap_add_item(keymap, "MASK_OT_duplicate_move", DKEY, KM_PRESS, KM_SHIFT, 0); + /* for image editor only */ WM_keymap_add_item(keymap, "UV_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0); @@ -514,7 +559,6 @@ void ED_keymap_mask(wmKeyConfig *keyconf) void ED_operatormacros_mask(void) { - /* XXX: just for sample */ wmOperatorType *ot; wmOperatorTypeMacro *otmacro; @@ -531,4 +575,11 @@ void ED_operatormacros_mask(void) WM_operatortype_macro_define(ot, "MASK_OT_add_feather_vertex"); otmacro = WM_operatortype_macro_define(ot, "MASK_OT_slide_point"); RNA_boolean_set(otmacro->ptr, "slide_feather", TRUE); + + ot = WM_operatortype_append_macro("MASK_OT_duplicate_move", "Add Duplicate", "Duplicate mask and move", + OPTYPE_UNDO | OPTYPE_REGISTER); + WM_operatortype_macro_define(ot, "MASK_OT_duplicate"); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_enum_set(otmacro->ptr, "proportional", 0); + RNA_boolean_set(otmacro->ptr, "mirror", FALSE); } diff --git a/source/blender/editors/mask/mask_intern.h b/source/blender/editors/mask/mask_intern.h index bd148c48980..51705aa5837 100644 --- a/source/blender/editors/mask/mask_intern.h +++ b/source/blender/editors/mask/mask_intern.h @@ -42,9 +42,12 @@ struct wmOperatorType; /* mask_add.c */ void MASK_OT_add_vertex(struct wmOperatorType *ot); void MASK_OT_add_feather_vertex(struct wmOperatorType *ot); +void MASK_OT_primitive_circle_add(struct wmOperatorType *ot); +void MASK_OT_primitive_square_add(struct wmOperatorType *ot); /* mask_ops.c */ struct Mask *ED_mask_new(struct bContext *C, const char *name); +struct MaskLayer *ED_mask_layer_ensure(struct bContext *C); void MASK_OT_new(struct wmOperatorType *ot); void MASK_OT_layer_new(struct wmOperatorType *ot); @@ -75,6 +78,8 @@ struct MaskSplinePoint *ED_mask_point_find_nearest( void MASK_OT_layer_move(struct wmOperatorType *ot); +void MASK_OT_duplicate(struct wmOperatorType *ot); + /* mask_relationships.c */ void MASK_OT_parent_set(struct wmOperatorType *ot); void MASK_OT_parent_clear(struct wmOperatorType *ot); diff --git a/source/blender/editors/mask/mask_ops.c b/source/blender/editors/mask/mask_ops.c index c9d3bd19941..5ca0d133b0e 100644 --- a/source/blender/editors/mask/mask_ops.c +++ b/source/blender/editors/mask/mask_ops.c @@ -292,6 +292,26 @@ Mask *ED_mask_new(bContext *C, const char *name) return mask; } +/* Get ative layer. Will create mask/layer to be sure there's an active layer. */ +MaskLayer *ED_mask_layer_ensure(bContext *C) +{ + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *mask_layer; + + if (mask == NULL) { + /* If there's no active mask, create one. */ + mask = ED_mask_new(C, NULL); + } + + mask_layer = BKE_mask_layer_active(mask); + if (mask_layer == NULL) { + /* If there's no active mask layer, create one. */ + mask_layer = BKE_mask_layer_new(mask, ""); + } + + return mask_layer; +} + static int mask_new_exec(bContext *C, wmOperator *op) { char name[MAX_ID_NAME - 2]; @@ -1467,3 +1487,110 @@ void MASK_OT_layer_move(wmOperatorType *ot) /* properties */ RNA_def_enum(ot->srna, "direction", direction_items, 0, "Direction", "Direction to move the active layer"); } + +/******************** duplicate *********************/ + +static int mask_duplicate_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Scene *scene = CTX_data_scene(C); + Mask *mask = CTX_data_edit_mask(C); + MaskLayer *mask_layer = BKE_mask_layer_active(mask); + MaskSpline *spline; + + if (mask_layer == NULL) { + return OPERATOR_CANCELLED; + } + + for (spline = mask_layer->splines.last; + spline; + spline = spline->prev) + { + MaskSplinePoint *point = spline->points; + int i = 0; + while (i < spline->tot_point) { + int start = i, end = -1; + /* Find next selected segment. */ + while (MASKPOINT_ISSEL_ANY(point)) { + BKE_mask_point_select_set(point, false); + end = i; + if (i >= spline->tot_point - 1) { + break; + } + i++; + point++; + } + if (end >= start) { + MaskSpline *new_spline = BKE_mask_spline_add(mask_layer); + MaskSplinePoint *new_point; + int b; + + /* BKE_mask_spline_add might allocate the points, need to free them in this case. */ + if (new_spline->points) { + MEM_freeN(new_spline->points); + } + + /* Copy options from old spline. */ + new_spline->flag = spline->flag; + new_spline->offset_mode = spline->offset_mode; + new_spline->weight_interp = spline->weight_interp; + new_spline->parent = spline->parent; + + /* Allocate new points and copy them from old spline. */ + new_spline->tot_point = end - start + 1; + new_spline->points = MEM_mallocN(sizeof(MaskSplinePoint) * new_spline->tot_point, + "duplicated mask points"); + + memcpy(new_spline->points, spline->points + start, + new_spline->tot_point * sizeof(MaskSplinePoint)); + + /* Select points and duplicate their UWs (if needed). */ + for (b = 0, new_point = new_spline->points; + b < new_spline->tot_point; + b++, new_point++) + { + if (new_point->uw) { + new_point->uw = MEM_dupallocN(new_point->uw); + } + BKE_mask_point_select_set(new_point, true); + } + + /* Clear cyclic flag if we didn't copy the whole spline. */ + if (new_spline->flag & MASK_SPLINE_CYCLIC) { + if (start != 0 || end != spline->tot_point - 1) { + new_spline->flag &= ~MASK_SPLINE_CYCLIC; + } + } + + /* Flush selection to splines. */ + new_spline->flag |= SELECT; + spline->flag &= ~SELECT; + + mask_layer->act_spline = new_spline; + } + i++; + point++; + } + } + + /* TODO: only update edited splines */ + BKE_mask_update_display(mask, CFRA); + + WM_event_add_notifier(C, NC_MASK | NA_EDITED, mask); + + return OPERATOR_FINISHED; +} + +void MASK_OT_duplicate(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Duplicate Mask"; + ot->description = "Duplicate selected control points and segments between them"; + ot->idname = "MASK_OT_duplicate"; + + /* api callbacks */ + ot->exec = mask_duplicate_exec; + ot->poll = ED_maskedit_mask_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} diff --git a/source/blender/editors/mask/mask_relationships.c b/source/blender/editors/mask/mask_relationships.c index 6ced2423074..9cc1702addb 100644 --- a/source/blender/editors/mask/mask_relationships.c +++ b/source/blender/editors/mask/mask_relationships.c @@ -137,6 +137,7 @@ static int mask_parent_set_exec(bContext *C, wmOperator *UNUSED(op)) sub_parent_name = track->name; parent_type = MASK_PARENT_POINT_TRACK; + memset(orig_corners, 0, sizeof(orig_corners)); } else if ((plane_track = BKE_tracking_plane_track_get_active(tracking)) != NULL) { MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, framenr); diff --git a/source/blender/editors/mesh/CMakeLists.txt b/source/blender/editors/mesh/CMakeLists.txt index 69ef4715df6..8d91b300ff3 100644 --- a/source/blender/editors/mesh/CMakeLists.txt +++ b/source/blender/editors/mesh/CMakeLists.txt @@ -42,6 +42,7 @@ set(SRC editface.c editmesh_add.c editmesh_bevel.c + editmesh_bisect.c editmesh_extrude.c editmesh_inset.c editmesh_knife.c diff --git a/source/blender/editors/mesh/editmesh_bisect.c b/source/blender/editors/mesh/editmesh_bisect.c new file mode 100644 index 00000000000..5968e0991d1 --- /dev/null +++ b/source/blender/editors/mesh/editmesh_bisect.c @@ -0,0 +1,331 @@ +/* + * ***** 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 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/mesh/editmesh_bisect.c + * \ingroup edmesh + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" + +#include "BLI_math.h" + +#include "BKE_global.h" +#include "BKE_context.h" +#include "BKE_editmesh.h" + +#include "RNA_define.h" +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_view3d.h" + + +#include "mesh_intern.h" /* own include */ + +static int mesh_bisect_exec(bContext *C, wmOperator *op); + +/* -------------------------------------------------------------------- */ +/* Model Helpers */ + +typedef struct { + /* modal only */ + BMBackup mesh_backup; + bool is_first; + short twtype; +} BisectData; + +static bool mesh_bisect_interactive_calc( + bContext *C, wmOperator *op, + BMEditMesh *em, + float plane_co[3], float plane_no[3]) +{ + wmGesture *gesture = op->customdata; + BisectData *opdata; + + ARegion *ar = CTX_wm_region(C); + RegionView3D *rv3d = ar->regiondata; + + int x_start = RNA_int_get(op->ptr, "xstart"); + int y_start = RNA_int_get(op->ptr, "ystart"); + int x_end = RNA_int_get(op->ptr, "xend"); + int y_end = RNA_int_get(op->ptr, "yend"); + + /* reference location (some point infront of the view) for finding a point on a plane */ + const float *co_ref = rv3d->ofs; + float co_a_ss[2] = {x_start, y_start}, co_b_ss[2] = {x_end, y_end}, co_delta_ss[2]; + float co_a[3], co_b[3]; + const float zfac = ED_view3d_calc_zfac(rv3d, co_ref, NULL); + + opdata = gesture->userdata; + + /* view vector */ + ED_view3d_win_to_vector(ar, co_a_ss, co_a); + + /* view delta */ + sub_v2_v2v2(co_delta_ss, co_a_ss, co_b_ss); + ED_view3d_win_to_delta(ar, co_delta_ss, co_b, zfac); + + /* cross both to get a normal */ + cross_v3_v3v3(plane_no, co_a, co_b); + normalize_v3(plane_no); /* not needed but nicer for user */ + + /* point on plane, can use either start or endpoint */ + ED_view3d_win_to_3d(ar, co_ref, co_a_ss, plane_co); + + if (opdata->is_first == false) + EDBM_redo_state_restore(opdata->mesh_backup, em, false); + + opdata->is_first = false; + + return true; +} + +static int mesh_bisect_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + int ret; + + /* if the properties are set or there is no rv3d, + * skip model and exec immediately */ + + if ((CTX_wm_region_view3d(C) == NULL) || + (RNA_struct_property_is_set(op->ptr, "plane_co") && + RNA_struct_property_is_set(op->ptr, "plane_no"))) + { + return mesh_bisect_exec(C, op); + } + + ret = WM_gesture_straightline_invoke(C, op, event); + if (ret & OPERATOR_RUNNING_MODAL) { + View3D *v3d = CTX_wm_view3d(C); + + wmGesture *gesture = op->customdata; + BisectData *opdata; + + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + opdata = MEM_mallocN(sizeof(BisectData), "inset_operator_data"); + opdata->mesh_backup = EDBM_redo_state_store(em); + opdata->is_first = true; + gesture->userdata = opdata; + + /* misc other vars */ + G.moving = G_TRANSFORM_EDIT; + opdata->twtype = v3d->twtype; + v3d->twtype = 0; + } + return ret; +} + +static void edbm_bisect_exit(bContext *C, BisectData *opdata) +{ + View3D *v3d = CTX_wm_view3d(C); + EDBM_redo_state_free(&opdata->mesh_backup, NULL, false); + v3d->twtype = opdata->twtype; + G.moving = 0; +} + +static int mesh_bisect_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + wmGesture *gesture = op->customdata; + BisectData *opdata = gesture->userdata; + BisectData opdata_back = *opdata; /* annoyance, WM_gesture_straightline_modal, frees */ + int ret; + + ret = WM_gesture_straightline_modal(C, op, event); + + if (ret & (OPERATOR_FINISHED | OPERATOR_CANCELLED)) { + edbm_bisect_exit(C, &opdata_back); + } + + return ret; +} + +/* End Model Helpers */ +/* -------------------------------------------------------------------- */ + + + +static int mesh_bisect_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + + /* both can be NULL, fallbacks values are used */ + View3D *v3d = CTX_wm_view3d(C); + RegionView3D *rv3d = ED_view3d_context_rv3d(C); + + Object *obedit = CTX_data_edit_object(C); + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMesh *bm; + BMOperator bmop; + float plane_co[3]; + float plane_no[3]; + float imat[4][4]; + + const float thresh = RNA_float_get(op->ptr, "threshold"); + const bool use_fill = RNA_boolean_get(op->ptr, "use_fill"); + const bool clear_inner = RNA_boolean_get(op->ptr, "clear_inner"); + const bool clear_outer = RNA_boolean_get(op->ptr, "clear_outer"); + + PropertyRNA *prop_plane_co; + PropertyRNA *prop_plane_no; + + prop_plane_co = RNA_struct_find_property(op->ptr, "plane_co"); + if (RNA_property_is_set(op->ptr, prop_plane_co)) { + RNA_property_float_get_array(op->ptr, prop_plane_co, plane_co); + } + else { + copy_v3_v3(plane_co, give_cursor(scene, v3d)); + RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co); + } + + prop_plane_no = RNA_struct_find_property(op->ptr, "plane_no"); + if (RNA_property_is_set(op->ptr, prop_plane_no)) { + RNA_property_float_get_array(op->ptr, prop_plane_no, plane_no); + } + else { + if (rv3d) { + copy_v3_v3(plane_no, rv3d->viewinv[1]); + } + else { + /* fallback... */ + plane_no[0] = plane_no[1] = 0.0f; plane_no[2] = 1.0f; + } + RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no); + } + + + + /* -------------------------------------------------------------------- */ + /* Modal support */ + /* Note: keep this isolated, exec can work wihout this */ + if ((op->customdata != NULL) && + mesh_bisect_interactive_calc(C, op, em, plane_co, plane_no)) + { + /* write back to the props */ + RNA_property_float_set_array(op->ptr, prop_plane_no, plane_no); + RNA_property_float_set_array(op->ptr, prop_plane_co, plane_co); + } + /* End Modal */ + /* -------------------------------------------------------------------- */ + + + + bm = em->bm; + + invert_m4_m4(imat, obedit->obmat); + mul_m4_v3(imat, plane_co); + mul_mat3_m4_v3(imat, plane_no); + + EDBM_op_init(em, &bmop, op, + "bisect_plane geom=%hvef plane_co=%v plane_no=%v dist=%f clear_inner=%b clear_outer=%b", + BM_ELEM_SELECT, plane_co, plane_no, thresh, clear_inner, clear_outer); + BMO_op_exec(bm, &bmop); + + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + + if (use_fill) { + float normal_fill[3]; + BMOperator bmop_fill; + BMOperator bmop_attr; + + normalize_v3_v3(normal_fill, plane_no); + if (clear_outer == true && clear_inner == false) { + negate_v3(normal_fill); + } + + /* Fill */ + BMO_op_initf( + bm, &bmop_fill, op->flag, + "triangle_fill edges=%S normal=%v use_dissolve=%b", + &bmop, "geom_cut.out", normal_fill, true); + BMO_op_exec(bm, &bmop_fill); + + /* Copy Attributes */ + BMO_op_initf(bm, &bmop_attr, op->flag, + "face_attribute_fill faces=%S use_normals=%b use_data=%b", + &bmop_fill, "geom.out", false, true); + BMO_op_exec(bm, &bmop_attr); + + BMO_slot_buffer_hflag_enable(bm, bmop_fill.slots_out, "geom.out", BM_FACE, BM_ELEM_SELECT, true); + + BMO_op_finish(bm, &bmop_attr); + BMO_op_finish(bm, &bmop_fill); + } + + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom_cut.out", BM_VERT | BM_EDGE, BM_ELEM_SELECT, true); + + if (!EDBM_op_finish(em, &bmop, op, true)) { + return OPERATOR_CANCELLED; + } + else { + EDBM_update_generic(em, true, true); + EDBM_selectmode_flush(em); + return OPERATOR_FINISHED; + } +} + + +void MESH_OT_bisect(struct wmOperatorType *ot) +{ + PropertyRNA *prop; + + /* identifiers */ + ot->name = "Bisect"; + ot->description = "Enforce symmetry (both form and topological) across an axis"; + ot->idname = "MESH_OT_bisect"; + + /* api callbacks */ + ot->exec = mesh_bisect_exec; + ot->invoke = mesh_bisect_invoke; + ot->modal = mesh_bisect_modal; + ot->cancel = WM_gesture_straightline_cancel; + ot->poll = ED_operator_editmesh; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + + prop = RNA_def_float_vector(ot->srna, "plane_co", 3, NULL, -FLT_MAX, FLT_MAX, + "Plane Point", "A point on the plane", -FLT_MAX, FLT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_float_vector(ot->srna, "plane_no", 3, NULL, -FLT_MAX, FLT_MAX, + "Plane Normal", "The direction the plane points", -FLT_MAX, FLT_MAX); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_boolean(ot->srna, "use_fill", false, "Fill", "Fill in the cut"); + RNA_def_boolean(ot->srna, "clear_inner", false, "Clear Inner", "Remove geometry behind the plane"); + RNA_def_boolean(ot->srna, "clear_outer", false, "Clear Outer", "Remove geometry infront of the plane"); + + RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Axis Threshold", "", 0.00001, 0.1); + + WM_operator_properties_gesture_straightline(ot, CURSOR_EDIT); +} diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index dba19ee5da6..3966826a5b2 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -228,10 +228,8 @@ static bool edbm_inset_calc(wmOperator *op) BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true); } else { - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT | BM_EDGE, BM_ELEM_SELECT, false); - BMO_slot_buffer_hflag_disable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, false); - /* re-select faces so the verts and edges get selected too */ - BM_mesh_elem_hflag_enable_test(em->bm, BM_FACE, BM_ELEM_SELECT, true, BM_ELEM_SELECT); + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_in, "faces", BM_FACE, BM_ELEM_SELECT, true); } if (!EDBM_op_finish(em, &bmop, op, true)) { diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 2e73cbd02ed..cc3d486c2f3 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -499,10 +499,12 @@ static void knife_add_single_cut(KnifeTool_OpData *kcd) { KnifeEdge *kfe = new_knife_edge(kcd), *kfe2 = NULL, *kfe3 = NULL; - if (kcd->prev.vert && kcd->prev.vert == kcd->curr.vert) - return; - if (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge) + if ((kcd->prev.vert && kcd->prev.vert == kcd->curr.vert) || + (kcd->prev.edge && kcd->prev.edge == kcd->curr.edge)) + { + kcd->prev = kcd->curr; return; + } kfe->draw = true; @@ -573,10 +575,17 @@ static int verge_linehit(const void *vlh1, const void *vlh2) if (lh1->l < lh2->l) return -1; else if (lh1->l > lh2->l) return 1; + else if (lh1->v && lh2->v) { + /* want like verts to sort together; just compare pointers */ + if (lh1->v < lh2->v) return -1; + else if (lh1->v > lh2->v) return 1; + else return 0; + } else return 0; } /* If there's a linehit connected (same face) as testi in range [firsti, lasti], return the first such, else -1. + * It also counts as connected if both linehits are snapped to the same vertex. * If testi is out of range, look for connection to f instead, if f is non-NULL */ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, int firsti, int lasti) { @@ -589,6 +598,11 @@ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, i { return i; } + else if (kcd->linehits[testi].v && + kcd->linehits[testi].v == kcd->linehits[i].v) + { + return i; + } } else if (f) { if (find_ref(&kcd->linehits[i].kfe->faces, f)) @@ -598,13 +612,38 @@ static int find_connected_linehit(KnifeTool_OpData *kcd, int testi, BMFace *f, i return -1; } -/* Sort in order of distance along cut line, but take care when distances are equal */ -static void knife_sort_linehits(KnifeTool_OpData *kcd) +/* Sort in order of distance along cut line. + * Remove any successive linehits that are snapped to the same vertex. + * If joinfaces, treat hits at same distance as follows: try to find + * ordering so that preceding and succeeding hits will share a face. + */ +static void knife_sort_linehits(KnifeTool_OpData *kcd, bool joinfaces) { int i, j, k, nexti, nsame; qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); + /* Remove duplicated linehits snapped to same vertex */ + i = j = 0; /* loop copies from j to i */ + while (j < kcd->totlinehit) { + nsame = 0; + if (kcd->linehits[j].v) { + for (k = j + 1; k < kcd->totlinehit; k++) { + if (kcd->linehits[k].v != kcd->linehits[j].v) + break; + nsame++; + } + } + if (i != j) + kcd->linehits[i] = kcd->linehits[j]; + i++; + j += 1 + nsame; + } + kcd->totlinehit = i; + + if (!joinfaces) + return; + /* for ranges of equal "l", swap if neccesary to make predecessor and * successor faces connected to the linehits at either end of the range */ for (i = 0; i < kcd->totlinehit - 1; i = nexti) { @@ -653,6 +692,7 @@ static void knife_add_single_cut_through(KnifeTool_OpData *kcd, KnifeVert *v1, K knife_edge_append_face(kcd, kfenew, f); } +#if 0 static void knife_get_vert_faces(KnifeTool_OpData *kcd, KnifeVert *kfv, BMFace *facef, ListBase *lst) { BMIter bmiter; @@ -685,20 +725,33 @@ static void knife_get_edge_faces(KnifeTool_OpData *kcd, KnifeEdge *kfe, ListBase } } } +#endif + +static void copy_hit_from_posdata(BMEdgeHit *lh, KnifePosData *pos, float lambda) +{ + lh->kfe = pos->edge; + lh->v = pos->vert; + lh->f = pos->bmface; + copy_v3_v3(lh->hit, pos->co); + copy_v3_v3(lh->cagehit, pos->cage); + copy_v3_v3(lh->realhit, pos->co); + lh->l = lambda; + /* perc and schit not used by callers of this function */ +} /* BMESH_TODO: add more functionality to cut-through: * - cutting "in face" (e.g., holes) should cut in all faces, not just visible one * - perhaps improve O(n^2) algorithm used here */ static void knife_cut_through(KnifeTool_OpData *kcd) { - BMEdgeHit *lh, *lh2; + BMEdgeHit *lh, *lh2, *linehits; BMFace *f; - KnifeEdge *kfe, *kfe2, *kfe3; - KnifeVert *v1, *v2, *firstv = NULL, *lastv = NULL; - ListBase firstfaces = {NULL, NULL}, lastfaces = {NULL, NULL}; - Ref *r, *r2; + KnifeEdge *kfe, *kfe2; + KnifeVert *v1, *v2, *lastv; + ListBase *faces1, *faces2; KnifeEdge **splitkfe; - int i, j; + bool needprev, needcurr; + int i, j, n; if (!kcd->totlinehit) { /* if no linehits then no interesting back face stuff to do */ @@ -706,93 +759,68 @@ static void knife_cut_through(KnifeTool_OpData *kcd) return; } - /* TODO: probably don't need to sort at all */ - qsort(kcd->linehits, kcd->totlinehit, sizeof(BMEdgeHit), verge_linehit); - splitkfe = MEM_callocN(kcd->totlinehit * sizeof(KnifeEdge *), "knife_cut_through"); + /* sort eliminates hits on same vertices */ + knife_sort_linehits(kcd, false); - if (kcd->prev.vert) { - if (kcd->prev.vert == kcd->curr.vert) - return; - firstv = kcd->prev.vert; - knife_get_vert_faces(kcd, firstv, kcd->prev.bmface, &firstfaces); - } - else if (kcd->prev.edge) { - if (kcd->prev.edge == kcd->curr.edge) - return; - firstv = knife_split_edge(kcd, kcd->prev.edge, kcd->prev.co, &kfe3); - knife_get_edge_faces(kcd, kcd->prev.edge, &firstfaces); + /* code is cleaner if make prev and curr into hits (if they are on edges or verts) */ + n = kcd->totlinehit; + needprev = ((kcd->prev.vert && kcd->prev.vert != kcd->linehits[0].v) || kcd->prev.edge); + needcurr = ((kcd->curr.vert && kcd->curr.vert != kcd->linehits[n - 1].v) || kcd->curr.edge); + n += needprev + needcurr; + linehits = MEM_callocN(n * sizeof(BMEdgeHit), "knife_cut_through"); + i = 0; + if (needprev) { + copy_hit_from_posdata(&linehits[0], &kcd->prev, 0.0f); + i++; } + memcpy(linehits + i, kcd->linehits, kcd->totlinehit * sizeof(BMEdgeHit)); + i += kcd->totlinehit; + if (needcurr) + copy_hit_from_posdata(&linehits[i], &kcd->curr, 1.0f); - if (kcd->curr.vert) { - lastv = kcd->curr.vert; - knife_get_vert_faces(kcd, lastv, kcd->curr.bmface, &lastfaces); - } - else if (kcd->curr.edge) { - lastv = knife_split_edge(kcd, kcd->curr.edge, kcd->curr.co, &kfe3); - knife_get_edge_faces(kcd, kcd->curr.edge, &lastfaces); - } - - if (firstv) { - /* 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; - 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 = true; - break; - } - } - } - if (!found && lastv) { - for (r2 = lastfaces.first; r2; r2 = r2->next) { - if (r2->ref == f) { - knife_add_single_cut_through(kcd, firstv, lastv, f); - break; - } - } - } - } - } - for (i = 0, lh = kcd->linehits; i < kcd->totlinehit; i++, lh++) { + splitkfe = MEM_callocN(n * sizeof(KnifeEdge *), "knife_cut_through"); + + lastv = NULL; + for (i = 0, lh = linehits; i < n; i++, lh++) { kfe = lh->kfe; + v1 = NULL; - /* 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; - 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) { - if (r2->ref == f) { - 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 = true; - break; - } - } + /* get faces incident on hit lh */ + if (lh->v) { + v1 = lh->v; + faces1 = &v1->faces; + } + else if (kfe) { + faces1 = &kfe->faces; + } + + /* For each following hit, connect if lh1 an lh2 share a face */ + for (j = i + 1, lh2 = lh + 1; j < n; j++, lh2++) { + kfe2 = lh2->kfe; + v2 = NULL; + if (lh2->v) { + v2 = lh2->v; + faces2 = &v2->faces; } - if (!found && lastv) { - for (r2 = lastfaces.first; r2; r2 = r2->next) { - if (r2->ref == f) { - v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]); - knife_add_single_cut_through(kcd, v1, lastv, f); - break; - } - } + else if (kfe2) { + faces2 = &kfe2->faces; + } + + f = knife_find_common_face(faces1, faces2); + if (f) { + if (!v1) + v1 = splitkfe[i] ? kfe->v1 : knife_split_edge(kcd, kfe, lh->hit, &splitkfe[i]); + if (!v2) + v2 = splitkfe[j] ? kfe2->v1 : knife_split_edge(kcd, kfe2, lh2->hit, &splitkfe[j]); + knife_add_single_cut_through(kcd, v1, v2, f); + lastv = v2; } } } MEM_freeN(splitkfe); + MEM_freeN(linehits); MEM_freeN(kcd->linehits); kcd->linehits = NULL; kcd->totlinehit = 0; @@ -816,7 +844,7 @@ static void knife_add_cut(KnifeTool_OpData *kcd) BMEdgeHit *lh, *lastlh, *firstlh; int i; - knife_sort_linehits(kcd); + knife_sort_linehits(kcd, true); lh = kcd->linehits; lastlh = firstlh = NULL; @@ -848,14 +876,14 @@ static void knife_add_cut(KnifeTool_OpData *kcd) continue; /* first linehit may be down face parallel to view */ - if (!lastlh && fabsf(lh->l) < KNIFE_FLT_EPS) + if (!lastlh && !lh->v && fabsf(lh->l) < KNIFE_FLT_EPS) continue; if (kcd->prev.is_space) { kcd->prev.is_space = 0; copy_v3_v3(kcd->prev.co, lh->hit); copy_v3_v3(kcd->prev.cage, lh->cagehit); - kcd->prev.vert = NULL; + kcd->prev.vert = lh->v; kcd->prev.edge = lh->kfe; kcd->prev.bmface = lh->f; continue; @@ -1181,9 +1209,9 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, BLI_array_declare(edges); BVHTreeOverlap *results, *result; BMLoop **ls; - float cos[9], lambda; + float cos[9], tri_norm[3], tri_plane[4], isects[2][3], lambda; unsigned int tot = 0; - int i; + int i, j, n_isects; /* for comparing distances, error of intersection depends on triangle scale. * need to scale down before squaring for accurate comparison */ @@ -1194,6 +1222,9 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, copy_v3_v3(cos + 3, v2); copy_v3_v3(cos + 6, v3); + normal_tri_v3(tri_norm, v1, v2, v3); + plane_from_point_normal_v3(tri_plane, v1, tri_norm); + BLI_bvhtree_insert(tree2, 0, cos, 3); BLI_bvhtree_balance(tree2); @@ -1217,11 +1248,24 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, continue; /* We already found a hit on this knife edge */ } - if (isect_line_tri_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL)) { + n_isects = 0; + if (fabsf(dist_to_plane_v3(kfe->v1->cageco, tri_plane)) < KNIFE_FLT_EPS && + fabsf(dist_to_plane_v3(kfe->v2->cageco, tri_plane)) < KNIFE_FLT_EPS) + { + /* both kfe ends are in cutting triangle */ + copy_v3_v3(isects[0], kfe->v1->cageco); + copy_v3_v3(isects[1], kfe->v2->cageco); + n_isects = 2; + } + else if (isect_line_tri_epsilon_v3(kfe->v1->cageco, kfe->v2->cageco, v1, v2, v3, &lambda, NULL, depsilon)) { + /* kfe intersects cutting triangle lambda of the way along kfe */ + interp_v3_v3v3(isects[0], kfe->v1->cageco, kfe->v2->cageco, lambda); + n_isects = 1; + } + for (j = 0; j < n_isects; j++) { float p[3], no[3], view[3], sp[2]; - interp_v3_v3v3(p, kfe->v1->cageco, kfe->v2->cageco, lambda); - + copy_v3_v3(p, isects[j]); if (kcd->curr.vert && len_squared_v3v3(kcd->curr.vert->cageco, p) < depsilon_sq) { continue; } @@ -1268,7 +1312,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, add_v3_v3(p1, no); /* ray cast */ - f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, NULL, NULL, NULL); + f_hit = BKE_bmbvh_ray_cast(bmtree, p1, no, KNIFE_FLT_EPS, NULL, NULL, NULL); } /* ok, if visible add the new point */ @@ -1283,6 +1327,7 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, hit.kfe = kfe; hit.v = NULL; + hit.l = 0.0f; knife_find_basef(kfe); hit.f = kfe->basef; @@ -1292,7 +1337,6 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, interp_v3_v3v3(p, kfe->v1->co, kfe->v2->co, hit.perc); copy_v3_v3(hit.realhit, p); - /* BMESH_TODO: should also snap to vertices */ if (kcd->snap_midpoints) { float perc = hit.perc; @@ -1310,6 +1354,12 @@ static BMEdgeHit *knife_edge_tri_isect(KnifeTool_OpData *kcd, BMBVHTree *bmtree, interp_v3_v3v3(hit.hit, kfe->v1->co, kfe->v2->co, perc); interp_v3_v3v3(hit.cagehit, kfe->v1->cageco, kfe->v2->cageco, perc); } + else if (hit.perc < KNIFE_FLT_EPS || hit.perc > 1.0f - KNIFE_FLT_EPS) { + /* snap to vert */ + hit.v = (hit.perc < KNIFE_FLT_EPS) ? kfe->v1 : kfe->v2; + copy_v3_v3(hit.hit, hit.v->co); + copy_v3_v3(hit.cagehit, hit.v->co); + } else { copy_v3_v3(hit.hit, p); } @@ -1502,7 +1552,7 @@ static BMFace *knife_find_closest_face(KnifeTool_OpData *kcd, float co[3], float knife_input_ray_segment(kcd, kcd->curr.mval, 1.0f, origin, origin_ofs); sub_v3_v3v3(ray, origin_ofs, origin); - f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, NULL, co, cageco); + f = BKE_bmbvh_ray_cast(kcd->bmbvh, origin, ray, 0.0f, NULL, co, cageco); if (is_space) *is_space = !f; @@ -1652,7 +1702,7 @@ static KnifeEdge *knife_find_closest_edge(KnifeTool_OpData *kcd, float p[3], flo if (fptr) *fptr = f; - if (cure && p) { + if (cure) { if (!kcd->ignore_edge_snapping || !(cure->e)) { KnifeVert *edgesnap = NULL; @@ -1745,7 +1795,7 @@ static KnifeVert *knife_find_closest_vert(KnifeTool_OpData *kcd, float p[3], flo if (fptr) *fptr = f; - if (curv && p) { + if (curv) { copy_v3_v3(p, curv->co); copy_v3_v3(cagep, curv->cageco); @@ -1993,7 +2043,7 @@ static void knifenet_fill_faces(KnifeTool_OpData *kcd) for (kfv = BLI_mempool_iterstep(&iter); kfv; kfv = BLI_mempool_iterstep(&iter)) { if (!kfv->v) { /* shouldn't we be at least copying the normal? - if not some comment here should explain why - campbell */ - kfv->v = BM_vert_create(bm, kfv->co, NULL); + kfv->v = BM_vert_create(bm, kfv->co, NULL, BM_CREATE_NOP); kfv->flag = 1; BMO_elem_flag_enable(bm, kfv->v, DEL); } @@ -2683,7 +2733,7 @@ static void knife_make_chain_cut(KnifeTool_OpData *kcd, BMFace *f, ListBase *cha BM_edge_select_set(bm, l_new->e, true); } } - else { + else if (f_new) { BM_elem_select_copy(bm, bm, f_new, f); } diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index e7eaa625843..18db21a8726 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -52,6 +52,9 @@ #include "WM_types.h" +#include "bmesh.h" +#include "bmesh_tools.h" + #include "mesh_intern.h" /* own include */ struct UserData { diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index 1360a180b2d..84952297235 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -50,6 +50,9 @@ #include "ED_transform.h" #include "ED_view3d.h" +#include "bmesh.h" +#include "bmesh_tools.h" + #include "mesh_intern.h" /* own include */ /** @@ -60,23 +63,29 @@ * point and would result in the same distance. */ #define INSET_DEFAULT 0.00001f -static float edbm_rip_edgedist(ARegion *ar, float mat[4][4], - const float co1[3], const float co2[3], const float mvalf[2], - const float inset) +static float edbm_rip_edgedist_squared(ARegion *ar, float mat[4][4], + const float co1[3], const float co2[3], const float mvalf[2], + const float inset) { - float vec1[2], vec2[2]; + float vec1[2], vec2[2], dist_sq; ED_view3d_project_float_v2_m4(ar, co1, vec1, mat); ED_view3d_project_float_v2_m4(ar, co2, vec2, mat); if (inset != 0.0f) { - const float dist = inset / len_v2v2(vec1, vec2); - interp_v2_v2v2(vec1, vec1, vec2, dist); - interp_v2_v2v2(vec2, vec2, vec1, dist); + const float dist_2d = len_v2v2(vec1, vec2); + if (dist_2d > FLT_EPSILON) { + const float dist = inset / dist_2d; + BLI_assert(finite(dist)); + interp_v2_v2v2(vec1, vec1, vec2, dist); + interp_v2_v2v2(vec2, vec2, vec1, dist); + } } - /* TODO: use dist_squared_to_line_segment_v2() looks like we only ever use for comparison */ - return dist_to_line_segment_v2(mvalf, vec1, vec2); + dist_sq = dist_squared_to_line_segment_v2(mvalf, vec1, vec2); + BLI_assert(finite(dist_sq)); + + return dist_sq; } #if 0 @@ -488,7 +497,7 @@ static void edbm_tagged_loop_pairs_do_fill_faces(BMesh *bm, UnorderedLoopPair *u /* face should never exist */ BLI_assert(BM_face_exists(f_verts, f_verts[3] ? 4 : 3, &f) == false); - f = BM_face_create_quad_tri_v(bm, f_verts, f_verts[3] ? 4 : 3, f_example, false); + f = BM_face_create_verts(bm, f_verts, f_verts[3] ? 4 : 3, f_example, BM_CREATE_NOP, true); l_iter = BM_FACE_FIRST_LOOP(f); @@ -525,11 +534,11 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BMIter iter, liter; BMLoop *l; BMEdge *e, *e2; - BMVert *v, *ripvert = NULL; + BMVert *v; const int totvert_orig = bm->totvert; int i; float projectMat[4][4], fmval[3] = {event->mval[0], event->mval[1]}; - float dist = FLT_MAX; + float dist_sq = FLT_MAX; float d; bool is_wire; @@ -562,15 +571,15 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve if (v->e) { /* find closest edge to mouse cursor */ BM_ITER_ELEM (e, &iter, v, BM_EDGES_OF_VERT) { - int is_boundary = BM_edge_is_boundary(e); + const bool is_boundary = BM_edge_is_boundary(e); /* consider wire as boundary for this purpose, * otherwise we can't a face away from a wire edge */ totboundary_edge += (is_boundary != 0 || BM_edge_is_wire(e)); if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { if (is_boundary == false && BM_edge_is_manifold(e)) { - d = edbm_rip_edgedist(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); - if (d < dist) { - dist = d; + d = edbm_rip_edgedist_squared(ar, projectMat, e->v1->co, e->v2->co, fmval, INSET_DEFAULT); + if ((e2 == NULL) || (d < dist_sq)) { + dist_sq = d; e2 = e; } } @@ -596,10 +605,9 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve float l_mid_co[3]; l = l_all[i1]; edbm_calc_loop_co(l, l_mid_co); - d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT); - - if (d < dist) { - dist = d; + d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_mid_co, fmval, INSET_DEFAULT); + if ((e2 == NULL) || (d < dist_sq)) { + dist_sq = d; /* find the edge that is not in this loop */ e2 = NULL; @@ -647,7 +655,7 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BM_select_history_remove(bm, ese.ele); } - dist = FLT_MAX; + dist_sq = FLT_MAX; /* in the loop below we find the best vertex to drag based on its connected geometry, * either by its face corner, or connected edge (when no faces are attached) */ @@ -658,12 +666,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BM_ITER_ELEM (l, &iter, vout[i], BM_LOOPS_OF_VERT) { if (!BM_elem_flag_test(l->f, BM_ELEM_HIDDEN)) { float l_mid_co[3]; - edbm_calc_loop_co(l, l_mid_co); - d = edbm_rip_edgedist(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT); + edbm_calc_loop_co(l, l_mid_co); + d = edbm_rip_edgedist_squared(ar, projectMat, v->co, l_mid_co, fmval, INSET_DEFAULT); - if (d < dist) { - dist = d; + if (d < dist_sq) { + dist_sq = d; vi_best = i; } } @@ -674,12 +682,12 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BM_ITER_ELEM (e, &iter, vout[i], BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { float e_mid_co[3]; - mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co); - d = edbm_rip_edgedist(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT); + mid_v3_v3v3(e_mid_co, e->v1->co, e->v2->co); + d = edbm_rip_edgedist_squared(ar, projectMat, v->co, e_mid_co, fmval, INSET_DEFAULT); - if (d < dist) { - dist = d; + if (d < dist_sq) { + dist_sq = d; vi_best = i; } } @@ -730,19 +738,36 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve /* rip two adjacent edges */ if (BM_edge_is_boundary(e2) || BM_vert_face_count(v) == 2) { /* Don't run the edge split operator in this case */ + BMVert *v_rip; - BM_elem_flag_enable(e2, BM_ELEM_TAG); /* only for face-fill (we don't call the operator) */ + l = BM_edge_vert_share_loop(e2->l, v); + + /* only tag for face-fill (we don't call the operator) */ + if (BM_edge_is_boundary(e2)) { + BM_elem_flag_enable(e2, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(l->e, BM_ELEM_TAG); + BM_elem_flag_enable(l->prev->e, BM_ELEM_TAG); + } /* keep directly before edgesplit */ if (do_fill) { fill_uloop_pairs = edbm_tagged_loop_pairs_to_fill(bm); } - l = e2->l; - ripvert = BM_face_vert_separate(bm, l->f, v); +#if 0 + v_rip = BM_face_vert_separate(bm, l->f, v); +#else + v_rip = BM_face_loop_separate(bm, l); +#endif + + BLI_assert(v_rip); - BLI_assert(ripvert); - if (!ripvert) { + if (v_rip) { + BM_vert_select_set(bm, v_rip, true); + } + else { if (fill_uloop_pairs) MEM_freeN(fill_uloop_pairs); return OPERATOR_CANCELLED; } @@ -769,37 +794,28 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve BM_mesh_edgesplit(em->bm, true, true, true); } - dist = FLT_MAX; + dist_sq = FLT_MAX; { /* --- select which vert --- */ BMVert *v_best = NULL; - float l_prev_co[3], l_next_co[3], l_corner_co[3]; - float scale; + float l_corner_co[3]; - dist = FLT_MAX; + dist_sq = FLT_MAX; BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(v, BM_ELEM_SELECT)) { /* disable by default, re-enable winner at end */ BM_vert_select_set(bm, v, false); + BM_select_history_remove(bm, v); BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { - /* calculate a point in the face, rather then calculate the middle, - * make a vector pointing between the 2 edges attached to this loop */ - sub_v3_v3v3(l_prev_co, l->prev->v->co, l->v->co); - sub_v3_v3v3(l_next_co, l->next->v->co, l->v->co); - - scale = normalize_v3(l_prev_co) + normalize_v3(l_next_co); - mul_v3_fl(l_prev_co, scale); - mul_v3_fl(l_next_co, scale); - - add_v3_v3v3(l_corner_co, l_prev_co, l_next_co); - add_v3_v3(l_corner_co, l->v->co); - d = edbm_rip_edgedist(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT); - if (d < dist) { + /* check if v_best is null in the _rare_ case there are numeric issues */ + edbm_calc_loop_co(l, l_corner_co); + d = edbm_rip_edgedist_squared(ar, projectMat, l->v->co, l_corner_co, fmval, INSET_DEFAULT); + if ((v_best == NULL) || (d < dist_sq)) { v_best = v; - dist = d; + dist_sq = d; } } } @@ -965,7 +981,7 @@ static int edbm_rip_invoke(bContext *C, wmOperator *op, const wmEvent *event) BMesh *bm = em->bm; BMIter iter; BMEdge *e; - int singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0); + const bool singlesel = (bm->totvertsel == 1 && bm->totedgesel == 0 && bm->totfacesel == 0); int ret; /* running in face mode hardly makes sense, so convert to region loop and rip */ diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index f4a55af742c..806ae96cb61 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -2510,7 +2510,7 @@ static int edbm_select_nth_exec(bContext *C, wmOperator *op) int offset = RNA_int_get(op->ptr, "offset"); /* so input of offset zero ends up being (nth - 1) */ - offset = (offset + (nth - 1)) % nth; + offset = mod_i(offset, nth); if (edbm_deselect_nth(em, nth, offset) == false) { BKE_report(op->reports, RPT_ERROR, "Mesh has no active vert/edge/face"); @@ -2538,7 +2538,7 @@ void MESH_OT_select_nth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_int(ot->srna, "nth", 2, 2, INT_MAX, "Nth Selection", "", 2, 100); - RNA_def_int(ot->srna, "offset", 0, 0, INT_MAX, "Offset", "", 0, 100); + RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "", -100, 100); } void em_setup_viewcontext(bContext *C, ViewContext *vc) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 38ce56b4bc7..75ff5256e10 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -29,6 +29,8 @@ * \ingroup edmesh */ +#include <stddef.h> + #include "MEM_guardedalloc.h" #include "DNA_key_types.h" @@ -43,6 +45,7 @@ #include "BLI_noise.h" #include "BLI_math.h" #include "BLI_rand.h" +#include "BLI_sort_utils.h" #include "BKE_material.h" #include "BKE_context.h" @@ -892,14 +895,30 @@ static int edbm_duplicate_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_edit_object(C); BMEditMesh *em = BKE_editmesh_from_object(ob); + BMesh *bm = em->bm; BMOperator bmop; + ListBase bm_selected_store = {NULL, NULL}; + + /* de-select all would clear otherwise */ + SWAP(ListBase, bm->selected, bm_selected_store); EDBM_op_init(em, &bmop, op, "duplicate geom=%hvef", BM_ELEM_SELECT); - BMO_op_exec(em->bm, &bmop); + BMO_op_exec(bm, &bmop); EDBM_flag_disable_all(em, BM_ELEM_SELECT); - BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true); + BMO_slot_buffer_hflag_enable(bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true); + + /* rebuild editselection */ + bm->selected = bm_selected_store; + + if (bm->selected.first) { + BMOpSlot *slot_vert_map_out = BMO_slot_get(bmop.slots_out, "vert_map.out"); + BMOpSlot *slot_edge_map_out = BMO_slot_get(bmop.slots_out, "edge_map.out"); + BMOpSlot *slot_face_map_out = BMO_slot_get(bmop.slots_out, "face_map.out"); + + BMO_mesh_selected_remap(bm, slot_vert_map_out, slot_edge_map_out, slot_face_map_out); + } if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; @@ -2292,7 +2311,7 @@ static int edbm_knife_cut_exec(bContext *C, wmOperator *op) mouse_path = MEM_mallocN(len * sizeof(*mouse_path), __func__); /* get the cut curve */ - RNA_BEGIN(op->ptr, itemptr, "path") + RNA_BEGIN (op->ptr, itemptr, "path") { RNA_float_get_array(&itemptr, "loc", (float *)&mouse_path[len]); } @@ -2816,6 +2835,146 @@ void MESH_OT_fill(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_beauty", true, "Beauty", "Use best triangulation division"); } + +/* -------------------------------------------------------------------- */ +/* Grid Fill (and helper functions) */ + +static bool bm_edge_test_fill_grid_cb(BMEdge *e, void *UNUSED(bm_v)) +{ + return BM_elem_flag_test_bool(e, BM_ELEM_TAG); +} + +static float edbm_fill_grid_vert_tag_angle(BMVert *v) +{ + BMIter iter; + BMEdge *e_iter; + BMVert *v_pair[2]; + int i = 0; + BM_ITER_ELEM (e_iter, &iter, v, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(e_iter, BM_ELEM_TAG)) { + v_pair[i++] = BM_edge_other_vert(e_iter, v); + } + } + BLI_assert(i == 2); + + return fabsf((float)M_PI - angle_v3v3v3(v_pair[0]->co, v->co, v_pair[1]->co)); +} + +/** + * non-essential utility function to select 2 open edge loops from a closed loop. + */ +static void edbm_fill_grid_prepare(BMesh *bm, int offset, int *r_span, bool span_calc) +{ + BMEdge *e; + BMIter iter; + int count; + int span = *r_span; + + ListBase eloops = {NULL}; + struct BMEdgeLoopStore *el_store; + // LinkData *el_store; + + /* select -> tag */ + BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) { + BM_elem_flag_set(e, BM_ELEM_TAG, BM_elem_flag_test(e, BM_ELEM_SELECT)); + } + + count = BM_mesh_edgeloops_find(bm, &eloops, bm_edge_test_fill_grid_cb, bm); + el_store = eloops.first; + + if (count == 1 && BM_edgeloop_is_closed(el_store) && (BM_edgeloop_length_get(el_store) & 1) == 0) { + /* be clever! detect 2 edge loops from one closed edge loop */ + const int verts_len = BM_edgeloop_length_get(el_store); + ListBase *verts = BM_edgeloop_verts_get(el_store); + BMVert *v_act = BM_mesh_active_vert_get(bm); + LinkData *v_act_link; + BMEdge **edges = MEM_mallocN(sizeof(*edges) * verts_len, __func__); + int i; + + if (v_act && (v_act_link = BLI_findptr(verts, v_act, offsetof(LinkData, data)))) { + /* pass */ + } + else { + /* find the vertex with the best angle (a corner vertex) */ + LinkData *v_link, *v_link_best = NULL; + float angle_best = -1.0f; + for (v_link = verts->first; v_link; v_link = v_link->next) { + const float angle = edbm_fill_grid_vert_tag_angle(v_link->data); + if ((angle > angle_best) || (v_link_best == NULL)) { + angle_best = angle; + v_link_best = v_link; + } + } + + v_act_link = v_link_best; + v_act = v_act_link->data; + } + + if (offset != 0) { + v_act_link = BLI_findlink(verts, offset); + v_act = v_act_link->data; + } + + /* set this vertex first */ + BLI_rotatelist_first(verts, v_act_link); + BM_edgeloop_edges_get(el_store, edges); + + + if (span_calc) { + /* calculate the span by finding the next corner in 'verts' + * we dont know what defines a corner exactly so find the 4 verts + * in the loop with the greatest angle. + * Tag them and use the first tagged vertex to calcualte the span. + * + * note: we may have already checked 'edbm_fill_grid_vert_tag_angle()' on each + * vert, but advantage of de-duplicating is minimal. */ + struct SortPointerByFloat *ele_sort = MEM_mallocN(sizeof(*ele_sort) * verts_len, __func__); + LinkData *v_link; + for (v_link = verts->first, i = 0; v_link; v_link = v_link->next, i++) { + BMVert *v = v_link->data; + const float angle = edbm_fill_grid_vert_tag_angle(v); + ele_sort[i].sort_value = angle; + ele_sort[i].data = v; + + BM_elem_flag_disable(v, BM_ELEM_TAG); + } + + qsort(ele_sort, verts_len, sizeof(*ele_sort), BLI_sortutil_cmp_float_reverse); + + for (i = 0; i < 4; i++) { + BMVert *v = ele_sort[i].data; + BM_elem_flag_enable(v, BM_ELEM_TAG); + } + + /* now find the first... */ + for (v_link = verts->first, i = 0; i < verts_len / 2; v_link = v_link->next, i++) { + BMVert *v = v_link->data; + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + if (v != v_act) { + span = i; + break; + } + } + } + MEM_freeN(ele_sort); + } + /* end span calc */ + + + /* un-flag 'rails' */ + for (i = 0; i < span; i++) { + BM_elem_flag_disable(edges[i], BM_ELEM_TAG); + BM_elem_flag_disable(edges[(verts_len / 2) + i], BM_ELEM_TAG); + } + MEM_freeN(edges); + } + /* else let the bmesh-operator handle it */ + + BM_mesh_edgeloops_free(&eloops); + + *r_span = span; +} + static int edbm_fill_grid_exec(bContext *C, wmOperator *op) { BMOperator bmop; @@ -2824,10 +2983,43 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) const short use_smooth = edbm_add_edge_face__smooth_get(em->bm); const int totedge_orig = em->bm->totedge; const int totface_orig = em->bm->totface; + const bool use_prepare = true; + + + if (use_prepare) { + /* use when we have a single loop selected */ + PropertyRNA *prop_span = RNA_struct_find_property(op->ptr, "span"); + PropertyRNA *prop_offset = RNA_struct_find_property(op->ptr, "offset"); + bool calc_span; + + const int clamp = em->bm->totvertsel; + int span; + int offset; + + if (RNA_property_is_set(op->ptr, prop_span)) { + span = RNA_property_int_get(op->ptr, prop_span); + span = min_ii(span, (clamp / 2) - 1); + calc_span = false; + } + else { + span = clamp / 4; + calc_span = true; + } + + offset = RNA_property_int_get(op->ptr, prop_offset); + offset = mod_i(offset, clamp); + + /* in simple cases, move selection for tags, but also support more advanced cases */ + edbm_fill_grid_prepare(em->bm, offset, &span, calc_span); + + RNA_property_int_set(op->ptr, prop_span, span); + } + /* end tricky prepare code */ + if (!EDBM_op_init(em, &bmop, op, "grid_fill edges=%he mat_nr=%i use_smooth=%b", - BM_ELEM_SELECT, em->mat_nr, use_smooth)) + use_prepare ? BM_ELEM_TAG : BM_ELEM_SELECT, em->mat_nr, use_smooth)) { return OPERATOR_CANCELLED; } @@ -2855,6 +3047,8 @@ static int edbm_fill_grid_exec(bContext *C, wmOperator *op) void MESH_OT_fill_grid(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Grid Fill"; ot->description = "Fill grid from two loops"; @@ -2866,6 +3060,12 @@ void MESH_OT_fill_grid(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + prop = RNA_def_int(ot->srna, "span", 1, 1, INT_MAX, "Span", "Number of sides (zero disables)", 1, 100); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "offset", 0, INT_MIN, INT_MAX, "Offset", "Number of sides (zero disables)", -100, 100); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } static int edbm_fill_holes_exec(bContext *C, wmOperator *op) @@ -4441,10 +4641,17 @@ static int mesh_symmetrize_exec(bContext *C, wmOperator *op) BMEditMesh *em = BKE_editmesh_from_object(obedit); BMOperator bmop; - EDBM_op_init(em, &bmop, op, "symmetrize input=%hvef direction=%i", - BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction")); + const float thresh = RNA_float_get(op->ptr, "threshold"); + + EDBM_op_init(em, &bmop, op, + "symmetrize input=%hvef direction=%i dist=%f", + BM_ELEM_SELECT, RNA_enum_get(op->ptr, "direction"), thresh); BMO_op_exec(em->bm, &bmop); + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + + BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "geom.out", BM_ALL_NOLOOP, BM_ELEM_SELECT, true); + if (!EDBM_op_finish(em, &bmop, op, true)) { return OPERATOR_CANCELLED; } @@ -4472,6 +4679,7 @@ void MESH_OT_symmetrize(struct wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "direction", symmetrize_direction_items, BMO_SYMMETRIZE_NEGATIVE_X, "Direction", "Which sides to copy from and to"); + RNA_def_float(ot->srna, "threshold", 0.0001, 0.0, 10.0, "Threshold", "", 0.00001, 0.1); } static int mesh_symmetry_snap_exec(bContext *C, wmOperator *op) diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c index 46cab3b4416..a64a23a9f4a 100644 --- a/source/blender/editors/mesh/editmesh_utils.c +++ b/source/blender/editors/mesh/editmesh_utils.c @@ -1481,7 +1481,7 @@ int BMBVH_VertVisible(BMBVHTree *tree, BMEdge *e, RegionView3D *r3d) static BMFace *edge_ray_cast(struct BMBVHTree *tree, const float co[3], const float dir[3], float *r_hitout, BMEdge *e) { - BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, NULL, r_hitout, NULL); + BMFace *f = BKE_bmbvh_ray_cast(tree, co, dir, 0.0f, NULL, r_hitout, NULL); if (f && BM_edge_in_face(e, f)) return NULL; diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 1dcc0e64183..ed026258e4b 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -95,6 +95,8 @@ void MESH_OT_primitive_ico_sphere_add(struct wmOperatorType *ot); /* *** editmesh_bevel.c *** */ void MESH_OT_bevel(struct wmOperatorType *ot); +/* *** editmesh_bisect.c *** */ +void MESH_OT_bisect(struct wmOperatorType *ot); /* *** editmesh_extrude.c *** */ void MESH_OT_extrude_repeat(struct wmOperatorType *ot); diff --git a/source/blender/editors/mesh/mesh_navmesh.c b/source/blender/editors/mesh/mesh_navmesh.c index 66e577975b6..d889ed1bc74 100644 --- a/source/blender/editors/mesh/mesh_navmesh.c +++ b/source/blender/editors/mesh/mesh_navmesh.c @@ -350,7 +350,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, co[1] = bmin[1] + v[1] * ch; co[2] = bmin[2] + v[2] * cs; SWAP(float, co[1], co[2]); - BM_vert_create(em->bm, co, NULL, 0); + BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP); } /* create custom data layer to save polygon idx */ @@ -381,7 +381,7 @@ static Object *createRepresentation(bContext *C, struct recast_polyMesh *pmesh, for (j = nv; j < ndv; j++) { copy_v3_v3(co, &dverts[3 * (vbase + j)]); SWAP(float, co[1], co[2]); - BM_vert_create(em->bm, co, NULL, 0); + BM_vert_create(em->bm, co, NULL, BM_CREATE_NOP); } /* need to rebuild entirely because array size changes */ diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index b5352fb35f4..c98ad13acf6 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -175,6 +175,7 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_convex_hull); #endif + WM_operatortype_append(MESH_OT_bisect); WM_operatortype_append(MESH_OT_symmetrize); WM_operatortype_append(MESH_OT_symmetry_snap); diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c index d012a8ac656..ce1cacdfb3a 100644 --- a/source/blender/editors/mesh/meshtools.c +++ b/source/blender/editors/mesh/meshtools.c @@ -178,7 +178,6 @@ int join_mesh_exec(bContext *C, wmOperator *op) if (kb->data) MEM_freeN(kb->data); kb->data = MEM_callocN(sizeof(float) * 3 * totvert, "join_shapekey"); kb->totelem = totvert; - kb->weights = NULL; } } else if (haskey) { @@ -1136,7 +1135,7 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em) mesh_octree_table(ob, em, NULL, 'e'); - fhash = BLI_ghash_new(mirror_facehash, mirror_facecmp, "mirror_facehash gh"); + fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface); for (a = 0, mf = mface; a < me->totface; a++, mf++) BLI_ghash_insert(fhash, mf, mf); diff --git a/source/blender/editors/metaball/mball_edit.c b/source/blender/editors/metaball/mball_edit.c index de0af1d1bb8..b79eeee49d7 100644 --- a/source/blender/editors/metaball/mball_edit.c +++ b/source/blender/editors/metaball/mball_edit.c @@ -112,6 +112,8 @@ MetaElem *add_metaball_primitive(bContext *UNUSED(C), Object *obedit, float mat[ ml = BKE_mball_element_add(mball, type); ml->rad *= dia; + mball->wiresize *= dia; + mball->rendersize *= dia; copy_v3_v3(&ml->x, mat[3]); ml->flag |= SELECT; @@ -499,19 +501,13 @@ bool mouse_mball(bContext *C, const int mval[2], bool extend, bool deselect, boo /* free all MetaElems from ListBase */ static void freeMetaElemlist(ListBase *lb) { - MetaElem *ml, *next; + MetaElem *ml; if (lb == NULL) return; - ml = lb->first; - while (ml) { - next = ml->next; - BLI_remlink(lb, ml); + while ((ml = BLI_pophead(lb))) { MEM_freeN(ml); - ml = next; } - - lb->first = lb->last = NULL; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index ce61b4fce50..b907cba33e2 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1243,7 +1243,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, ob->parent = NULL; ob->constraints.first = ob->constraints.last = NULL; - ob->disp.first = ob->disp.last = NULL; + ob->curve_cache = NULL; ob->transflag &= ~OB_DUPLI; ob->lay = base->lay; @@ -1385,7 +1385,7 @@ static EnumPropertyItem convert_target_items[] = { static void curvetomesh(Scene *scene, Object *ob) { - if (ob->disp.first == NULL) + if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) BKE_displist_make_curveTypes(scene, ob, 0); /* force creation */ BKE_mesh_from_nurbs(ob); /* also does users */ @@ -1553,7 +1553,7 @@ static int convert_exec(bContext *C, wmOperator *op) cu = newob->data; - if (!newob->disp.first) + if ( !newob->curve_cache || !newob->curve_cache->disp.first) BKE_displist_make_curveTypes(scene, newob, 0); newob->type = OB_CURVE; @@ -1595,7 +1595,7 @@ static int convert_exec(bContext *C, wmOperator *op) curvetomesh(scene, newob); /* meshes doesn't use displist */ - BKE_displist_free(&newob->disp); + BKE_object_free_curve_cache(newob); } } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { @@ -1616,7 +1616,7 @@ static int convert_exec(bContext *C, wmOperator *op) newob = ob; /* meshes doesn't use displist */ - BKE_displist_free(&newob->disp); + BKE_object_free_curve_cache(newob); } curvetomesh(scene, newob); @@ -1635,7 +1635,7 @@ static int convert_exec(bContext *C, wmOperator *op) ob->flag |= OB_DONE; } - if (!baseob->disp.first) { + if (!baseob->curve_cache || !baseob->curve_cache->disp.first) { BKE_displist_make_mball(scene, baseob); } @@ -1658,7 +1658,7 @@ static int convert_exec(bContext *C, wmOperator *op) for (a = 0; a < newob->totcol; a++) id_us_plus((ID *)me->mat[a]); } - BKE_mesh_from_metaball(&baseob->disp, newob->data); + BKE_mesh_from_metaball(&baseob->curve_cache->disp, newob->data); if (obact->type == OB_MBALL) { basact = basen; diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 7f7a0777bbf..c69210e2450 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -79,6 +79,7 @@ #include "BKE_softbody.h" #include "BKE_modifier.h" #include "BKE_editmesh.h" +#include "BKE_report.h" #include "ED_armature.h" #include "ED_curve.h" @@ -556,11 +557,20 @@ void ED_object_editmode_enter(bContext *C, int flag) if (flag & EM_WAITCURSOR) waitcursor(0); } -static int editmode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +static int editmode_toggle_exec(bContext *C, wmOperator *op) { + const int mode_flag = OB_MODE_EDIT; + const bool is_mode_set = CTX_data_edit_object(C); ToolSettings *toolsettings = CTX_data_tool_settings(C); - if (!CTX_data_edit_object(C)) + if (!is_mode_set) { + Scene *scene = CTX_data_scene(C); + if (!ED_object_mode_compat_set(C, scene->basact->object, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } + } + + if (!is_mode_set) ED_object_editmode_enter(C, EM_WAITCURSOR); else ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */ @@ -582,10 +592,7 @@ static int editmode_toggle_poll(bContext *C) if ((ob->restrictflag & OB_RESTRICT_VIEW) && !(ob->mode & OB_MODE_EDIT)) return 0; - return (ob->type == OB_MESH || ob->type == OB_ARMATURE || - ob->type == OB_FONT || ob->type == OB_MBALL || - ob->type == OB_LATTICE || ob->type == OB_SURF || - ob->type == OB_CURVE); + return (ELEM7(ob->type, OB_MESH, OB_ARMATURE, OB_FONT, OB_MBALL, OB_LATTICE, OB_SURF, OB_CURVE)); } void OBJECT_OT_editmode_toggle(wmOperatorType *ot) @@ -598,7 +605,6 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) /* api callbacks */ ot->exec = editmode_toggle_exec; - ot->poll = editmode_toggle_poll; /* flags */ @@ -607,16 +613,25 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) /* *************************** */ -static int posemode_exec(bContext *C, wmOperator *UNUSED(op)) +static int posemode_exec(bContext *C, wmOperator *op) { Base *base = CTX_data_active_base(C); + Object *ob = base->object; + const int mode_flag = OB_MODE_POSE; + const bool is_mode_set = (ob->mode & mode_flag) != 0; - if (base->object->type == OB_ARMATURE) { - if (base->object == CTX_data_edit_object(C)) { + if (!is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } + } + + if (ob->type == OB_ARMATURE) { + if (ob == CTX_data_edit_object(C)) { ED_object_editmode_exit(C, EM_FREEDATA | EM_DO_UNDO); ED_armature_enter_posemode(C, base); } - else if (base->object->mode & OB_MODE_POSE) + else if (is_mode_set) ED_armature_exit_posemode(C, base); else ED_armature_enter_posemode(C, base); @@ -1417,8 +1432,9 @@ static void UNUSED_FUNCTION(image_aspect) (Scene *scene, View3D *v3d) space = size[0] / size[1]; } else if (ELEM3(ob->type, OB_CURVE, OB_FONT, OB_SURF)) { - Curve *cu = ob->data; - space = cu->size[0] / cu->size[1]; + float size[3]; + BKE_curve_texspace_get(ob->data, NULL, NULL, size); + space = size[0] / size[1]; } x = ibuf->x / space; @@ -1500,19 +1516,21 @@ static const char *object_mode_op_string(int mode) } /* checks the mode to be set is compatible with the object - * should be made into a generic function */ -static bool object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object *ob) + * should be made into a generic function + */ +static bool object_mode_compat_test(Object *ob, ObjectMode mode) { - ObjectMode mode = RNA_enum_get(op->ptr, "mode"); - if (ob) { if (mode == OB_MODE_OBJECT) return true; switch (ob->type) { case OB_MESH: - if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT)) + if (mode & (OB_MODE_EDIT | OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | + OB_MODE_TEXTURE_PAINT | OB_MODE_PARTICLE_EDIT)) + { return true; + } break; case OB_CURVE: case OB_SURF: @@ -1535,6 +1553,30 @@ static bool object_mode_set_compat(bContext *UNUSED(C), wmOperator *op, Object * return false; } +/** + * Sets the mode to a compatible state (use before entering the mode). + * + * This is so each mode's exec function can call + */ +bool ED_object_mode_compat_set(bContext *C, Object *ob, int mode, ReportList *reports) +{ + bool ok; + if (!ELEM(ob->mode, mode, OB_MODE_OBJECT)) { + const char *opstring = object_mode_op_string(ob->mode); + WM_operator_name_call(C, opstring, WM_OP_EXEC_REGION_WIN, NULL); + ok = ELEM(ob->mode, mode, OB_MODE_OBJECT); + if (!ok) { + wmOperatorType *ot = WM_operatortype_find(opstring, false); + BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name); + } + } + else { + ok = true; + } + + return ok; +} + static int object_mode_set_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); @@ -1542,25 +1584,31 @@ static int object_mode_set_exec(bContext *C, wmOperator *op) ObjectMode restore_mode = (ob) ? ob->mode : OB_MODE_OBJECT; int toggle = RNA_boolean_get(op->ptr, "toggle"); - if (!ob || !object_mode_set_compat(C, op, ob)) + if (!ob || !object_mode_compat_test(ob, mode)) return OPERATOR_PASS_THROUGH; - /* Exit current mode if it's not the mode we're setting */ - if (ob->mode != OB_MODE_OBJECT && ob->mode != mode) - WM_operator_name_call(C, object_mode_op_string(ob->mode), WM_OP_EXEC_REGION_WIN, NULL); + if (ob->mode != mode) { + /* we should be able to remove this call, each operator calls */ + ED_object_mode_compat_set(C, ob, mode, op->reports); + } - if (mode != OB_MODE_OBJECT) { + /* Exit current mode if it's not the mode we're setting */ + if (mode != OB_MODE_OBJECT && (ob->mode != mode || toggle)) { /* Enter new mode */ - if (ob->mode != mode || toggle) - WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL); - - if (toggle) { - if (ob->mode == mode) - /* For toggling, store old mode so we know what to go back to */ - ob->restore_mode = restore_mode; - else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) { - WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL); - } + WM_operator_name_call(C, object_mode_op_string(mode), WM_OP_EXEC_REGION_WIN, NULL); + } + + if (toggle) { + /* Special case for Object mode! */ + if (mode == OB_MODE_OBJECT && restore_mode == OB_MODE_OBJECT && ob->restore_mode != OB_MODE_OBJECT) { + WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL); + } + else if (ob->mode == mode) { + /* For toggling, store old mode so we know what to go back to */ + ob->restore_mode = restore_mode; + } + else if (ob->restore_mode != OB_MODE_OBJECT && ob->restore_mode != mode) { + WM_operator_name_call(C, object_mode_op_string(ob->restore_mode), WM_OP_EXEC_REGION_WIN, NULL); } } @@ -1569,6 +1617,8 @@ static int object_mode_set_exec(bContext *C, wmOperator *op) void OBJECT_OT_mode_set(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Set Object Mode"; ot->description = "Sets the object interaction mode"; @@ -1584,14 +1634,20 @@ void OBJECT_OT_mode_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "mode", object_mode_items, OB_MODE_OBJECT, "Mode", ""); RNA_def_enum_funcs(ot->prop, object_mode_set_itemsf); + RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); - RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", ""); + prop = RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", ""); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } void ED_object_toggle_modes(bContext *C, int mode) { + /* Couldn't we use object_mode_op_string() here? + * Also, if several bits are set in mode, several toggle ops will be called, is this expected? + * If so, would be nice to explain why. ;) --mont29 + */ if (mode & OB_MODE_SCULPT) WM_operator_name_call(C, "SCULPT_OT_sculptmode_toggle", WM_OP_EXEC_REGION_WIN, NULL); if (mode & OB_MODE_VERTEX_PAINT) diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 03d51fcbe82..0ba84e27420 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -637,9 +637,9 @@ static int modifier_apply_obdata(ReportList *reports, Scene *scene, Object *ob, cu = ob->data; BKE_report(reports, RPT_INFO, "Applied modifier only changed CV points, not tessellated/bevel vertices"); - vertexCos = BKE_curve_vertexCos_get(cu, &cu->nurb, &numVerts); + vertexCos = BKE_curve_nurbs_vertexCos_get(&cu->nurb, &numVerts); mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0); - BK_curve_vertexCos_apply(cu, &cu->nurb, vertexCos); + BK_curve_nurbs_vertexCos_apply(&cu->nurb, vertexCos); MEM_freeN(vertexCos); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 52f51cfcf48..be4948d8a80 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -55,6 +55,7 @@ #include "BLI_listbase.h" #include "BLI_linklist.h" #include "BLI_string.h" +#include "BLI_kdtree.h" #include "BLI_utildefines.h" #include "BLF_translation.h" @@ -584,12 +585,12 @@ EnumPropertyItem prop_make_parent_types[] = { {PAR_PATH_CONST, "PATH_CONST", 0, "Path Constraint", ""}, {PAR_LATTICE, "LATTICE", 0, "Lattice Deform", ""}, {PAR_VERTEX, "VERTEX", 0, "Vertex", ""}, - {PAR_TRIA, "TRIA", 0, "Triangle", ""}, + {PAR_VERTEX_TRI, "VERTEX_TRI", 0, "Vertex (Triangle)", ""}, {0, NULL, 0, NULL, NULL} }; int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object *ob, Object *par, - int partype, int xmirror, int keep_transform) + int partype, bool xmirror, bool keep_transform, const int vert_par[3]) { bPoseChannel *pchan = NULL; int pararm = ELEM4(partype, PAR_ARMATURE, PAR_ARMATURE_NAME, PAR_ARMATURE_ENVELOPE, PAR_ARMATURE_AUTO); @@ -718,8 +719,17 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object if (pchan->bone) pchan->bone->flag |= BONE_RELATIVE_PARENTING; } - else + else if (partype == PAR_VERTEX) { + ob->partype = PARVERT1; + ob->par1 = vert_par[0]; + } + else if (partype == PAR_VERTEX_TRI) { + ob->partype = PARVERT3; + copy_v3_v3_int(&ob->par1, vert_par); + } + else { ob->partype = PAROBJECT; /* note, dna define, not operator property */ + } /* constraint */ if (partype == PAR_PATH_CONST) { @@ -766,25 +776,83 @@ int ED_object_parent_set(ReportList *reports, Main *bmain, Scene *scene, Object return 1; } + + +static void parent_set_vert_find(KDTree *tree, Object *child, int vert_par[3], bool is_tri) +{ + const float *co_find = child->obmat[3]; + if (is_tri) { + KDTreeNearest nearest[3]; + int tot; + + tot = BLI_kdtree_find_nearest_n(tree, co_find, NULL, nearest, 3); + BLI_assert(tot == 3); + + vert_par[0] = nearest[0].index; + vert_par[1] = nearest[1].index; + vert_par[2] = nearest[2].index; + + BLI_assert(min_iii(UNPACK3(vert_par)) >= 0); + } + else { + vert_par[0] = BLI_kdtree_find_nearest(tree, co_find, NULL, NULL); + BLI_assert(vert_par[0] >= 0); + vert_par[1] = 0; + vert_par[2] = 0; + } +} + static int parent_set_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); Object *par = ED_object_active_context(C); int partype = RNA_enum_get(op->ptr, "type"); - int xmirror = RNA_boolean_get(op->ptr, "xmirror"); - int keep_transform = RNA_boolean_get(op->ptr, "keep_transform"); - int ok = 1; + bool xmirror = RNA_boolean_get(op->ptr, "xmirror"); + bool keep_transform = RNA_boolean_get(op->ptr, "keep_transform"); + bool ok = true; + + /* vertex parent (kdtree) */ + const bool is_vert_par = ELEM(partype, PAR_VERTEX, PAR_VERTEX_TRI); + const bool is_tri = partype == PAR_VERTEX_TRI; + int tree_tot; + struct KDTree *tree = NULL; + int vert_par[3] = {0, 0, 0}; + int *vert_par_p = is_vert_par ? vert_par : NULL; + + + if (is_vert_par) { + tree = BKE_object_as_kdtree(par, &tree_tot); + BLI_assert(tree != NULL); + + if (tree_tot < (is_tri ? 3 : 1)) { + BKE_report(op->reports, RPT_ERROR, "Not enough vertices for vertex-parent"); + ok = false; + goto cleanup; + } + } + + /* Non vertex-parent */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform)) { - ok = 0; + if (is_vert_par) { + parent_set_vert_find(tree, ob, vert_par, is_tri); + } + + if (!ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, xmirror, keep_transform, vert_par_p)) { + ok = false; break; } } CTX_DATA_END; + +cleanup: + if (is_vert_par) { + BLI_kdtree_free(tree); + } + if (!ok) return OPERATOR_CANCELLED; @@ -835,6 +903,12 @@ static int parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_LATTICE); } + /* vertex parenting */ + if (OB_TYPE_SUPPORT_PARVERT(ob->type)) { + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX); + uiItemEnumO_ptr(layout, ot, NULL, 0, "type", PAR_VERTEX_TRI); + } + uiPupMenuEnd(C, pup); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 366aa72f2b8..36ce72f1cab 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -562,6 +562,21 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo if (apply_scale) BKE_tracking_reconstruction_scale(&clip->tracking, ob->size); } + else if (ob->type == OB_EMPTY) { + /* It's possible for empties too, even though they don't + * really have obdata, since we can simply apply the maximum + * scaling to the empty's drawsize. + * + * Core Assumptions: + * 1) Most scaled empties have uniform scaling + * (i.e. for visibility reasons), AND/OR + * 2) Preserving non-uniform scaling is not that important, + * and is something that many users would be willing to + * sacrifice for having an easy way to do this. + */ + float max_scale = MAX3(ob->size[0], ob->size[1], ob->size[2]); + ob->empty_drawsize *= max_scale; + } else { continue; } @@ -589,8 +604,10 @@ static int apply_objects_internal(bContext *C, ReportList *reports, int apply_lo } CTX_DATA_END; - if (!change) + if (!change) { + BKE_report(reports, RPT_WARNING, "Objects have no data to transform"); return OPERATOR_CANCELLED; + } WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); return OPERATOR_FINISHED; @@ -768,7 +785,7 @@ static int object_origin_set_exec(bContext *C, wmOperator *op) } if (ctx_ob_act) { - BLI_rotatelist(&ctx_data_list, (LinkData *)ctx_ob_act); + BLI_rotatelist_first(&ctx_data_list, (LinkData *)ctx_ob_act); } for (tob = bmain->object.first; tob; tob = tob->id.next) { diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 294b0632015..b68fa150777 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -1561,9 +1561,12 @@ static void getVerticalAndHorizontalChange(const float norm[3], float d, const f /* A = Q - ((Q - P).N)N * D = (a * x0 + b * y0 +c * z0 + d) */ float projA[3], projB[3]; + float plane[4]; - closest_to_plane_v3(projA, coord, norm, start); - closest_to_plane_v3(projB, coord, norm, end); + plane_from_point_normal_v3(plane, coord, norm); + + closest_to_plane_v3(projA, plane, start); + closest_to_plane_v3(projB, plane, end); /* (vertical and horizontal refer to the plane's y and xz respectively) * vertical distance */ dists[index] = dot_v3v3(norm, end) + d; diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index d6bb394ff79..1a561efd217 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -69,6 +69,7 @@ #include "BIF_gl.h" #include "BIF_glutil.h" +#include "ED_object.h" #include "ED_physics.h" #include "ED_mesh.h" #include "ED_particle.h" @@ -2452,7 +2453,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) copy_v3_v3(co, point->keys->co); mul_m4_v3(mat, co); - totn= BLI_kdtree_find_n_nearest(tree, 10, co, NULL, nearest); + totn = BLI_kdtree_find_nearest_n(tree, co, NULL, nearest, 10); for (n=0; n<totn; n++) { /* this needs a custom threshold still */ @@ -3458,7 +3459,7 @@ static int brush_add(PEData *data, short number) float maxd, totw=0.0, weight[3]; psys_particle_on_dm(psmd->dm, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0); - maxw= BLI_kdtree_find_n_nearest(tree, 3, co1, NULL, ptn); + maxw = BLI_kdtree_find_nearest_n(tree, co1, NULL, ptn, 3); maxd= ptn[maxw-1].dist; @@ -4345,23 +4346,36 @@ static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, static int particle_edit_toggle_poll(bContext *C) { - Scene *scene= CTX_data_scene(C); - Object *ob= CTX_data_active_object(C); + Object *ob = CTX_data_active_object(C); - if (!scene || !ob || ob->id.lib) + if (ob == NULL || ob->type != OB_MESH) return 0; - - return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || modifiers_findByType(ob, eModifierType_Softbody)); + if (!ob->data || ((ID *)ob->data)->lib) + return 0; + if (CTX_data_edit_object(C)) + return 0; + + return (ob->particlesystem.first || + modifiers_findByType(ob, eModifierType_Cloth) || + modifiers_findByType(ob, eModifierType_Softbody)); } -static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +static int particle_edit_toggle_exec(bContext *C, wmOperator *op) { - Scene *scene= CTX_data_scene(C); - Object *ob= CTX_data_active_object(C); + Scene *scene = CTX_data_scene(C); + Object *ob = CTX_data_active_object(C); + const int mode_flag = OB_MODE_PARTICLE_EDIT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; + + if (!is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } + } - if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { + if (!is_mode_set) { PTCacheEdit *edit; - ob->mode |= OB_MODE_PARTICLE_EDIT; + ob->mode |= mode_flag; edit= PE_create_current(scene, ob); /* mesh may have changed since last entering editmode. @@ -4373,7 +4387,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *UNUSED(op)) WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL); } else { - ob->mode &= ~OB_MODE_PARTICLE_EDIT; + ob->mode &= ~mode_flag; toggle_particle_cursor(C, 0); WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 3a6bd05df0b..0d6e6fb5ac1 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -164,7 +164,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin, &scene->view_settings, &scene->display_settings, - rxmin, rymin, rxmin + xmax, rymin + ymax, TRUE); + rxmin, rymin, rxmin + xmax, rymin + ymax, true); } /* ****************************** render invoking ***************** */ @@ -270,6 +270,7 @@ typedef struct RenderJob { short anim, write_still; Image *image; ImageUser iuser; + bool image_outdated; short *stop; short *do_update; float *progress; @@ -409,9 +410,19 @@ static void image_rect_update(void *rjv, RenderResult *rr, volatile rcti *renrec void *lock; /* only update if we are displaying the slot being rendered */ - if (ima->render_slot != ima->last_render_slot) + if (ima->render_slot != ima->last_render_slot) { + rj->image_outdated = true; return; + } + else if (rj->image_outdated) { + /* update entire render */ + rj->image_outdated = false; + BKE_image_signal(ima, NULL, IMA_SIGNAL_COLORMANAGE); + *(rj->do_update) = TRUE; + return; + } + /* update part of render */ ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); if (ibuf) { image_buffer_rect_update(rj->scene, rr, ibuf, renrect); @@ -491,7 +502,9 @@ static void render_endjob(void *rjv) * engine API, so lets use simple and robust way for now * - sergey - */ - if (rj->scene->r.layers.first != rj->scene->r.layers.last) { + if (rj->scene->r.layers.first != rj->scene->r.layers.last || + rj->image_outdated) + { void *lock; Image *ima = rj->image; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); @@ -804,6 +817,11 @@ static bool render_view3d_get_rects(ARegion *ar, View3D *v3d, RegionView3D *rv3d return true; } +static bool render_view3d_is_valid(RenderPreview *rp) +{ + return (rp->rv3d->render_engine != NULL); +} + /* called by renderer, checks job value */ static int render_view3d_break(void *rpv) { @@ -813,8 +831,9 @@ static int render_view3d_break(void *rpv) return 1; /* during render, rv3d->engine can get freed */ - if (rp->rv3d->render_engine == NULL) + if (render_view3d_is_valid(rp) == false) { *rp->stop = 1; + } return *(rp->stop); } @@ -928,8 +947,11 @@ static void render_view3d_startjob(void *customdata, short *stop, short *do_upda RE_Database_Preprocess(re); /* conversion not completed, need to do it again */ - if (!rstats->convertdone) - rp->engine->job_update_flag |= PR_UPDATE_DATABASE; + if (!rstats->convertdone) { + if (render_view3d_is_valid(rp)) { + rp->engine->job_update_flag |= PR_UPDATE_DATABASE; + } + } // printf("dbase update\n"); } @@ -1116,7 +1138,7 @@ void render_view3d_draw(RenderEngine *engine, const bContext *C) /* Try using GLSL display transform. */ if (force_fallback == false) { - if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, TRUE)) { + if (IMB_colormanagement_setup_glsl_draw(NULL, &scene->display_settings, true, false)) { glEnable(GL_BLEND); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glaDrawPixelsTex(rres.xof, rres.yof, rres.rectx, rres.recty, GL_RGBA, GL_FLOAT, diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index e21e889d99d..57416a59aa1 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -591,7 +591,7 @@ static int screen_opengl_render_anim_step(bContext *C, wmOperator *op) ibuf_save = ibuf; if (is_movie || !BKE_imtype_requires_linear_float(scene->r.im_format.imtype)) { - ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, + ibuf_save = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings, &scene->display_settings, &scene->r.im_format); needs_free = TRUE; diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 4bd8a7d426a..2bf8a48edc4 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -587,6 +587,7 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r ID *parent = (ID *)parentp; MTex *slot = (MTex *)slotp; SpaceButs *sbuts = sa->spacedata.first; + ShaderPreview *sp = WM_jobs_customdata(wm, sa); rcti newrect; int ok; int newx = BLI_rcti_size_x(rect); @@ -608,9 +609,11 @@ void ED_preview_draw(const bContext *C, void *idp, void *parentp, void *slotp, r *rect = newrect; /* start a new preview render job if signalled through sbuts->preview, - * or if no render result was found and no preview render job is running */ + * if no render result was found and no preview render job is running, + * or if the job is running and the size of preview changed */ if ((sbuts->spacetype == SPACE_BUTS && sbuts->preview) || - (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW))) + (!ok && !WM_jobs_test(wm, sa, WM_JOB_TYPE_RENDER_PREVIEW)) || + (sp && (ABS(sp->sizex - newx) >= 2 || ABS(sp->sizey - newy) > 2))) { sbuts->preview = 0; ED_preview_shader_job(C, sa, id, parent, slot, newx, newy, PR_BUTS_RENDER); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index e805b3f30fc..7cbc8c9b277 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -1806,7 +1806,7 @@ void ED_region_header_init(ARegion *ar) /* UI_UNIT_Y is defined as U variable now, depending dpi */ int ED_area_headersize(void) { - return (int)(1.3f * UI_UNIT_Y); + return (int)(HEADERY * UI_DPI_FAC); } void ED_region_info_draw(ARegion *ar, const char *text, int block, float fill_color[4]) diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 723dce5e226..13befeceee9 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -1091,15 +1091,18 @@ void glaDrawImBuf_glsl(ImBuf *ibuf, float x, float y, int zoomfilter, if (ibuf->rect_float) { if (ibuf->float_colorspace) { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->float_colorspace, TRUE); + ibuf->float_colorspace, + true, false); } else { - ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, TRUE); + ok = IMB_colormanagement_setup_glsl_draw(view_settings, display_settings, + true, false); } } else { ok = IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - ibuf->rect_colorspace, FALSE); + ibuf->rect_colorspace, + false, false); } if (ok) { @@ -1178,7 +1181,7 @@ int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int ro GPU_offscreen_bind(ofs); - if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) { + if (!IMB_colormanagement_setup_transform_from_role_glsl(role, true)) { GPU_offscreen_unbind(ofs); GPU_offscreen_free(ofs); return FALSE; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 498762f1603..10c2ecd6fd9 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -327,10 +327,12 @@ static void screen_delarea(bContext *C, bScreen *sc, ScrArea *sa) static short testsplitpoint(ScrArea *sa, char dir, float fac) { short x, y; + const short area_min_x = AREAMINX; + const short area_min_y = ED_area_headersize(); // area big enough? - if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * AREAMINX)) return 0; - if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * AREAMINY)) return 0; + if (dir == 'v' && (sa->v4->vec.x - sa->v1->vec.x <= 2 * area_min_x)) return 0; + if (dir == 'h' && (sa->v2->vec.y - sa->v1->vec.y <= 2 * area_min_y)) return 0; // to be sure CLAMP(fac, 0.0f, 1.0f); @@ -338,10 +340,10 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac) if (dir == 'h') { y = sa->v1->vec.y + fac * (sa->v2->vec.y - sa->v1->vec.y); - if (y - sa->v1->vec.y < AREAMINY) - y = sa->v1->vec.y + AREAMINY; - else if (sa->v2->vec.y - y < AREAMINY) - y = sa->v2->vec.y - AREAMINY; + if (y - sa->v1->vec.y < area_min_y) + y = sa->v1->vec.y + area_min_y; + else if (sa->v2->vec.y - y < area_min_y) + y = sa->v2->vec.y - area_min_y; else y -= (y % AREAGRID); return y; @@ -349,10 +351,10 @@ static short testsplitpoint(ScrArea *sa, char dir, float fac) else { x = sa->v1->vec.x + fac * (sa->v4->vec.x - sa->v1->vec.x); - if (x - sa->v1->vec.x < AREAMINX) - x = sa->v1->vec.x + AREAMINX; - else if (sa->v4->vec.x - x < AREAMINX) - x = sa->v4->vec.x - AREAMINX; + if (x - sa->v1->vec.x < area_min_x) + x = sa->v1->vec.x + area_min_x; + else if (sa->v4->vec.x - x < area_min_x) + x = sa->v4->vec.x - area_min_x; else x -= (x % AREAGRID); return x; diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 3066b733fc5..a02bd1ea391 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -696,28 +696,39 @@ static int actionzone_invoke(bContext *C, wmOperator *op, const wmEvent *event) static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) { sActionzoneData *sad = op->customdata; - int deltax, deltay; - int mindelta = sad->az->type == AZONE_REGION ? 1 : 12; switch (event->type) { case MOUSEMOVE: + { + bool is_gesture; + + const int delta_x = (event->x - sad->x); + const int delta_y = (event->y - sad->y); + /* calculate gesture direction */ - deltax = (event->x - sad->x); - deltay = (event->y - sad->y); - - if (deltay > ABS(deltax)) + if (delta_y > ABS(delta_x)) sad->gesture_dir = 'n'; - else if (deltax > ABS(deltay)) + else if (delta_x > ABS(delta_y)) sad->gesture_dir = 'e'; - else if (deltay < -ABS(deltax)) + else if (delta_y < -ABS(delta_x)) sad->gesture_dir = 's'; else sad->gesture_dir = 'w'; + if (sad->az->type == AZONE_AREA) { + /* once we drag outside the actionzone, register a gesture + * check we're not on an edge so join finds the other area */ + is_gesture = ((is_in_area_actionzone(sad->sa1, &event->x) != sad->az) && + (screen_find_active_scredge(CTX_wm_screen(C), event->x, event->y) == NULL)); + } + else { + const int delta_min = 1; + is_gesture = (ABS(delta_x) > delta_min || ABS(delta_y) > delta_min); + } + /* gesture is large enough? */ - if (ABS(deltax) > mindelta || ABS(deltay) > mindelta) { - - /* second area, for join */ + if (is_gesture) { + /* second area, for join when (sa1 != sa2) */ sad->sa2 = screen_areahascursor(CTX_wm_screen(C), event->x, event->y); /* apply sends event */ actionzone_apply(C, op, sad->az->type); @@ -726,6 +737,7 @@ static int actionzone_modal(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_FINISHED; } break; + } case ESCKEY: actionzone_exit(op); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index db6380e920f..345db7a0ed0 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -71,18 +71,6 @@ #include <assert.h> -static int planes_contain_v3(float (*planes)[4], int totplane, const float p[3]) -{ - int i; - - for (i = 0; i < totplane; i++) { - if (dot_v3v3(planes[i], p) + planes[i][3] > 0) - return 0; - } - - return 1; -} - /* return true if the element should be hidden/shown */ static int is_effected(PartialVisArea area, float planes[4][4], @@ -95,7 +83,7 @@ static int is_effected(PartialVisArea area, return mask > 0.5f; } else { - int inside = planes_contain_v3(planes, 4, co); + bool inside = isect_point_planes_v3(planes, 4, co); return ((inside && area == PARTIALVIS_INSIDE) || (!inside && area == PARTIALVIS_OUTSIDE)); } @@ -235,20 +223,20 @@ static void partialvis_update_grids(Object *ob, } static void partialvis_update_bmesh_verts(BMesh *bm, - GHash *verts, - PartialVisAction action, - PartialVisArea area, - float planes[4][4], - int *any_changed, - int *any_visible) + GSet *verts, + PartialVisAction action, + PartialVisArea area, + float planes[4][4], + int *any_changed, + int *any_visible) { - GHashIterator gh_iter; + GSetIterator gs_iter; - GHASH_ITER (gh_iter, verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); float *vmask = CustomData_bmesh_get(&bm->vdata, - v->head.data, - CD_PAINT_MASK); + v->head.data, + CD_PAINT_MASK); /* hide vertex if in the hide volume */ if (is_effected(area, planes, v->co, *vmask)) { @@ -272,7 +260,7 @@ static void partialvis_update_bmesh(Object *ob, float planes[4][4]) { BMesh *bm; - GHash *unique, *other; + GSet *unique, *other; int any_changed = 0, any_visible = 0; bm = BKE_pbvh_get_bmesh(pbvh); diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index fcf00d4ab2c..feff02fa121 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -82,6 +82,7 @@ #include "UI_view2d.h" #include "ED_image.h" +#include "ED_object.h" #include "ED_screen.h" #include "ED_sculpt.h" #include "ED_uvedit.h" @@ -1006,9 +1007,12 @@ void PAINT_OT_sample_color(wmOperatorType *ot) static int texture_paint_toggle_poll(bContext *C) { - if (CTX_data_edit_object(C)) + Object *ob = CTX_data_active_object(C); + if (ob == NULL || ob->type != OB_MESH) return 0; - if (CTX_data_active_object(C) == NULL) + if (!ob->data || ((ID *)ob->data)->lib) + return 0; + if (CTX_data_edit_object(C)) return 0; return 1; @@ -1018,25 +1022,20 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - Mesh *me = NULL; - - if (ob == NULL) - return OPERATOR_CANCELLED; - - if (BKE_object_obdata_is_libdata(ob)) { - BKE_report(op->reports, RPT_ERROR, "Cannot edit external libdata"); - return OPERATOR_CANCELLED; + const int mode_flag = OB_MODE_TEXTURE_PAINT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; + Mesh *me; + + if (!is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } } me = BKE_mesh_from_object(ob); - if (!(ob->mode & OB_MODE_TEXTURE_PAINT) && !me) { - BKE_report(op->reports, RPT_ERROR, "Can only enter texture paint mode for mesh objects"); - return OPERATOR_CANCELLED; - } - - if (ob->mode & OB_MODE_TEXTURE_PAINT) { - ob->mode &= ~OB_MODE_TEXTURE_PAINT; + if (ob->mode & mode_flag) { + ob->mode &= ~mode_flag; if (U.glreslimit != 0) GPU_free_images(); @@ -1045,7 +1044,7 @@ static int texture_paint_toggle_exec(bContext *C, wmOperator *op) toggle_paint_cursor(C, 0); } else { - ob->mode |= OB_MODE_TEXTURE_PAINT; + ob->mode |= mode_flag; if (me->mtface == NULL) me->mtface = CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index db55dc271f1..dfada683dda 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -3883,7 +3883,7 @@ static void *do_projectpaint_thread(void *ph_v) float mask = ((float)projPixel->mask) * (1.0f / 65535.0f); straight_uchar_to_premul_float(newColor_f, projPixel->newColor.ch); - IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, TRUE, ps->reproject_ibuf->rect_colorspace); + IMB_colormanagement_colorspace_to_scene_linear_v4(newColor_f, true, ps->reproject_ibuf->rect_colorspace); mul_v4_v4fl(newColor_f, newColor_f, mask); blend_color_mix_float(projPixel->pixel.f_pt, projPixel->origColor.f, @@ -4279,9 +4279,6 @@ void *paint_proj_new_stroke(bContext *C, Object *ob, const float mouse[2], int m 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; diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index bdf542526ee..0b0607babc1 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -1011,7 +1011,8 @@ typedef enum { RC_COLOR = 1, RC_ROTATION = 2, RC_ZOOM = 4, - RC_WEIGHT = 8 + RC_WEIGHT = 8, + RC_SECONDARY_ROTATION = 16 } RCFlags; static void set_brush_rc_path(PointerRNA *ptr, const char *brush_path, @@ -1043,7 +1044,10 @@ static void set_brush_rc_props(PointerRNA *ptr, const char *paint, RNA_string_set(ptr, "data_path_secondary", ""); } set_brush_rc_path(ptr, brush_path, "color_path", "cursor_color_add"); - set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle"); + if (flags & RC_SECONDARY_ROTATION) + set_brush_rc_path(ptr, brush_path, "rotation_path", "mask_texture_slot.angle"); + else + set_brush_rc_path(ptr, brush_path, "rotation_path", "texture_slot.angle"); RNA_string_set(ptr, "image_id", brush_path); if (flags & RC_COLOR) @@ -1055,6 +1059,11 @@ static void set_brush_rc_props(PointerRNA *ptr, const char *paint, else RNA_string_set(ptr, "zoom_path", ""); + if (flags & RC_SECONDARY_ROTATION) + RNA_boolean_set(ptr, "secondary_tex", true); + else + RNA_boolean_set(ptr, "secondary_tex", false); + MEM_freeN(brush_path); } @@ -1064,6 +1073,7 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p wmKeyMapItem *kmi; /* only size needs to follow zoom, strength shows fixed size circle */ int flags_nozoom = flags & (~RC_ZOOM); + int flags_noradial_secondary = flags & (~(RC_SECONDARY_ROTATION | RC_ZOOM)); kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, 0, 0); set_brush_rc_props(kmi->ptr, paint, "size", "use_unified_size", flags); @@ -1078,7 +1088,12 @@ static void ed_keymap_paint_brush_radial_control(wmKeyMap *keymap, const char *p if (flags & RC_ROTATION) { kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL, 0); - set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_nozoom); + set_brush_rc_props(kmi->ptr, paint, "texture_slot.angle", NULL, flags_noradial_secondary); + } + + if (flags & RC_SECONDARY_ROTATION) { + kmi = WM_keymap_add_item(keymap, "WM_OT_radial_control", FKEY, KM_PRESS, KM_CTRL | KM_ALT, 0); + set_brush_rc_props(kmi->ptr, paint, "mask_texture_slot.angle", NULL, flags_nozoom); } } @@ -1265,7 +1280,7 @@ void ED_keymap_paint(wmKeyConfig *keyconf) 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 | RC_ROTATION); + ed_keymap_paint_brush_radial_control(keymap, "image_paint", RC_COLOR | RC_ZOOM | RC_ROTATION | RC_SECONDARY_ROTATION); ed_keymap_stencil(keymap); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 36e1b1feb38..e41d4a741ae 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -46,6 +46,7 @@ #include "BKE_context.h" #include "BKE_paint.h" #include "BKE_brush.h" +#include "BKE_colortools.h" #include "WM_api.h" #include "WM_types.h" @@ -477,6 +478,9 @@ PaintStroke *paint_stroke_new(bContext *C, stroke->redraw = redraw; stroke->done = done; stroke->event_type = event_type; /* for modal, return event */ + + /* initialize here to avoid initialization conflict with threaded strokes */ + curvemapping_initialize(br->curve); BKE_paint_set_overlay_override(br->overlay_flags); diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 2c654507015..538e8394b1f 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -61,6 +61,7 @@ #include "BKE_object_deform.h" #include "BKE_paint.h" #include "BKE_report.h" +#include "BKE_colortools.h" #include "WM_api.h" #include "WM_types.h" @@ -68,12 +69,14 @@ #include "GPU_buffers.h" #include "ED_armature.h" +#include "ED_object.h" #include "ED_mesh.h" #include "ED_screen.h" #include "ED_view3d.h" #include "paint_intern.h" /* own include */ + /* check if we can do partial updates and have them draw realtime * (without rebuilding the 'derivedFinal') */ static int vertex_paint_use_fast_update_check(Object *ob) @@ -916,15 +919,13 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co co, co_ss, V3D_PROJ_TEST_CLIP_BB | V3D_PROJ_TEST_CLIP_NEAR) == V3D_PROJ_RET_OK) { - float delta[2]; - float dist_squared; - float factor = 1.0; + const float dist_squared = len_squared_v2v2(mval, co_ss); - 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 = BKE_paint_brush(&vp->paint); const float dist = sqrtf(dist_squared); + float factor; + 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); @@ -935,6 +936,9 @@ static float calc_vp_strength_col_dl(VPaint *vp, ViewContext *vc, const float co } factor = rgba[3]; } + else { + factor = 1.0f; + } return factor * BKE_brush_curve_strength_clamp(brush, dist, brush_size_pressure); } } @@ -2025,41 +2029,28 @@ static void do_weight_paint_vertex( /* *************** set wpaint operator ****************** */ -static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* toggle */ +/** + * \note Keep in sync with #vpaint_mode_toggle_exec + */ +static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); + const int mode_flag = OB_MODE_WEIGHT_PAINT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; Scene *scene = CTX_data_scene(C); VPaint *wp = scene->toolsettings->wpaint; Mesh *me; - - me = BKE_mesh_from_object(ob); - if (ob->id.lib || me == NULL) return OPERATOR_PASS_THROUGH; - - if (ob->mode & OB_MODE_WEIGHT_PAINT) ob->mode &= ~OB_MODE_WEIGHT_PAINT; - else ob->mode |= OB_MODE_WEIGHT_PAINT; - - - /* Weightpaint works by overriding colors in mesh, - * so need to make sure we recalc on enter and - * exit (exit needs doing regardless because we - * should redeform). - */ - DAG_id_tag_update(&me->id, 0); - - if (ob->mode & OB_MODE_WEIGHT_PAINT) { - if (wp == NULL) - wp = scene->toolsettings->wpaint = new_vpaint(1); - BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT); - paint_cursor_start(C, weight_paint_poll); - - mesh_octree_table(ob, NULL, NULL, 's'); - - ED_vgroup_sync_from_pose(ob); + if (!is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } } - else { - mesh_octree_table(NULL, NULL, NULL, 'e'); - mesh_mirrtopo_table(NULL, 'e'); + + me = BKE_mesh_from_object(ob); + + if (ob->mode & mode_flag) { + ob->mode &= ~mode_flag; if (me->editflag & ME_EDIT_PAINT_VERT_SEL) { BKE_mesh_flush_select_from_verts(me); @@ -2067,10 +2058,35 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* togg else if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { BKE_mesh_flush_select_from_polys(me); } + + /* weight paint spesific */ + mesh_octree_table(NULL, NULL, NULL, 'e'); + mesh_mirrtopo_table(NULL, 'e'); + } + else { + ob->mode |= mode_flag; + + if (wp == NULL) + wp = scene->toolsettings->wpaint = new_vpaint(1); + + paint_cursor_start(C, weight_paint_poll); + + BKE_paint_init(&wp->paint, PAINT_CURSOR_WEIGHT_PAINT); + + /* weight paint spesific */ + mesh_octree_table(ob, NULL, NULL, 's'); + ED_vgroup_sync_from_pose(ob); } + /* Weightpaint works by overriding colors in mesh, + * so need to make sure we recalc on enter and + * exit (exit needs doing regardless because we + * should redeform). + */ + DAG_id_tag_update(&me->id, 0); + WM_event_add_notifier(C, NC_SCENE | ND_MODE, scene); - + return OPERATOR_FINISHED; } @@ -2078,12 +2094,12 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) /* togg static int paint_poll_test(bContext *C) { Object *ob = CTX_data_active_object(C); - if (CTX_data_edit_object(C)) - return 0; - if (CTX_data_active_object(C) == NULL) + if (ob == NULL || ob->type != OB_MESH) return 0; if (!ob->data || ((ID *)ob->data)->lib) return 0; + if (CTX_data_edit_object(C)) + return 0; return 1; } @@ -2633,7 +2649,7 @@ void PAINT_OT_weight_set(wmOperatorType *ot) /* api callbacks */ ot->exec = weight_paint_set_exec; - ot->poll = mask_paint_poll; /* it was facemask_paint_poll */ + ot->poll = mask_paint_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; @@ -2641,40 +2657,41 @@ void PAINT_OT_weight_set(wmOperatorType *ot) /* ************ set / clear vertex paint mode ********** */ - -static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) /* toggle */ +/** + * \note Keep in sync with #wpaint_mode_toggle_exec + */ +static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op) { Object *ob = CTX_data_active_object(C); + const int mode_flag = OB_MODE_VERTEX_PAINT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; Scene *scene = CTX_data_scene(C); VPaint *vp = scene->toolsettings->vpaint; Mesh *me; - - me = BKE_mesh_from_object(ob); - - if (me == NULL || BKE_object_obdata_is_libdata(ob)) { - ob->mode &= ~OB_MODE_VERTEX_PAINT; - return OPERATOR_PASS_THROUGH; - } - - if (me && me->mloopcol == NULL) { - make_vertexcol(ob); + + if (!is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } } + + me = BKE_mesh_from_object(ob); /* toggle: end vpaint */ - if (ob->mode & OB_MODE_VERTEX_PAINT) { - - ob->mode &= ~OB_MODE_VERTEX_PAINT; + if (is_mode_set) { + ob->mode &= ~mode_flag; if (me->editflag & ME_EDIT_PAINT_FACE_SEL) { BKE_mesh_flush_select_from_polys(me); } } else { - ob->mode |= OB_MODE_VERTEX_PAINT; - /* Turn off weight painting */ - if (ob->mode & OB_MODE_WEIGHT_PAINT) - wpaint_mode_toggle_exec(C, op); - + ob->mode |= mode_flag; + + if (me->mloopcol == NULL) { + make_vertexcol(ob); + } + if (vp == NULL) vp = scene->toolsettings->vpaint = new_vpaint(0); @@ -3407,6 +3424,9 @@ static int paint_weight_gradient_exec(bContext *C, wmOperator *op) ToolSettings *ts = CTX_data_tool_settings(C); VPaint *wp = ts->wpaint; struct Brush *brush = BKE_paint_brush(&wp->paint); + + curvemapping_initialize(brush->curve); + data.brush = brush; data.weightpaint = BKE_brush_weight_get(scene, brush); } diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 2edd00c015d..9ba4f507b69 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -70,6 +70,7 @@ #include "BKE_node.h" #include "BKE_object.h" #include "BKE_subsurf.h" +#include "BKE_colortools.h" #include "BIF_glutil.h" @@ -77,6 +78,7 @@ #include "WM_types.h" #include "ED_sculpt.h" +#include "ED_object.h" #include "ED_screen.h" #include "ED_view3d.h" #include "ED_util.h" /* for crazyspace correction */ @@ -91,6 +93,7 @@ #include "GPU_buffers.h" #include "bmesh.h" +#include "bmesh_tools.h" #include <math.h> #include <stdlib.h> @@ -150,6 +153,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob) { Mesh *me = (Mesh *)ob->data; ModifierData *md; + VirtualModifierData virtualModifierData; if (ob->sculpt && ob->sculpt->bm) { /* can't combine multires and dynamic topology */ @@ -161,7 +165,7 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob) return NULL; } - for (md = modifiers_getVirtualModifierList(ob); md; md = md->next) { + for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) { if (md->type == eModifierType_Multires) { MultiresModifierData *mmd = (MultiresModifierData *)md; @@ -180,8 +184,9 @@ MultiresModifierData *sculpt_multires_active(Scene *scene, Object *ob) static int sculpt_has_active_modifiers(Scene *scene, Object *ob) { ModifierData *md; + VirtualModifierData virtualModifierData; - md = modifiers_getVirtualModifierList(ob); + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); /* exception for shape keys because we can edit those */ for (; md; md = md->next) { @@ -198,6 +203,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) ModifierData *md; Mesh *me = (Mesh *)ob->data; MultiresModifierData *mmd = sculpt_multires_active(scene, ob); + VirtualModifierData virtualModifierData; if (mmd || ob->sculpt->bm) return 0; @@ -206,7 +212,7 @@ static int sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr) return 1; - md = modifiers_getVirtualModifierList(ob); + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); /* exception for shape keys because we can edit those */ for (; md; md = md->next) { @@ -327,7 +333,7 @@ typedef struct { /* Original coordinate, normal, and mask */ const float *co; float mask; - short no[3]; + const short *no; } SculptOrigVertData; @@ -378,11 +384,10 @@ static void sculpt_orig_vert_data_update(SculptOrigVertData *orig_data, } if (orig_data->normals) { - copy_v3_v3_short(orig_data->no, orig_data->normals[iter->i]); + orig_data->no = orig_data->normals[iter->i]; } else { - /* TODO: log doesn't store normals yet */ - normal_float_to_short_v3(orig_data->no, iter->bm_vert->no); + orig_data->no = BM_log_original_vert_no(orig_data->bm_log, iter->bm_vert); } } else if (orig_data->unode->type == SCULPT_UNDO_MASK) { @@ -3422,7 +3427,7 @@ static void sculpt_update_tex(const Scene *scene, Sculpt *sd, SculptSession *ss) /* Need to allocate a bigger buffer for bigger brush size */ ss->texcache_side = 2 * radius; if (!ss->texcache || ss->texcache_side > ss->texcache_actual) { - ss->texcache = BKE_brush_gen_texture_cache(brush, radius); + ss->texcache = BKE_brush_gen_texture_cache(brush, radius, false); ss->texcache_actual = ss->texcache_side; ss->tex_pool = BKE_image_pool_new(); } @@ -3716,7 +3721,8 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio Brush *brush = BKE_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]; + float mat[3][3]; + float viewDir[3] = {0.0f, 0.0f, 1.0f}; int i; int mode; @@ -3768,6 +3774,7 @@ static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSessio brush = br; cache->saved_smooth_size = BKE_brush_size_get(scene, brush); BKE_brush_size_set(scene, brush, size); + curvemapping_initialize(brush->curve); } } } @@ -3784,12 +3791,13 @@ 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); + invert_m4_m4(ob->imat, ob->obmat); + copy_m3_m4(mat, cache->vc->rv3d->viewinv); + mul_m3_v3(mat, viewDir); + copy_m3_m4(mat, ob->imat); + mul_m3_v3(mat, viewDir); + normalize_v3_v3(cache->true_view_normal, viewDir); + /* Initialize layer brush displacements and persistent coords */ if (brush->sculpt_tool == SCULPT_TOOL_LAYER) { /* not supported yet for multires or dynamic topology */ @@ -4561,7 +4569,9 @@ static void SCULPT_OT_set_persistent_base(wmOperatorType *ot) static void sculpt_dynamic_topology_triangulate(BMesh *bm) { - BM_mesh_triangulate(bm, false, false, NULL, NULL); + if (bm->totloop != bm->totface * 3) { + BM_mesh_triangulate(bm, false, false, NULL, NULL); + } } void sculpt_pbvh_clear(Object *ob) @@ -4800,8 +4810,8 @@ static int sculpt_symmetrize_exec(bContext *C, wmOperator *UNUSED(op)) /* Symmetrize and re-triangulate */ BMO_op_callf(ss->bm, BMO_FLAG_DEFAULTS, - "symmetrize input=%avef direction=%i", - sd->symmetrize_direction); + "symmetrize input=%avef direction=%i dist=%f", + sd->symmetrize_direction, 0.00001f); sculpt_dynamic_topology_triangulate(ss->bm); /* Finish undo */ @@ -4907,21 +4917,31 @@ int ED_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) return ret; } -static int sculpt_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) +static int sculpt_mode_toggle_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); ToolSettings *ts = CTX_data_tool_settings(C); Object *ob = CTX_data_active_object(C); - Mesh *me = ob->data; + const int mode_flag = OB_MODE_SCULPT; + const bool is_mode_set = (ob->mode & mode_flag) != 0; + Mesh *me; MultiresModifierData *mmd = sculpt_multires_active(scene, ob); int flush_recalc = 0; + if (!is_mode_set) { + if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) { + return OPERATOR_CANCELLED; + } + } + + me = BKE_mesh_from_object(ob); + /* multires in sculpt mode could have different from object mode subdivision level */ flush_recalc |= mmd && mmd->sculptlvl != mmd->lvl; /* if object has got active modifiers, it's dm could be different in sculpt mode */ flush_recalc |= sculpt_has_active_modifiers(scene, ob); - if (ob->mode & OB_MODE_SCULPT) { + if (is_mode_set) { if (mmd) multires_force_update(ob); @@ -4936,13 +4956,13 @@ static int sculpt_mode_toggle_exec(bContext *C, wmOperator *UNUSED(op)) } /* Leave sculptmode */ - ob->mode &= ~OB_MODE_SCULPT; + ob->mode &= ~mode_flag; free_sculptsession(ob); } else { /* Enter sculptmode */ - ob->mode |= OB_MODE_SCULPT; + ob->mode |= mode_flag; /* Remove dynamic-topology flag; this will be enabled if the * file was saved with dynamic topology on, but we don't diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 51e740e539f..8508123f942 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -150,20 +150,31 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts) bool valid_particles = ED_texture_context_check_particles(C); bool valid_others = ED_texture_context_check_others(C); + /* this is similar to direct user action, no need to keep "better" ctxt in _prev */ if ((sbuts->mainb == BCONTEXT_WORLD) && valid_world) { - sbuts->texture_context = SB_TEXC_WORLD; + sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_WORLD; } else if ((sbuts->mainb == BCONTEXT_MATERIAL) && valid_material) { - sbuts->texture_context = SB_TEXC_MATERIAL; + sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_MATERIAL; } else if ((sbuts->mainb == BCONTEXT_DATA) && valid_lamp) { - sbuts->texture_context = SB_TEXC_LAMP; + sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_LAMP; } else if ((sbuts->mainb == BCONTEXT_PARTICLE) && valid_particles) { - sbuts->texture_context = SB_TEXC_PARTICLES; + sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_PARTICLES; } else if ((ELEM(sbuts->mainb, BCONTEXT_MODIFIER, BCONTEXT_PHYSICS)) && valid_others) { - sbuts->texture_context = SB_TEXC_OTHER; + sbuts->texture_context = sbuts->texture_context_prev = SB_TEXC_OTHER; + } + /* Else, try to revive a previous "better" ctxt... */ + else if ((sbuts->texture_context_prev != sbuts->texture_context) && + (((sbuts->texture_context_prev == SB_TEXC_WORLD) && valid_world) || + ((sbuts->texture_context_prev == SB_TEXC_MATERIAL) && valid_material) || + ((sbuts->texture_context_prev == SB_TEXC_LAMP) && valid_lamp) || + ((sbuts->texture_context_prev == SB_TEXC_PARTICLES) && valid_particles) || + ((sbuts->texture_context_prev == SB_TEXC_OTHER) && valid_others))) + { + sbuts->texture_context = sbuts->texture_context_prev; } /* Else, just be sure that current context is valid! */ else if (((sbuts->texture_context == SB_TEXC_WORLD) && !valid_world) || @@ -172,13 +183,9 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts) ((sbuts->texture_context == SB_TEXC_PARTICLES) && !valid_particles) || ((sbuts->texture_context == SB_TEXC_OTHER) && !valid_others)) { - if (valid_others) { - sbuts->texture_context = SB_TEXC_OTHER; - } - else if (valid_world) { - sbuts->texture_context = SB_TEXC_WORLD; - } - else if (valid_material) { + /* this is default fallback, do keep "better" ctxt in _prev */ + sbuts->texture_context_prev = sbuts->texture_context; + if (valid_material) { sbuts->texture_context = SB_TEXC_MATERIAL; } else if (valid_lamp) { @@ -187,6 +194,12 @@ static void set_texture_context(const bContext *C, SpaceButs *sbuts) else if (valid_particles) { sbuts->texture_context = SB_TEXC_PARTICLES; } + else if (valid_world) { + sbuts->texture_context = SB_TEXC_WORLD; + } + else if (valid_others) { + sbuts->texture_context = SB_TEXC_OTHER; + } } } } diff --git a/source/blender/editors/space_clip/clip_buttons.c b/source/blender/editors/space_clip/clip_buttons.c index 18248f4775b..50bb8a0e061 100644 --- a/source/blender/editors/space_clip/clip_buttons.c +++ b/source/blender/editors/space_clip/clip_buttons.c @@ -238,7 +238,8 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) { MarkerUpdateCb *cb = (MarkerUpdateCb *) arg_cb; MovieTrackingMarker *marker; - int width, height, ok = FALSE; + int width, height; + bool ok = false; BKE_movieclip_get_size(cb->clip, cb->user, &width, &height); @@ -252,7 +253,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) DAG_id_tag_update(&cb->clip->id, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - ok = TRUE; + ok = true; } else if (event == B_MARKER_PAT_DIM) { float dim[2], pat_dim[2], pat_min[2], pat_max[2]; @@ -276,7 +277,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) BKE_tracking_marker_clamp(cb->marker, CLAMP_PAT_DIM); - ok = TRUE; + ok = true; } else if (event == B_MARKER_SEARCH_POS) { float delta[2], side[2]; @@ -292,7 +293,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_POS); - ok = TRUE; + ok = true; } else if (event == B_MARKER_SEARCH_DIM) { float dim[2], search_dim[2]; @@ -313,12 +314,12 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) BKE_tracking_marker_clamp(cb->marker, CLAMP_SEARCH_DIM); - ok = TRUE; + ok = true; } else if (event == B_MARKER_FLAG) { marker->flag = cb->marker_flag; - ok = TRUE; + ok = true; } else if (event == B_MARKER_OFFSET) { float offset[2], delta[2]; @@ -337,7 +338,7 @@ static void marker_block_handler(bContext *C, void *arg_cb, int event) DAG_id_tag_update(&cb->clip->id, 0); WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL); - ok = TRUE; + ok = true; } if (ok) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index eb58bdc7696..4f3f81e38dc 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -127,9 +127,11 @@ static int generic_track_get_marker_framenr(MovieTrackingTrack *track, MovieTrac int marker_index) { if (track) { + BLI_assert(marker_index < track->markersnr); return track->markers[marker_index].framenr; } else if (plane_track) { + BLI_assert(marker_index < plane_track->markersnr); return plane_track->markers[marker_index].framenr; } @@ -140,6 +142,7 @@ static bool generic_track_is_marker_enabled(MovieTrackingTrack *track, MovieTrac int marker_index) { if (track) { + BLI_assert(marker_index < track->markersnr); return (track->markers[marker_index].flag & MARKER_DISABLED) == 0; } else if (plane_track) { @@ -153,9 +156,11 @@ static bool generic_track_is_marker_keyframed(MovieTrackingTrack *track, MovieTr int marker_index) { if (track) { + BLI_assert(marker_index < track->markersnr); return (track->markers[marker_index].flag & MARKER_TRACKED) == 0; } else if (plane_track) { + BLI_assert(marker_index < plane_track->markersnr); return (plane_track->markers[marker_index].flag & PLANE_MARKER_TRACKED) == 0; } @@ -212,6 +217,8 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc a++; } + a = min_ii(a, markersnr - 1); + if (generic_track_is_marker_enabled(act_track, act_plane_track, a)) { framenr = generic_track_get_marker_framenr(act_track, act_plane_track, a); @@ -235,11 +242,11 @@ static void draw_movieclip_cache(SpaceClip *sc, ARegion *ar, MovieClip *clip, Sc glColor4ub(255, 0, 0, 96); for (i = sfra, a = 0; i <= efra; i++) { - int ok = FALSE; + bool ok = false; while (a < n) { if (cameras[a].framenr == i) { - ok = TRUE; + ok = true; break; } else if (cameras[a].framenr > i) { @@ -280,11 +287,11 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; char str[256] = {0}; - int block = FALSE; + bool block = false; if (tracking->stats) { BLI_strncpy(str, tracking->stats->message, sizeof(str)); - block = TRUE; + block = true; } else { if (sc->flag & SC_LOCK_SELECTION) @@ -490,7 +497,7 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT float marker_pos[2], int width, int height) { int tiny = sc->flag & SC_SHOW_TINY_MARKER; - int show_search = FALSE; + bool show_search = false; float px[2]; UI_ThemeColor(TH_MARKER_OUTLINE); @@ -553,8 +560,8 @@ static void draw_marker_outline(SpaceClip *sc, MovieTrackingTrack *track, MovieT glEnd(); } - show_search = TRACK_VIEW_SELECTED(sc, track) && - ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0); + show_search = (TRACK_VIEW_SELECTED(sc, track) && + ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; if (sc->flag & SC_SHOW_MARKER_SEARCH && show_search) { glBegin(GL_LINE_LOOP); glVertex2f(marker->search_min[0], marker->search_min[1]); @@ -593,7 +600,7 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra float marker_pos[2], int width, int height, int act, int sel) { int tiny = sc->flag & SC_SHOW_TINY_MARKER; - int show_search = 0; + bool show_search = false; float col[3], scol[3], px[2]; track_colors(track, act, col, scol); @@ -708,8 +715,8 @@ static void draw_marker_areas(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } /* search */ - show_search = TRACK_VIEW_SELECTED(sc, track) && - ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0); + show_search = (TRACK_VIEW_SELECTED(sc, track) && + ((marker->flag & MARKER_DISABLED) == 0 || (sc->flag & SC_SHOW_MARKER_PATTERN) == 0)) != 0; if ((track->search_flag & SELECT) == sel && (sc->flag & SC_SHOW_MARKER_SEARCH) && show_search) { if (track->flag & TRACK_LOCKED) { if (act) @@ -997,17 +1004,6 @@ static void draw_marker_texts(SpaceClip *sc, MovieTrackingTrack *track, MovieTra } } -static void view2d_to_region_float(View2D *v2d, float x, float y, float *regionx, float *regiony) -{ - /* express given coordinates as proportional values */ - x = -v2d->cur.xmin / BLI_rctf_size_x(&v2d->cur); - y = -v2d->cur.ymin / BLI_rctf_size_y(&v2d->cur); - - /* convert proportional distances to screen coordinates */ - *regionx = v2d->mask.xmin + x * BLI_rcti_size_x(&v2d->mask); - *regiony = v2d->mask.ymin + y * BLI_rcti_size_y(&v2d->mask); -} - static void plane_track_colors(bool is_active, float color[3], float selected_color[3]) { UI_GetThemeColor3fv(TH_MARKER, color); @@ -1071,8 +1067,6 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t else if (tiny) { glLineStipple(3, 0xaaaa); glEnable(GL_LINE_STIPPLE); - glEnable(GL_COLOR_LOGIC_OP); - glLogicOp(GL_NOR); } /* Draw rectangle itself. */ @@ -1120,10 +1114,7 @@ static void draw_plane_marker_ex(SpaceClip *sc, MovieTrackingPlaneTrack *plane_t } } else if (tiny) { - glDisable(GL_COLOR_LOGIC_OP); glDisable(GL_LINE_STIPPLE); - glLineStipple(3, 0xaaaa); - glEnable(GL_LINE_STIPPLE); } } @@ -1173,7 +1164,7 @@ static void draw_tracking_tracks(SpaceClip *sc, ARegion *ar, MovieClip *clip, * to avoid this flickering, calculate base point in the same way as it happens * in UI_view2d_to_region_no_clip, but do it in floats here */ - view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y); + UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y); glPushMatrix(); glTranslatef(x, y, 0); @@ -1416,7 +1407,7 @@ static void draw_distortion(SpaceClip *sc, ARegion *ar, MovieClip *clip, if ((sc->flag & SC_SHOW_GRID) == 0 && (sc->flag & SC_MANUAL_CALIBRATION) == 0) return; - view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y); + UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y); glPushMatrix(); glTranslatef(x, y, 0); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 08d0af817a8..0d64a3ce594 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -262,15 +262,15 @@ ImBuf *ED_space_clip_get_stable_buffer(SpaceClip *sc, float loc[2], float *scale /* returns color in SRGB */ /* matching ED_space_image_color_sample() */ -int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3]) +bool ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_col[3]) { ImBuf *ibuf; float fx, fy, co[2]; - int ret = FALSE; + bool ret = false; ibuf = ED_space_clip_get_buffer(sc); if (!ibuf) { - return FALSE; + return false; } /* map the mouse coords to the backdrop image space */ @@ -290,12 +290,12 @@ int ED_space_clip_color_sample(SpaceClip *sc, ARegion *ar, int mval[2], float r_ if (ibuf->rect_float) { fp = (ibuf->rect_float + (ibuf->channels) * (y * ibuf->x + x)); linearrgb_to_srgb_v3_v3(r_col, fp); - ret = TRUE; + ret = true; } else if (ibuf->rect) { cp = (unsigned char *)(ibuf->rect + y * ibuf->x + x); rgb_uchar_to_float(r_col, cp); - ret = TRUE; + ret = true; } } @@ -325,11 +325,12 @@ void ED_clip_update_frame(const Main *mainp, int cfra) } } -static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) +static bool selected_boundbox(SpaceClip *sc, float min[2], float max[2]) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTrackingTrack *track; - int width, height, ok = FALSE; + int width, height; + bool ok = false; ListBase *tracksbase = BKE_tracking_get_active_tracks(&clip->tracking); int framenr = ED_space_clip_get_clip_frame_number(sc); @@ -362,7 +363,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) minmax_v2v2_v2(min, max, pos); - ok = TRUE; + ok = true; } } @@ -372,7 +373,7 @@ static int selected_boundbox(SpaceClip *sc, float min[2], float max[2]) return ok; } -int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit) +bool ED_clip_view_selection(const bContext *C, ARegion *ar, bool fit) { SpaceClip *sc = CTX_wm_space_clip(C); int w, h, frame_width, frame_height; @@ -381,10 +382,10 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit) ED_space_clip_get_size(sc, &frame_width, &frame_height); if ((frame_width == 0) || (frame_height == 0) || (sc->clip == NULL)) - return FALSE; + return false; if (!selected_boundbox(sc, min, max)) - return FALSE; + return false; /* center view */ clip_view_center_to_point(sc, (max[0] + min[0]) / (2 * frame_width), @@ -412,7 +413,7 @@ int ED_clip_view_selection(const bContext *C, ARegion *ar, int fit) sc->zoom = newzoom; } - return TRUE; + return true; } void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[2]) @@ -500,22 +501,22 @@ void ED_clip_mouse_pos(SpaceClip *sc, ARegion *ar, const int mval[2], float co[2 ED_clip_point_stable_pos(sc, ar, mval[0], mval[1], &co[0], &co[1]); } -int ED_space_clip_check_show_trackedit(SpaceClip *sc) +bool ED_space_clip_check_show_trackedit(SpaceClip *sc) { if (sc) { return ELEM3(sc->mode, SC_MODE_TRACKING, SC_MODE_RECONSTRUCTION, SC_MODE_DISTORTION); } - return FALSE; + return false; } -int ED_space_clip_check_show_maskedit(SpaceClip *sc) +bool ED_space_clip_check_show_maskedit(SpaceClip *sc) { if (sc) { return sc->mode == SC_MODE_MASKEDIT; } - return FALSE; + return false; } /* ******** clip editing functions ******** */ diff --git a/source/blender/editors/space_clip/clip_graph_draw.c b/source/blender/editors/space_clip/clip_graph_draw.c index 973200dc340..173d65ee4fc 100644 --- a/source/blender/editors/space_clip/clip_graph_draw.c +++ b/source/blender/editors/space_clip/clip_graph_draw.c @@ -126,7 +126,7 @@ static void tracking_segment_end_cb(void *UNUSED(userdata)) static void tracking_segment_knot_cb(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, int scene_framenr, float val) { - struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } *data = userdata; + struct { MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; } *data = userdata; int sel = 0, sel_flag; if (track != data->act_track) @@ -151,7 +151,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc) MovieTracking *tracking = &clip->tracking; MovieTrackingTrack *act_track = BKE_tracking_track_get_active(tracking); int width, height; - struct { MovieTrackingTrack *act_track; int sel; float xscale, yscale, hsize; } userdata; + struct { MovieTrackingTrack *act_track; bool sel; float xscale, yscale, hsize; } userdata; BKE_movieclip_get_size(clip, &sc->user, &width, &height); @@ -160,7 +160,7 @@ static void draw_tracks_curves(View2D *v2d, SpaceClip *sc) /* non-selected knot handles */ userdata.hsize = UI_GetThemeValuef(TH_HANDLE_VERTEX_SIZE); - userdata.sel = FALSE; + userdata.sel = false; userdata.act_track = act_track; UI_view2d_getscale(v2d, &userdata.xscale, &userdata.yscale); clip_graph_tracking_values_iterate(sc, sc->flag & SC_SHOW_GRAPH_SEL_ONLY, sc->flag & SC_SHOW_GRAPH_HIDDEN, diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index cdb0fdadebd..393f92f5af5 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -96,8 +96,8 @@ static void toggle_selection_cb(void *userdata, MovieTrackingMarker *marker) /******************** mouse select operator ********************/ typedef struct { - int coord, /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */ - has_prev; /* if there's valid coordinate of previous point of curve segment */ + int coord; /* coordinate index of found entuty (0 = X-axis, 1 = Y-axis) */ + bool has_prev; /* if there's valid coordinate of previous point of curve segment */ float min_dist, /* minimal distance between mouse and currently found entuty */ mouse_co[2], /* mouse coordinate */ @@ -134,7 +134,7 @@ static void find_nearest_tracking_segment_end_cb(void *userdata) { MouseSelectUserData *data = userdata; - data->has_prev = FALSE; + data->has_prev = false; } static void find_nearest_tracking_knot_cb(void *userdata, MovieTrackingTrack *track, @@ -163,7 +163,7 @@ static void mouse_select_init_data(MouseSelectUserData *userdata, float *co) copy_v2_v2(userdata->mouse_co, co); } -static int mouse_select_knot(bContext *C, float co[2], int extend) +static bool mouse_select_knot(bContext *C, float co[2], bool extend) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); @@ -200,15 +200,15 @@ static int mouse_select_knot(bContext *C, float co[2], int extend) else userdata.marker->flag |= MARKER_GRAPH_SEL_Y; - return TRUE; + return true; } } } - return FALSE; + return false; } -static int mouse_select_curve(bContext *C, float co[2], int extend) +static bool mouse_select_curve(bContext *C, float co[2], bool extend) { SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); @@ -242,15 +242,15 @@ static int mouse_select_curve(bContext *C, float co[2], int extend) toggle_selection_cb); } - return TRUE; + return true; } - return FALSE; + return false; } -static int mouse_select(bContext *C, float co[2], int extend) +static int mouse_select(bContext *C, float co[2], bool extend) { - int sel = FALSE; + bool sel = false; /* first try to select knot on selected curves */ sel = mouse_select_knot(C, co, extend); @@ -269,7 +269,7 @@ static int mouse_select(bContext *C, float co[2], int extend) static int select_exec(bContext *C, wmOperator *op) { float co[2]; - int extend = RNA_boolean_get(op->ptr, "extend"); + bool extend = RNA_boolean_get(op->ptr, "extend"); RNA_float_get_array(op->ptr, "location", co); @@ -313,7 +313,8 @@ void CLIP_OT_graph_select(wmOperatorType *ot) typedef struct BorderSelectuserData { rctf rect; - int change, mode, extend; + int mode; + bool change, extend; } BorderSelectuserData; static void border_select_cb(void *userdata, MovieTrackingTrack *UNUSED(track), @@ -352,13 +353,17 @@ static int border_select_graph_exec(bContext *C, wmOperator *op) BorderSelectuserData userdata; rcti rect; + if (act_track == NULL) { + return OPERATOR_CANCELLED; + } + /* get rectangle from operator */ WM_operator_properties_border_to_rcti(op, &rect); UI_view2d_region_to_view(&ar->v2d, rect.xmin, rect.ymin, &userdata.rect.xmin, &userdata.rect.ymin); UI_view2d_region_to_view(&ar->v2d, rect.xmax, rect.ymax, &userdata.rect.xmax, &userdata.rect.ymax); - userdata.change = FALSE; + userdata.change = false; userdata.mode = RNA_int_get(op->ptr, "gesture_mode"); userdata.extend = RNA_boolean_get(op->ptr, "extend"); diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 8d112b7413c..e6f1813b3a4 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -112,6 +112,8 @@ void CLIP_OT_prefetch(struct wmOperatorType *ot); void CLIP_OT_set_scene_frames(wmOperatorType *ot); +void CLIP_OT_cursor_set(struct wmOperatorType *ot); + /* clip_toolbar.c */ struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa); void CLIP_OT_tools(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index de19df9abe2..f96a0e71dfc 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -181,7 +181,7 @@ static int open_exec(bContext *C, wmOperator *op) PointerRNA fileptr; PropertyRNA *prop; char dir_only[FILE_MAX], file_only[FILE_MAX]; - int relative = RNA_boolean_get(op->ptr, "relative_path"); + bool relative = RNA_boolean_get(op->ptr, "relative_path"); RNA_string_get(op->ptr, "directory", dir_only); if (relative) @@ -353,7 +353,7 @@ static void view_pan_init(bContext *C, wmOperator *op, const wmEvent *event) WM_event_add_modal_handler(C, op); } -static void view_pan_exit(bContext *C, wmOperator *op, int cancel) +static void view_pan_exit(bContext *C, wmOperator *op, bool cancel) { ViewPanData *vpd = op->customdata; @@ -502,7 +502,7 @@ static void view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) WM_event_add_modal_handler(C, op); } -static void view_zoom_exit(bContext *C, wmOperator *op, int cancel) +static void view_zoom_exit(bContext *C, wmOperator *op, bool cancel) { SpaceClip *sc = CTX_wm_space_clip(C); ViewZoomData *vpd = op->customdata; @@ -736,7 +736,7 @@ static int view_all_exec(bContext *C, wmOperator *op) ARegion *ar; int w, h, width, height; float aspx, aspy; - int fit_view = RNA_boolean_get(op->ptr, "fit_view"); + bool fit_view = RNA_boolean_get(op->ptr, "fit_view"); float zoomx, zoomy; /* retrieve state */ @@ -782,6 +782,8 @@ static int view_all_exec(bContext *C, wmOperator *op) void CLIP_OT_view_all(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "View All"; ot->idname = "CLIP_OT_view_all"; @@ -792,7 +794,8 @@ void CLIP_OT_view_all(wmOperatorType *ot) ot->poll = ED_space_clip_view_clip_poll; /* properties */ - RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport"); + prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /********************** view selected operator *********************/ @@ -943,7 +946,8 @@ typedef struct ProxyBuildJob { Scene *scene; struct Main *main; MovieClip *clip; - int clip_flag, stop; + int clip_flag; + bool stop; struct IndexBuildContext *index_context; } ProxyJob; @@ -1123,10 +1127,10 @@ static void *do_proxy_thread(void *data_v) 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); + 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); + data->build_undistort_sizes, data->build_undistort_count, true); IMB_freeImBuf(ibuf); @@ -1455,6 +1459,51 @@ void CLIP_OT_set_scene_frames(wmOperatorType *ot) ot->exec = clip_set_scene_frames_exec; } +/******************** set 3d cursor operator ********************/ + +static int clip_set_2d_cursor_exec(bContext *C, wmOperator *op) +{ + SpaceClip *sclip = CTX_wm_space_clip(C); + + RNA_float_get_array(op->ptr, "location", sclip->cursor); + + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_CLIP, NULL); + + return OPERATOR_FINISHED; +} + +static int clip_set_2d_cursor_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ARegion *ar = CTX_wm_region(C); + SpaceClip *sclip = CTX_wm_space_clip(C); + float location[2]; + + ED_clip_mouse_pos(sclip, ar, event->mval, location); + RNA_float_set_array(op->ptr, "location", location); + + return clip_set_2d_cursor_exec(C, op); +} + +void CLIP_OT_cursor_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set 2D Cursor"; + ot->description = "Set 2D cursor location"; + ot->idname = "CLIP_OT_cursor_set"; + + /* api callbacks */ + ot->exec = clip_set_2d_cursor_exec; + ot->invoke = clip_set_2d_cursor_invoke; + ot->poll = ED_space_clip_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + RNA_def_float_vector(ot->srna, "location", 2, NULL, -FLT_MAX, FLT_MAX, "Location", + "Cursor location in normalized clip coordinates", -10.0f, 10.0f); +} + /********************** macroses *********************/ void ED_operatormacros_clip(void) diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 72a3cb98a6a..635aa388541 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -76,7 +76,8 @@ void clip_graph_tracking_values_iterate_track( BKE_movieclip_get_size(clip, &sc->user, &width, &height); for (coord = 0; coord < 2; coord++) { - int i, open = FALSE, prevfra = 0; + int i, prevfra = 0; + bool open = false; float prevval = 0.0f; for (i = 0; i < track->markersnr; i++) { @@ -88,7 +89,7 @@ void clip_graph_tracking_values_iterate_track( if (segment_end) segment_end(userdata); - open = FALSE; + open = false; } continue; @@ -98,7 +99,7 @@ void clip_graph_tracking_values_iterate_track( if (segment_start) segment_start(userdata, track, coord); - open = TRUE; + open = true; prevval = marker->pos[coord]; } @@ -184,7 +185,7 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); - int has_bundle = FALSE, update_stab = FALSE; + bool has_bundle = false, update_stab = false; if (track == act_track) tracking->act_track = NULL; @@ -192,19 +193,19 @@ void clip_delete_track(bContext *C, MovieClip *clip, MovieTrackingTrack *track) if (track == stab->rot_track) { stab->rot_track = NULL; - update_stab = TRUE; + update_stab = true; } /* handle reconstruction display in 3d viewport */ if (track->flag & TRACK_HAS_BUNDLE) - has_bundle = TRUE; + has_bundle = true; /* Make sure no plane will use freed track */ for (plane_track = plane_tracks_base->first; plane_track; plane_track = next_plane_track) { - bool found = false; + bool found = false; int i; next_plane_track = plane_track->next; diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 8213853c937..8ecf9635af9 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -56,6 +56,7 @@ #include "ED_screen.h" #include "ED_clip.h" #include "ED_transform.h" +#include "ED_uvedit.h" /* just for draw_image_cursor */ #include "IMB_imbuf.h" @@ -442,6 +443,7 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_view_ndof); WM_operatortype_append(CLIP_OT_prefetch); WM_operatortype_append(CLIP_OT_set_scene_frames); + WM_operatortype_append(CLIP_OT_cursor_set); /* ** clip_toolbar.c ** */ WM_operatortype_append(CLIP_OT_tools); @@ -724,6 +726,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "action", TRACK_CLEAR_ALL); RNA_boolean_set(kmi->ptr, "clear_active", FALSE); + /* Cursor */ + WM_keymap_add_item(keymap, "CLIP_OT_cursor_set", ACTIONMOUSE, KM_PRESS, 0, 0); + /* ******** Hotkeys avalaible for preview region only ******** */ keymap = WM_keymap_find(keyconf, "Clip Graph Editor", SPACE_CLIP, 0); @@ -854,36 +859,36 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ARegion *ar_preview = ED_clip_has_preview_region(C, sa); ARegion *ar_properties = ED_clip_has_properties_region(sa); ARegion *ar_channels = ED_clip_has_channels_region(sa); - int main_visible = FALSE, preview_visible = FALSE, tools_visible = FALSE; - int tool_props_visible = FALSE, properties_visible = FALSE, channels_visible = FALSE; - int view_changed = FALSE; + bool main_visible = false, preview_visible = false, tools_visible = false; + bool tool_props_visible = false, properties_visible = false, channels_visible = false; + bool view_changed = false; switch (sc->view) { case SC_VIEW_CLIP: - main_visible = TRUE; - preview_visible = FALSE; - tools_visible = TRUE; - tool_props_visible = TRUE; - properties_visible = TRUE; - channels_visible = FALSE; + main_visible = true; + preview_visible = false; + tools_visible = true; + tool_props_visible = true; + properties_visible = true; + channels_visible = false; break; case SC_VIEW_GRAPH: - main_visible = FALSE; - preview_visible = TRUE; - tools_visible = FALSE; - tool_props_visible = FALSE; - properties_visible = FALSE; - channels_visible = FALSE; + main_visible = false; + preview_visible = true; + tools_visible = false; + tool_props_visible = false; + properties_visible = false; + channels_visible = false; reinit_preview_region(C, ar_preview); break; case SC_VIEW_DOPESHEET: - main_visible = FALSE; - preview_visible = TRUE; - tools_visible = FALSE; - tool_props_visible = FALSE; - properties_visible = FALSE; - channels_visible = TRUE; + main_visible = false; + preview_visible = true; + tools_visible = false; + tool_props_visible = false; + properties_visible = false; + channels_visible = true; reinit_preview_region(C, ar_preview); break; @@ -893,12 +898,12 @@ static void clip_refresh(const bContext *C, ScrArea *sa) if (ar_main && (ar_main->flag & RGN_FLAG_HIDDEN)) { ar_main->flag &= ~RGN_FLAG_HIDDEN; ar_main->v2d.flag &= ~V2D_IS_INITIALISED; - view_changed = TRUE; + view_changed = true; } if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) { ar_main->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } else { @@ -906,11 +911,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_main->flag |= RGN_FLAG_HIDDEN; ar_main->v2d.flag &= ~V2D_IS_INITIALISED; WM_event_remove_handlers((bContext *)C, &ar_main->handlers); - view_changed = TRUE; + view_changed = true; } if (ar_main && ar_main->alignment != RGN_ALIGN_NONE) { ar_main->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } @@ -918,11 +923,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) if (ar_properties && (ar_properties->flag & RGN_FLAG_HIDDEN)) { ar_properties->flag &= ~RGN_FLAG_HIDDEN; ar_properties->v2d.flag &= ~V2D_IS_INITIALISED; - view_changed = TRUE; + view_changed = true; } if (ar_properties && ar_properties->alignment != RGN_ALIGN_RIGHT) { ar_properties->alignment = RGN_ALIGN_RIGHT; - view_changed = TRUE; + view_changed = true; } } else { @@ -930,11 +935,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_properties->flag |= RGN_FLAG_HIDDEN; ar_properties->v2d.flag &= ~V2D_IS_INITIALISED; WM_event_remove_handlers((bContext *)C, &ar_properties->handlers); - view_changed = TRUE; + view_changed = true; } if (ar_properties && ar_properties->alignment != RGN_ALIGN_NONE) { ar_properties->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } @@ -942,11 +947,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) if (ar_tools && (ar_tools->flag & RGN_FLAG_HIDDEN)) { ar_tools->flag &= ~RGN_FLAG_HIDDEN; ar_tools->v2d.flag &= ~V2D_IS_INITIALISED; - view_changed = TRUE; + view_changed = true; } if (ar_tools && ar_tools->alignment != RGN_ALIGN_LEFT) { ar_tools->alignment = RGN_ALIGN_LEFT; - view_changed = TRUE; + view_changed = true; } } else { @@ -954,11 +959,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_tools->flag |= RGN_FLAG_HIDDEN; ar_tools->v2d.flag &= ~V2D_IS_INITIALISED; WM_event_remove_handlers((bContext *)C, &ar_tools->handlers); - view_changed = TRUE; + view_changed = true; } if (ar_tools && ar_tools->alignment != RGN_ALIGN_NONE) { ar_tools->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } @@ -966,11 +971,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) if (ar_tool_props && (ar_tool_props->flag & RGN_FLAG_HIDDEN)) { ar_tool_props->flag &= ~RGN_FLAG_HIDDEN; ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED; - view_changed = TRUE; + view_changed = true; } if (ar_tool_props && (ar_tool_props->alignment != (RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV))) { ar_tool_props->alignment = RGN_ALIGN_BOTTOM | RGN_SPLIT_PREV; - view_changed = TRUE; + view_changed = true; } } else { @@ -978,11 +983,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_tool_props->flag |= RGN_FLAG_HIDDEN; ar_tool_props->v2d.flag &= ~V2D_IS_INITIALISED; WM_event_remove_handlers((bContext *)C, &ar_tool_props->handlers); - view_changed = TRUE; + view_changed = true; } if (ar_tool_props && ar_tool_props->alignment != RGN_ALIGN_NONE) { ar_tool_props->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } @@ -991,11 +996,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_preview->flag &= ~RGN_FLAG_HIDDEN; ar_preview->v2d.flag &= ~V2D_IS_INITIALISED; ar_preview->v2d.cur = ar_preview->v2d.tot; - view_changed = TRUE; + view_changed = true; } if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) { ar_preview->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } else { @@ -1003,11 +1008,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_preview->flag |= RGN_FLAG_HIDDEN; ar_preview->v2d.flag &= ~V2D_IS_INITIALISED; WM_event_remove_handlers((bContext *)C, &ar_preview->handlers); - view_changed = TRUE; + view_changed = true; } if (ar_preview && ar_preview->alignment != RGN_ALIGN_NONE) { ar_preview->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } @@ -1015,11 +1020,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) if (ar_channels && (ar_channels->flag & RGN_FLAG_HIDDEN)) { ar_channels->flag &= ~RGN_FLAG_HIDDEN; ar_channels->v2d.flag &= ~V2D_IS_INITIALISED; - view_changed = TRUE; + view_changed = true; } if (ar_channels && ar_channels->alignment != RGN_ALIGN_LEFT) { ar_channels->alignment = RGN_ALIGN_LEFT; - view_changed = TRUE; + view_changed = true; } } else { @@ -1027,11 +1032,11 @@ static void clip_refresh(const bContext *C, ScrArea *sa) ar_channels->flag |= RGN_FLAG_HIDDEN; ar_channels->v2d.flag &= ~V2D_IS_INITIALISED; WM_event_remove_handlers((bContext *)C, &ar_channels->handlers); - view_changed = TRUE; + view_changed = true; } if (ar_channels && ar_channels->alignment != RGN_ALIGN_NONE) { ar_channels->alignment = RGN_ALIGN_NONE; - view_changed = TRUE; + view_changed = true; } } @@ -1116,6 +1121,8 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) /* draw entirely, view changes should be handled here */ SpaceClip *sc = CTX_wm_space_clip(C); MovieClip *clip = ED_space_clip_get_clip(sc); + float aspx, aspy, zoomx, zoomy, x, y; + int width, height; /* if tracking is in progress, we should synchronize framenr from clipuser * so latest tracked frame would be shown */ @@ -1147,29 +1154,38 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) clip_draw_main(C, sc, ar); - if (sc->mode == SC_MODE_MASKEDIT) { + /* TODO(sergey): would be nice to find a way to de-duplicate all this space conversions */ + UI_view2d_to_region_float(&ar->v2d, 0.0f, 0.0f, &x, &y); + ED_space_clip_get_size(sc, &width, &height); + ED_space_clip_get_zoom(sc, ar, &zoomx, &zoomy); + ED_space_clip_get_aspect(sc, &aspx, &aspy); + if (sc->mode == SC_MODE_MASKEDIT) { Mask *mask = CTX_data_edit_mask(C); if (mask) { ScrArea *sa = CTX_wm_area(C); - int width, height; - float aspx, aspy; - ED_mask_get_size(sa, &width, &height); - ED_space_clip_get_aspect(sc, &aspx, &aspy); + int mask_width, mask_height; + ED_mask_get_size(sa, &mask_width, &mask_height); ED_mask_draw_region(mask, ar, sc->mask_info.draw_flag, sc->mask_info.draw_type, - width, height, + mask_width, mask_height, aspx, aspy, TRUE, TRUE, sc->stabmat, C); } - - } + glPushMatrix(); + glTranslatef(x, y, 0); + glScalef(zoomx, zoomy, 0); + glMultMatrixf(sc->stabmat); + glScalef(width, height, 0); + draw_image_cursor(ar, sc->cursor); + glPopMatrix(); + if (sc->flag & SC_SHOW_GPENCIL) { /* Grease Pencil */ - clip_draw_grease_pencil((bContext *)C, TRUE); + clip_draw_grease_pencil((bContext *)C, true); } /* reset view matrix */ @@ -1177,7 +1193,7 @@ static void clip_main_area_draw(const bContext *C, ARegion *ar) if (sc->flag & SC_SHOW_GPENCIL) { /* draw Grease Pencil - screen space only */ - clip_draw_grease_pencil((bContext *)C, FALSE); + clip_draw_grease_pencil((bContext *)C, false); } } diff --git a/source/blender/editors/space_clip/tracking_ops.c b/source/blender/editors/space_clip/tracking_ops.c index e14fc8ad399..8106befcab8 100644 --- a/source/blender/editors/space_clip/tracking_ops.c +++ b/source/blender/editors/space_clip/tracking_ops.c @@ -593,14 +593,14 @@ static int mouse_on_tilt(SpaceClip *sc, MovieTrackingMarker *marker, float co[2] return mouse_on_slide_zone(sc, marker, TRACK_AREA_PAT, co, slider, 0.0f, width, height); } -static int slide_check_corners(float (*corners)[2]) +static bool slide_check_corners(float (*corners)[2]) { int i, next, prev; float cross = 0.0f; float p[2] = {0.0f, 0.0f}; if (!isect_point_quad_v2(p, corners[0], corners[1], corners[2], corners[3])) - return FALSE; + return false; for (i = 0; i < 4; i++) { float v1[2], v2[2], cur_cross; @@ -618,12 +618,12 @@ static int slide_check_corners(float (*corners)[2]) cross = cur_cross; } else if (cross * cur_cross < 0.0f) { - return FALSE; + return false; } } } - return TRUE; + return true; } static void hide_cursor(bContext *C) @@ -664,25 +664,25 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even while (track) { if (TRACK_VIEW_SELECTED(sc, track) && (track->flag & TRACK_LOCKED) == 0) { MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - int ok = FALSE; + bool ok = false; if ((marker->flag & MARKER_DISABLED) == 0) { if (mouse_on_offset(sc, track, marker, co, width, height)) { area = TRACK_AREA_POINT; action = SLIDE_ACTION_POS; - ok = TRUE; + ok = true; } if (!ok && (sc->flag & SC_SHOW_MARKER_SEARCH)) { if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 1, 0.0f, width, height)) { area = TRACK_AREA_SEARCH; action = SLIDE_ACTION_OFFSET; - ok = TRUE; + ok = true; } else if (mouse_on_corner(sc, marker, TRACK_AREA_SEARCH, co, 0, 0.0f, width, height)) { area = TRACK_AREA_SEARCH; action = SLIDE_ACTION_SIZE; - ok = TRUE; + ok = true; } } @@ -693,7 +693,7 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even area = TRACK_AREA_PAT; action = SLIDE_ACTION_POS; corner = current_corner; - ok = TRUE; + ok = true; } else { #if 0 @@ -702,18 +702,18 @@ MovieTrackingTrack *tracking_marker_check_slide(bContext *C, const wmEvent *even if (mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 1, 12.0f, width, height)) { area = TRACK_AREA_PAT; action = SLIDE_ACTION_OFFSET; - ok = TRUE; + ok = true; } if (!ok && mouse_on_corner(sc, marker, TRACK_AREA_PAT, co, 0, 12.0f, width, height)) { area = TRACK_AREA_PAT; action = SLIDE_ACTION_SIZE; - ok = TRUE; + ok = true; } #endif if (!ok && mouse_on_tilt(sc, marker, co, width, height)) { area = TRACK_AREA_PAT; action = SLIDE_ACTION_TILT_SIZE; - ok = TRUE; + ok = true; } } } @@ -1145,18 +1145,18 @@ static void track_init_markers(SpaceClip *sc, MovieClip *clip, int *frames_limit *frames_limit_r = frames_limit; } -static int track_markers_check_direction(int backwards, int curfra, int efra) +static bool track_markers_check_direction(int backwards, int curfra, int efra) { if (backwards) { if (curfra < efra) - return FALSE; + return false; } else { if (curfra > efra) - return FALSE; + return false; } - return TRUE; + return true; } static int track_markers_initjob(bContext *C, TrackMarkersJob *tmj, int backwards) @@ -1960,7 +1960,7 @@ static int count_selected_bundles(bContext *C) static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat[4][4]) { bConstraint *con; - int found = FALSE; + bool found = false; for (con = ob->constraints.first; con; con = con->next) { bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con); @@ -1979,7 +1979,7 @@ static void object_solver_inverted_matrix(Scene *scene, Object *ob, float invmat mul_m4_m4m4(invmat, invmat, data->invmat); - found = TRUE; + found = true; } } @@ -2099,7 +2099,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb { Object *camera = get_camera_with_movieclip(scene, clip); int is_camera = tracking_object->flag & TRACKING_OBJECT_CAMERA; - int flip = FALSE; + bool flip = false; float mat[4][4], vec[3], obmat[4][4], dvec[3]; BKE_object_to_mat4(ob, obmat); @@ -2127,7 +2127,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb if (axis == 'X') { if (fabsf(dvec[1]) < 1e-3f) { - flip = TRUE; + flip = true; mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f; mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f; @@ -2151,7 +2151,7 @@ static void set_axis(Scene *scene, Object *ob, MovieClip *clip, MovieTrackingOb } else { if (fabsf(dvec[0]) < 1e-3f) { - flip = TRUE; + flip = true; mat[0][0] = -1.0f; mat[0][1] = 0.0f; mat[0][2] = 0.0f; mat[1][0] = 0.0f; mat[1][1] = -1.0f; mat[1][2] = 0.0f; diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index 6e4d10173fb..7cb5f9b5dc0 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -461,7 +461,8 @@ static int border_select_exec(bContext *C, wmOperator *op) ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); rcti rect; rctf rectf; - int change = FALSE, mode, extend; + bool change = false; + int mode, extend; int framenr = ED_space_clip_get_clip_frame_number(sc); /* get rectangle from operator */ @@ -490,7 +491,7 @@ static int border_select_exec(bContext *C, wmOperator *op) BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT); } - change = TRUE; + change = true; } } @@ -520,7 +521,7 @@ static int border_select_exec(bContext *C, wmOperator *op) } } - change = TRUE; + change = true; } } @@ -569,7 +570,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); rcti rect; - int change = FALSE; + bool change = false; int framenr = ED_space_clip_get_clip_frame_number(sc); /* get rectangle from operator */ @@ -596,7 +597,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT); } - change = TRUE; + change = true; } } @@ -630,7 +631,7 @@ static int do_lasso_select_marker(bContext *C, const int mcords[][2], const shor } } - change = TRUE; + change = true; } } @@ -713,7 +714,8 @@ static int circle_select_exec(bContext *C, wmOperator *op) MovieTrackingPlaneTrack *plane_track; ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); - int x, y, radius, width, height, mode, change = FALSE; + int x, y, radius, width, height, mode; + bool change = false; float zoomx, zoomy, offset[2], ellipse[2]; int framenr = ED_space_clip_get_clip_frame_number(sc); @@ -745,7 +747,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) else BKE_tracking_track_flag_clear(track, TRACK_AREA_ALL, SELECT); - change = TRUE; + change = true; } } @@ -772,7 +774,7 @@ static int circle_select_exec(bContext *C, wmOperator *op) } } - change = TRUE; + change = true; } } @@ -824,7 +826,7 @@ static int select_all_exec(bContext *C, wmOperator *op) ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(tracking); int action = RNA_enum_get(op->ptr, "action"); int framenr = ED_space_clip_get_clip_frame_number(sc); - int has_selection = FALSE; + bool has_selection = false; if (action == SEL_TOGGLE) { action = SEL_SELECT; @@ -877,7 +879,7 @@ static int select_all_exec(bContext *C, wmOperator *op) } if (TRACK_VIEW_SELECTED(sc, track)) - has_selection = TRUE; + has_selection = true; } for (plane_track = plane_tracks_base->first; @@ -899,7 +901,7 @@ static int select_all_exec(bContext *C, wmOperator *op) } if (plane_track->flag & SELECT) { - has_selection = TRUE; + has_selection = true; } } @@ -945,7 +947,7 @@ static int select_groped_exec(bContext *C, wmOperator *op) track = tracksbase->first; while (track) { - int ok = FALSE; + bool ok = false; marker = BKE_tracking_marker_get(track, framenr); diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 8f25ac38963..19a6296993d 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -152,17 +152,27 @@ static ImBuf *gSpecialFileImages[SPECIAL_IMG_MAX]; /* ******************* SORT ******************* */ +static bool compare_is_directory(const struct direntry *entry) +{ + /* for library browse .blend files may be treated as directories, but + * for sorting purposes they should be considered regular files */ + if (S_ISDIR(entry->type)) + return !(entry->flags & (BLENDERFILE | BLENDERFILE_BACKUP)); + + return false; +} + static int compare_name(const void *a1, const void *a2) { const struct direntry *entry1 = a1, *entry2 = a2; /* type is equal to stat.st_mode */ - if (S_ISDIR(entry1->type)) { - if (S_ISDIR(entry2->type) == 0) return (-1); + if (compare_is_directory(entry1)) { + if (compare_is_directory(entry2) == 0) return (-1); } else { - if (S_ISDIR(entry2->type)) return (1); + if (compare_is_directory(entry2)) return (1); } if (S_ISREG(entry1->type)) { if (S_ISREG(entry2->type) == 0) return (-1); @@ -188,11 +198,11 @@ static int compare_date(const void *a1, const void *a2) /* type is equal to stat.st_mode */ - if (S_ISDIR(entry1->type)) { - if (S_ISDIR(entry2->type) == 0) return (-1); + if (compare_is_directory(entry1)) { + if (compare_is_directory(entry2) == 0) return (-1); } else { - if (S_ISDIR(entry2->type)) return (1); + if (compare_is_directory(entry2)) return (1); } if (S_ISREG(entry1->type)) { if (S_ISREG(entry2->type) == 0) return (-1); @@ -221,11 +231,11 @@ static int compare_size(const void *a1, const void *a2) /* type is equal to stat.st_mode */ - if (S_ISDIR(entry1->type)) { - if (S_ISDIR(entry2->type) == 0) return (-1); + if (compare_is_directory(entry1)) { + if (compare_is_directory(entry2) == 0) return (-1); } else { - if (S_ISDIR(entry2->type)) return (1); + if (compare_is_directory(entry2)) return (1); } if (S_ISREG(entry1->type)) { if (S_ISREG(entry2->type) == 0) return (-1); @@ -262,11 +272,11 @@ static int compare_extension(const void *a1, const void *a2) /* type is equal to stat.st_mode */ - if (S_ISDIR(entry1->type)) { - if (S_ISDIR(entry2->type) == 0) return (-1); + if (compare_is_directory(entry1)) { + if (compare_is_directory(entry2) == 0) return (-1); } else { - if (S_ISDIR(entry2->type)) return (1); + if (compare_is_directory(entry2)) return (1); } if (S_ISREG(entry1->type)) { if (S_ISREG(entry2->type) == 0) return (-1); diff --git a/source/blender/editors/space_file/filesel.c b/source/blender/editors/space_file/filesel.c index 85e4d255603..9d762c80405 100644 --- a/source/blender/editors/space_file/filesel.c +++ b/source/blender/editors/space_file/filesel.c @@ -59,6 +59,7 @@ #include "BLI_dynstr.h" #include "BLI_utildefines.h" #include "BLI_fileops_types.h" +#include "BLI_fnmatch.h" #include "BKE_context.h" #include "BKE_global.h" @@ -81,12 +82,6 @@ #include "file_intern.h" #include "filelist.h" -#if defined WIN32 && !defined _LIBC -# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ -#else -# include <fnmatch.h> -#endif - FileSelectParams *ED_fileselect_get_params(struct SpaceFile *sfile) { if (!sfile->params) { @@ -115,6 +110,7 @@ short ED_fileselect_set_params(SpaceFile *sfile) /* set the parameters from the operator, if it exists */ if (op) { + PropertyRNA *prop; const short is_files = (RNA_struct_find_property(op->ptr, "files") != NULL); const short is_filepath = (RNA_struct_find_property(op->ptr, "filepath") != NULL); const short is_filename = (RNA_struct_find_property(op->ptr, "filename") != NULL); @@ -163,30 +159,30 @@ short ED_fileselect_set_params(SpaceFile *sfile) } params->filter = 0; - if (RNA_struct_find_property(op->ptr, "filter_blender")) - params->filter |= RNA_boolean_get(op->ptr, "filter_blender") ? BLENDERFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_backup")) - params->filter |= RNA_boolean_get(op->ptr, "filter_backup") ? BLENDERFILE_BACKUP : 0; - if (RNA_struct_find_property(op->ptr, "filter_image")) - params->filter |= RNA_boolean_get(op->ptr, "filter_image") ? IMAGEFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_movie")) - params->filter |= RNA_boolean_get(op->ptr, "filter_movie") ? MOVIEFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_python")) - params->filter |= RNA_boolean_get(op->ptr, "filter_python") ? PYSCRIPTFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_font")) - params->filter |= RNA_boolean_get(op->ptr, "filter_font") ? FTFONTFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_sound")) - params->filter |= RNA_boolean_get(op->ptr, "filter_sound") ? SOUNDFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_text")) - params->filter |= RNA_boolean_get(op->ptr, "filter_text") ? TEXTFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_folder")) - params->filter |= RNA_boolean_get(op->ptr, "filter_folder") ? FOLDERFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_btx")) - params->filter |= RNA_boolean_get(op->ptr, "filter_btx") ? BTXFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_collada")) - params->filter |= RNA_boolean_get(op->ptr, "filter_collada") ? COLLADAFILE : 0; - if (RNA_struct_find_property(op->ptr, "filter_glob")) { - RNA_string_get(op->ptr, "filter_glob", params->filter_glob); + if ((prop = RNA_struct_find_property(op->ptr, "filter_blender"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_backup"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BLENDERFILE_BACKUP : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_image"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? IMAGEFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_movie"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? MOVIEFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_python"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? PYSCRIPTFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_font"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FTFONTFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_sound"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? SOUNDFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_text"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? TEXTFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_folder"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? FOLDERFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_btx"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? BTXFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_collada"))) + params->filter |= RNA_property_boolean_get(op->ptr, prop) ? COLLADAFILE : 0; + if ((prop = RNA_struct_find_property(op->ptr, "filter_glob"))) { + RNA_property_string_get(op->ptr, prop, params->filter_glob); params->filter |= (OPERATORFILE | FOLDERFILE); } else { diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 6f3d0367574..9758e2e9135 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -148,7 +148,6 @@ static void file_free(SpaceLink *sl) static void file_init(wmWindowManager *UNUSED(wm), ScrArea *sa) { SpaceFile *sfile = (SpaceFile *)sa->spacedata.first; - //printf("file_init\n"); /* refresh system directory list */ fsmenu_refresh_system_category(fsmenu_get()); @@ -313,7 +312,6 @@ static void file_main_area_draw(const bContext *C, ARegion *ar) /* draw entirely, view changes should be handled here */ SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); - FileLayout *layout = NULL; View2D *v2d = &ar->v2d; View2DScrollers *scrollers; @@ -323,15 +321,14 @@ static void file_main_area_draw(const bContext *C, ARegion *ar) if (!sfile->files || filelist_empty(sfile->files)) file_refresh(C, NULL); - layout = ED_fileselect_get_layout(sfile, ar); - /* clear and setup matrix */ UI_GetThemeColor3fv(TH_BACK, col); glClearColor(col[0], col[1], col[2], 0.0); glClear(GL_COLOR_BUFFER_BIT); /* Allow dynamically sliders to be set, saves notifiers etc. */ - if (layout && (layout->flag == FILE_LAYOUT_VER)) { + + if (params->display == FILE_IMGDISPLAY) { v2d->scroll = V2D_SCROLL_RIGHT; v2d->keepofs &= ~V2D_LOCKOFS_Y; v2d->keepofs |= V2D_LOCKOFS_X; diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 9d22d6fcc95..5546682e470 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -882,8 +882,12 @@ static void delete_graph_keys(bAnimContext *ac) delete_fcurve_keys(fcu); /* Only delete curve too if it won't be doing anything anymore */ - if ((fcu->totvert == 0) && (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0)) + if ((fcu->totvert == 0) && + (list_has_suitable_fmodifier(&fcu->modifiers, 0, FMI_TYPE_GENERATE_CURVE) == 0) && + (fcu->driver == NULL)) + { ANIM_fcurve_delete_from_animdata(ac, adt, fcu); + } } /* free filtered list */ @@ -1676,7 +1680,7 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) /* FIXME: there are more complicated methods that will be needed to fix more cases than just some */ for (f = 0; f < 3; f++) { FCurve *fcu = euf->fcurves[f]; - BezTriple *bezt, *prev = NULL; + BezTriple *bezt, *prev; unsigned int i; /* skip if not enough vets to do a decent analysis of... */ @@ -1684,29 +1688,19 @@ static int graphkeys_euler_filter_exec(bContext *C, wmOperator *op) continue; /* prev follows bezt, bezt = "current" point to be fixed */ - for (i = 0, bezt = fcu->bezt; i < fcu->totvert; i++, prev = bezt, bezt++) { - /* our method depends on determining a "difference" from the previous vert */ - if (prev == NULL) - continue; + /* our method depends on determining a "difference" from the previous vert */ + for (i = 1, prev = fcu->bezt, bezt = fcu->bezt + 1; i < fcu->totvert; i++, prev = bezt++) { + const float sign = (prev->vec[1][1] > bezt->vec[1][1]) ? 1.0f : -1.0f; /* > 180 degree flip? */ - if (fabs(prev->vec[1][1] - bezt->vec[1][1]) >= M_PI) { + if ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) { /* 360 degrees to add/subtract frame value until difference is acceptably small that there's no more flip */ - const float fac = 2.0f * (float)M_PI; + const float fac = sign * 2.0f * (float)M_PI; - if (prev->vec[1][1] > bezt->vec[1][1]) { - while (fabsf(bezt->vec[1][1] - prev->vec[1][1]) >= (float)M_PI) { - bezt->vec[0][1] += fac; - bezt->vec[1][1] += fac; - bezt->vec[2][1] += fac; - } - } - else { /* if (prev->vec[1][1] < bezt->vec[1][1]) */ - while (fabsf(bezt->vec[1][1] - prev->vec[1][1]) >= (float)M_PI) { - bezt->vec[0][1] -= fac; - bezt->vec[1][1] -= fac; - bezt->vec[2][1] -= fac; - } + while ((sign * (prev->vec[1][1] - bezt->vec[1][1])) >= (float)M_PI) { + bezt->vec[0][1] += fac; + bezt->vec[1][1] += fac; + bezt->vec[2][1] += fac; } } } diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index cbec3072c44..d87bd9a5077 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -149,17 +149,37 @@ static void deselect_graph_keys(bAnimContext *ac, short test, short sel, short d static int graphkeys_deselectall_exec(bContext *C, wmOperator *op) { bAnimContext ac; + bAnimListElem *ale_active = NULL; /* get editor data */ if (ANIM_animdata_get_context(C, &ac) == 0) return OPERATOR_CANCELLED; - + + /* find active F-Curve, and preserve this for later + * or else it becomes annoying with the current active + * curve keeps fading out even while you're editing it + */ + ale_active = get_active_fcurve_channel(&ac); + /* 'standard' behavior - check if selected, then apply relevant selection */ if (RNA_boolean_get(op->ptr, "invert")) deselect_graph_keys(&ac, 0, SELECT_INVERT, TRUE); else deselect_graph_keys(&ac, 1, SELECT_ADD, TRUE); + /* restore active F-Curve... */ + if (ale_active) { + FCurve *fcu = (FCurve *)ale_active->data; + + /* all others should not be disabled, so we should be able to just set this directly... + * - selection needs to be set too, or else this won't work... + */ + fcu->flag |= (FCURVE_SELECTED | FCURVE_ACTIVE); + + MEM_freeN(ale_active); + ale_active = NULL; + } + /* set notifier that things have changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); @@ -1049,10 +1069,7 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches) /* if list only has 1 item, remove it from the list and return */ if (matches->first == matches->last) { /* need to remove from the list, otherwise it gets freed and then we can't return it */ - nvi = matches->first; - BLI_remlink(matches, nvi); - - return nvi; + return BLI_pophead(matches); } /* try to find the first selected F-Curve vert, then take the one after it */ @@ -1075,9 +1092,7 @@ static tNearestVertInfo *get_best_nearest_fcurve_vert(ListBase *matches) /* if we're still here, this means that we failed to find anything appropriate in the first pass, * so just take the first item now... */ - nvi = matches->first; - BLI_remlink(matches, nvi); - return nvi; + return BLI_pophead(matches); } /* Find the nearest vertices (either a handle or the keyframe) that are nearest to the mouse cursor (in area coordinates) diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 2da3f3adb67..6a3259e030e 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -646,12 +646,13 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot) * Default behavior is to reset the position of the image and set the zoom to 1 * If the image will not fit within the window rectangle, the zoom is adjusted */ -static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op)) +static int image_view_all_exec(bContext *C, wmOperator *op) { SpaceImage *sima; ARegion *ar; float aspx, aspy, zoomx, zoomy, w, h; int width, height; + int fit_view = RNA_boolean_get(op->ptr, "fit_view"); /* retrieve state */ sima = CTX_wm_space_image(C); @@ -667,14 +668,25 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op)) width = BLI_rcti_size_x(&ar->winrct) + 1; height = BLI_rcti_size_y(&ar->winrct) + 1; - if ((w >= width || h >= height) && (width > 0 && height > 0)) { - /* find the zoom value that will fit the image in the image space */ - zoomx = width / w; - zoomy = height / h; - sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL); + if (fit_view) { + const int margin = 5; /* margin from border */ + + zoomx = (float) width / (w + 2 * margin); + zoomy = (float) height / (h + 2 * margin); + + sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL); + } + else { + if ((w >= width || h >= height) && (width > 0 && height > 0)) { + zoomx = (float) width / w; + zoomy = (float) height / h; + + /* find the zoom value that will fit the image in the image space */ + sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL); + } + else + sima_zoom_set(sima, ar, 1.0f, NULL); } - else - sima_zoom_set(sima, ar, 1.0f, NULL); sima->xof = sima->yof = 0.0f; @@ -685,6 +697,8 @@ static int image_view_all_exec(bContext *C, wmOperator *UNUSED(op)) void IMAGE_OT_view_all(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "View All"; ot->idname = "IMAGE_OT_view_all"; @@ -693,6 +707,10 @@ void IMAGE_OT_view_all(wmOperatorType *ot) /* api callbacks */ ot->exec = image_view_all_exec; ot->poll = space_image_main_area_poll; + + /* properties */ + prop = RNA_def_boolean(ot->srna, "fit_view", 0, "Fit View", "Fit frame to the viewport"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /********************** view selected operator *********************/ @@ -1318,7 +1336,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id); const short relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); const short save_copy = (RNA_struct_find_property(op->ptr, "copy") && RNA_boolean_get(op->ptr, "copy")); - const short save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); + const bool save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") && RNA_boolean_get(op->ptr, "save_as_render")); ImageFormatData *imf = &simopts->im_format; short ok = FALSE; @@ -1344,7 +1362,7 @@ static void save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveI } } - colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, TRUE, &imf->view_settings, &imf->display_settings, imf); + colormanaged_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, save_as_render, true, &imf->view_settings, &imf->display_settings, imf); if (simopts->im_format.imtype == R_IMF_IMTYPE_MULTILAYER) { Scene *scene = CTX_data_scene(C); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index c0ef59e9e25..5a8292abcab 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -277,6 +277,10 @@ static void image_keymap(struct wmKeyConfig *keyconf) keymap = WM_keymap_find(keyconf, "Image", SPACE_IMAGE, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_all", HOMEKEY, KM_PRESS, 0, 0); + + kmi = WM_keymap_add_item(keymap, "IMAGE_OT_view_all", FKEY, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "fit_view", TRUE); + WM_keymap_add_item(keymap, "IMAGE_OT_view_selected", PADPERIOD, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); @@ -670,7 +674,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) } else if (sima->mode == SI_MODE_MASK) { mask = ED_space_image_get_mask(sima); - draw_image_cursor(sima, ar); + draw_image_cursor(ar, sima->cursor); } ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); @@ -719,7 +723,7 @@ static void image_main_area_draw(const bContext *C, ARegion *ar) ED_mask_draw_frames(mask, ar, CFRA, mask->sfra, mask->efra); - draw_image_cursor(sima, ar); + draw_image_cursor(ar, sima->cursor); } /* scrollers? */ diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index 98c9c8d15fe..c1cddf092aa 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -115,8 +115,8 @@ static void stats_object(Object *ob, int sel, int totob, SceneStats *stats) { int totv = 0, totf = 0, tottri = 0; - if (ob->disp.first) - BKE_displist_count(&ob->disp, &totv, &totf, &tottri); + if (ob->curve_cache && ob->curve_cache->disp.first) + BKE_displist_count(&ob->curve_cache->disp, &totv, &totf, &tottri); totv *= totob; totf *= totob; diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index aed5699a9d7..2c89d6f6448 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -427,8 +427,6 @@ static const char *sensor_name(int type) switch (type) { case SENS_ALWAYS: return "Always"; - case SENS_TOUCH: - return "Touch"; case SENS_NEAR: return "Near"; case SENS_KEYBOARD: @@ -1233,11 +1231,6 @@ static void draw_sensor_ray(uiLayout *layout, PointerRNA *ptr, bContext *C) uiItemR(row, ptr, "use_x_ray", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); } -static void draw_sensor_touch(uiLayout *layout, PointerRNA *ptr) -{ - uiItemR(layout, ptr, "material", 0, NULL, ICON_NONE); -} - static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C) { uiLayout *box; @@ -1292,9 +1285,6 @@ static void draw_brick_sensor(uiLayout *layout, PointerRNA *ptr, bContext *C) case SENS_RAY: draw_sensor_ray(box, ptr, C); break; - case SENS_TOUCH: - draw_sensor_touch(box, ptr); - break; } } diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 5cc22b25f72..4e98c9fd894 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -809,9 +809,13 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin } static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) -{ +{ + uiItemR(layout, ptr, "sky_type", 0, "", ICON_NONE); uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE); uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE); + + if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) + uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE); } static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -907,6 +911,11 @@ static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), Point uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); } +static void node_shader_buts_subsurface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE); +} + static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiItemR(layout, ptr, "component", 0, "", ICON_NONE); @@ -1039,6 +1048,9 @@ static void node_shader_set_butfunc(bNodeType *ntype) case SH_NODE_BSDF_REFRACTION: ntype->uifunc = node_shader_buts_glossy; break; + case SH_NODE_SUBSURFACE_SCATTERING: + ntype->uifunc = node_shader_buts_subsurface; + break; case SH_NODE_BSDF_TOON: ntype->uifunc = node_shader_buts_toon; break; @@ -1620,12 +1632,14 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C active_index = RNA_int_get(ptr, "active_input_index"); /* using different collection properties if multilayer format is enabled */ if (multilayer) { - uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0); + uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "layer_slots", ptr, "active_input_index", + 0, 0, 0, 0); RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"), active_index, &active_input_ptr); } else { - uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0); + uiTemplateList(col, C, "UI_UL_list", "file_output_node", ptr, "file_slots", ptr, "active_input_index", + 0, 0, 0, 0); RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"), active_index, &active_input_ptr); } @@ -3061,7 +3075,16 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa { float dist, vec[4][2]; float deltax, deltay; + float cursor[2] = {0.0f, 0.0f}; int toreroute, fromreroute; + + /* this function can be called with snode null (via cut_links_intersect) */ + /* XXX map snode->cursor back to view space */ + if (snode) { + cursor[0] = snode->cursor[0] * UI_DPI_FAC; + cursor[1] = snode->cursor[1] * UI_DPI_FAC; + } + /* in v0 and v3 we put begin/end points */ if (link->fromsock) { vec[0][0] = link->fromsock->locx; @@ -3070,7 +3093,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa } else { if (snode == NULL) return 0; - copy_v2_v2(vec[0], snode->cursor); + copy_v2_v2(vec[0], cursor); fromreroute = 0; } if (link->tosock) { @@ -3080,7 +3103,7 @@ int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, floa } else { if (snode == NULL) return 0; - copy_v2_v2(vec[3], snode->cursor); + copy_v2_v2(vec[3], cursor); toreroute = 0; } diff --git a/source/blender/editors/space_node/node_add.c b/source/blender/editors/space_node/node_add.c index c9618daa7c5..00769975893 100644 --- a/source/blender/editors/space_node/node_add.c +++ b/source/blender/editors/space_node/node_add.c @@ -84,10 +84,6 @@ bNode *node_add_node(const bContext *C, const char *idname, int type, float locx node->locy = locy + 60.0f; /* arbitrary... so its visible, (0,0) is top of node */ nodeSetSelected(node, TRUE); - /* node location is mapped */ - locx /= UI_DPI_FAC; - locy /= UI_DPI_FAC; - node->locx = locx; node->locy = locy + 60.0f; @@ -215,7 +211,7 @@ static int add_reroute_exec(bContext *C, wmOperator *op) int i = 0; /* Get the cut path */ - RNA_BEGIN(op->ptr, itemptr, "path") + RNA_BEGIN (op->ptr, itemptr, "path") { float loc[2]; @@ -417,9 +413,8 @@ static int node_add_mask_poll(bContext *C) return ED_operator_node_editable(C) && snode->nodetree->type == NTREE_COMPOSIT; } -static int node_add_mask_invoke(bContext *C, wmOperator *op, const wmEvent *event) +static int node_add_mask_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); SpaceNode *snode = CTX_wm_space_node(C); bNode *node; ID *mask = NULL; @@ -435,9 +430,6 @@ static int node_add_mask_invoke(bContext *C, wmOperator *op, const wmEvent *even ED_preview_kill_jobs(C); - /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], - &snode->cursor[0], &snode->cursor[1]); node = node_add_node(C, NULL, CMP_NODE_MASK, snode->cursor[0], snode->cursor[1]); if (!node) { @@ -462,7 +454,7 @@ void NODE_OT_add_mask(wmOperatorType *ot) ot->idname = "NODE_OT_add_mask"; /* callbacks */ - ot->invoke = node_add_mask_invoke; + ot->exec = node_add_mask_exec; ot->poll = node_add_mask_poll; /* flags */ diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index f95e895bef2..53b373e728e 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -145,13 +145,15 @@ static void node_tree_interface_panel(const bContext *C, Panel *pa) split = uiLayoutRow(row, TRUE); col = uiLayoutColumn(split, TRUE); uiItemL(col, IFACE_("Inputs:"), ICON_NONE); - uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", 0, 0, 0); + uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "inputs", &ptr, "inputs", &ptr, "active_input", + 0, 0, 0, 0); opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_IN); col = uiLayoutColumn(split, TRUE); uiItemL(col, IFACE_("Outputs:"), ICON_NONE); - uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", 0, 0, 0); + uiTemplateList(col, (bContext *)C, "NODE_UL_interface_sockets", "outputs", &ptr, "outputs", &ptr, "active_output", + 0, 0, 0, 0); opptr = uiItemFullO(col, "NODE_OT_tree_socket_add", "", ICON_PLUS, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_O_RETURN_PROPS); RNA_enum_set(&opptr, "in_out", SOCK_OUT); diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index dce04bb8c42..b40a7e4702e 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -1075,31 +1075,31 @@ int node_get_resize_cursor(int directions) return CURSOR_EDIT; } -void node_set_cursor(wmWindow *win, SpaceNode *snode) +void node_set_cursor(wmWindow *win, SpaceNode *snode, float cursor[2]) { bNodeTree *ntree = snode->edittree; bNode *node; bNodeSocket *sock; - int cursor = CURSOR_STD; + int wmcursor = CURSOR_STD; if (ntree) { - if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN | SOCK_OUT)) { + if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN | SOCK_OUT)) { /* pass */ } else { /* check nodes front to back */ for (node = ntree->nodes.last; node; node = node->prev) { - if (BLI_rctf_isect_pt(&node->totr, snode->cursor[0], snode->cursor[1])) + if (BLI_rctf_isect_pt(&node->totr, cursor[0], cursor[1])) break; /* first hit on node stops */ } if (node) { - int dir = node->typeinfo->resize_area_func(node, snode->cursor[0], snode->cursor[1]); - cursor = node_get_resize_cursor(dir); + int dir = node->typeinfo->resize_area_func(node, cursor[0], cursor[1]); + wmcursor = node_get_resize_cursor(dir); } } } - WM_cursor_set(win, cursor); + WM_cursor_set(win, wmcursor); } void node_draw_default(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node, bNodeInstanceKey key) @@ -1251,6 +1251,7 @@ static void draw_group_overlay(const bContext *C, ARegion *ar) void drawnodespace(const bContext *C, ARegion *ar) { + wmWindow *win = CTX_wm_window(C); View2DScrollers *scrollers; SpaceNode *snode = CTX_wm_space_node(C); View2D *v2d = &ar->v2d; @@ -1259,7 +1260,13 @@ void drawnodespace(const bContext *C, ARegion *ar) glClear(GL_COLOR_BUFFER_BIT); UI_view2d_view_ortho(v2d); - + + /* XXX snode->cursor set in coordspace for placing new nodes, used for drawing noodles too */ + UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin, + &snode->cursor[0], &snode->cursor[1]); + snode->cursor[0] /= UI_DPI_FAC; + snode->cursor[1] /= UI_DPI_FAC; + ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); /* only set once */ diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index b7e9cb0268f..3ba749a8eff 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1056,7 +1056,7 @@ void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set) /* checks snode->mouse position, and returns found node/socket */ /* type is SOCK_IN and/or SOCK_OUT */ -int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, int in_out) +int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **sockp, float cursor[2], int in_out) { bNode *node; bNodeSocket *sock; @@ -1068,10 +1068,10 @@ int node_find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **so /* check if we click in a socket */ for (node = snode->edittree->nodes.first; node; node = node->next) { - rect.xmin = snode->cursor[0] - (NODE_SOCKSIZE + 4); - rect.ymin = snode->cursor[1] - (NODE_SOCKSIZE + 4); - rect.xmax = snode->cursor[0] + (NODE_SOCKSIZE + 4); - rect.ymax = snode->cursor[1] + (NODE_SOCKSIZE + 4); + rect.xmin = cursor[0] - (NODE_SOCKSIZE + 4); + rect.ymin = cursor[1] - (NODE_SOCKSIZE + 4); + rect.xmax = cursor[0] + (NODE_SOCKSIZE + 4); + rect.ymax = cursor[1] + (NODE_SOCKSIZE + 4); if (!(node->flag & NODE_HIDDEN)) { /* extra padding inside and out - allow dragging on the text areas too */ @@ -2087,17 +2087,6 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -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); - - /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); - - return node_clipboard_paste_exec(C, op); -} - void NODE_OT_clipboard_paste(wmOperatorType *ot) { /* identifiers */ @@ -2107,7 +2096,6 @@ void NODE_OT_clipboard_paste(wmOperatorType *ot) /* api callbacks */ ot->exec = node_clipboard_paste_exec; - ot->invoke = node_clipboard_paste_invoke; ot->poll = ED_operator_node_editable; /* flags */ diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 1a2e90e5522..9b7b00fba00 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -84,7 +84,7 @@ void node_draw_nodetree(const struct bContext *C, struct ARegion *ar, struct Spa struct bNodeTree *ntree, bNodeInstanceKey parent_key); void drawnodespace(const bContext *C, ARegion *ar); -void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode); +void node_set_cursor(struct wmWindow *win, struct SpaceNode *snode, float cursor[2]); /* DPI scaled coords */ void node_to_view(struct bNode *node, float x, float y, float *rx, float *ry); void node_from_view(struct bNode *node, float x, float y, float *rx, float *ry); @@ -129,6 +129,7 @@ void NODE_OT_view_selected(struct wmOperatorType *ot); void NODE_OT_backimage_move(struct wmOperatorType *ot); void NODE_OT_backimage_zoom(struct wmOperatorType *ot); +void NODE_OT_backimage_fit(struct wmOperatorType *ot); void NODE_OT_backimage_sample(struct wmOperatorType *ot); /* drawnode.c */ @@ -182,7 +183,7 @@ int composite_node_editable(struct bContext *C); int node_has_hidden_sockets(bNode *node); void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set); int node_render_changed_exec(bContext *, struct wmOperator *); -int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, int in_out); +int node_find_indicated_socket(struct SpaceNode *snode, struct bNode **nodep, struct bNodeSocket **sockp, float cursor[2], int in_out); void NODE_OT_duplicate(struct wmOperatorType *ot); void NODE_OT_delete(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 566bb1600cc..f0d3deb24df 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -98,6 +98,7 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_backimage_move); WM_operatortype_append(NODE_OT_backimage_zoom); + WM_operatortype_append(NODE_OT_backimage_fit); WM_operatortype_append(NODE_OT_backimage_sample); WM_operatortype_append(NODE_OT_add_file); @@ -249,6 +250,7 @@ void node_keymap(struct wmKeyConfig *keyconf) RNA_float_set(kmi->ptr, "factor", 0.83333f); kmi = WM_keymap_add_item(keymap, "NODE_OT_backimage_zoom", VKEY, KM_PRESS, KM_ALT, 0); RNA_float_set(kmi->ptr, "factor", 1.2f); + WM_keymap_add_item(keymap, "NODE_OT_backimage_fit", HOMEKEY, KM_PRESS, KM_ALT, 0); WM_keymap_add_item(keymap, "NODE_OT_backimage_sample", ACTIONMOUSE, KM_PRESS, KM_ALT, 0); kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 244b222811e..4b5cc9e42b6 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -443,18 +443,19 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) bNodeSocket *tsock = NULL; bNodeLink *link; LinkData *linkdata; + float cursor[2]; int in_out; in_out = nldrag->in_out; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], - &snode->cursor[0], &snode->cursor[1]); + &cursor[0], &cursor[1]); switch (event->type) { case MOUSEMOVE: if (in_out == SOCK_OUT) { - if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) { + if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_IN)) { for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; @@ -480,7 +481,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) } } else { - if (node_find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) { + if (node_find_indicated_socket(snode, &tnode, &tsock, cursor, SOCK_OUT)) { for (linkdata = nldrag->links.first; linkdata; linkdata = linkdata->next) { link = linkdata->data; @@ -550,7 +551,7 @@ static int node_link_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* return 1 when socket clicked */ -static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) +static bNodeLinkDrag *node_link_init(SpaceNode *snode, float cursor[2], int detach) { bNode *node; bNodeSocket *sock; @@ -560,7 +561,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) int num_links; /* output indicated? */ - if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) { + if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); num_links = nodeCountSocketLinks(snode->edittree, sock); @@ -596,7 +597,7 @@ static bNodeLinkDrag *node_link_init(SpaceNode *snode, int detach) } } /* or an input? */ - else if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) { + else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { nldrag = MEM_callocN(sizeof(bNodeLinkDrag), "drag link op customdata"); num_links = nodeCountSocketLinks(snode->edittree, sock); @@ -644,14 +645,16 @@ 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); bNodeLinkDrag *nldrag; + float cursor[2]; + int detach = RNA_boolean_get(op->ptr, "detach"); UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], - &snode->cursor[0], &snode->cursor[1]); + &cursor[0], &cursor[1]); ED_preview_kill_jobs(C); - nldrag = node_link_init(snode, detach); + nldrag = node_link_init(snode, cursor, detach); if (nldrag) { op->customdata = nldrag; @@ -762,7 +765,7 @@ static int cut_links_exec(bContext *C, wmOperator *op) float mcoords[256][2]; int i = 0; - RNA_BEGIN(op->ptr, itemptr, "path") + RNA_BEGIN (op->ptr, itemptr, "path") { float loc[2]; @@ -1065,18 +1068,23 @@ void NODE_OT_join(wmOperatorType *ot) /* ****************** Attach ******************* */ -static int node_attach_exec(bContext *C, wmOperator *UNUSED(op)) +static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { + ARegion *ar = CTX_wm_region(C); SpaceNode *snode = CTX_wm_space_node(C); bNodeTree *ntree = snode->edittree; bNode *frame; + float cursor[2]; + + /* convert mouse coordinates to v2d space */ + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &cursor[0], &cursor[1]); /* check nodes front to back */ for (frame = ntree->nodes.last; frame; frame = frame->prev) { /* skip selected, those are the nodes we want to attach */ if ((frame->type != NODE_FRAME) || (frame->flag & NODE_SELECT)) continue; - if (BLI_rctf_isect_pt(&frame->totr, snode->cursor[0], snode->cursor[1])) + if (BLI_rctf_isect_pt(&frame->totr, cursor[0], cursor[1])) break; } if (frame) { @@ -1116,16 +1124,6 @@ static int node_attach_exec(bContext *C, wmOperator *UNUSED(op)) return OPERATOR_FINISHED; } -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); - - /* convert mouse coordinates to v2d space */ - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &snode->cursor[0], &snode->cursor[1]); - - return node_attach_exec(C, op); -} void NODE_OT_attach(wmOperatorType *ot) { @@ -1135,7 +1133,7 @@ void NODE_OT_attach(wmOperatorType *ot) ot->idname = "NODE_OT_attach"; /* api callbacks */ - ot->exec = node_attach_exec; + ot->invoke = node_attach_invoke; ot->poll = ED_operator_node_editable; diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index e17699309ef..6ce31783bff 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -306,24 +306,21 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i { bNode *node, *tnode; bNodeSocket *sock, *tsock; - float mx, my; + float cursor[2]; int selected = 0; /* get mouse coordinates in view2d space */ - UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &mx, &my); - /* node_find_indicated_socket uses snode->mx/my */ - snode->cursor[0] = mx; - snode->cursor[1] = my; + UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &cursor[0], &cursor[1]); if (extend) { /* first do socket selection, these generally overlap with nodes. * socket selection only in extend mode. */ - if (node_find_indicated_socket(snode, &node, &sock, SOCK_IN)) { + if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_IN)) { node_socket_toggle(node, sock, 1); selected = 1; } - else if (node_find_indicated_socket(snode, &node, &sock, SOCK_OUT)) { + else if (node_find_indicated_socket(snode, &node, &sock, cursor, SOCK_OUT)) { if (sock->flag & SELECT) { node_socket_deselect(node, sock, 1); } @@ -341,7 +338,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i } else { /* find the closest visible node */ - node = node_under_mouse_select(snode->edittree, mx, my); + node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]); if (node) { if ((node->flag & SELECT) && (node->flag & NODE_ACTIVE) == 0) { @@ -362,7 +359,7 @@ static int node_mouse_select(Main *bmain, SpaceNode *snode, ARegion *ar, const i else { /* extend == 0 */ /* find the closest visible node */ - node = node_under_mouse_select(snode->edittree, mx, my); + node = node_under_mouse_select(snode->edittree, cursor[0], cursor[1]); if (node) { for (tnode = snode->edittree->nodes.first; tnode; tnode = tnode->next) { diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 9e6e1e628f6..e47a1315663 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -327,6 +327,60 @@ void NODE_OT_backimage_zoom(wmOperatorType *ot) RNA_def_float(ot->srna, "factor", 1.2f, 0.0f, 10.0f, "Factor", "", 0.0f, 10.0f); } +static int backimage_fit_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceNode *snode = CTX_wm_space_node(C); + ARegion *ar = CTX_wm_region(C); + + Image *ima; + ImBuf *ibuf; + + const float pad = 32.0f; + + void *lock; + + float facx, facy; + + ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node"); + ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock); + + if (ibuf == NULL) { + BKE_image_release_ibuf(ima, ibuf, lock); + return OPERATOR_CANCELLED; + } + + facx = 1.0f * (ar->sizex - pad) / (ibuf->x * snode->zoom); + facy = 1.0f * (ar->sizey - pad) / (ibuf->y * snode->zoom); + + BKE_image_release_ibuf(ima, ibuf, lock); + + snode->zoom *= min_ff(facx, facy); + + snode->xof = 0; + snode->yof = 0; + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void NODE_OT_backimage_fit(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name = "Background Image Fit"; + ot->idname = "NODE_OT_backimage_fit"; + ot->description = "Zoom in/out the background image"; + + /* api callbacks */ + ot->exec = backimage_fit_exec; + ot->poll = composite_node_active; + + /* flags */ + ot->flag = OPTYPE_BLOCKING; + +} + /******************** sample backdrop operator ********************/ typedef struct ImageSampleInfo { diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 922912fa540..a59b2fc21df 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -602,8 +602,14 @@ static void node_cursor(wmWindow *win, ScrArea *sa, ARegion *ar) /* convert mouse coordinates to v2d space */ UI_view2d_region_to_view(&ar->v2d, win->eventstate->x - ar->winrct.xmin, win->eventstate->y - ar->winrct.ymin, &snode->cursor[0], &snode->cursor[1]); + + /* here snode->cursor is used to detect the node edge for sizing */ + node_set_cursor(win, snode, snode->cursor); - node_set_cursor(win, snode); + /* XXX snode->cursor is in placing new nodes space */ + snode->cursor[0] /= UI_DPI_FAC; + snode->cursor[1] /= UI_DPI_FAC; + } /* Initialize main area, setting handlers. */ diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 44d5672e7da..6200b98350f 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1389,6 +1389,8 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto tselem_draw_icon_uibut(&arg, ICON_GROUP); break; case ID_LI: tselem_draw_icon_uibut(&arg, ICON_LIBRARY_DATA_DIRECT); break; + case ID_LS: + tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break; /* FIXME proper icon */ } } } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 1e9b681197c..2de8f52d677 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -1469,7 +1469,7 @@ static int parent_drop_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "child", childname); ob = (Object *)BKE_libblock_find_name(ID_OB, childname); - ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE); + ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL); DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); @@ -1525,7 +1525,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) } if ((par->type != OB_ARMATURE) && (par->type != OB_CURVE) && (par->type != OB_LATTICE)) { - if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, FALSE, FALSE)) { + if (ED_object_parent_set(op->reports, bmain, scene, ob, par, partype, false, false, NULL)) { DAG_relations_tag_update(bmain); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_PARENT, NULL); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index c1950e62817..a0af9340fe2 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -57,6 +57,7 @@ #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_sequencer.h" +#include "BKE_treehash.h" #include "ED_armature.h" #include "ED_object.h" @@ -113,7 +114,7 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb, case ID_LA: case ID_AR: case ID_CA: case ID_SPK: case ID_MA: case ID_TE: case ID_IP: case ID_IM: case ID_SO: case ID_KE: case ID_WO: case ID_AC: - case ID_NLA: case ID_TXT: case ID_GR: + case ID_NLA: case ID_TXT: case ID_GR: case ID_LS: if (*idlevel == 0) *idlevel = idcode; else if (*idlevel != idcode) *idlevel = -1; break; @@ -299,17 +300,13 @@ static void object_delete_cb(bContext *C, Scene *scene, TreeElement *te, if (base == NULL) base = BKE_scene_base_find(scene, (Object *)tselem->id); if (base) { - SpaceOops *soops = CTX_wm_space_outliner(C); - // check also library later if (scene->obedit == base->object) ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR | EM_DO_UNDO); ED_base_object_free_and_unlink(CTX_data_main(C), scene, base); te->directdata = NULL; - BLI_ghash_remove(soops->treehash, tselem, NULL, NULL); tselem->id = NULL; - BLI_ghash_insert(soops->treehash, tselem, tselem); } } diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index 404821900df..b86fba1398a 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -32,15 +32,6 @@ #include <math.h> #include <string.h> -#if defined WIN32 && !defined _LIBC || defined __sun -# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ -#else -# ifndef _GNU_SOURCE -# define _GNU_SOURCE -# endif -# include <fnmatch.h> -#endif - #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" @@ -59,12 +50,14 @@ #include "DNA_sequence_types.h" #include "DNA_speaker_types.h" #include "DNA_object_types.h" +#include "DNA_linestyle_types.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math.h" #include "BLI_ghash.h" #include "BLI_mempool.h" +#include "BLI_fnmatch.h" #include "BLF_translation.h" @@ -74,6 +67,7 @@ #include "BKE_modifier.h" #include "BKE_sequencer.h" #include "BKE_idcode.h" +#include "BKE_treehash.h" #include "ED_armature.h" #include "ED_screen.h" @@ -116,9 +110,8 @@ static void outliner_storage_cleanup(SpaceOops *soops) if (BLI_mempool_count(ts) == unused) { BLI_mempool_destroy(ts); soops->treestore = NULL; - if (soops->treehash) { - BLI_ghash_free(soops->treehash, NULL, NULL); + BKE_treehash_free(soops->treehash); soops->treehash = NULL; } } @@ -135,14 +128,9 @@ static void outliner_storage_cleanup(SpaceOops *soops) } BLI_mempool_destroy(ts); soops->treestore = new_ts; - if (soops->treehash) { /* update hash table to fix broken pointers */ - BLI_ghash_clear(soops->treehash, NULL, NULL); - BLI_mempool_iternew(soops->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BLI_ghash_insert(soops->treehash, tselem, tselem); - } + BKE_treehash_rebuild_from_treestore(soops->treehash, soops->treestore); } } } @@ -150,63 +138,22 @@ static void outliner_storage_cleanup(SpaceOops *soops) } } -/* This function hashes only by type, nr and id, while cmp function also compares 'used' flag; - * This is done to skip full treehash rebuild in outliner_storage_cleanup */ -static unsigned int tse_hash(const void *ptr) -{ - const TreeStoreElem *tse = (const TreeStoreElem *)ptr; - unsigned int hash; - BLI_assert(tse->type || !tse->nr); - hash = BLI_ghashutil_inthash(SET_INT_IN_POINTER((tse->nr << 16) + tse->type)); - hash ^= BLI_ghashutil_inthash(tse->id); - return hash; -} - -static int tse_cmp(const void *a, const void *b) -{ - const TreeStoreElem *tse_a = (const TreeStoreElem *)a; - const TreeStoreElem *tse_b = (const TreeStoreElem *)b; - return tse_a->type != tse_b->type || tse_a->nr != tse_b->nr || - tse_a->id != tse_b->id || tse_a->used != tse_b->used; -} - -static TreeStoreElem *lookup_treehash(GHash *th, short type, short nr, short used, ID *id) -{ - TreeStoreElem tse_template; - tse_template.type = type; - tse_template.nr = type ? nr : 0; // we're picky! :) - tse_template.id = id; - tse_template.used = used; - return BLI_ghash_lookup(th, &tse_template); -} - static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short type, short nr) { - /* When treestore comes directly from readfile.c, treehash is empty; - * In this case we don't want to get TSE_CLOSED while adding elements one by one, - * that is why this function restores treehash */ - bool restore_treehash = (soops->treestore && !soops->treehash); TreeStoreElem *tselem; if (soops->treestore == NULL) { /* if treestore was not created in readfile.c, create it here */ soops->treestore = BLI_mempool_create(sizeof(TreeStoreElem), 1, 512, BLI_MEMPOOL_ALLOW_ITER); + } if (soops->treehash == NULL) { - soops->treehash = BLI_ghash_new(tse_hash, tse_cmp, "treehash"); - BLI_ghash_flag_set(soops->treehash, GHASH_FLAG_ALLOW_DUPES); - } - - if (restore_treehash) { - BLI_mempool_iter iter; - BLI_mempool_iternew(soops->treestore, &iter); - while ((tselem = BLI_mempool_iterstep(&iter))) { - BLI_ghash_insert(soops->treehash, tselem, tselem); - } + soops->treehash = BKE_treehash_create_from_treestore(soops->treestore); } - /* check for unused tree elements is in treestore */ - tselem = lookup_treehash(soops->treehash, type, nr, 0, id); + /* find any unused tree element in treestore and mark it as used + * (note that there may be multiple unused elements in case of linked objects) */ + tselem = BKE_treehash_lookup_unused(soops->treehash, type, nr, id); if (tselem) { te->store_elem = tselem; tselem->used = 1; @@ -221,7 +168,7 @@ static void check_persistent(SpaceOops *soops, TreeElement *te, ID *id, short ty tselem->used = 0; tselem->flag = TSE_CLOSED; te->store_elem = tselem; - BLI_ghash_insert(soops->treehash, tselem, tselem); + BKE_treehash_add_element(soops->treehash, tselem); } /* ********************************************************* */ @@ -266,7 +213,7 @@ TreeElement *outliner_find_tse(SpaceOops *soops, TreeStoreElem *tse) if (tse->id == NULL) return NULL; /* check if 'tse' is in treestore */ - tselem = lookup_treehash(soops->treehash, tse->type, tse->nr, tse->used, tse->id); + tselem = BKE_treehash_lookup_any(soops->treehash, tse->type, tse->nr, tse->id); if (tselem) return outliner_find_tree_element(&soops->tree, tselem); @@ -430,6 +377,28 @@ static bool outliner_animdata_test(AnimData *adt) return false; } +static void outliner_add_line_styles(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te) +{ + SceneRenderLayer *srl; + FreestyleLineSet *lineset; + + for (srl = sce->r.layers.first; srl; srl = srl->next) { + for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + lineset->linestyle->id.flag |= LIB_DOIT; + } + } + for (srl = sce->r.layers.first; srl; srl = srl->next) { + for (lineset = srl->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + FreestyleLineStyle *linestyle = lineset->linestyle; + + if (!(linestyle->id.flag & LIB_DOIT)) + continue; + linestyle->id.flag &= ~LIB_DOIT; + outliner_add_element(soops, lb, linestyle, te, 0, 0); + } + } +} + static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *sce, TreeElement *te) { SceneRenderLayer *srl; @@ -455,6 +424,8 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s outliner_add_element(soops, lb, sce, te, TSE_ANIM_DATA, 0); outliner_add_element(soops, lb, sce->world, te, 0, 0); + + outliner_add_line_styles(soops, lb, sce, te); } // can be inlined if necessary @@ -813,6 +784,14 @@ static void outliner_add_id_contents(SpaceOops *soops, TreeElement *te, TreeStor } break; } + case ID_LS: + { + FreestyleLineStyle *linestyle = (FreestyleLineStyle *)id; + + if (outliner_animdata_test(linestyle->adt)) + outliner_add_element(soops, &te->subtree, linestyle, te, TSE_ANIM_DATA, 0); + break; + } } } diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 874852ee320..d695ffa46d5 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -43,6 +43,7 @@ #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_scene.h" +#include "BKE_treehash.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -435,7 +436,7 @@ static void outliner_free(SpaceLink *sl) BLI_mempool_destroy(soutliner->treestore); } if (soutliner->treehash) { - BLI_ghash_free(soutliner->treehash, NULL, NULL); + BKE_treehash_free(soutliner->treehash); } } diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 68fd09f5fb7..ebec818bb36 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -1086,10 +1086,10 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq type = GL_FLOAT; if (ibuf->float_colorspace) { - glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, TRUE); + glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->float_colorspace, true); } else { - glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, TRUE); + glsl_used = IMB_colormanagement_setup_glsl_draw_ctx(C, true); } } else if (ibuf->rect) { @@ -1097,7 +1097,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq format = GL_RGBA; type = GL_UNSIGNED_BYTE; - glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, FALSE); + glsl_used = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, false); } else { format = GL_RGBA; diff --git a/source/blender/editors/space_sequencer/sequencer_view.c b/source/blender/editors/space_sequencer/sequencer_view.c index 68428cd890f..18733d4e409 100644 --- a/source/blender/editors/space_sequencer/sequencer_view.c +++ b/source/blender/editors/space_sequencer/sequencer_view.c @@ -152,7 +152,8 @@ static void sample_apply(bContext *C, wmOperator *op, const wmEvent *event) info->colfp = info->colf; /* sequencer's image buffers are in non-linear space, need to make them linear */ - BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->colf); + copy_v4_v4(info->linearcol, info->colf); + BKE_sequencer_pixel_from_sequencer_space_v4(scene, info->linearcol); info->color_manage = TRUE; } diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index 04b2a21bf79..84c6329db53 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -491,6 +491,7 @@ static void sequencer_main_area_listener(bScreen *UNUSED(sc), ScrArea *UNUSED(sa case ND_MARKERS: case ND_RENDER_OPTIONS: /* for FPS and FPS Base */ case ND_SEQUENCER: + case ND_RENDER_RESULT: ED_region_tag_redraw(ar); break; } diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 95fd7fce878..e92cab72042 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -1133,23 +1133,23 @@ static void draw_cursor(SpaceText *st, ARegion *ar) wrap_offset_in_line(st, ar, text->sell, text->selc, &offl, &offc); - y1 = ar->winy - 2 - (vsell - offl) * lheight; - y2 = y1 - (lheight * visible_lines + TXT_LINE_SPACING); + y1 = ar->winy - (vsell - offl) * lheight; + y2 = y1 - (lheight * visible_lines); } else { - y1 = ar->winy - 2 - vsell * lheight; - y2 = y1 - (lheight + TXT_LINE_SPACING); + y1 = ar->winy - vsell * lheight; + y2 = y1 - (lheight); } if (!(y1 < 0 || y2 > ar->winy)) { /* check we need to draw */ - x1 = st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; + x1 = 0; // st->showlinenrs ? TXT_OFFSET + TEXTXLOC : TXT_OFFSET; x2 = x1 + ar->winx; glColor4ub(255, 255, 255, 32); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - glRecti(x1 - 4, y1, x2, y2 + TXT_LINE_SPACING); + glRecti(x1 - 4, y1, x2, y2); glDisable(GL_BLEND); } } @@ -1317,15 +1317,13 @@ void draw_text_main(SpaceText *st, ARegion *ar) int wraplinecount = 0, wrap_skip = 0; int margin_column_x; - /* dpi controlled line height and font size */ - st->lheight_dpi = (U.widget_unit * st->lheight) / 20; - - if (st->lheight_dpi) st->viewlines = (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING); - else st->viewlines = 0; - /* if no text, nothing to do */ if (!text) return; + + /* dpi controlled line height and font size */ + st->lheight_dpi = (U.widget_unit * st->lheight) / 20; + st->viewlines = (st->lheight_dpi) ? (int)ar->winy / (st->lheight_dpi + TXT_LINE_SPACING) : 0; text_update_drawcache(st, ar); diff --git a/source/blender/editors/space_text/text_intern.h b/source/blender/editors/space_text/text_intern.h index 371ccfd9bd9..b4c2062ab00 100644 --- a/source/blender/editors/space_text/text_intern.h +++ b/source/blender/editors/space_text/text_intern.h @@ -54,10 +54,10 @@ void text_scroll_to_cursor(struct SpaceText *st, struct ScrArea *sa); void text_update_cursor_moved(struct bContext *C); /* TXT_OFFSET used to be 35 when the scrollbar was on the left... */ -#define TXT_OFFSET ((int)(0.75f * U.widget_unit)) +#define TXT_OFFSET ((int)(0.2f * U.widget_unit)) #define TXT_SCROLL_WIDTH U.widget_unit #define TXT_SCROLL_SPACE ((int)(0.1f * U.widget_unit)) -#define TXT_LINE_SPACING ((int)(0.2f * U.widget_unit)) /* space between lines */ +#define TXT_LINE_SPACING ((int)(0.3f * st->lheight_dpi)) /* space between lines */ #define TEXTXLOC (st->cwidth * st->linenrs_tot) #define SUGG_LIST_SIZE 7 diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index dec61a0e1ca..2c2a8b255da 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -949,7 +949,7 @@ static int text_indent_exec(bContext *C, wmOperator *UNUSED(op)) text_drawcache_tag_update(CTX_wm_space_text(C), 0); if (txt_has_sel(text)) { - txt_order_cursors(text); + txt_order_cursors(text, false); txt_indent(text); } else @@ -983,7 +983,7 @@ static int text_unindent_exec(bContext *C, wmOperator *UNUSED(op)) text_drawcache_tag_update(CTX_wm_space_text(C), 0); - txt_order_cursors(text); + txt_order_cursors(text, false); txt_unindent(text); text_update_edited(text); @@ -1063,7 +1063,7 @@ static int text_comment_exec(bContext *C, wmOperator *UNUSED(op)) if (txt_has_sel(text)) { text_drawcache_tag_update(CTX_wm_space_text(C), 0); - txt_order_cursors(text); + txt_order_cursors(text, false); txt_comment(text); text_update_edited(text); @@ -1096,7 +1096,7 @@ static int text_uncomment_exec(bContext *C, wmOperator *UNUSED(op)) if (txt_has_sel(text)) { text_drawcache_tag_update(CTX_wm_space_text(C), 0); - txt_order_cursors(text); + txt_order_cursors(text, false); txt_uncomment(text); text_update_edited(text); @@ -1861,11 +1861,23 @@ static int text_move_cursor(bContext *C, int type, int select) break; case PREV_CHAR: - txt_move_left(text, select); + if (txt_has_sel(text) && !select) { + txt_order_cursors(text, false); + txt_pop_sel(text); + } + else { + txt_move_left(text, select); + } break; case NEXT_CHAR: - txt_move_right(text, select); + if (txt_has_sel(text) && !select) { + txt_order_cursors(text, true); + txt_pop_sel(text); + } + else { + txt_move_right(text, select); + } break; case PREV_LINE: @@ -2086,10 +2098,17 @@ void TEXT_OT_overwrite_toggle(wmOperatorType *ot) static void txt_screen_clamp(SpaceText *st, ARegion *ar) { - int last; - last = text_get_total_lines(st, ar); - last = last - (st->viewlines / 2); - CLAMP(st->top, 0, last); + if (st->top <= 0) { + st->top = 0; + } + else { + int last; + last = text_get_total_lines(st, ar); + last = last - (st->viewlines / 2); + if (last > 0 && st->top > last) { + st->top = last; + } + } } /* Moves the view vertically by the specified number of lines */ diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index d3d8868520d..6961ada462d 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -34,7 +34,6 @@ #include <string.h> #include <math.h> - #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -1099,12 +1098,14 @@ static void draw_b_bone_boxes(const short dt, bPoseChannel *pchan, float xwidth, if ((segments > 1) && (pchan)) { float dlen = length / (float)segments; - Mat4 *bbone = b_bone_spline_setup(pchan, 0); + Mat4 bbone[MAX_BBONE_SUBDIV]; int a; - - for (a = 0; a < segments; a++, bbone++) { + + b_bone_spline_setup(pchan, 0, bbone); + + for (a = 0; a < segments; a++) { glPushMatrix(); - glMultMatrixf(bbone->mat); + glMultMatrixf(bbone[a].mat); if (dt == OB_SOLID) drawsolidcube_size(xwidth, dlen, zwidth); else drawcube_size(xwidth, dlen, zwidth); glPopMatrix(); @@ -1235,6 +1236,7 @@ static void draw_wire_bone_segments(bPoseChannel *pchan, Mat4 *bbones, float len static void draw_wire_bone(const short dt, int armflag, int boneflag, short constflag, unsigned int id, bPoseChannel *pchan, EditBone *ebone) { + Mat4 bbones_array[MAX_BBONE_SUBDIV]; Mat4 *bbones = NULL; int segments = 0; float length; @@ -1243,8 +1245,10 @@ static void draw_wire_bone(const short dt, int armflag, int boneflag, short cons segments = pchan->bone->segments; length = pchan->bone->length; - if (segments > 1) - bbones = b_bone_spline_setup(pchan, 0); + if (segments > 1) { + b_bone_spline_setup(pchan, 0, bbones_array); + bbones = bbones_array; + } } else length = ebone->length; diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 62e3f8471a3..ac216907c7f 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1900,9 +1900,9 @@ static void drawlattice(Scene *scene, View3D *v3d, Object *ob) const bool is_edit = (lt->editlatt != NULL); /* now we default make displist, this will modifiers work for non animated case */ - if (ob->disp.first == NULL) + if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) BKE_lattice_modifiers_calc(scene, ob); - dl = BKE_displist_find(&ob->disp, DL_VERTS); + dl = BKE_displist_find(&ob->curve_cache->disp, DL_VERTS); if (is_edit) { lt = lt->editlatt->latt; @@ -3094,9 +3094,6 @@ static void draw_em_fancy(Scene *scene, ARegion *ar, View3D *v3d, BMVert *eve_act = NULL; bool use_occlude_wire = (v3d->flag2 & V3D_OCCLUDE_WIRE) && (dt > OB_WIRE); - // BLI_assert(!cageDM || !(cageDM->dirty & DM_DIRTY_NORMALS)); - BLI_assert(!finalDM || !(finalDM->dirty & DM_DIRTY_NORMALS)); - if (em->bm->selected.last) { BMEditSelection *ese = em->bm->selected.last; /* face is handeled above */ @@ -3369,8 +3366,6 @@ static void draw_mesh_fancy(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D if (!dm) return; - if (dm) BLI_assert(!(dm->dirty & DM_DIRTY_NORMALS)); - /* Check to draw dynamic paint colors (or weights from WeightVG modifiers). * Note: Last "preview-active" modifier in stack will win! */ if (DM_get_tessface_data_layer(dm, CD_PREVIEW_MCOL) && modifiers_isPreview(ob)) @@ -3971,7 +3966,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 case OB_CURVE: cu = ob->data; - lb = &ob->disp; + lb = &ob->curve_cache->disp; if (solid) { dl = lb->first; @@ -4021,7 +4016,7 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 break; case OB_SURF: - lb = &ob->disp; + lb = &ob->curve_cache->disp; if (solid) { dl = lb->first; @@ -4049,8 +4044,11 @@ static bool drawDispList_nobackface(Scene *scene, View3D *v3d, RegionView3D *rv3 case OB_MBALL: if (BKE_mball_is_basis(ob)) { - lb = &ob->disp; - if (lb->first == NULL) BKE_displist_make_mball(scene, ob); + lb = ob->curve_cache ? &ob->curve_cache->disp : NULL; + if (ELEM(lb, lb->first, NULL)) { + BKE_displist_make_mball(scene, ob); + lb = &ob->curve_cache->disp; + } if (lb->first == NULL) { return true; } @@ -4566,7 +4564,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->ma_col = ma_col; } - psys->lattice = psys_get_lattice(&sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* circles don't use drawdata, so have to add a special case here */ if ((pdd || draw_as == PART_DRAW_CIRC) && draw_as != PART_DRAW_PATH) { @@ -4892,9 +4890,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv pdd->flag &= ~PARTICLE_DRAW_DATA_UPDATED; } - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice = NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } if (pdd) { @@ -5642,7 +5640,7 @@ static void drawnurb(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *base, if ((cu->flag & CU_3D) && (ts->normalsize > 0.0015f) && (cu->drawflag & CU_HIDE_NORMALS) == 0) { UI_ThemeColor(TH_WIRE_EDIT); - for (bl = cu->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { + for (bl = ob->curve_cache->bev.first, nu = nurb; nu && bl; bl = bl->next, nu = nu->next) { BevPoint *bevp = (BevPoint *)(bl + 1); int nr = bl->nr; int skip = nu->resolu / 16; @@ -6065,7 +6063,7 @@ static void draw_forcefield(Object *ob, RegionView3D *rv3d, } else if (pd->forcefield == PFIELD_GUIDE && ob->type == OB_CURVE) { Curve *cu = ob->data; - if ((cu->flag & CU_PATH) && cu->path && cu->path->data) { + if ((cu->flag & CU_PATH) && ob->curve_cache->path && ob->curve_cache->path->data) { float mindist, guidevec1[4], guidevec2[3]; //if (has_ipo_code(ob->ipo, OB_PD_FSTR)) @@ -6248,7 +6246,7 @@ static void draw_bounding_volume(Scene *scene, Object *ob, char type) bb = BKE_mesh_boundbox_get(ob); } else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - bb = ob->bb ? ob->bb : ( (Curve *)ob->data)->bb; + bb = BKE_curve_boundbox_get(ob); } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { @@ -6283,9 +6281,7 @@ static void drawtexspace(Object *ob) BKE_mesh_texspace_get(ob->data, loc, NULL, size); } else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { - Curve *cu = ob->data; - copy_v3_v3(size, cu->size); - copy_v3_v3(loc, cu->loc); + BKE_curve_texspace_get(ob->data, loc, NULL, size); } else if (ob->type == OB_MBALL) { MetaBall *mb = ob->data; @@ -6323,7 +6319,6 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, glDepthMask(0); if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { - Curve *cu = ob->data; DerivedMesh *dm = ob->derivedFinal; bool has_faces = false; @@ -6331,16 +6326,16 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, has_faces = dm->getNumTessFaces(dm); } else { - has_faces = BKE_displist_has_faces(&ob->disp); + has_faces = BKE_displist_has_faces(&ob->curve_cache->disp); } - if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { + if (has_faces && ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) { draw_index_wire = false; if (dm) { draw_mesh_object_outline(v3d, ob, dm); } else { - drawDispListwire(&ob->disp); + drawDispListwire(&ob->curve_cache->disp); } draw_index_wire = true; } @@ -6348,7 +6343,7 @@ static void drawObjectSelect(Scene *scene, View3D *v3d, ARegion *ar, Base *base, else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { if ((base->flag & OB_FROMDUPLI) == 0) - drawDispListwire(&ob->disp); + drawDispListwire(&ob->curve_cache->disp); } } else if (ob->type == OB_ARMATURE) { @@ -6375,8 +6370,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign glDepthMask(0); /* disable write in zbuffer, selected edge wires show better */ if (ELEM3(ob->type, OB_FONT, OB_CURVE, OB_SURF)) { - Curve *cu = ob->data; - if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { + if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) { if (ob->type == OB_CURVE) draw_index_wire = false; @@ -6384,7 +6378,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign drawCurveDMWired(ob); } else { - drawDispListwire(&ob->disp); + drawDispListwire(&ob->curve_cache->disp); } if (ob->type == OB_CURVE) @@ -6393,7 +6387,7 @@ static void draw_wire_extra(Scene *scene, RegionView3D *rv3d, Object *ob, unsign } else if (ob->type == OB_MBALL) { if (BKE_mball_is_basis(ob)) { - drawDispListwire(&ob->disp); + drawDispListwire(&ob->curve_cache->disp); } } @@ -6662,23 +6656,17 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* faceselect exception: also draw solid when (dt == wire), except in editmode */ if (is_obact && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { - if (ob->type == OB_MESH) { - - if (ob->mode & OB_MODE_EDIT) { - /* pass */ + if (ob->type == OB_MESH) { + if (dt < OB_SOLID) { + zbufoff = 1; + dt = OB_SOLID; } - else { - if (dt < OB_SOLID) { - zbufoff = 1; - dt = OB_SOLID; - } - - if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { - dt = OB_PAINT; - } - glEnable(GL_DEPTH_TEST); + if (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT)) { + dt = OB_PAINT; } + + glEnable(GL_DEPTH_TEST); } else { if (dt < OB_SOLID) { @@ -6703,7 +6691,9 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short /* bad exception, solve this! otherwise outline shows too late */ if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { /* still needed for curves hidden in other layers. depgraph doesnt handle that yet */ - if (ob->disp.first == NULL) BKE_displist_make_curveTypes(scene, ob, 0); + if (ELEM(NULL, ob->curve_cache, ob->curve_cache->disp.first)) { + BKE_displist_make_curveTypes(scene, ob, 0); + } } /* draw outline for selected objects, mesh does itself */ @@ -6807,7 +6797,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short draw_bounding_volume(scene, ob, ob->boundtype); } } - else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { + else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) { empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); } @@ -6825,7 +6815,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short draw_bounding_volume(scene, ob, ob->boundtype); } } - else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb ? ob->bb : cu->bb)) { + else if (ED_view3d_boundbox_clip(rv3d, ob->obmat, ob->bb)) { empty_object = drawDispList(scene, v3d, rv3d, base, dt, dflag, ob_wire_col); //XXX old animsys if (cu->path) @@ -7050,6 +7040,7 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short // get view vector copy_v3_v3(viewnormal, rv3d->viewinv[2]); + invert_m4_m4(ob->imat, ob->obmat); mul_mat3_m4_v3(ob->imat, viewnormal); normalize_v3(viewnormal); diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c index 542ed7af0e6..a7940faa47d 100644 --- a/source/blender/editors/space_view3d/drawvolume.c +++ b/source/blender/editors/space_view3d/drawvolume.c @@ -83,6 +83,7 @@ struct GPUTexture; #ifdef DEBUG_DRAW_TIME # include "PIL_time.h" +# include "PIL_time_utildefines.h" #endif static int intersect_edges(float *points, float a, float b, float c, float d, float edges[12][2][3]) diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index bae2134591a..4ebd9706ac9 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -220,10 +220,10 @@ void ED_view3d_clipping_enable(void) static bool view3d_clipping_test(const float co[3], float clip[6][4]) { - 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])) + if (plane_point_side_v3(clip[0], co) > 0.0f) + if (plane_point_side_v3(clip[1], co) > 0.0f) + if (plane_point_side_v3(clip[2], co) > 0.0f) + if (plane_point_side_v3(clip[3], co) > 0.0f) return false; return true; @@ -2073,7 +2073,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas bb = *bb_tmp; /* must make a copy */ /* disable boundbox check for list creation */ - BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 1); + BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 1); /* need this for next part of code */ unit_m4(dob->ob->obmat); /* obmat gets restored */ @@ -2083,7 +2083,7 @@ static void draw_dupli_objects_color(Scene *scene, ARegion *ar, View3D *v3d, Bas glEndList(); use_displist = true; - BKE_object_boundbox_flag(dob->ob, OB_BB_DISABLED, 0); + BKE_object_boundbox_flag(dob->ob, BOUNDBOX_DISABLED, 0); } } if (use_displist) { diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 7b8c197f3e6..f78d8981400 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -3533,6 +3533,189 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit"); } + +/* ************************ viewroll ******************************** */ + +static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle) +{ + RegionView3D *rv3d = ar->regiondata; + float quat_mul[4]; + + /* camera axis */ + axis_angle_to_quat(quat_mul, dvec, angle); + + mul_qt_qtqt(quat, orig_quat, quat_mul); + rv3d->view = RV3D_VIEW_USER; +} + +static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y)) +{ + float angle = 0.0; + + { + float len1, len2, tot; + + tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin; + len1 = (vod->ar->winrct.xmax - x) / tot; + len2 = (vod->ar->winrct.xmax - vod->origx) / tot; + angle = (len1 - len2) * (float)M_PI * 4.0f; + } + + if (angle != 0.0f) + view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->oldquat, vod->mousevec, angle); + + if (vod->rv3d->viewlock & RV3D_BOXVIEW) + view3d_boxview_sync(vod->sa, vod->ar); + + ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); + + ED_region_tag_redraw(vod->ar); +} + +static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event) +{ + ViewOpsData *vod = op->customdata; + short event_code = VIEW_PASS; + + /* execute the events */ + if (event->type == MOUSEMOVE) { + event_code = VIEW_APPLY; + } + else if (event->type == EVT_MODAL_MAP) { + switch (event->val) { + case VIEW_MODAL_CONFIRM: + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_MOVE: + WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + case VIEWROT_MODAL_SWITCH_ROTATE: + WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL); + event_code = VIEW_CONFIRM; + break; + } + } + else if (event->type == vod->origkey && event->val == KM_RELEASE) { + event_code = VIEW_CONFIRM; + } + + if (event_code == VIEW_APPLY) { + viewroll_apply(vod, event->x, event->y); + } + else if (event_code == VIEW_CONFIRM) { + ED_view3d_depth_tag_update(vod->rv3d); + viewops_data_free(C, op); + + return OPERATOR_FINISHED; + } + + return OPERATOR_RUNNING_MODAL; +} + +static int viewroll_exec(bContext *C, wmOperator *op) +{ + View3D *v3d; + RegionView3D *rv3d; + ARegion *ar; + float mousevec[3]; + + if (op->customdata) { + ViewOpsData *vod = op->customdata; + ar = vod->ar; + v3d = vod->v3d; + } + else { + ar = CTX_wm_region(C); + v3d = CTX_wm_view3d(C); + } + + negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv[2]); + normalize_v3(mousevec); + + rv3d = ar->regiondata; + if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d)) { + const float angle = RNA_float_get(op->ptr, "angle"); + float mousevec[3]; + float quat_new[4]; + + normalize_v3_v3(mousevec, rv3d->viewinv[2]); + negate_v3(mousevec); + view_roll_angle(ar, quat_new, rv3d->viewquat, mousevec, angle); + + view3d_smooth_view(C, v3d, ar, NULL, NULL, NULL, quat_new, NULL, NULL); + + viewops_data_free(C, op); + return OPERATOR_FINISHED; + } + else { + viewops_data_free(C, op); + return OPERATOR_CANCELLED; + } +} + +static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + ViewOpsData *vod; + + /* makes op->customdata */ + viewops_data_create(C, op, event); + vod = op->customdata; + + if (RNA_struct_property_is_set(op->ptr, "angle")) { + viewroll_exec(C, op); + } + else { + /* overwrite the mouse vector with the view direction */ + normalize_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]); + negate_v3(vod->mousevec); + + if (event->type == MOUSEROTATE) { + vod->origx = vod->oldx = event->x; + viewroll_apply(vod, event->prevx, event->prevy); + ED_view3d_depth_tag_update(vod->rv3d); + + viewops_data_free(C, op); + return OPERATOR_FINISHED; + } + else { + /* add temp handler */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; + } + } + return OPERATOR_FINISHED; +} + +static int viewroll_cancel(bContext *C, wmOperator *op) +{ + viewops_data_free(C, op); + + return OPERATOR_CANCELLED; +} + +void VIEW3D_OT_view_roll(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "View Roll"; + ot->description = "Roll the view"; + ot->idname = "VIEW3D_OT_view_roll"; + + /* api callbacks */ + ot->invoke = viewroll_invoke; + ot->exec = viewroll_exec; + ot->modal = viewroll_modal; + ot->poll = ED_operator_rv3d_user_region_poll; + ot->cancel = viewroll_cancel; + + /* flags */ + ot->flag = 0; + + /* properties */ + ot->prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX); +} + static EnumPropertyItem prop_view_pan_items[] = { {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"}, {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Right"}, diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index a1a13130b27..9341ea9d3e6 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -159,6 +159,11 @@ void fly_modal_keymap(wmKeyConfig *keyconf) WM_modalkeymap_add_item(keymap, RKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_UP); WM_modalkeymap_add_item(keymap, FKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_DOWN); + WM_modalkeymap_add_item(keymap, UPARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_FORWARD); + WM_modalkeymap_add_item(keymap, DOWNARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_BACKWARD); + WM_modalkeymap_add_item(keymap, LEFTARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_LEFT); + WM_modalkeymap_add_item(keymap, RIGHTARROWKEY, KM_PRESS, 0, 0, FLY_MODAL_DIR_RIGHT); + WM_modalkeymap_add_item(keymap, XKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_X); WM_modalkeymap_add_item(keymap, ZKEY, KM_PRESS, 0, 0, FLY_MODAL_AXIS_LOCK_Z); @@ -580,6 +585,12 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event) double time_currwheel; float time_wheel; + /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */ + if (fly->axis == -1) { + fly->axis = 2; + fly->speed = fabsf(fly->speed); + } + time_currwheel = PIL_check_seconds_timer(); time_wheel = (float)(time_currwheel - fly->time_lastwheel); fly->time_lastwheel = time_currwheel; @@ -599,6 +610,12 @@ static void flyEvent(FlyInfo *fly, const wmEvent *event) double time_currwheel; float time_wheel; + /* not quite correct but avoids confusion WASD/arrow keys 'locking up' */ + if (fly->axis == -1) { + fly->axis = 2; + fly->speed = -fabsf(fly->speed); + } + time_currwheel = PIL_check_seconds_timer(); time_wheel = (float)(time_currwheel - fly->time_lastwheel); fly->time_lastwheel = time_currwheel; @@ -806,9 +823,10 @@ static void flyMoveCamera(bContext *C, RegionView3D *rv3d, FlyInfo *fly, static int flyApply(bContext *C, FlyInfo *fly) { -#define FLY_ROTATE_FAC 2.5f /* more is faster */ +#define FLY_ROTATE_FAC 10.0f /* more is faster */ #define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */ #define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */ +#define FLY_SMOOTH_FAC 20.0f /* higher value less lag */ /* fly mode - Shift+F * a fly loop where the user can move move the view as if they are flying @@ -1052,7 +1070,7 @@ static int flyApply(bContext *C, FlyInfo *fly) } /* impose a directional lag */ - interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * 5.0f)))); + interp_v3_v3v3(dvec, dvec_tmp, fly->dvec_prev, (1.0f / (1.0f + (time_redraw * FLY_SMOOTH_FAC)))); if (rv3d->persp == RV3D_CAMOB) { Object *lock_ob = fly->root_parent ? fly->root_parent : fly->v3d->camera; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 085af4e5c18..54999b1ae95 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -95,6 +95,7 @@ void VIEW3D_OT_view_persportho(struct wmOperatorType *ot); void VIEW3D_OT_background_image_add(struct wmOperatorType *ot); void VIEW3D_OT_background_image_remove(struct wmOperatorType *ot); void VIEW3D_OT_view_orbit(struct wmOperatorType *ot); +void VIEW3D_OT_view_roll(struct wmOperatorType *ot); void VIEW3D_OT_clip_border(struct wmOperatorType *ot); void VIEW3D_OT_cursor3d(struct wmOperatorType *ot); void VIEW3D_OT_manipulator(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index d13ab15d837..2023513ad92 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -368,7 +368,7 @@ void lattice_foreachScreenVert( Object *obedit = vc->obedit; Lattice *lt = obedit->data; BPoint *bp = lt->editlatt->latt->def; - DispList *dl = BKE_displist_find(&obedit->disp, DL_VERTS); + DispList *dl = obedit->curve_cache ? BKE_displist_find(&obedit->curve_cache->disp, DL_VERTS) : NULL; float *co = dl ? dl->verts : NULL; int i, N = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw; diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 6780b71c906..e7da921bba2 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -138,6 +138,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); WM_operatortype_append(VIEW3D_OT_view_orbit); + WM_operatortype_append(VIEW3D_OT_view_roll); WM_operatortype_append(VIEW3D_OT_view_pan); WM_operatortype_append(VIEW3D_OT_view_persportho); WM_operatortype_append(VIEW3D_OT_background_image_add); @@ -283,7 +284,9 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD4, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD6, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", PAD8, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANUP); - + RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD4, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / -12); + RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", PAD6, KM_PRESS, KM_SHIFT, 0)->ptr, "angle", M_PI / 12); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANRIGHT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL, 0)->ptr, "type", V3D_VIEW_PANLEFT); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_pan", WHEELUPMOUSE, KM_PRESS, KM_SHIFT, 0)->ptr, "type", V3D_VIEW_PANUP); @@ -294,6 +297,9 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELUPMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPUP); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_orbit", WHEELDOWNMOUSE, KM_PRESS, KM_SHIFT | KM_ALT, 0)->ptr, "type", V3D_VIEW_STEPDOWN); + RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELUPMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / -12); + RNA_float_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_roll", WHEELDOWNMOUSE, KM_PRESS, KM_CTRL | KM_SHIFT, 0)->ptr, "angle", M_PI / 12); + /* active aligned, replaces '*' key in 2.4x */ kmi = WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, KM_SHIFT, 0); RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index 5e71913ea4a..28ffdea0e6c 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -405,15 +405,15 @@ void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float float line_end[3]; if (rv3d->is_persp) { - float mousevec[3]; + float mousevec[3], lambda; copy_v3_v3(line_sta, rv3d->viewinv[3]); ED_view3d_win_to_vector(ar, mval, mousevec); add_v3_v3v3(line_end, line_sta, mousevec); - if (isect_line_plane_v3(out, line_sta, line_end, depth_pt, rv3d->viewinv[2], true) == 0) { - /* highly unlikely to ever happen, mouse vector parallel with view plane */ - zero_v3(out); - } + /* note, we could use isect_line_plane_v3() however we want the intersection to be infront of the + * view no matter what, so apply the unsigned factor instead */ + lambda = line_plane_factor_v3(depth_pt, rv3d->viewinv[2], line_sta, line_end); + interp_v3_v3v3(out, line_sta, line_end, fabsf(lambda)); } else { float dx = (2.0f * mval[0] / (float)ar->winx) - 1.0f; diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index 44c338d22b9..0246e2b75a9 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -40,6 +40,7 @@ #include "BLI_rect.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "BLI_callbacks.h" #include "BKE_anim.h" #include "BKE_action.h" @@ -617,7 +618,7 @@ bool ED_view3d_boundbox_clip(RegionView3D *rv3d, float obmat[4][4], const BoundB int a, flag = -1, fl; if (bb == NULL) return true; - if (bb->flag & OB_BB_DISABLED) return true; + if (bb->flag & BOUNDBOX_DISABLED) return true; mul_m4_m4m4(mat, rv3d->persmat, obmat); @@ -1433,6 +1434,7 @@ static int game_engine_exec(bContext *C, wmOperator *op) { #ifdef WITH_GAMEENGINE Scene *startscene = CTX_data_scene(C); + Main *bmain = CTX_data_main(C); ScrArea /* *sa, */ /* UNUSED */ *prevsa = CTX_wm_area(C); ARegion *ar, *prevar = CTX_wm_region(C); wmWindow *prevwin = CTX_wm_window(C); @@ -1449,6 +1451,8 @@ static int game_engine_exec(bContext *C, wmOperator *op) * the window manager until after this operator exits */ WM_redraw_windows(C); + BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_PRE); + rv3d = CTX_wm_region_view3d(C); /* sa = CTX_wm_area(C); */ /* UNUSED */ ar = CTX_wm_region(C); @@ -1504,6 +1508,8 @@ static int game_engine_exec(bContext *C, wmOperator *op) BKE_scene_set_background(CTX_data_main(C), startscene); //XXX BKE_scene_update_for_newframe(bmain, scene, scene->lay); + BLI_callback_exec(bmain, &startscene->id, BLI_CB_EVT_GAME_POST); + return OPERATOR_FINISHED; #else (void)C; /* unused */ diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 6d801b86685..82c117a7486 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1749,29 +1749,32 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) // If modal, save settings back in scene if not set as operator argument if (t->flag & T_MODAL) { - /* save settings if not set in operator */ - if ((prop = RNA_struct_find_property(op->ptr, "proportional")) && - !RNA_property_is_set(op->ptr, prop)) - { - if (t->obedit) - ts->proportional = proportional; - else if (t->options & CTX_MASK) - ts->proportional_mask = (proportional != PROP_EDIT_OFF); - else - ts->proportional_objects = (proportional != PROP_EDIT_OFF); - } - if ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) && - !RNA_property_is_set(op->ptr, prop)) - { - ts->proportional_size = t->prop_size; - } + /* skip saving proportional edit if it was not actually used */ + if (!(t->options & CTX_NO_PET)) { + if ((prop = RNA_struct_find_property(op->ptr, "proportional")) && + !RNA_property_is_set(op->ptr, prop)) + { + if (t->obedit) + ts->proportional = proportional; + else if (t->options & CTX_MASK) + ts->proportional_mask = (proportional != PROP_EDIT_OFF); + else + ts->proportional_objects = (proportional != PROP_EDIT_OFF); + } - if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) && - !RNA_property_is_set(op->ptr, prop)) - { - ts->prop_mode = t->prop_mode; + if ((prop = RNA_struct_find_property(op->ptr, "proportional_size")) && + !RNA_property_is_set(op->ptr, prop)) + { + ts->proportional_size = t->prop_size; + } + + if ((prop = RNA_struct_find_property(op->ptr, "proportional_edit_falloff")) && + !RNA_property_is_set(op->ptr, prop)) + { + ts->prop_mode = t->prop_mode; + } } /* do we check for parameter? */ @@ -4825,7 +4828,7 @@ static bool bm_loop_calc_opposite_co(BMLoop *l_tmp, float tvec[3]; if (isect_line_plane_v3(tvec, l_iter->v->co, l_iter->next->v->co, - l_tmp->v->co, plane_no, false)) + l_tmp->v->co, plane_no)) { const float fac = line_point_factor_v3(tvec, l_iter->v->co, l_iter->next->v->co); /* allow some overlap to avoid missing the intersection because of float precision */ diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 4954f861934..a0550c99988 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -350,6 +350,7 @@ typedef struct TransInfo { struct ToolSettings *settings; struct wmTimer *animtimer; struct wmKeyMap *keymap; /* so we can do lookups for header text */ + struct ReportList *reports; /* assign from the operator, or can be NULL */ int mval[2]; /* current mouse position */ float zfac; /* use for 3d view */ struct Object *obedit; diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index fd8fba91fc9..a73bf86feb1 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -727,6 +727,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) RegionView3D *rv3d = CTX_wm_region_view3d(C); float tmat[4][4], imat[4][4]; float center[3]; + int depth_test_enabled; UI_ThemeColor(TH_GRID); @@ -759,10 +760,17 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) glScalef(1.0f / aspx, 1.0f / aspy, 1.0); } + depth_test_enabled = glIsEnabled(GL_DEPTH_TEST); + if (depth_test_enabled) + glDisable(GL_DEPTH_TEST); + set_inverted_drawing(1); drawcircball(GL_LINE_LOOP, center, t->prop_size, imat); set_inverted_drawing(0); + if (depth_test_enabled) + glEnable(GL_DEPTH_TEST); + glPopMatrix(); } } diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 1849bfecc51..73c0b3c0ff4 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -275,6 +275,13 @@ static void createTransTexspace(TransInfo *t) id = ob->data; if (id == NULL || !ELEM3(GS(id->name), ID_ME, ID_CU, ID_MB)) { + BKE_report(t->reports, RPT_ERROR, "Unsupported object type for text-space transform"); + t->total = 0; + return; + } + + if (BKE_object_obdata_is_libdata(ob)) { + BKE_report(t->reports, RPT_ERROR, "Linked data can't text-space transform"); t->total = 0; return; } @@ -990,8 +997,7 @@ static void createTransPose(TransInfo *t, Object *ob) if (arm->flag & ARM_RESTPOS) { if (ELEM(t->mode, TFM_DUMMY, TFM_BONESIZE) == 0) { - // XXX use transform operator reports - // BKE_report(op->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled"); + BKE_report(t->reports, RPT_ERROR, "Cannot select linked when sync selection is enabled"); return; } } @@ -1031,8 +1037,7 @@ static void createTransPose(TransInfo *t, Object *ob) } if (td != (t->data + t->total)) { - // XXX use transform operator reports - // BKE_report(op->reports, RPT_DEBUG, "Bone selection count error"); + BKE_report(t->reports, RPT_DEBUG, "Bone selection count error"); } /* initialize initial auto=ik chainlen's? */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 4c7ac4193b3..359f6425126 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1063,6 +1063,7 @@ int initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *even t->ar = ar; t->obedit = obedit; t->settings = ts; + t->reports = op ? op->reports : NULL; if (obedit) { copy_m3_m4(t->obedit_mat, obedit->obmat); @@ -1522,7 +1523,6 @@ void calculateCenterCursor2D(TransInfo *t) if (t->spacetype == SPACE_IMAGE) { SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; - /* only space supported right now but may change */ if (t->options & CTX_MASK) { ED_space_image_get_aspect(sima, &aspx, &aspy); } @@ -1531,17 +1531,37 @@ void calculateCenterCursor2D(TransInfo *t) } cursor = sima->cursor; } + else if (t->spacetype == SPACE_CLIP) { + SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first; + if (t->options & CTX_MOVIECLIP) { + ED_space_clip_get_aspect_dimension_aware(space_clip, &aspx, &aspy); + } + else { + ED_space_clip_get_aspect(space_clip, &aspx, &aspy); + } + cursor = space_clip->cursor; + } if (cursor) { if (t->options & CTX_MASK) { float co[2]; float frame_size[2]; - SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; - ED_space_image_get_size_fl(sima, frame_size); - - BKE_mask_coord_from_frame(co, cursor, frame_size); - ED_space_image_get_aspect(sima, &aspx, &aspy); + if (t->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)t->sa->spacedata.first; + ED_space_image_get_size_fl(sima, frame_size); + BKE_mask_coord_from_frame(co, cursor, frame_size); + ED_space_image_get_aspect(sima, &aspx, &aspy); + } + else if (t->spacetype == SPACE_CLIP) { + SpaceClip *space_clip = (SpaceClip *) t->sa->spacedata.first; + ED_space_clip_get_size_fl(space_clip, frame_size); + BKE_mask_coord_from_frame(co, cursor, frame_size); + ED_space_clip_get_aspect(space_clip, &aspx, &aspy); + } + else { + BLI_assert(!"Shall not happen"); + } t->center[0] = co[0] * aspx; t->center[1] = co[1] * aspy; @@ -1620,7 +1640,7 @@ void calculateCenter(TransInfo *t) calculateCenterMedian(t); break; case V3D_CURSOR: - if (t->spacetype == SPACE_IMAGE) + if (ELEM(t->spacetype, SPACE_IMAGE, SPACE_CLIP)) calculateCenterCursor2D(t); else if (t->spacetype == SPACE_IPO) calculateCenterCursorGraph2D(t); diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index 909ca68cc20..86bdcbdb394 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -1147,7 +1147,7 @@ static void TargetSnapClosest(TransInfo *t) } } -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], +static bool snapEdge(ARegion *ar, const float v1co[3], const short v1no[3], const float v2co[3], const 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_fl[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth) { @@ -1234,7 +1234,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s return retval; } -static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3], +static bool snapVertex(ARegion *ar, const float vco[3], const 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_fl[2], float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth) { @@ -1518,6 +1518,45 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes return retval; } +/* may extend later (for now just snaps to empty center) */ +static bool snapEmpty(short snap_mode, ARegion *ar, Object *ob, 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), float *r_dist_px, float *r_depth) +{ + float imat[4][4]; + float ray_start_local[3], ray_normal_local[3]; + bool retval = false; + + if (ob->transflag & OB_DUPLI) { + return retval; + } + /* for now only vertex supported */ + if (snap_mode != SCE_SNAP_MODE_VERTEX) { + return retval; + } + + invert_m4_m4(imat, obmat); + + copy_v3_v3(ray_start_local, ray_start); + copy_v3_v3(ray_normal_local, ray_normal); + + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); + + switch (snap_mode) { + case SCE_SNAP_MODE_VERTEX: + { + const float zero_co[3] = {0.0f}; + retval |= snapVertex(ar, zero_co, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); + break; + } + default: + break; + } + + return retval; +} + static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, float obmat[4][4], bool use_obedit, Object **r_ob, float r_obmat[4][4], const float ray_start[3], const float ray_normal[3], const float mval[2], @@ -1545,6 +1584,9 @@ static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, f else if (ob->type == OB_ARMATURE) { retval = snapArmature(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth); } + else if (ob->type == OB_EMPTY) { + retval = snapEmpty(snap_mode, ar, ob, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth); + } if (retval) { if (r_ob) { diff --git a/source/blender/editors/util/crazyspace.c b/source/blender/editors/util/crazyspace.c index bed8aaaddf2..721a7a3b855 100644 --- a/source/blender/editors/util/crazyspace.c +++ b/source/blender/editors/util/crazyspace.c @@ -260,11 +260,12 @@ int editbmesh_get_first_deform_matrices(Scene *scene, Object *ob, BMEditMesh *em int i, a, numleft = 0, numVerts = 0; int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; + VirtualModifierData virtualModifierData; modifiers_clearErrors(ob); dm = NULL; - md = modifiers_getVirtualModifierList(ob); + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); /* compute the deformation matrices and coordinates for the first * modifiers with on cage editing that are enabled and support computing @@ -314,6 +315,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); int has_multires = mmd != NULL && mmd->sculptlvl > 0; int numleft = 0; + VirtualModifierData virtualModifierData; if (has_multires) { *deformmats = NULL; @@ -322,7 +324,7 @@ int sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformma } dm = NULL; - md = modifiers_getVirtualModifierList(ob); + md = modifiers_getVirtualModifierList(ob, &virtualModifierData); for (; md; md = md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -375,7 +377,8 @@ void crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3 float (*origVerts)[3] = MEM_dupallocN(deformedVerts); float *quats = NULL; int i, deformed = 0; - ModifierData *md = modifiers_getVirtualModifierList(ob); + VirtualModifierData virtualModifierData; + ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); Mesh *me = (Mesh *)ob->data; for (; md; md = md->next) { diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index a873702b5b8..d20ef0e70e0 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -69,7 +69,7 @@ #define USE_EDBM_LOOPTRIS -void draw_image_cursor(SpaceImage *sima, ARegion *ar) +void draw_image_cursor(ARegion *ar, const float cursor[2]) { float zoom[2], x_fac, y_fac; @@ -80,7 +80,7 @@ void draw_image_cursor(SpaceImage *sima, ARegion *ar) y_fac = zoom[1]; cpack(0xFFFFFF); - glTranslatef(sima->cursor[0], sima->cursor[1], 0.0); + glTranslatef(cursor[0], cursor[1], 0.0); fdrawline(-0.05f * x_fac, 0, 0, 0.05f * y_fac); fdrawline(0, 0.05f * y_fac, 0.05f * x_fac, 0.0f); fdrawline(0.05f * x_fac, 0.0f, 0.0f, -0.05f * y_fac); @@ -108,7 +108,7 @@ void draw_image_cursor(SpaceImage *sima, ARegion *ar) fdrawline(0.0f, -0.020f * y_fac, 0.0f, -0.1f * y_fac); fdrawline(0.0f, 0.1f * y_fac, 0.0f, 0.020f * y_fac); - glTranslatef(-sima->cursor[0], -sima->cursor[1], 0.0); + glTranslatef(-cursor[0], -cursor[1], 0.0); setlinestyle(0); } @@ -158,7 +158,7 @@ static int draw_uvs_dm_shadow(DerivedMesh *dm) /* draw shadow mesh - this is the mesh with the modifier applied */ if (dm && dm->drawUVEdges && CustomData_has_layer(&dm->loopData, CD_MLOOPUV)) { - glColor3ub(112, 112, 112); + UI_ThemeColor(TH_UV_SHADOW); dm->drawUVEdges(dm); return 1; } @@ -362,7 +362,7 @@ static void draw_uvs_other(Scene *scene, Object *obedit, Image *curimage) { Base *base; - glColor3ub(96, 96, 96); + UI_ThemeColor(TH_UV_OTHERS); for (base = scene->base.first; base; base = base->next) { Object *ob = base->object; @@ -404,7 +404,7 @@ static void draw_uvs_texpaint(SpaceImage *sima, Scene *scene, Object *ob) if (sima->flag & SI_DRAW_OTHER) draw_uvs_other(scene, ob, curimage); - glColor3ub(112, 112, 112); + UI_ThemeColor(TH_UV_SHADOW); if (me->mtpoly) { MPoly *mpoly = me->mpoly; @@ -884,7 +884,7 @@ void draw_uvedit_main(SpaceImage *sima, ARegion *ar, Scene *scene, Object *obedi draw_uvs_texpaint(sima, scene, obact); if (show_uvedit && !(toolsettings->use_uv_sculpt)) - draw_image_cursor(sima, ar); + draw_image_cursor(ar, sima->cursor); } } diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index 0b514e3f6fd..8c299cccbc2 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -3823,6 +3823,12 @@ static void UV_OT_reveal(wmOperatorType *ot) /******************** set 3d cursor operator ********************/ +static int uv_set_2d_cursor_poll(bContext *C) +{ + return ED_operator_uvedit_space_image(C) || + ED_space_image_maskedit_poll(C); +} + static int uv_set_2d_cursor_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); @@ -3858,7 +3864,7 @@ static void UV_OT_cursor_set(wmOperatorType *ot) /* api callbacks */ ot->exec = uv_set_2d_cursor_exec; ot->invoke = uv_set_2d_cursor_invoke; - ot->poll = ED_operator_uvedit_space_image; + ot->poll = uv_set_2d_cursor_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; diff --git a/source/blender/freestyle/intern/application/Controller.cpp b/source/blender/freestyle/intern/application/Controller.cpp index dbf3fa8349e..c61f72295d2 100644 --- a/source/blender/freestyle/intern/application/Controller.cpp +++ b/source/blender/freestyle/intern/application/Controller.cpp @@ -290,6 +290,8 @@ int Controller::LoadMesh(Render *re, SceneRenderLayer *srl) _ListOfModels.push_back("Blender_models"); + _Scene3dBBox = _RootNode->bbox(); + _bboxDiag = (_RootNode->bbox().getMax() - _RootNode->bbox().getMin()).norm(); if (G.debug & G_DEBUG_FREESTYLE) { cout << "Triangles nb : " << _SceneNumFaces << endl; @@ -339,6 +341,7 @@ void Controller::DeleteWingedEdge() // clears the grid _Grid.clear(); + _Scene3dBBox.clear(); _SceneNumFaces = 0; _minEdgeSize = DBL_MAX; } @@ -540,8 +543,8 @@ void Controller::ComputeViewMap() } _Chrono.start(); // Build View Map - _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _RootNode->bbox(), _SceneNumFaces); - _ViewMap->setScene3dBBox(_RootNode->bbox()); + _ViewMap = vmBuilder.BuildViewMap(*_winged_edge, _VisibilityAlgo, _EPSILON, _Scene3dBBox, _SceneNumFaces); + _ViewMap->setScene3dBBox(_Scene3dBBox); if (G.debug & G_DEBUG_FREESTYLE) { printf("ViewMap edge count : %i\n", _ViewMap->viewedges_size()); diff --git a/source/blender/freestyle/intern/application/Controller.h b/source/blender/freestyle/intern/application/Controller.h index d4537f5f987..f5e50347d0f 100644 --- a/source/blender/freestyle/intern/application/Controller.h +++ b/source/blender/freestyle/intern/application/Controller.h @@ -211,6 +211,7 @@ private: FastGrid _Grid; //HashGrid _Grid; + BBox<Vec3r> _Scene3dBBox; unsigned int _SceneNumFaces; real _minEdgeSize; real _EPSILON; diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h index 794ceba48e7..c557c2a6368 100644 --- a/source/blender/freestyle/intern/geometry/BBox.h +++ b/source/blender/freestyle/intern/geometry/BBox.h @@ -28,6 +28,10 @@ * \date 22/05/2003 */ +#include <stdlib.h> + +#include "BLI_utildefines.h" + #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif @@ -95,6 +99,7 @@ public: inline BBox<Point>& operator=(const BBox<Point>& b) { + BLI_assert(!b.empty()); _min = b.getMin(); _max = b.getMax(); _empty = false; @@ -103,6 +108,7 @@ public: inline BBox<Point>& operator+=(const BBox<Point>& b) { + BLI_assert(!b.empty()); if (_empty) { _min = b.getMin(); _max = b.getMax(); diff --git a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp index 9b915df03d1..869ada0d058 100644 --- a/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp +++ b/source/blender/freestyle/intern/python/Interface1D/BPy_ViewEdge.cpp @@ -44,7 +44,7 @@ PyDoc_STRVAR(ViewEdge_doc, "Class hierarchy: :class:`Interface1D` > :class:`ViewEdge`\n" "\n" "Class defining a ViewEdge. A ViewEdge in an edge of the image graph.\n" -"it connnects two :class:`ViewVertex` objects. It is made by connecting\n" +"it connects two :class:`ViewVertex` objects. It is made by connecting\n" "a set of FEdges.\n" "\n" ".. method:: __init__()\n" diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp index 18815ab6f62..b54ed48edc3 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_Material/BPy_MaterialF0D.cpp @@ -48,7 +48,7 @@ static char MaterialF0D___doc__[] = " evaluation can be ambiguous (in the case of a :class:`TVertex` for\n" " example. This functor tries to remove this ambiguity using the\n" " context offered by the 1D element to which the Interface0DIterator\n" -" belongs to and by arbitrary chosing the material of the face that\n" +" belongs to and by arbitrary choosing the material of the face that\n" " lies on its left when following the 1D element if there are two\n" " different materials on each side of the point. However, there\n" " still can be problematic cases, and the user willing to deal with\n" diff --git a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp index 8f7fccb5293..b64f6c06e93 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction0D/UnaryFunction0D_double/BPy_ZDiscontinuityF0D.cpp @@ -47,7 +47,7 @@ static char ZDiscontinuityF0D___doc__[] = " :class:`Interface0D` pointed by the Interface0DIterator and the\n" " shape that lies behind (occludee). This distance is evaluated in\n" " the camera space and normalized between 0 and 1. Therefore, if no\n" -" oject is occluded by the shape to which the Interface0D belongs to,\n" +" object is occluded by the shape to which the Interface0D belongs to,\n" " 1 is returned.\n" "\n" " :arg it: An Interface0DIterator object.\n" diff --git a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp index 5c3dc3eed9f..65fde596e23 100644 --- a/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp +++ b/source/blender/freestyle/intern/python/UnaryFunction1D/UnaryFunction1D_double/BPy_ZDiscontinuityF1D.cpp @@ -52,7 +52,7 @@ static char ZDiscontinuityF1D___doc__[] = " Returns a real value giving the distance between an Interface1D\n" " and the shape that lies behind (occludee). This distance is\n" " evaluated in the camera space and normalized between 0 and 1.\n" -" Therefore, if no oject is occluded by the shape to which the\n" +" Therefore, if no object is occluded by the shape to which the\n" " Interface1D belongs to, 1 is returned.\n" "\n" " :arg inter: An Interface1D object.\n" diff --git a/source/blender/freestyle/intern/stroke/StrokeShader.h b/source/blender/freestyle/intern/stroke/StrokeShader.h index 7986a08e303..4657e98be61 100644 --- a/source/blender/freestyle/intern/stroke/StrokeShader.h +++ b/source/blender/freestyle/intern/stroke/StrokeShader.h @@ -63,7 +63,7 @@ class Stroke; * \endcode * Here is a C++ code example of such an iteration: * \code - * for(StrokeInternal::StrokeVertexIterator v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); + * for (StrokeInternal::StrokeVertexIterator v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); * v != vend; * ++v) * { diff --git a/source/blender/freestyle/intern/view_map/Functions0D.h b/source/blender/freestyle/intern/view_map/Functions0D.h index 69f6f42e022..e9474191319 100644 --- a/source/blender/freestyle/intern/view_map/Functions0D.h +++ b/source/blender/freestyle/intern/view_map/Functions0D.h @@ -346,7 +346,7 @@ public: // ZDiscontinuity /*! Returns a real giving the distance between and Interface0D and the shape that lies behind (occludee). - * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded + * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no object is occluded * by the shape to which the Interface0D belongs to, 1 is returned. */ class LIB_VIEW_MAP_EXPORT ZDiscontinuityF0D : public UnaryFunction0D<real> @@ -383,7 +383,7 @@ public: /*! Returns the material of the object evaluated at the Interface0D. * This evaluation can be ambiguous (in the case of a TVertex for example. * This functor tries to remove this ambiguity using the context offered by the 1D element to which the - * Interface0DIterator& belongs to and by arbitrary chosing the material of the face that lies on its left when + * Interface0DIterator& belongs to and by arbitrary choosing the material of the face that lies on its left when * following the 1D element if there are two different materials on each side of the point. * However, there still can be problematic cases, and the user willing to deal with this cases in a specific way * should implement its own getMaterial functor. diff --git a/source/blender/freestyle/intern/view_map/Functions1D.h b/source/blender/freestyle/intern/view_map/Functions1D.h index 2d3da151d13..7b10d1b5185 100644 --- a/source/blender/freestyle/intern/view_map/Functions1D.h +++ b/source/blender/freestyle/intern/view_map/Functions1D.h @@ -377,7 +377,7 @@ public: // ZDiscontinuityF1D /*! Returns a real giving the distance between and Interface1D and the shape that lies behind (occludee). - * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no oject is occluded + * This distance is evaluated in the camera space and normalized between 0 and 1. Therefore, if no object is occluded * by the shape to which the Interface1D belongs to, 1 is returned. */ class LIB_VIEW_MAP_EXPORT ZDiscontinuityF1D : public UnaryFunction1D<real> diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.h b/source/blender/freestyle/intern/view_map/SteerableViewMap.h index 23681b43c48..581155fa6e8 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.h +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.h @@ -89,7 +89,7 @@ public: /*! Returns the number of the SVM to which a FEdge belongs most. * \param id - * The First element of the Id struct of the FEdge we're intersted in. + * The First element of the Id struct of the FEdge we're interested in. */ unsigned getSVMNumber(unsigned id); diff --git a/source/blender/freestyle/intern/view_map/ViewMap.h b/source/blender/freestyle/intern/view_map/ViewMap.h index 987a5bda9b3..0ab089b7d7a 100644 --- a/source/blender/freestyle/intern/view_map/ViewMap.h +++ b/source/blender/freestyle/intern/view_map/ViewMap.h @@ -888,7 +888,7 @@ template<class Traits> class vertex_iterator_base; } // end of namespace ViewEdgeInternal -/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connnects two ViewVertex. +/*! Class defining a ViewEdge. A ViewEdge in an edge of the image graph. it connects two ViewVertex. * It is made by connecting a set of FEdges. */ class LIB_VIEW_MAP_EXPORT ViewEdge : public Interface1D diff --git a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h index 01e93ba77c7..a8c046c4dc1 100644 --- a/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h +++ b/source/blender/freestyle/intern/view_map/ViewMapAdvancedIterators.h @@ -232,7 +232,7 @@ public: // operator corresponding to i++, i.e. which returns the value *and then* increments it. // That's why we store the value in a temp. - virtual Self operator++(int) // opérateur correspondant à i++ + virtual Self operator++(int) { Self tmp = *this; increment(); diff --git a/source/blender/gpu/GPU_buffers.h b/source/blender/gpu/GPU_buffers.h index fca8dcc3392..cc22063a83c 100644 --- a/source/blender/gpu/GPU_buffers.h +++ b/source/blender/gpu/GPU_buffers.h @@ -46,6 +46,7 @@ struct CustomData; struct DMFlagMat; struct DerivedMesh; struct GHash; +struct GSet; struct GPUVertPointLink; struct PBVH; @@ -175,10 +176,10 @@ GPU_Buffers *GPU_build_grid_buffers(int *grid_indices, int totgrid, GPU_Buffers *GPU_build_bmesh_buffers(int smooth_shading); void GPU_update_bmesh_buffers(GPU_Buffers *buffers, - struct BMesh *bm, - struct GHash *bm_faces, - struct GHash *bm_unique_verts, - struct GHash *bm_other_verts); + struct BMesh *bm, + struct GHash *bm_faces, + struct GSet *bm_unique_verts, + struct GSet *bm_other_verts); void GPU_update_grid_buffers(GPU_Buffers *buffers, struct CCGElem **grids, const struct DMFlagMat *grid_flag_mats, diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index c54f937f4a9..384b7cce2ff 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -77,6 +77,8 @@ static int useVBOs = -1; static GPUBufferState GLStates = 0; static GPUAttrib attribData[MAX_GPU_ATTRIB_DATA] = { { -1, 0, 0 } }; +static ThreadMutex buffer_mutex = BLI_MUTEX_INITIALIZER; + /* stores recently-deleted buffers so that new buffers won't have to * be recreated as often * @@ -203,8 +205,11 @@ void GPU_global_buffer_pool_free_unused(void) } /* get a GPUBuffer of at least `size' bytes; uses one from the buffer - * pool if possible, otherwise creates a new one */ -GPUBuffer *GPU_buffer_alloc(int size) + * pool if possible, otherwise creates a new one + * + * Thread-unsafe version for internal usage only. + */ +static GPUBuffer *gpu_buffer_alloc_intern(int size) { GPUBufferPool *pool; GPUBuffer *buf; @@ -284,10 +289,30 @@ GPUBuffer *GPU_buffer_alloc(int size) return buf; } +/* Same as above, but safe for threading. */ +GPUBuffer *GPU_buffer_alloc(int size) +{ + GPUBuffer *buffer; + + if (size == 0) { + /* Early out, no lock needed in this case. */ + return NULL; + } + + BLI_mutex_lock(&buffer_mutex); + buffer = gpu_buffer_alloc_intern(size); + BLI_mutex_unlock(&buffer_mutex); + + return buffer; +} + /* release a GPUBuffer; does not free the actual buffer or its data, * but rather moves it to the pool of recently-freed buffers for - * possible re-use*/ -void GPU_buffer_free(GPUBuffer *buffer) + * possible re-use + * + * Thread-unsafe version for internal usage only. + */ +static void gpu_buffer_free_intern(GPUBuffer *buffer) { GPUBufferPool *pool; int i; @@ -326,6 +351,19 @@ void GPU_buffer_free(GPUBuffer *buffer) pool->totbuf++; } +/* Same as above, but safe for threading. */ +void GPU_buffer_free(GPUBuffer *buffer) +{ + if (!buffer) { + /* Early output, no need to lock in this case, */ + return; + } + + BLI_mutex_lock(&buffer_mutex); + gpu_buffer_free_intern(buffer); + BLI_mutex_unlock(&buffer_mutex); +} + typedef struct GPUVertPointLink { struct GPUVertPointLink *next; /* -1 means uninitialized */ @@ -510,13 +548,17 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, pool = gpu_get_global_buffer_pool(); + BLI_mutex_lock(&buffer_mutex); + /* alloc a GPUBuffer; fall back to legacy mode on failure */ - if (!(buffer = GPU_buffer_alloc(size))) + if (!(buffer = gpu_buffer_alloc_intern(size))) dm->drawObject->legacy = 1; /* nothing to do for legacy mode */ - if (dm->drawObject->legacy) + if (dm->drawObject->legacy) { + BLI_mutex_unlock(&buffer_mutex); return NULL; + } cur_index_per_mat = MEM_mallocN(sizeof(int) * object->totmaterial, "GPU_buffer_setup.cur_index_per_mat"); @@ -541,7 +583,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, /* attempt to map the buffer */ if (!(varray = glMapBufferARB(target, GL_WRITE_ONLY_ARB))) { /* failed to map the buffer; delete it */ - GPU_buffer_free(buffer); + gpu_buffer_free_intern(buffer); gpu_buffer_pool_delete_last(pool); buffer = NULL; @@ -549,7 +591,7 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, * and reallocating the buffer */ if (pool->totbuf > 0) { gpu_buffer_pool_delete_last(pool); - buffer = GPU_buffer_alloc(size); + buffer = gpu_buffer_alloc_intern(size); } /* allocation still failed; fall back @@ -591,6 +633,8 @@ static GPUBuffer *gpu_buffer_setup(DerivedMesh *dm, GPUDrawObject *object, MEM_freeN(cur_index_per_mat); + BLI_mutex_unlock(&buffer_mutex); + return buffer; } @@ -1911,6 +1955,7 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, /* Assign index for use in the triangle index buffer */ + /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */ BM_elem_index_set(v, (*v_index)); /* set_dirty! */ (*v_index)++; @@ -1918,19 +1963,19 @@ static void gpu_bmesh_vert_to_buffer_copy(BMVert *v, } /* Return the total number of vertices that don't have BM_ELEM_HIDDEN set */ -static int gpu_bmesh_vert_visible_count(GHash *bm_unique_verts, - GHash *bm_other_verts) +static int gpu_bmesh_vert_visible_count(GSet *bm_unique_verts, + GSet *bm_other_verts) { - GHashIterator gh_iter; + GSetIterator gs_iter; int totvert = 0; - GHASH_ITER (gh_iter, bm_unique_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, bm_unique_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) totvert++; } - GHASH_ITER (gh_iter, bm_other_verts) { - BMVert *v = BLI_ghashIterator_getKey(&gh_iter); + GSET_ITER (gs_iter, bm_other_verts) { + BMVert *v = BLI_gsetIterator_getKey(&gs_iter); if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) totvert++; } @@ -1957,10 +2002,10 @@ static int gpu_bmesh_face_visible_count(GHash *bm_faces) /* Creates a vertex buffer (coordinate, normal, color) and, if smooth * shading, an element index buffer. */ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, - BMesh *bm, - GHash *bm_faces, - GHash *bm_unique_verts, - GHash *bm_other_verts) + BMesh *bm, + GHash *bm_faces, + GSet *bm_unique_verts, + GSet *bm_other_verts) { VertexBufferFormat *vert_data; void *tri_data; @@ -1991,22 +2036,23 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, /* Fill vertex buffer */ vert_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); if (vert_data) { - GHashIterator gh_iter; int v_index = 0; if (buffers->smooth) { + GSetIterator gs_iter; + /* Vertices get an index assigned for use in the triangle * index buffer */ bm->elem_index_dirty |= BM_VERT; - GHASH_ITER (gh_iter, bm_unique_verts) { - gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter), + GSET_ITER (gs_iter, bm_unique_verts) { + gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter), vert_data, &v_index, NULL, NULL, cd_vert_mask_offset); } - GHASH_ITER (gh_iter, bm_other_verts) { - gpu_bmesh_vert_to_buffer_copy(BLI_ghashIterator_getKey(&gh_iter), + GSET_ITER (gs_iter, bm_other_verts) { + gpu_bmesh_vert_to_buffer_copy(BLI_gsetIterator_getKey(&gs_iter), vert_data, &v_index, NULL, NULL, cd_vert_mask_offset); } @@ -2014,6 +2060,8 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, maxvert = v_index; } else { + GHashIterator gh_iter; + GHASH_ITER (gh_iter, bm_faces) { BMFace *f = BLI_ghashIterator_getKey(&gh_iter); @@ -2045,6 +2093,9 @@ void GPU_update_bmesh_buffers(GPU_Buffers *buffers, } glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); + + /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */ + bm->elem_index_dirty |= BM_VERT; } else { /* Memory map failed */ diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index e244c7cf57f..d7919125fee 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -1039,9 +1039,7 @@ static void GPU_nodes_free(ListBase *nodes) { GPUNode *node; - while (nodes->first) { - node = nodes->first; - BLI_remlink(nodes, node); + while ((node = BLI_pophead(nodes))) { GPU_node_free(node); } } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 2aee5b4846a..cd8c2db1821 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2087,7 +2087,7 @@ void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result) node_bsdf_diffuse(color, 0.0, N, result); } -void node_subsurface_scattering(vec4 color, float roughness, vec3 N, out vec4 result) +void node_subsurface_scattering(vec4 color, float scale, vec3 radius, float sharpen, float texture_blur, vec3 N, out vec4 result) { node_bsdf_diffuse(color, 0.0, N, result); } diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 7399b8554aa..1f1fdedfa40 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -31,6 +31,8 @@ #ifndef __IMB_COLORMANAGEMENT_H__ #define __IMB_COLORMANAGEMENT_H__ +#include "BLI_sys_types.h" + #define BCM_CONFIG_FILE "config.ocio" struct bContext; @@ -62,19 +64,22 @@ void IMB_colormanagement_check_is_data(struct ImBuf *ibuf, const char *name); void IMB_colormanagement_assign_float_colorspace(struct ImBuf *ibuf, const char *name); void IMB_colormanagement_assign_rect_colorspace(struct ImBuf *ibuf, const char *name); +const char *IMB_colormanagement_get_float_colorspace(struct ImBuf *ibuf); +const char *IMB_colormanagement_get_rect_colorspace(struct ImBuf *ibuf); + /* ** Color space transformation functions ** */ void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, int predivide); + const char *from_colorspace, const char *to_colorspace, bool predivide); void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, int predivide); + const char *from_colorspace, const char *to_colorspace, bool predivide); void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace); void IMB_colormanagement_colorspace_to_scene_linear_v3(float pixel[3], struct ColorSpace *colorspace); -void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predivide, struct ColorSpace *colorspace); +void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], bool predivide, struct ColorSpace *colorspace); void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], struct ColorSpace *colorspace); -void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide); +void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide); void IMB_colormanagement_scene_linear_to_display_v3(float pixel[3], struct ColorManagedDisplay *display); void IMB_colormanagement_display_to_scene_linear_v3(float pixel[3], struct ColorManagedDisplay *display); @@ -88,7 +93,7 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float void IMB_colormanagement_imbuf_make_display_space(struct ImBuf *ibuf, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings); -struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, int save_as_render, int allocate_result, +struct ImBuf *IMB_colormanagement_imbuf_for_write(struct ImBuf *ibuf, bool save_as_render, bool allocate_result, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, struct ImageFormatData *image_format_data); @@ -110,7 +115,7 @@ unsigned char *IMB_display_buffer_acquire_ctx(const struct bContext *C, struct I void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, int predivide); + const struct ColorManagedDisplaySettings *display_settings, bool predivide); void IMB_display_buffer_release(void *cache_handle); @@ -142,7 +147,7 @@ void IMB_partial_display_buffer_update(struct ImBuf *ibuf, const float *linear_b int stride, int offset_x, int offset_y, const struct ColorManagedViewSettings *view_settings, const struct ColorManagedDisplaySettings *display_settings, int xmin, int ymin, int xmax, int ymax, - int update_orig_byte_buffer); + bool update_orig_byte_buffer); void IMB_partial_display_buffer_update_delayed(struct ImBuf *ibuf, int xmin, int ymin, int xmax, int ymax); @@ -154,29 +159,34 @@ void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_proc void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor, float pixel[4]); void IMB_colormanagement_processor_apply_v3(struct ColormanageProcessor *cm_processor, float pixel[3]); void IMB_colormanagement_processor_apply(struct ColormanageProcessor *cm_processor, float *buffer, int width, int height, - int channels, int predivide); + int channels, bool predivide); void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processor); /* ** OpenGL drawing routines using GLSL for color space transform ** */ +/* Test if GLSL drawing is supported for combination of graphics card and this configuration */ +bool IMB_colormanagement_support_glsl_draw(const struct ColorManagedViewSettings *view_settings, + bool skip_curves); /* Configures GLSL shader for conversion from scene linear to display space */ -int IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, - int predivide); +bool IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + bool predivide, + bool skip_curves); /* Same as above, but display space conversion happens from a specified space */ -int IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings, - struct ColorSpace *colorspace, - int predivide); +bool IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + struct ColorSpace *colorspace, + bool predivide, + bool skip_curves); /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ -int IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, int predivide); +bool IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, bool predivide); /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ -int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, int predivide); +bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, bool predivide); /* Finish GLSL-based display space conversion */ void IMB_colormanagement_finish_glsl_draw(void); /* Configures GLSL shader for conversion from space defined by role to scene linear space */ -int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide); +bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide); /* Finish GLSL-based color space conversion */ void IMB_colormanagement_finish_glsl_transform(void); diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index c372e125a66..3e201a2fc28 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -28,10 +28,11 @@ * */ -#ifndef IMB_COLORMANAGEMENT_INTERN_H -#define IMB_COLORMANAGEMENT_INTERN_H +#ifndef __IMB_COLORMANAGEMENT_INTERN_H__ +#define __IMB_COLORMANAGEMENT_INTERN_H__ #include "DNA_listBase.h" +#include "BLI_sys_types.h" struct OCIO_ConstProcessorRcPtr; struct ImBuf; @@ -48,8 +49,8 @@ typedef struct ColorSpace { struct OCIO_ConstProcessorRcPtr *to_scene_linear; struct OCIO_ConstProcessorRcPtr *from_scene_linear; - int is_invertible; - int is_data; + bool is_invertible; + bool is_data; } ColorSpace; typedef struct ColorManagedDisplay { @@ -87,7 +88,7 @@ struct ColorManagedView *colormanage_view_add(const char *name); struct ColorManagedView *colormanage_view_get_indexed(int index); struct ColorManagedView *colormanage_view_get_named(const char *name); -struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data); +struct ColorSpace *colormanage_colorspace_add(const char *name, const char *description, bool is_invertible, bool is_data); struct ColorSpace *colormanage_colorspace_get_named(const char *name); struct ColorSpace *colormanage_colorspace_get_roled(int role); struct ColorSpace *colormanage_colorspace_get_indexed(int index); @@ -97,4 +98,4 @@ void colorspace_set_default_role(char *colorspace, int size, int role); void colormanage_imbuf_set_default_spaces(struct ImBuf *ibuf); void colormanage_imbuf_make_linear(struct ImBuf *ibuf, const char *from_colorspace); -#endif /* IMB_COLORMANAGEMENT_INTERN_H */ +#endif /* __IMB_COLORMANAGEMENT_INTERN_H__ */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 0167eaccef0..a466074d06f 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -99,7 +99,7 @@ static pthread_mutex_t processor_lock = BLI_MUTEX_INITIALIZER; typedef struct ColormanageProcessor { OCIO_ConstProcessorRcPtr *processor; CurveMapping *curve_mapping; - int is_data_result; + bool is_data_result; } ColormanageProcessor; static struct global_glsl_state { @@ -470,7 +470,7 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) for (index = 0 ; index < tot_colorspace; index++) { OCIO_ConstColorSpaceRcPtr *ocio_colorspace; const char *description; - int is_invertible, is_data; + bool is_invertible, is_data; name = OCIO_configGetColorSpaceNameByIndex(config, index); @@ -923,7 +923,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) imb_freerectImBuf(ibuf); IMB_colormanagement_transform(ibuf->rect_float, ibuf->x, ibuf->y, ibuf->channels, - from_colorspace, to_colorspace, TRUE); + from_colorspace, to_colorspace, true); } } @@ -1134,6 +1134,21 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; } +const char *IMB_colormanagement_get_float_colorspace(ImBuf *ibuf) +{ + if (ibuf->float_colorspace) { + return ibuf->float_colorspace->name; + } + else { + return IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_SCENE_LINEAR); + } +} + +const char *IMB_colormanagement_get_rect_colorspace(ImBuf *ibuf) +{ + return ibuf->rect_colorspace->name; +} + /*********************** Threaded display buffer transform routines *************************/ typedef struct DisplayBufferThread { @@ -1151,7 +1166,7 @@ typedef struct DisplayBufferThread { int channels; float dither; - int is_data; + bool is_data; const char *byte_colorspace; const char *float_colorspace; @@ -1180,7 +1195,7 @@ static void display_buffer_init_handle(void *handle_v, int start_line, int tot_l int channels = ibuf->channels; float dither = ibuf->dither; - int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; + bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; int offset = channels * start_line * ibuf->x; int display_buffer_byte_offset = DISPLAY_BUFFER_CHANNELS * start_line * ibuf->x; @@ -1224,8 +1239,8 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle int buffer_size = channels * width * height; - int is_data = handle->is_data; - int is_data_display = handle->cm_processor->is_data_result; + bool is_data = handle->is_data; + bool is_data_display = handle->cm_processor->is_data_result; linear_buffer = MEM_callocN(buffer_size * sizeof(float), "color conversion linear buffer"); @@ -1258,7 +1273,7 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle if (!is_data && !is_data_display) { /* convert float buffer to scene linear space */ IMB_colormanagement_transform(linear_buffer, width, height, channels, - from_colorspace, to_colorspace, FALSE); + from_colorspace, to_colorspace, false); } *is_straight_alpha = true; @@ -1277,7 +1292,7 @@ static float *display_buffer_apply_get_linear_buffer(DisplayBufferThread *handle if (!is_data && !is_data_display) { IMB_colormanagement_transform(linear_buffer, width, height, channels, - from_colorspace, to_colorspace, TRUE); + from_colorspace, to_colorspace, true); } *is_straight_alpha = false; @@ -1310,7 +1325,7 @@ static void *do_display_buffer_apply_thread(void *handle_v) int width = handle->width; int height = handle->tot_line; float dither = handle->dither; - int is_data = handle->is_data; + bool is_data = handle->is_data; if (cm_processor == NULL) { if (display_buffer_byte) { @@ -1403,8 +1418,8 @@ static void display_buffer_apply_threaded(ImBuf *ibuf, float *buffer, unsigned c display_buffer_init_handle, do_display_buffer_apply_thread); } -static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +static bool is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings) { if ((view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) == 0 && view_settings->exposure == 0.0f && @@ -1414,10 +1429,10 @@ static int is_ibuf_rect_in_display_space(ImBuf *ibuf, const ColorManagedViewSett const char *to_colorspace = display_transform_get_colorspace_name(view_settings, display_settings); if (to_colorspace && !strcmp(from_colorspace, to_colorspace)) - return TRUE; + return true; } - return FALSE; + return false; } static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_buffer, unsigned char *display_buffer_byte, @@ -1425,7 +1440,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu const ColorManagedDisplaySettings *display_settings) { ColormanageProcessor *cm_processor = NULL; - int skip_transform = FALSE; + bool skip_transform = false; /* if we're going to transform byte buffer, check whether transformation would * happen to the same color space as byte buffer itself is @@ -1436,7 +1451,7 @@ static void colormanage_display_buffer_process_ex(ImBuf *ibuf, float *display_bu skip_transform = is_ibuf_rect_in_display_space(ibuf, view_settings, display_settings); } - if (skip_transform == FALSE) + if (skip_transform == false) cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); display_buffer_apply_threaded(ibuf, ibuf->rect_float, (unsigned char *) ibuf->rect, @@ -1462,7 +1477,7 @@ typedef struct ProcessorTransformThread { int start_line; int tot_line; int channels; - int predivide; + bool predivide; } ProcessorTransformThread; typedef struct ProcessorTransformInit { @@ -1471,7 +1486,7 @@ typedef struct ProcessorTransformInit { int width; int height; int channels; - int predivide; + bool predivide; } ProcessorTransformInitData; static void processor_transform_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v) @@ -1481,7 +1496,7 @@ static void processor_transform_init_handle(void *handle_v, int start_line, int int channels = init_data->channels; int width = init_data->width; - int predivide = init_data->predivide; + bool predivide = init_data->predivide; int offset = channels * start_line * width; @@ -1507,7 +1522,7 @@ static void *do_processor_transform_thread(void *handle_v) int channels = handle->channels; int width = handle->width; int height = handle->tot_line; - int predivide = handle->predivide; + bool predivide = handle->predivide; IMB_colormanagement_processor_apply(handle->cm_processor, buffer, width, height, channels, predivide); @@ -1515,7 +1530,7 @@ static void *do_processor_transform_thread(void *handle_v) } static void processor_transform_apply_threaded(float *buffer, int width, int height, int channels, - ColormanageProcessor *cm_processor, int predivide) + ColormanageProcessor *cm_processor, bool predivide) { ProcessorTransformInitData init_data; @@ -1534,7 +1549,7 @@ static void processor_transform_apply_threaded(float *buffer, int width, int hei /* convert the whole buffer from specified by name color space to another - internal implementation */ static void colormanagement_transform_ex(float *buffer, int width, int height, int channels, const char *from_colorspace, - const char *to_colorspace, int predivide, int do_threaded) + const char *to_colorspace, bool predivide, bool do_threaded) { ColormanageProcessor *cm_processor; @@ -1561,18 +1576,18 @@ static void colormanagement_transform_ex(float *buffer, int width, int height, i /* convert the whole buffer from specified by name color space to another */ void IMB_colormanagement_transform(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, int predivide) + const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, FALSE); + colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, false); } /* convert the whole buffer from specified by name color space to another * will do threaded conversion */ void IMB_colormanagement_transform_threaded(float *buffer, int width, int height, int channels, - const char *from_colorspace, const char *to_colorspace, int predivide) + const char *from_colorspace, const char *to_colorspace, bool predivide) { - colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, TRUE); + colormanagement_transform_ex(buffer, width, height, channels, from_colorspace, to_colorspace, predivide, true); } void IMB_colormanagement_transform_v4(float pixel[4], const char *from_colorspace, const char *to_colorspace) @@ -1633,7 +1648,7 @@ void IMB_colormanagement_scene_linear_to_colorspace_v3(float pixel[3], ColorSpac OCIO_processorApplyRGB(processor, pixel); } -void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predivide, ColorSpace *colorspace) +void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], bool predivide, ColorSpace *colorspace) { OCIO_ConstProcessorRcPtr *processor; @@ -1653,7 +1668,7 @@ void IMB_colormanagement_colorspace_to_scene_linear_v4(float pixel[4], int predi } } -void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, int predivide) +void IMB_colormanagement_colorspace_to_scene_linear(float *buffer, int width, int height, int channels, struct ColorSpace *colorspace, bool predivide) { OCIO_ConstProcessorRcPtr *processor; @@ -1732,7 +1747,7 @@ void IMB_colormanagement_pixel_to_display_space_v3(float result[3], const float } static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, int make_byte) + const ColorManagedDisplaySettings *display_settings, bool make_byte) { if (!ibuf->rect && make_byte) imb_addrectImBuf(ibuf); @@ -1750,7 +1765,7 @@ static void colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorMan void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { - colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, FALSE); + colormanagement_imbuf_make_display_space(ibuf, view_settings, display_settings, false); } /* prepare image buffer to be saved on disk, applying color management if needed @@ -1764,14 +1779,14 @@ void IMB_colormanagement_imbuf_make_display_space(ImBuf *ibuf, const ColorManage * in image format write callback and if float_colorspace is not NULL, no color * space transformation should be applied on this buffer. */ -ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int allocate_result, const ColorManagedViewSettings *view_settings, +ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, bool save_as_render, bool allocate_result, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, ImageFormatData *image_format_data) { ImBuf *colormanaged_ibuf = ibuf; - int do_colormanagement; + bool do_colormanagement; 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; + bool requires_linear_float = BKE_imtype_requires_linear_float(image_format_data->imtype); + bool do_alpha_under = image_format_data->planes != R_IMF_PLANES_RGBA; do_colormanagement = save_as_render && (is_movie || !requires_linear_float); @@ -1827,7 +1842,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int } if (do_colormanagement) { - int make_byte = FALSE; + bool make_byte = false; ImFileType *type; /* for proper check whether byte buffer is required by a format or not @@ -1843,7 +1858,7 @@ ImBuf *IMB_colormanagement_imbuf_for_write(ImBuf *ibuf, int save_as_render, int for (type = IMB_FILE_TYPES; type->is_a; type++) { if (type->save && type->ftype(type, colormanaged_ibuf)) { if ((type->flag & IM_FTYPE_FLOAT) == 0) - make_byte = TRUE; + make_byte = true; break; } @@ -1878,7 +1893,7 @@ void IMB_colormanagement_buffer_make_display_space(float *buffer, unsigned char cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); processor_transform_apply_threaded(display_buffer_float, width, height, channels, - cm_processor, TRUE); + cm_processor, true); IMB_buffer_byte_from_float(display_buffer, display_buffer_float, channels, dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, @@ -1964,7 +1979,7 @@ unsigned char *IMB_display_buffer_acquire(ImBuf *ibuf, const ColorManagedViewSet ibuf->x, 0, 0, applied_view_settings, display_settings, ibuf->invalid_rect.xmin, ibuf->invalid_rect.ymin, ibuf->invalid_rect.xmax, ibuf->invalid_rect.ymax, - FALSE); + false); } BLI_rcti_init(&ibuf->invalid_rect, 0, 0, 0, 0); @@ -2019,7 +2034,7 @@ unsigned char *IMB_display_buffer_acquire_ctx(const bContext *C, ImBuf *ibuf, vo void IMB_display_buffer_transform_apply(unsigned char *display_buffer, float *linear_buffer, int width, int height, int channels, const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, int predivide) + const ColorManagedDisplaySettings *display_settings, bool predivide) { if (global_tot_display == 0 || global_tot_view == 0) { IMB_buffer_byte_from_float(display_buffer, linear_buffer, channels, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_LINEAR_RGB, FALSE, @@ -2281,7 +2296,7 @@ static void colormanage_description_strip(char *description) } } -ColorSpace *colormanage_colorspace_add(const char *name, const char *description, int is_invertible, int is_data) +ColorSpace *colormanage_colorspace_add(const char *name, const char *description, bool is_invertible, bool is_data) { ColorSpace *colorspace, *prev_space; int counter = 1; @@ -2480,7 +2495,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe float *display_buffer_float = NULL; const int width = xmax - xmin; const int height = ymax - ymin; - int is_data = ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA; + bool is_data = (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA) != 0; if (dither != 0.0f) { /* cm_processor is NULL in cases byte_buffer's space matches display @@ -2561,7 +2576,7 @@ static void partial_buffer_update_rect(ImBuf *ibuf, unsigned char *display_buffe void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, const unsigned char *byte_buffer, int stride, int offset_x, int offset_y, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings, - int xmin, int ymin, int xmax, int ymax, int update_orig_byte_buffer) + int xmin, int ymin, int xmax, int ymax, bool update_orig_byte_buffer) { if ((ibuf->rect && ibuf->rect_float) || update_orig_byte_buffer) { /* update byte buffer created by legacy color management */ @@ -2608,7 +2623,7 @@ void IMB_partial_display_buffer_update(ImBuf *ibuf, const float *linear_buffer, if (display_buffer) { ColormanageProcessor *cm_processor = NULL; - int skip_transform = 0; + bool skip_transform = false; /* byte buffer is assumed to be in imbuf's rect space, so if byte buffer * is known we could skip display->linear->display conversion in case @@ -2673,7 +2688,7 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); - curvemapping_premultiply(cm_processor->curve_mapping, FALSE); + curvemapping_premultiply(cm_processor->curve_mapping, false); } return cm_processor; @@ -2722,7 +2737,7 @@ void IMB_colormanagement_processor_apply_v3(ColormanageProcessor *cm_processor, } void IMB_colormanagement_processor_apply(ColormanageProcessor *cm_processor, float *buffer, int width, int height, - int channels, int predivide) + int channels, bool predivide) { /* apply curve mapping */ if (cm_processor->curve_mapping) { @@ -2807,6 +2822,17 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s } } +bool IMB_colormanagement_support_glsl_draw(const ColorManagedViewSettings *view_settings, + bool skip_curves) +{ + /* curves not supported yet */ + if (!skip_curves) + if (view_settings && (view_settings->flag & COLORMANAGE_VIEW_USE_CURVES)) + return 0; + + return OCIO_supportGLSLDraw(); +} + /** * Configures GLSL shader for conversion from specified to * display color space @@ -2820,9 +2846,10 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s * This is low-level function, use glaDrawImBuf_glsl_ctx if you * only need to display given image buffer */ -int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, - struct ColorSpace *from_colorspace, int predivide) +bool IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + struct ColorSpace *from_colorspace, bool predivide, + bool skip_curves) { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -2840,8 +2867,9 @@ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSetting } /* RGB curves mapping is not supported on GPU yet. */ - if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) - return FALSE; + if (!skip_curves) + if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) + return false; /* Make sure OCIO processor is up-to-date. */ update_glsl_display_processor(applied_view_settings, display_settings, @@ -2851,27 +2879,27 @@ int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSetting } /* Configures GLSL shader for conversion from scene linear to display space */ -int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings, - int predivide) +bool IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + bool predivide, bool skip_curves) { return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, - NULL, predivide); + NULL, predivide, skip_curves); } /* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ -int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, int predivide) +bool IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, bool predivide) { ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings); - return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide); + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide, false); } /* Same as setup_glsl_draw, but color management settings are guessing from a given context */ -int IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, int predivide) +bool IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, bool predivide) { return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, predivide); } @@ -2897,7 +2925,7 @@ void IMB_colormanagement_finish_glsl_draw(void) * When there's no need to apply transform on 2D textures, use * IMB_colormanagement_finish_glsl_transform(). */ -int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide) +bool IMB_colormanagement_setup_transform_from_role_glsl(int role, bool predivide) { OCIO_ConstProcessorRcPtr *processor; ColorSpace *colorspace; diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 76a5e98da7e..af9f7109106 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -565,7 +565,7 @@ void IMB_rect_from_float(ImBuf *ibuf) buffer = MEM_dupallocN(ibuf->rect_float); /* first make float buffer in byte space */ - IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, TRUE); + IMB_colormanagement_transform(buffer, ibuf->x, ibuf->y, ibuf->channels, from_colorspace, ibuf->rect_colorspace->name, true); /* convert from float's premul alpha to byte's straight alpha */ IMB_unpremultiply_rect_float(buffer, ibuf->planes, ibuf->x, ibuf->y); @@ -657,7 +657,7 @@ void IMB_float_from_rect(ImBuf *ibuf) /* then make float be in linear space */ IMB_colormanagement_colorspace_to_scene_linear(rect_float, ibuf->x, ibuf->y, ibuf->channels, - ibuf->rect_colorspace, FALSE); + ibuf->rect_colorspace, false); /* byte buffer is straight alpha, float should always be premul */ IMB_premultiply_rect_float(rect_float, ibuf->channels, ibuf->x, ibuf->y); diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 26dd0f2977a..bde17e17419 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -359,17 +359,21 @@ void IMB_alpha_under_color_byte(unsigned char *rect, int x, int y, float backcol unsigned char *cp = rect; while (a--) { - if (cp[3] == 0) { + if (cp[3] == 255) { + /* pass */ + } + else if (cp[3] == 0) { cp[0] = backcol[0] * 255; cp[1] = backcol[1] * 255; cp[2] = backcol[2] * 255; } else { - int mul = 255 - cp[3]; + float alpha = cp[3] / 255.0; + float mul = 1.0f - alpha; - cp[0] = (cp[0] * cp[3] >> 8) + mul * backcol[0] / 255; - cp[1] = (cp[1] * cp[3] >> 8) + mul * backcol[1] / 255; - cp[2] = (cp[2] * cp[3] >> 8) + mul * backcol[2] / 255; + cp[0] = (cp[0] * alpha) + mul * backcol[0]; + cp[1] = (cp[1] * alpha) + mul * backcol[1]; + cp[2] = (cp[2] * alpha) + mul * backcol[2]; } cp[3] = 255; diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 38caf224c42..a31ed5e7420 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -59,11 +59,7 @@ #define IS_maxjpg(x) ((x->ftype & JPG_MSK) == JPG_MAX) /* the types are from the jpeg lib */ -static void jpeg_error(j_common_ptr cinfo) -#ifdef __GNUC__ -__attribute__((noreturn)) -#endif -; +static void jpeg_error(j_common_ptr cinfo) ATTR_NORETURN; static void init_source(j_decompress_ptr cinfo); static boolean fill_input_buffer(j_decompress_ptr cinfo); static void skip_input_data(j_decompress_ptr cinfo, long num_bytes); diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 7ff8667f90e..2cfbbbd516b 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -184,12 +184,9 @@ typedef struct Curve { struct Object *bevobj, *taperobj, *textoncurve; struct Ipo *ipo DNA_DEPRECATED; /* old animation system, deprecated for 2.5 */ - Path *path; struct Key *key; struct Material **mat; - ListBase bev; - /* texture space, copied as one block in editobject.c */ float loc[3]; float size[3]; diff --git a/source/blender/makesdna/DNA_ipo_types.h b/source/blender/makesdna/DNA_ipo_types.h index 3e641fba1ac..2699c6e576e 100644 --- a/source/blender/makesdna/DNA_ipo_types.h +++ b/source/blender/makesdna/DNA_ipo_types.h @@ -42,6 +42,8 @@ #include "DNA_ID.h" +#include "BLI_compiler_attrs.h" + /* -------------------------- Type Defines --------------------------- */ /* sometimes used - mainly for GE/Ketsji */ diff --git a/source/blender/makesdna/DNA_key_types.h b/source/blender/makesdna/DNA_key_types.h index 0a09a82b2bb..f5ce3c8d8c1 100644 --- a/source/blender/makesdna/DNA_key_types.h +++ b/source/blender/makesdna/DNA_key_types.h @@ -60,7 +60,6 @@ typedef struct KeyBlock { int uid; /* for meshes only, match the unique number with the customdata layer */ void *data; /* array of shape key values, size is (Key->elemsize * KeyBlock->totelem) */ - float *weights; /* store an aligned array of weights from 'vgroup' */ char name[64]; /* MAX_NAME (unique name, user assigned) */ char vgroup[64]; /* MAX_VGROUP_NAME (optional vertex group), array gets allocated into 'weights' when set */ diff --git a/source/blender/makesdna/DNA_lattice_types.h b/source/blender/makesdna/DNA_lattice_types.h index 837f0c354e6..242d6f0feeb 100644 --- a/source/blender/makesdna/DNA_lattice_types.h +++ b/source/blender/makesdna/DNA_lattice_types.h @@ -68,10 +68,6 @@ typedef struct Lattice { struct MDeformVert *dvert; char vgroup[64]; /* multiply the influence, MAX_VGROUP_NAME */ - /* used while deforming, always free and NULL after use */ - float *latticedata; - float latmat[4][4]; - struct EditLatt *editlatt; } Lattice; diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index 9f9bc25a61c..1114549f2da 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -42,7 +42,7 @@ struct Image; typedef struct MFace { unsigned int v1, v2, v3, v4; short mat_nr; - char edcode, flag; /* we keep edcode, for conversion to edges draw flags in old files */ + char edcode, flag; /* we keep edcode, for conversion to edges draw flags in old files */ } MFace; typedef struct MEdge { @@ -52,44 +52,42 @@ typedef struct MEdge { } MEdge; typedef struct MDeformWeight { - int def_nr; - float weight; + int def_nr; + float weight; } MDeformWeight; typedef struct MDeformVert { struct MDeformWeight *dw; int totweight; - int flag; /* flag only in use for weightpaint now */ + int flag; /* flag only in use for weightpaint now */ } MDeformVert; typedef struct MVert { - float co[3]; - short no[3]; + float co[3]; + short no[3]; char flag, bweight; } MVert; /* tessellation vertex color data. - * at the moment alpha is abused for vertex painting - * and not used for transparency, note that red and blue are swapped */ + * at the moment alpha is abused for vertex painting and not used for transparency, note that red and blue are swapped + */ typedef struct MCol { char a, r, g, b; } MCol; -/* new face structure, replaces MFace, which is now - * only used for storing tessellations.*/ +/* new face structure, replaces MFace, which is now only used for storing tessellations.*/ typedef struct MPoly { /* offset into loop array and number of loops in the face */ int loopstart; - int totloop; /* keep signed since we need to subtract when getting the previous loop */ + int totloop; /* keep signed since we need to subtract when getting the previous loop */ short mat_nr; char flag, pad; } MPoly; -/* the e here is because we want to move away from - * relying on edge hashes.*/ +/* the e here is because we want to move away from relying on edge hashes.*/ typedef struct MLoop { - unsigned int v; /*vertex index*/ - unsigned int e; /*edge index*/ + unsigned int v; /* vertex index */ + unsigned int e; /* edge index */ } MLoop; typedef struct MTexPoly { @@ -114,9 +112,11 @@ typedef struct MLoopUV { } MLoopUV; /*mloopuv->flag*/ -#define MLOOPUV_EDGESEL 1 -#define MLOOPUV_VERTSEL 2 -#define MLOOPUV_PINNED 4 +enum { + MLOOPUV_EDGESEL = (1 << 0), + MLOOPUV_VERTSEL = (1 << 1), + MLOOPUV_PINNED = (1 << 2), +}; /** * at the moment alpha is abused for vertex painting, @@ -166,13 +166,13 @@ typedef struct MTFace { /*Custom Data Properties*/ typedef struct MFloatProperty { - float f; + float f; } MFloatProperty; typedef struct MIntProperty { - int i; + int i; } MIntProperty; typedef struct MStringProperty { - char s[255], s_len; + char s[255], s_len; } MStringProperty; typedef struct OrigSpaceFace { @@ -188,11 +188,10 @@ typedef struct MDisps { int totdisp; int level; float (*disps)[3]; - - /* Used for hiding parts of a multires mesh. Essentially the multires - * equivalent of MVert.flag's ME_HIDE bit. - * - * This is a bitmap, keep in sync with type used in BLI_bitmap.h */ + + /* Used for hiding parts of a multires mesh. Essentially the multires equivalent of MVert.flag's ME_HIDE bit. + * NOTE: This is a bitmap, keep in sync with type used in BLI_bitmap.h + */ unsigned int *hidden; } MDisps; @@ -200,15 +199,18 @@ typedef struct MDisps { typedef struct MultiresCol { float a, r, g, b; } MultiresCol; + typedef struct MultiresColFace { /* vertex colors */ MultiresCol col[4]; } MultiresColFace; + typedef struct MultiresFace { unsigned int v[4]; unsigned int mid; char flag, mat_nr, pad[2]; } MultiresFace; + typedef struct MultiresEdge { unsigned int v[2]; unsigned int mid; @@ -245,7 +247,7 @@ typedef struct Multires { /** End Multires **/ typedef struct MRecast { - int i; + int i; } MRecast; typedef struct GridPaintMask { @@ -259,20 +261,19 @@ typedef struct GridPaintMask { } GridPaintMask; typedef enum MVertSkinFlag { - /* Marks a vertex as the edge-graph root, used for calculating - * rotations for all connected edges (recursively.) Also used to - * choose a root when generating an armature. */ + /* Marks a vertex as the edge-graph root, used for calculating rotations for all connected edges (recursively). + * Also used to choose a root when generating an armature. + */ MVERT_SKIN_ROOT = 1, - /* Marks a branch vertex (vertex with more than two connected - * edges) so that it's neighbors are directly hulled together, - * rather than the default of generating intermediate frames. */ - MVERT_SKIN_LOOSE = 2 + /* Marks a branch vertex (vertex with more than two connected edges), so that it's neighbors are + * directly hulled together, rather than the default of generating intermediate frames. + */ + MVERT_SKIN_LOOSE = 2, } MVertSkinFlag; typedef struct MVertSkin { - /* Radii of the skin, define how big the generated frames - * are. Currently only the first two elements are used. */ + /* Radii of the skin, define how big the generated frames are. Currently only the first two elements are used. */ float radius[3]; /* MVertSkinFlag */ @@ -285,7 +286,9 @@ typedef struct FreestyleEdge { } FreestyleEdge; /* FreestyleEdge->flag */ -#define FREESTYLE_EDGE_MARK 1 +enum { + FREESTYLE_EDGE_MARK = 1, +}; typedef struct FreestyleFace { char flag; @@ -293,96 +296,118 @@ typedef struct FreestyleFace { } FreestyleFace; /* FreestyleFace->flag */ -#define FREESTYLE_FACE_MARK 1 - -/* mvert->flag (1=SELECT) */ -#define ME_SPHERETEST 2 -#define ME_VERT_TMP_TAG 4 -#define ME_HIDE 16 -#define ME_VERT_MERGED (1<<6) -#define ME_VERT_PBVH_UPDATE (1<<7) - -/* medge->flag (1=SELECT)*/ -#define ME_EDGEDRAW (1<<1) -#define ME_SEAM (1<<2) -#define ME_FGON (1<<3) /* no longer used (now we have ngons), only defined so we can clear it */ - /* reserve 16 for ME_HIDE */ -#define ME_EDGERENDER (1<<5) -#define ME_LOOSEEDGE (1<<7) -#define ME_EDGE_TMP_TAG (1 << 8) -#define ME_SHARP (1<<9) /* only reason this flag remains a 'short' */ +enum { + FREESTYLE_FACE_MARK = 1, +}; + +/* mvert->flag */ +enum { +/* SELECT = (1 << 0), */ + ME_SPHERETEST = (1 << 1), + ME_VERT_TMP_TAG = (1 << 2), + ME_HIDE = (1 << 4), + ME_VERT_MERGED = (1 << 6), + ME_VERT_PBVH_UPDATE = (1 << 7), +}; + +/* medge->flag */ +enum { +/* SELECT = (1 << 0), */ + ME_EDGEDRAW = (1 << 1), + ME_SEAM = (1 << 2), + ME_FGON = (1 << 3), /* no longer used (now we have ngons), only defined so we can clear it */ +/* ME_HIDE = (1 << 4), */ + ME_EDGERENDER = (1 << 5), + ME_LOOSEEDGE = (1 << 7), + ME_EDGE_TMP_TAG = (1 << 8), + ME_SHARP = (1 << 9), /* only reason this flag remains a 'short' */ +}; /* puno = vertexnormal (mface) */ -#define ME_PROJXY 16 -#define ME_PROJXZ 32 -#define ME_PROJYZ 64 +enum { + ME_PROJXY = (1 << 4), + ME_PROJXZ = (1 << 5), + ME_PROJYZ = (1 << 6), +}; /* edcode (mface) */ -#define ME_V1V2 1 -#define ME_V2V3 2 -#define ME_V3V1 4 -#define ME_V3V4 4 -#define ME_V4V1 8 +enum { + ME_V1V2 = (1 << 0), + ME_V2V3 = (1 << 1), + ME_V3V1 = (1 << 2), + ME_V3V4 = ME_V3V1, + ME_V4V1 = (1 << 3), +}; /* flag (mface) */ -#define ME_SMOOTH 1 -#define ME_FACE_SEL 2 -/* flag ME_HIDE==16 is used here too */ +enum { + ME_SMOOTH = (1 << 0), + ME_FACE_SEL = (1 << 1), +/* ME_HIDE = (1 << 4), */ +}; #define ME_POLY_LOOP_PREV(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + (mp)->totloop - 1) % (mp)->totloop)]) #define ME_POLY_LOOP_NEXT(mloop, mp, i) (&(mloop)[(mp)->loopstart + (((i) + 1) % (mp)->totloop)]) /* mselect->type */ -#define ME_VSEL 0 -#define ME_ESEL 1 -#define ME_FSEL 2 +enum { + ME_VSEL = 0, + ME_ESEL = 1, + ME_FSEL = 2, +}; /* mtface->flag */ -#define TF_SELECT 1 /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */ -#define TF_ACTIVE 2 /* deprecated! */ -#define TF_SEL1 4 -#define TF_SEL2 8 -#define TF_SEL3 16 -#define TF_SEL4 32 +enum { + TF_SELECT = (1 << 0), /* use MFace hide flag (after 2.43), should be able to reuse after 2.44 */ + TF_ACTIVE = (1 << 1), /* deprecated! */ + TF_SEL1 = (1 << 2), + TF_SEL2 = (1 << 3), + TF_SEL3 = (1 << 4), + TF_SEL4 = (1 << 5), +}; /* mtface->mode */ -#define TF_DYNAMIC 1 -#define TF_ALPHASORT 2 -#define TF_TEX 4 -#define TF_SHAREDVERT 8 -#define TF_LIGHT 16 - -#define TF_CONVERTED 32 /* tface converted to material */ - -#define TF_SHAREDCOL 64 -#define TF_TILES 128 /* deprecated */ -#define TF_BILLBOARD 256 -#define TF_TWOSIDE 512 -#define TF_INVISIBLE 1024 - -#define TF_OBCOL 2048 -#define TF_BILLBOARD2 4096 /* with Z axis constraint */ -#define TF_SHADOW 8192 -#define TF_BMFONT 16384 +enum { + TF_DYNAMIC = (1 << 0), + TF_ALPHASORT = (1 << 1), + TF_TEX = (1 << 2), + TF_SHAREDVERT = (1 << 3), + TF_LIGHT = (1 << 4), + + TF_CONVERTED = (1 << 5), /* tface converted to material */ + + TF_SHAREDCOL = (1 << 6), + TF_TILES = (1 << 7), /* deprecated */ + TF_BILLBOARD = (1 << 8), + TF_TWOSIDE = (1 << 9), + TF_INVISIBLE = (1 << 10), + + TF_OBCOL = (1 << 11), + TF_BILLBOARD2 = (1 << 12), /* with Z axis constraint */ + TF_SHADOW = (1 << 13), + TF_BMFONT = (1 << 14), +}; /* mtface->transp, values 1-4 are used as flags in the GL, WARNING, TF_SUB cant work with this */ -#define TF_SOLID 0 -#define TF_ADD 1 -#define TF_ALPHA 2 -#define TF_CLIP 4 /* clipmap alpha/binary alpha all or nothing! */ - -/* sub is not available in the user interface anymore */ -#define TF_SUB 3 +enum { + TF_SOLID = 0, + TF_ADD = (1 << 0), + TF_ALPHA = (1 << 1), + TF_CLIP = (1 << 2), /* clipmap alpha/binary alpha all or nothing! */ + TF_SUB = 3, /* sub is not available in the user interface anymore */ +}; /* mtface->unwrap */ -#define TF_DEPRECATED1 1 -#define TF_DEPRECATED2 2 -#define TF_DEPRECATED3 4 -#define TF_DEPRECATED4 8 -#define TF_PIN1 16 -#define TF_PIN2 32 -#define TF_PIN3 64 -#define TF_PIN4 128 - -#endif +enum { + TF_DEPRECATED1 = (1 << 0), + TF_DEPRECATED2 = (1 << 1), + TF_DEPRECATED3 = (1 << 2), + TF_DEPRECATED4 = (1 << 3), + TF_PIN1 = (1 << 4), + TF_PIN2 = (1 << 5), + TF_PIN3 = (1 << 6), + TF_PIN4 = (1 << 7), +}; + +#endif /* __DNA_MESHDATA_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_meta_types.h b/source/blender/makesdna/DNA_meta_types.h index 56683bf4797..8bbe53b33a6 100644 --- a/source/blender/makesdna/DNA_meta_types.h +++ b/source/blender/makesdna/DNA_meta_types.h @@ -65,8 +65,6 @@ typedef struct MetaBall { ID id; struct AnimData *adt; - struct BoundBox *bb; - ListBase elems; ListBase disp; ListBase *editelems; /* not saved in files, note we use pointer for editmode check */ diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 65e5c4e347a..799968335b7 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -29,7 +29,8 @@ #include "DNA_listBase.h" /* WARNING ALERT! TYPEDEF VALUES ARE WRITTEN IN FILES! SO DO NOT CHANGE! - * (ONLY ADD NEW ITEMS AT THE END) */ + * (ONLY ADD NEW ITEMS AT THE END) + */ typedef enum ModifierType { eModifierType_None = 0, @@ -83,14 +84,14 @@ typedef enum ModifierType { } ModifierType; typedef enum ModifierMode { - eModifierMode_Realtime = (1<<0), - eModifierMode_Render = (1<<1), - eModifierMode_Editmode = (1<<2), - eModifierMode_OnCage = (1<<3), - eModifierMode_Expanded = (1<<4), - eModifierMode_Virtual = (1<<5), - eModifierMode_ApplyOnSpline = (1<<6), - eModifierMode_DisableTemporary = (1 << 31) + eModifierMode_Realtime = (1 << 0), + eModifierMode_Render = (1 << 1), + eModifierMode_Editmode = (1 << 2), + eModifierMode_OnCage = (1 << 3), + eModifierMode_Expanded = (1 << 4), + eModifierMode_Virtual = (1 << 5), + eModifierMode_ApplyOnSpline = (1 << 6), + eModifierMode_DisableTemporary = (1 << 31) } ModifierMode; typedef struct ModifierData { @@ -98,19 +99,19 @@ typedef struct ModifierData { int type, mode; int stackindex, pad; - char name[64]; /* MAX_NAME */ - + char name[64]; /* MAX_NAME */ + /* XXX for timing info set by caller... solve later? (ton) */ struct Scene *scene; - + char *error; } ModifierData; typedef enum { - eSubsurfModifierFlag_Incremental = (1<<0), - eSubsurfModifierFlag_DebugIncr = (1<<1), - eSubsurfModifierFlag_ControlEdges = (1<<2), - eSubsurfModifierFlag_SubsurfUv = (1<<3) + eSubsurfModifierFlag_Incremental = (1 << 0), + eSubsurfModifierFlag_DebugIncr = (1 << 1), + eSubsurfModifierFlag_ControlEdges = (1 << 2), + eSubsurfModifierFlag_SubsurfUv = (1 << 3), } SubsurfModifierFlag; /* not a real modifier */ @@ -119,7 +120,7 @@ typedef struct MappingInfoModifierData { struct Tex *texture; struct Object *map_object; - char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ int uvlayer_tmp; int texmapping; } MappingInfoModifierData; @@ -136,7 +137,7 @@ typedef struct LatticeModifierData { ModifierData modifier; struct Object *object; - char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ float strength; char pad[4]; } LatticeModifierData; @@ -145,18 +146,20 @@ typedef struct CurveModifierData { ModifierData modifier; struct Object *object; - char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ - short defaxis; /* axis along which curve deforms */ + char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + short defaxis; /* axis along which curve deforms */ char pad[6]; } CurveModifierData; /* CurveModifierData->defaxis */ -#define MOD_CURVE_POSX 1 -#define MOD_CURVE_POSY 2 -#define MOD_CURVE_POSZ 3 -#define MOD_CURVE_NEGX 4 -#define MOD_CURVE_NEGY 5 -#define MOD_CURVE_NEGZ 6 +enum { + MOD_CURVE_POSX = 1, + MOD_CURVE_POSY = 2, + MOD_CURVE_POSZ = 3, + MOD_CURVE_NEGX = 4, + MOD_CURVE_NEGY = 5, + MOD_CURVE_NEGZ = 6, +}; typedef struct BuildModifierData { ModifierData modifier; @@ -168,20 +171,24 @@ typedef struct BuildModifierData { /* Mask Modifier */ typedef struct MaskModifierData { ModifierData modifier; - - struct Object *ob_arm; /* armature to use to in place of hardcoded vgroup */ - char vgroup[64]; /* name of vertex group to use to mask, MAX_VGROUP_NAME */ - - int mode; /* using armature or hardcoded vgroup */ - int flag; /* flags for various things */ + + struct Object *ob_arm; /* armature to use to in place of hardcoded vgroup */ + char vgroup[64]; /* name of vertex group to use to mask, MAX_VGROUP_NAME */ + + int mode; /* using armature or hardcoded vgroup */ + int flag; /* flags for various things */ } MaskModifierData; /* Mask Modifier -> mode */ -#define MOD_MASK_MODE_VGROUP 0 -#define MOD_MASK_MODE_ARM 1 +enum { + MOD_MASK_MODE_VGROUP = 0, + MOD_MASK_MODE_ARM = 1, +}; /* Mask Modifier -> flag */ -#define MOD_MASK_INV (1<<0) +enum { + MOD_MASK_INV = (1 << 0), +}; typedef struct ArrayModifierData { ModifierData modifier; @@ -228,18 +235,24 @@ typedef struct ArrayModifierData { } ArrayModifierData; /* ArrayModifierData->fit_type */ -#define MOD_ARR_FIXEDCOUNT 0 -#define MOD_ARR_FITLENGTH 1 -#define MOD_ARR_FITCURVE 2 +enum { + MOD_ARR_FIXEDCOUNT = 0, + MOD_ARR_FITLENGTH = 1, + MOD_ARR_FITCURVE = 2, +}; /* ArrayModifierData->offset_type */ -#define MOD_ARR_OFF_CONST (1<<0) -#define MOD_ARR_OFF_RELATIVE (1<<1) -#define MOD_ARR_OFF_OBJ (1<<2) +enum { + MOD_ARR_OFF_CONST = (1 << 0), + MOD_ARR_OFF_RELATIVE = (1 << 1), + MOD_ARR_OFF_OBJ = (1 << 2), +}; /* ArrayModifierData->flags */ -#define MOD_ARR_MERGE (1<<0) -#define MOD_ARR_MERGEFINAL (1<<1) +enum { + MOD_ARR_MERGE = (1 << 0), + MOD_ARR_MERGEFINAL = (1 << 1), +}; typedef struct MirrorModifierData { ModifierData modifier; @@ -251,14 +264,16 @@ typedef struct MirrorModifierData { } MirrorModifierData; /* MirrorModifierData->flag */ -#define MOD_MIR_CLIPPING (1<<0) -#define MOD_MIR_MIRROR_U (1<<1) -#define MOD_MIR_MIRROR_V (1<<2) -#define MOD_MIR_AXIS_X (1<<3) -#define MOD_MIR_AXIS_Y (1<<4) -#define MOD_MIR_AXIS_Z (1<<5) -#define MOD_MIR_VGROUP (1<<6) -#define MOD_MIR_NO_MERGE (1<<7) +enum { + MOD_MIR_CLIPPING = (1 << 0), + MOD_MIR_MIRROR_U = (1 << 1), + MOD_MIR_MIRROR_V = (1 << 2), + MOD_MIR_AXIS_X = (1 << 3), + MOD_MIR_AXIS_Y = (1 << 4), + MOD_MIR_AXIS_Z = (1 << 5), + MOD_MIR_VGROUP = (1 << 6), + MOD_MIR_NO_MERGE = (1 << 7), +}; typedef struct EdgeSplitModifierData { ModifierData modifier; @@ -268,8 +283,10 @@ typedef struct EdgeSplitModifierData { } EdgeSplitModifierData; /* EdgeSplitModifierData->flags */ -#define MOD_EDGESPLIT_FROMANGLE (1<<1) -#define MOD_EDGESPLIT_FROMFLAG (1<<2) +enum { + MOD_EDGESPLIT_FROMANGLE = (1 << 1), + MOD_EDGESPLIT_FROMFLAG = (1 << 2), +}; typedef struct BevelModifierData { ModifierData modifier; @@ -281,29 +298,29 @@ typedef struct BevelModifierData { short val_flags; /* flags used to interpret the bevel value */ short lim_flags; /* flags to tell the tool how to limit the bevel */ short e_flags; /* flags to direct how edge weights are applied to verts */ - float bevel_angle; /* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */ - char defgrp_name[64]; /* if the MOD_BEVEL_VWEIGHT option is set, this will be the name of the vert group, MAX_VGROUP_NAME */ + /* if the MOD_BEVEL_ANGLE is set, this will be how "sharp" an edge must be before it gets beveled */ + float bevel_angle; + /* if the MOD_BEVEL_VWEIGHT option is set, this will be the name of the vert group, MAX_VGROUP_NAME */ + char defgrp_name[64]; } BevelModifierData; -#define MOD_BEVEL_VERT (1 << 1) -// #define MOD_BEVEL_RADIUS (1 << 2) -#define MOD_BEVEL_ANGLE (1 << 3) -#define MOD_BEVEL_WEIGHT (1 << 4) -#define MOD_BEVEL_VGROUP (1 << 5) -#define MOD_BEVEL_EMIN (1 << 7) -#define MOD_BEVEL_EMAX (1 << 8) -// #define MOD_BEVEL_RUNNING (1 << 9) -// #define MOD_BEVEL_RES (1 << 10) -// #define MOD_BEVEL_EVEN (1 << 11) /* this is a new setting not related to old (trunk bmesh bevel code) but adding -// * here because they are mixed - campbell */ -// #define MOD_BEVEL_DIST (1 << 12) /* same as above */ -#define MOD_BEVEL_OVERLAP_OK (1 << 13) - - -/* Smoke modifier flags */ -#define MOD_SMOKE_TYPE_DOMAIN (1 << 0) -#define MOD_SMOKE_TYPE_FLOW (1 << 1) -#define MOD_SMOKE_TYPE_COLL (1 << 2) +enum { + MOD_BEVEL_VERT = (1 << 1), +/* MOD_BEVEL_RADIUS = (1 << 2), */ + MOD_BEVEL_ANGLE = (1 << 3), + MOD_BEVEL_WEIGHT = (1 << 4), + MOD_BEVEL_VGROUP = (1 << 5), + MOD_BEVEL_EMIN = (1 << 7), + MOD_BEVEL_EMAX = (1 << 8), +/* MOD_BEVEL_RUNNING = (1 << 9), */ +/* MOD_BEVEL_RES = (1 << 10), */ + /* This is a new setting not related to old (trunk bmesh bevel code) + * but adding here because they are mixed - campbell + */ +/* MOD_BEVEL_EVEN = (1 << 11), */ +/* MOD_BEVEL_DIST = (1 << 12), */ /* same as above */ + MOD_BEVEL_OVERLAP_OK = (1 << 13), +}; typedef struct SmokeModifierData { ModifierData modifier; @@ -315,70 +332,79 @@ typedef struct SmokeModifierData { int type; /* domain, inflow, outflow, ... */ } SmokeModifierData; +/* Smoke modifier flags */ +enum { + MOD_SMOKE_TYPE_DOMAIN = (1 << 0), + MOD_SMOKE_TYPE_FLOW = (1 << 1), + MOD_SMOKE_TYPE_COLL = (1 << 2), +}; + typedef struct DisplaceModifierData { ModifierData modifier; /* keep in sync with MappingInfoModifierData */ struct Tex *texture; struct Object *map_object; - char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ int uvlayer_tmp; int texmapping; /* end MappingInfoModifierData */ float strength; int direction; - char defgrp_name[64]; /* MAX_VGROUP_NAME */ + char defgrp_name[64]; /* MAX_VGROUP_NAME */ float midlevel; int pad; } DisplaceModifierData; /* DisplaceModifierData->direction */ enum { - MOD_DISP_DIR_X = 0, - MOD_DISP_DIR_Y = 1, - MOD_DISP_DIR_Z = 2, - MOD_DISP_DIR_NOR = 3, + MOD_DISP_DIR_X = 0, + MOD_DISP_DIR_Y = 1, + MOD_DISP_DIR_Z = 2, + MOD_DISP_DIR_NOR = 3, MOD_DISP_DIR_RGB_XYZ = 4, }; /* DisplaceModifierData->texmapping */ enum { - MOD_DISP_MAP_LOCAL = 0, + MOD_DISP_MAP_LOCAL = 0, MOD_DISP_MAP_GLOBAL = 1, MOD_DISP_MAP_OBJECT = 2, - MOD_DISP_MAP_UV = 3 + MOD_DISP_MAP_UV = 3, }; typedef struct UVProjectModifierData { ModifierData modifier; /* the objects which do the projecting */ - struct Object *projectors[10]; /* MOD_UVPROJECT_MAX */ - struct Image *image; /* the image to project */ + struct Object *projectors[10]; /* MOD_UVPROJECT_MAXPROJECTORS */ + struct Image *image; /* the image to project */ int flags; int num_projectors; float aspectx, aspecty; float scalex, scaley; - char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ int uvlayer_tmp, pad; } UVProjectModifierData; #define MOD_UVPROJECT_MAXPROJECTORS 10 /* UVProjectModifierData->flags */ -#define MOD_UVPROJECT_OVERRIDEIMAGE (1<<0) +enum { + MOD_UVPROJECT_OVERRIDEIMAGE = (1 << 0), +}; typedef struct DecimateModifierData { ModifierData modifier; float percent; /* (mode == MOD_DECIM_MODE_COLLAPSE) */ - short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */ + short iter; /* (mode == MOD_DECIM_MODE_UNSUBDIV) */ char delimit; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ char pad; - float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ + float angle; /* (mode == MOD_DECIM_MODE_DISSOLVE) */ - char defgrp_name[64]; /* MAX_VGROUP_NAME */ + char defgrp_name[64]; /* MAX_VGROUP_NAME */ short flag, mode; /* runtime only */ @@ -388,20 +414,15 @@ typedef struct DecimateModifierData { enum { MOD_DECIM_FLAG_INVERT_VGROUP = (1 << 0), MOD_DECIM_FLAG_TRIANGULATE = (1 << 1), /* for collapse only. dont convert tri pairs back to quads */ - MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS = (1 << 2) /* for dissolve only. collapse all verts between 2 faces */ + MOD_DECIM_FLAG_ALL_BOUNDARY_VERTS = (1 << 2), /* for dissolve only. collapse all verts between 2 faces */ }; enum { MOD_DECIM_MODE_COLLAPSE, MOD_DECIM_MODE_UNSUBDIV, - MOD_DECIM_MODE_DISSOLVE /* called planar in the UI */ + MOD_DECIM_MODE_DISSOLVE, /* called planar in the UI */ }; -/* Smooth modifier flags */ -#define MOD_SMOOTH_X (1<<1) -#define MOD_SMOOTH_Y (1<<2) -#define MOD_SMOOTH_Z (1<<3) - typedef struct SmoothModifierData { ModifierData modifier; float fac; @@ -410,17 +431,12 @@ typedef struct SmoothModifierData { } SmoothModifierData; -/* Cast modifier flags */ -#define MOD_CAST_X (1<<1) -#define MOD_CAST_Y (1<<2) -#define MOD_CAST_Z (1<<3) -#define MOD_CAST_USE_OB_TRANSFORM (1<<4) -#define MOD_CAST_SIZE_FROM_RADIUS (1<<5) - -/* Cast modifier projection types */ -#define MOD_CAST_TYPE_SPHERE 0 -#define MOD_CAST_TYPE_CYLINDER 1 -#define MOD_CAST_TYPE_CUBOID 2 +/* Smooth modifier flags */ +enum { + MOD_SMOOTH_X = (1 << 1), + MOD_SMOOTH_Y = (1 << 2), + MOD_SMOOTH_Z = (1 << 3), +}; typedef struct CastModifierData { ModifierData modifier; @@ -429,18 +445,26 @@ typedef struct CastModifierData { float fac; float radius; float size; - char defgrp_name[64]; /* MAX_VGROUP_NAME */ + char defgrp_name[64]; /* MAX_VGROUP_NAME */ short flag, type; } CastModifierData; -/* WaveModifierData.flag */ -#define MOD_WAVE_X (1<<1) -#define MOD_WAVE_Y (1<<2) -#define MOD_WAVE_CYCL (1<<3) -#define MOD_WAVE_NORM (1<<4) -#define MOD_WAVE_NORM_X (1<<5) -#define MOD_WAVE_NORM_Y (1<<6) -#define MOD_WAVE_NORM_Z (1<<7) +/* Cast modifier flags */ +enum { + /* And what bout (1 << 0) flag? ;) */ + MOD_CAST_X = (1 << 1), + MOD_CAST_Y = (1 << 2), + MOD_CAST_Z = (1 << 3), + MOD_CAST_USE_OB_TRANSFORM = (1 << 4), + MOD_CAST_SIZE_FROM_RADIUS = (1 << 5), +}; + +/* Cast modifier projection types */ +enum { + MOD_CAST_TYPE_SPHERE = 0, + MOD_CAST_TYPE_CYLINDER = 1, + MOD_CAST_TYPE_CUBOID = 2, +}; typedef struct WaveModifierData { ModifierData modifier; @@ -448,13 +472,13 @@ typedef struct WaveModifierData { /* keep in sync with MappingInfoModifierData */ struct Tex *texture; struct Object *map_object; - char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ int uvlayer_tmp; int texmapping; /* end MappingInfoModifierData */ struct Object *objectcenter; - char defgrp_name[64]; /* MAX_VGROUP_NAME */ + char defgrp_name[64]; /* MAX_VGROUP_NAME */ short flag, pad; @@ -465,30 +489,42 @@ typedef struct WaveModifierData { float pad1; } WaveModifierData; +/* WaveModifierData.flag */ +enum { + /* And what bout (1 << 0) flag? ;) */ + MOD_WAVE_X = (1 << 1), + MOD_WAVE_Y = (1 << 2), + MOD_WAVE_CYCL = (1 << 3), + MOD_WAVE_NORM = (1 << 4), + MOD_WAVE_NORM_X = (1 << 5), + MOD_WAVE_NORM_Y = (1 << 6), + MOD_WAVE_NORM_Z = (1 << 7), +}; + typedef struct ArmatureModifierData { ModifierData modifier; - short deformflag, multi; /* deformflag replaces armature->deformflag */ + short deformflag, multi; /* deformflag replaces armature->deformflag */ int pad2; struct Object *object; - float *prevCos; /* stored input of previous modifier, for vertexgroup blending */ - char defgrp_name[64]; /* MAX_VGROUP_NAME */ + float *prevCos; /* stored input of previous modifier, for vertexgroup blending */ + char defgrp_name[64]; /* MAX_VGROUP_NAME */ } ArmatureModifierData; typedef struct HookModifierData { ModifierData modifier; struct Object *object; - char subtarget[64]; /* optional name of bone target, MAX_ID_NAME-2 */ - - float parentinv[4][4]; /* matrix making current transform unmodified */ - float cent[3]; /* visualization of hook */ - float falloff; /* if not zero, falloff is distance where influence zero */ - - int *indexar; /* if NULL, it's using vertexgroup */ + char subtarget[64]; /* optional name of bone target, MAX_ID_NAME-2 */ + + float parentinv[4][4]; /* matrix making current transform unmodified */ + float cent[3]; /* visualization of hook */ + float falloff; /* if not zero, falloff is distance where influence zero */ + + int *indexar; /* if NULL, it's using vertexgroup */ int totindex; float force; - char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + char name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ } HookModifierData; typedef struct SoftbodyModifierData { @@ -496,36 +532,36 @@ typedef struct SoftbodyModifierData { } SoftbodyModifierData; typedef struct ClothModifierData { - ModifierData modifier; + ModifierData modifier; - struct Scene *scene; /* the context, time etc is here */ - struct Cloth *clothObject; /* The internal data structure for cloth. */ - struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */ + struct Scene *scene; /* the context, time etc is here */ + struct Cloth *clothObject; /* The internal data structure for cloth. */ + struct ClothSimSettings *sim_parms; /* definition is in DNA_cloth_types.h */ struct ClothCollSettings *coll_parms; /* definition is in DNA_cloth_types.h */ - struct PointCache *point_cache; /* definition is in DNA_object_force.h */ + struct PointCache *point_cache; /* definition is in DNA_object_force.h */ struct ListBase ptcaches; } ClothModifierData; typedef struct CollisionModifierData { - ModifierData modifier; - - struct MVert *x; /* position at the beginning of the frame */ - struct MVert *xnew; /* position at the end of the frame */ - struct MVert *xold; /* unsued atm, but was discussed during sprint */ + ModifierData modifier; + + struct MVert *x; /* position at the beginning of the frame */ + struct MVert *xnew; /* position at the end of the frame */ + struct MVert *xold; /* unused atm, but was discussed during sprint */ struct MVert *current_xnew; /* new position at the actual inter-frame step */ - struct MVert *current_x; /* position at the actual inter-frame step */ - struct MVert *current_v; /* (xnew - x) at the actual inter-frame step */ - - struct MFace *mfaces; /* object face data */ - + struct MVert *current_x; /* position at the actual inter-frame step */ + struct MVert *current_v; /* (xnew - x) at the actual inter-frame step */ + + struct MFace *mfaces; /* object face data */ + unsigned int numverts; unsigned int numfaces; - float time_x, time_xnew; /* cfra time of modifier */ - struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */ + float time_x, time_xnew; /* cfra time of modifier */ + struct BVHTree *bvhtree; /* bounding volume hierarchy for this cloth object */ } CollisionModifierData; typedef struct SurfaceModifierData { - ModifierData modifier; + ModifierData modifier; struct MVert *x; /* old position */ struct MVert *v; /* velocity */ @@ -537,11 +573,6 @@ typedef struct SurfaceModifierData { int cfra, numverts; } SurfaceModifierData; -typedef enum { - eBooleanModifierOp_Intersect = 0, - eBooleanModifierOp_Union = 1, - eBooleanModifierOp_Difference = 2, -} BooleanModifierOp; typedef struct BooleanModifierData { ModifierData modifier; @@ -549,11 +580,11 @@ typedef struct BooleanModifierData { int operation, pad; } BooleanModifierData; -#define MOD_MDEF_INVERT_VGROUP (1<<0) -#define MOD_MDEF_DYNAMIC_BIND (1<<1) - -#define MOD_MDEF_VOLUME 0 -#define MOD_MDEF_SURFACE 1 +typedef enum { + eBooleanModifierOp_Intersect = 0, + eBooleanModifierOp_Union = 1, + eBooleanModifierOp_Difference = 2, +} BooleanModifierOp; typedef struct MDefInfluence { int vertex; @@ -568,45 +599,49 @@ typedef struct MDefCell { typedef struct MeshDeformModifierData { ModifierData modifier; - struct Object *object; /* mesh object */ - char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + struct Object *object; /* mesh object */ + char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ short gridsize, flag, mode, pad; /* result of static binding */ - MDefInfluence *bindinfluences; /* influences */ - int *bindoffsets; /* offsets into influences array */ - float *bindcagecos; /* coordinates that cage was bound with */ - int totvert, totcagevert; /* total vertices in mesh and cage */ + MDefInfluence *bindinfluences; /* influences */ + int *bindoffsets; /* offsets into influences array */ + float *bindcagecos; /* coordinates that cage was bound with */ + int totvert, totcagevert; /* total vertices in mesh and cage */ /* result of dynamic binding */ - MDefCell *dyngrid; /* grid with dynamic binding cell points */ - MDefInfluence *dyninfluences; /* dynamic binding vertex influences */ - int *dynverts, *pad2; /* is this vertex bound or not? */ - int dyngridsize; /* size of the dynamic bind grid */ - int totinfluence; /* total number of vertex influences */ - float dyncellmin[3]; /* offset of the dynamic bind grid */ - float dyncellwidth; /* width of dynamic bind cell */ - float bindmat[4][4]; /* matrix of cage at binding time */ + MDefCell *dyngrid; /* grid with dynamic binding cell points */ + MDefInfluence *dyninfluences; /* dynamic binding vertex influences */ + int *dynverts, *pad2; /* is this vertex bound or not? */ + int dyngridsize; /* size of the dynamic bind grid */ + int totinfluence; /* total number of vertex influences */ + float dyncellmin[3]; /* offset of the dynamic bind grid */ + float dyncellwidth; /* width of dynamic bind cell */ + float bindmat[4][4]; /* matrix of cage at binding time */ /* deprecated storage */ - float *bindweights; /* deprecated inefficient storage */ - float *bindcos; /* deprecated storage of cage coords */ + float *bindweights; /* deprecated inefficient storage */ + float *bindcos; /* deprecated storage of cage coords */ /* runtime */ - void (*bindfunc)(struct Scene *scene, - struct MeshDeformModifierData *mmd, - float *vertexcos, int totvert, float cagemat[4][4]); + void (*bindfunc)(struct Scene *scene, struct MeshDeformModifierData *mmd, + float *vertexcos, int totvert, float cagemat[4][4]); } MeshDeformModifierData; -typedef enum { - eParticleSystemFlag_Pars = (1<<0), - eParticleSystemFlag_psys_updated = (1<<1), - eParticleSystemFlag_file_loaded = (1<<2), -} ParticleSystemModifierFlag; +enum { + MOD_MDEF_INVERT_VGROUP = (1 << 0), + MOD_MDEF_DYNAMIC_BIND = (1 << 1), +}; + +enum { + MOD_MDEF_VOLUME = 0, + MOD_MDEF_SURFACE = 1, +}; typedef struct ParticleSystemModifierData { ModifierData modifier; + struct ParticleSystem *psys; struct DerivedMesh *dm; int totdmvert, totdmedge, totdmface; @@ -614,38 +649,46 @@ typedef struct ParticleSystemModifierData { } ParticleSystemModifierData; typedef enum { - eParticleInstanceFlag_Parents = (1<<0), - eParticleInstanceFlag_Children = (1<<1), - eParticleInstanceFlag_Path = (1<<2), - eParticleInstanceFlag_Unborn = (1<<3), - eParticleInstanceFlag_Alive = (1<<4), - eParticleInstanceFlag_Dead = (1<<5), - eParticleInstanceFlag_KeepShape = (1<<6), - eParticleInstanceFlag_UseSize = (1<<7), + eParticleSystemFlag_Pars = (1 << 0), + eParticleSystemFlag_psys_updated = (1 << 1), + eParticleSystemFlag_file_loaded = (1 << 2), +} ParticleSystemModifierFlag; + +typedef enum { + eParticleInstanceFlag_Parents = (1 << 0), + eParticleInstanceFlag_Children = (1 << 1), + eParticleInstanceFlag_Path = (1 << 2), + eParticleInstanceFlag_Unborn = (1 << 3), + eParticleInstanceFlag_Alive = (1 << 4), + eParticleInstanceFlag_Dead = (1 << 5), + eParticleInstanceFlag_KeepShape = (1 << 6), + eParticleInstanceFlag_UseSize = (1 << 7), } ParticleInstanceModifierFlag; typedef struct ParticleInstanceModifierData { ModifierData modifier; + struct Object *ob; short psys, flag, axis, rt; float position, random_position; } ParticleInstanceModifierData; typedef enum { - eExplodeFlag_CalcFaces = (1<<0), - eExplodeFlag_PaSize = (1<<1), - eExplodeFlag_EdgeCut = (1<<2), - eExplodeFlag_Unborn = (1<<3), - eExplodeFlag_Alive = (1<<4), - eExplodeFlag_Dead = (1<<5), + eExplodeFlag_CalcFaces = (1 << 0), + eExplodeFlag_PaSize = (1 << 1), + eExplodeFlag_EdgeCut = (1 << 2), + eExplodeFlag_Unborn = (1 << 3), + eExplodeFlag_Alive = (1 << 4), + eExplodeFlag_Dead = (1 << 5), } ExplodeModifierFlag; typedef struct ExplodeModifierData { ModifierData modifier; + int *facepa; short flag, vgroup; float protect; - char uvname[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char uvname[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ } ExplodeModifierData; typedef struct MultiresModifierData { @@ -656,83 +699,93 @@ typedef struct MultiresModifierData { } MultiresModifierData; typedef enum { - eMultiresModifierFlag_ControlEdges = (1<<0), - eMultiresModifierFlag_PlainUv = (1<<1), + eMultiresModifierFlag_ControlEdges = (1 << 0), + eMultiresModifierFlag_PlainUv = (1 << 1), } MultiresModifierFlag; typedef struct FluidsimModifierData { ModifierData modifier; - - struct FluidsimSettings *fss; /* definition is in DNA_object_fluidsim.h */ - struct PointCache *point_cache; /* definition is in DNA_object_force.h */ + + struct FluidsimSettings *fss; /* definition is in DNA_object_fluidsim.h */ + struct PointCache *point_cache; /* definition is in DNA_object_force.h */ } FluidsimModifierData; typedef struct ShrinkwrapModifierData { ModifierData modifier; - struct Object *target; /* shrink target */ + struct Object *target; /* shrink target */ struct Object *auxTarget; /* additional shrink target */ - char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ - float keepDist; /* distance offset to keep from mesh/projection point */ - short shrinkType; /* shrink type projection */ - short shrinkOpts; /* shrink options */ - float projLimit; /* limit the projection ray cast */ - char projAxis; /* axis to project over */ - - /* - * if using projection over vertex normal this controls the - * the level of subsurface that must be done before getting the - * vertex coordinates and normal + char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + float keepDist; /* distance offset to keep from mesh/projection point */ + short shrinkType; /* shrink type projection */ + short shrinkOpts; /* shrink options */ + float projLimit; /* limit the projection ray cast */ + char projAxis; /* axis to project over */ + + /* If using projection over vertex normal this controls the level of subsurface that must be done + * before getting the vertex coordinates and normal */ char subsurfLevels; char pad[2]; - } ShrinkwrapModifierData; /* Shrinkwrap->shrinkType */ -#define MOD_SHRINKWRAP_NEAREST_SURFACE 0 -#define MOD_SHRINKWRAP_PROJECT 1 -#define MOD_SHRINKWRAP_NEAREST_VERTEX 2 +enum { + MOD_SHRINKWRAP_NEAREST_SURFACE = 0, + MOD_SHRINKWRAP_PROJECT = 1, + MOD_SHRINKWRAP_NEAREST_VERTEX = 2, +}; /* Shrinkwrap->shrinkOpts */ -#define MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR (1<<0) /* allow shrinkwrap to move the vertex in the positive direction of axis */ -#define MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR (1<<1) /* allow shrinkwrap to move the vertex in the negative direction of axis */ +enum { + /* allow shrinkwrap to move the vertex in the positive direction of axis */ + MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR = (1 << 0), + /* allow shrinkwrap to move the vertex in the negative direction of axis */ + MOD_SHRINKWRAP_PROJECT_ALLOW_NEG_DIR = (1 << 1), -#define MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (1<<3) /* ignore vertex moves if a vertex ends projected on a front face of the target */ -#define MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (1<<4) /* ignore vertex moves if a vertex ends projected on a back face of the target */ + /* ignore vertex moves if a vertex ends projected on a front face of the target */ + MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE = (1 << 3), + /* ignore vertex moves if a vertex ends projected on a back face of the target */ + MOD_SHRINKWRAP_CULL_TARGET_BACKFACE = (1 << 4), -#define MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE (1<<5) /* distance is measure to the front face of the target */ + MOD_SHRINKWRAP_KEEP_ABOVE_SURFACE = (1 << 5), /* distance is measure to the front face of the target */ +}; -#define MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS (1<<0) -#define MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS (1<<1) -#define MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS (1<<2) -#define MOD_SHRINKWRAP_PROJECT_OVER_NORMAL 0 /* projection over normal is used if no axis is selected */ +/* Shrinkwrap->projAxis */ +enum { + MOD_SHRINKWRAP_PROJECT_OVER_NORMAL = 0, /* projection over normal is used if no axis is selected */ + MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS = (1 << 0), + MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS = (1 << 1), + MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS = (1 << 2), +}; typedef struct SimpleDeformModifierData { ModifierData modifier; - struct Object *origin; /* object to control the origin of modifier space coordinates */ - char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ - float factor; /* factors to control simple deforms */ - float limit[2]; /* lower and upper limit */ + struct Object *origin; /* object to control the origin of modifier space coordinates */ + char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + float factor; /* factors to control simple deforms */ + float limit[2]; /* lower and upper limit */ - char mode; /* deform function */ - char axis; /* lock axis (for taper and strech) */ + char mode; /* deform function */ + char axis; /* lock axis (for taper and strech) */ char pad[2]; } SimpleDeformModifierData; -#define MOD_SIMPLEDEFORM_MODE_TWIST 1 -#define MOD_SIMPLEDEFORM_MODE_BEND 2 -#define MOD_SIMPLEDEFORM_MODE_TAPER 3 -#define MOD_SIMPLEDEFORM_MODE_STRETCH 4 - -#define MOD_SIMPLEDEFORM_LOCK_AXIS_X (1<<0) -#define MOD_SIMPLEDEFORM_LOCK_AXIS_Y (1<<1) +enum { + MOD_SIMPLEDEFORM_MODE_TWIST = 1, + MOD_SIMPLEDEFORM_MODE_BEND = 2, + MOD_SIMPLEDEFORM_MODE_TAPER = 3, + MOD_SIMPLEDEFORM_MODE_STRETCH = 4, +}; -#define MOD_UVPROJECT_MAX 10 +enum { + MOD_SIMPLEDEFORM_LOCK_AXIS_X = (1 << 0), + MOD_SIMPLEDEFORM_LOCK_AXIS_Y = (1 << 1), +}; typedef struct ShapeKeyModifierData { ModifierData modifier; @@ -741,11 +794,12 @@ typedef struct ShapeKeyModifierData { typedef struct SolidifyModifierData { ModifierData modifier; - char defgrp_name[64]; /* name of vertex group to use, MAX_VGROUP_NAME */ - 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 */ + char defgrp_name[64]; /* name of vertex group to use, MAX_VGROUP_NAME */ + float offset; /* new surface offset level*/ + float offset_fac; /* midpoint of the offset */ + /* factor for the minimum weight to use when vgroups are used, avoids 0.0 weights giving duplicate geometry */ + float offset_fac_vg; + float offset_clamp; /* clamp offset based on surrounding geometry */ float pad; float crease_inner; float crease_outer; @@ -755,98 +809,107 @@ typedef struct SolidifyModifierData { short mat_ofs_rim; } SolidifyModifierData; -#define MOD_SOLIDIFY_RIM (1 << 0) -#define MOD_SOLIDIFY_EVEN (1 << 1) -#define MOD_SOLIDIFY_NORMAL_CALC (1 << 2) -#define MOD_SOLIDIFY_VGROUP_INV (1 << 3) -#define MOD_SOLIDIFY_RIM_MATERIAL (1 << 4) /* deprecated, used in do_versions */ -#define MOD_SOLIDIFY_FLIP (1 << 5) +enum { + MOD_SOLIDIFY_RIM = (1 << 0), + MOD_SOLIDIFY_EVEN = (1 << 1), + MOD_SOLIDIFY_NORMAL_CALC = (1 << 2), + MOD_SOLIDIFY_VGROUP_INV = (1 << 3), + MOD_SOLIDIFY_RIM_MATERIAL = (1 << 4), /* deprecated, used in do_versions */ + MOD_SOLIDIFY_FLIP = (1 << 5), +}; typedef struct ScrewModifierData { ModifierData modifier; + struct Object *ob_axis; - int steps; - int render_steps; - int iter; - float screw_ofs; - float angle; - short axis; - short flag; + int steps; + int render_steps; + int iter; + float screw_ofs; + float angle; + short axis; + short flag; } ScrewModifierData; -#define MOD_SCREW_NORMAL_FLIP (1 << 0) -#define MOD_SCREW_NORMAL_CALC (1 << 1) -#define MOD_SCREW_OBJECT_OFFSET (1 << 2) -// #define MOD_SCREW_OBJECT_ANGLE (1 << 4) -#define MOD_SCREW_SMOOTH_SHADING (1 << 5) +enum { + MOD_SCREW_NORMAL_FLIP = (1 << 0), + MOD_SCREW_NORMAL_CALC = (1 << 1), + MOD_SCREW_OBJECT_OFFSET = (1 << 2), +/* MOD_SCREW_OBJECT_ANGLE = (1 << 4), */ + MOD_SCREW_SMOOTH_SHADING = (1 << 5), +}; typedef struct OceanModifierData { ModifierData modifier; - + struct Ocean *ocean; struct OceanCache *oceancache; - int resolution; - int spatial_size; - - float wind_velocity; - - float damp; - float smallest_wave; - float depth; - - float wave_alignment; - float wave_direction; - float wave_scale; - - float chop_amount; - float foam_coverage; - float time; - - int bakestart; - int bakeend; - - char cachepath[1024]; // FILE_MAX - char foamlayername[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ - char cached; - char geometry_mode; + int resolution; + int spatial_size; - char flag; - char refresh; + float wind_velocity; - short repeat_x; - short repeat_y; + float damp; + float smallest_wave; + float depth; - int seed; + float wave_alignment; + float wave_direction; + float wave_scale; - float size; - - float foam_fade; + float chop_amount; + float foam_coverage; + float time; - int pad; + int bakestart; + int bakeend; -} OceanModifierData; + char cachepath[1024]; /* FILE_MAX */ + char foamlayername[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char cached; + char geometry_mode; -#define MOD_OCEAN_GEOM_GENERATE 0 -#define MOD_OCEAN_GEOM_DISPLACE 1 -#define MOD_OCEAN_GEOM_SIM_ONLY 2 + char flag; + char refresh; + + short repeat_x; + short repeat_y; + + int seed; + + float size; + + float foam_fade; -#define MOD_OCEAN_REFRESH_RESET 1 -#define MOD_OCEAN_REFRESH_SIM 2 -#define MOD_OCEAN_REFRESH_ADD 4 -#define MOD_OCEAN_REFRESH_CLEAR_CACHE 8 -#define MOD_OCEAN_REFRESH_TOPOLOGY 16 + int pad; +} OceanModifierData; -#define MOD_OCEAN_GENERATE_FOAM 1 -#define MOD_OCEAN_GENERATE_NORMALS 2 +enum { + MOD_OCEAN_GEOM_GENERATE = 0, + MOD_OCEAN_GEOM_DISPLACE = 1, + MOD_OCEAN_GEOM_SIM_ONLY = 2, +}; +enum { + MOD_OCEAN_REFRESH_RESET = (1 << 0), + MOD_OCEAN_REFRESH_SIM = (1 << 1), + MOD_OCEAN_REFRESH_ADD = (1 << 2), + MOD_OCEAN_REFRESH_CLEAR_CACHE = (1 << 3), + MOD_OCEAN_REFRESH_TOPOLOGY = (1 << 4), +}; + +enum { + MOD_OCEAN_GENERATE_FOAM = (1 << 0), + MOD_OCEAN_GENERATE_NORMALS = (1 << 1), +}; typedef struct WarpModifierData { ModifierData modifier; /* keep in sync with MappingInfoModifierData */ struct Tex *texture; struct Object *map_object; - char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ int uvlayer_tmp; int texmapping; /* end MappingInfoModifierData */ @@ -854,7 +917,7 @@ typedef struct WarpModifierData { struct Object *object_from; struct Object *object_to; struct CurveMapping *curfalloff; - char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + char defgrp_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ float strength; float falloff_radius; char flag; /* not used yet */ @@ -865,189 +928,175 @@ typedef struct WarpModifierData { #define MOD_WARP_VOLUME_PRESERVE 1 typedef enum { - eWarp_Falloff_None = 0, - eWarp_Falloff_Curve = 1, - eWarp_Falloff_Sharp = 2, /* PROP_SHARP */ - eWarp_Falloff_Smooth = 3, /* PROP_SMOOTH */ - eWarp_Falloff_Root = 4, /* PROP_ROOT */ - eWarp_Falloff_Linear = 5, /* PROP_LIN */ - eWarp_Falloff_Const = 6, /* PROP_CONST */ - eWarp_Falloff_Sphere = 7, /* PROP_SPHERE */ + eWarp_Falloff_None = 0, + eWarp_Falloff_Curve = 1, + eWarp_Falloff_Sharp = 2, /* PROP_SHARP */ + eWarp_Falloff_Smooth = 3, /* PROP_SMOOTH */ + eWarp_Falloff_Root = 4, /* PROP_ROOT */ + eWarp_Falloff_Linear = 5, /* PROP_LIN */ + eWarp_Falloff_Const = 6, /* PROP_CONST */ + eWarp_Falloff_Sphere = 7, /* PROP_SPHERE */ /* PROP_RANDOM not used */ } WarpModifierFalloff; typedef struct WeightVGEditModifierData { ModifierData modifier; - /* Note: I tried to keep everything logically ordered - provided the - * alignment constraints... */ - - char defgrp_name[64]; /* Name of vertex group to edit. MAX_VGROUP_NAME. */ + char defgrp_name[64]; /* Name of vertex group to edit. MAX_VGROUP_NAME. */ - short edit_flags; /* Using MOD_WVG_EDIT_* flags. */ - short falloff_type; /* Using MOD_WVG_MAPPING_* defines. */ - float default_weight; /* Weight for vertices not in vgroup. */ + short edit_flags; /* Using MOD_WVG_EDIT_* flags. */ + short falloff_type; /* Using MOD_WVG_MAPPING_* defines. */ + float default_weight; /* Weight for vertices not in vgroup. */ /* Mapping stuff. */ struct CurveMapping *cmap_curve; /* The custom mapping curve! */ /* The add/remove vertices weight thresholds. */ - float add_threshold, rem_threshold; + float add_threshold, rem_threshold; /* Masking options. */ - float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */ - /* Name of mask vertex group from which to get weight factors. */ - char mask_defgrp_name[64]; /* MAX_VGROUP_NAME */ + float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */ + char mask_defgrp_name[64]; /* Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME */ /* Texture masking. */ - int mask_tex_use_channel; /* Which channel to use as weightf. */ + int mask_tex_use_channel; /* Which channel to use as weightf. */ struct Tex *mask_texture; /* The texture. */ struct Object *mask_tex_map_obj; /* Name of the map object. */ - /* How to map the texture (using MOD_DISP_MAP_* constants). */ - int mask_tex_mapping; - char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME */ + int mask_tex_mapping; /* How to map the texture (using MOD_DISP_MAP_* enums). */ + char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME */ /* Padding... */ int pad_i1; } WeightVGEditModifierData; /* WeightVGEdit flags. */ -/* Use parametric mapping. */ -//#define MOD_WVG_EDIT_MAP (1 << 0) -/* Use curve mapping. */ -//#define MOD_WVG_EDIT_CMAP (1 << 1) -/* Reverse weights (in the [0.0, 1.0] standard range). */ -//#define MOD_WVG_EDIT_REVERSE_WEIGHTS (1 << 2) -/* Add vertices with higher weight than threshold to vgroup. */ -#define MOD_WVG_EDIT_ADD2VG (1 << 3) -/* Remove vertices with lower weight than threshold from vgroup. */ -#define MOD_WVG_EDIT_REMFVG (1 << 4) -/* Clamp weights. */ -//#define MOD_WVG_EDIT_CLAMP (1 << 5) +enum { + /* (1 << 0), (1 << 1) and (1 << 2) are free for future use! */ + MOD_WVG_EDIT_ADD2VG = (1 << 3), /* Add vertices with higher weight than threshold to vgroup. */ + MOD_WVG_EDIT_REMFVG = (1 << 4), /* Remove vertices with lower weight than threshold from vgroup. */ +}; typedef struct WeightVGMixModifierData { ModifierData modifier; - /* XXX Note: I tried to keep everything logically ordered - provided the - * alignment constraints... */ - - char defgrp_name_a[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ - char defgrp_name_b[64]; /* Name of other vertex group to mix in. MAX_VGROUP_NAME. */ - float default_weight_a; /* Default weight value for first vgroup. */ - float default_weight_b; /* Default weight value to mix in. */ - char mix_mode; /* How second vgroups weights affect first ones */ - char mix_set; /* What vertices to affect. */ + char defgrp_name_a[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ + char defgrp_name_b[64]; /* Name of other vertex group to mix in. MAX_VGROUP_NAME. */ + float default_weight_a; /* Default weight value for first vgroup. */ + float default_weight_b; /* Default weight value to mix in. */ + char mix_mode; /* How second vgroups weights affect first ones */ + char mix_set; /* What vertices to affect. */ - char pad_c1[6]; + char pad_c1[6]; /* Masking options. */ - float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */ - /* Name of mask vertex group from which to get weight factors. */ - char mask_defgrp_name[64]; /* MAX_VGROUP_NAME */ + float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */ + char mask_defgrp_name[64]; /* Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME */ /* Texture masking. */ - int mask_tex_use_channel; /* Which channel to use as weightf. */ - struct Tex *mask_texture; /* The texture. */ - struct Object *mask_tex_map_obj; /* Name of the map object. */ - int mask_tex_mapping; /* How to map the texture! */ - char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME. */ + int mask_tex_use_channel; /* Which channel to use as weightf. */ + struct Tex *mask_texture; /* The texture. */ + struct Object *mask_tex_map_obj; /* Name of the map object. */ + int mask_tex_mapping; /* How to map the texture! */ + char mask_tex_uvlayer_name[64]; /* Name of the UV map. MAX_CUSTOMDATA_LAYER_NAME. */ /* Padding... */ int pad_i1; } WeightVGMixModifierData; /* How second vgroup's weights affect first ones. */ -#define MOD_WVG_MIX_SET 1 /* Second weights replace weights. */ -#define MOD_WVG_MIX_ADD 2 /* Second weights are added to weights. */ -#define MOD_WVG_MIX_SUB 3 /* Second weights are subtracted from weights. */ -#define MOD_WVG_MIX_MUL 4 /* Second weights are multiplied with weights. */ -#define MOD_WVG_MIX_DIV 5 /* Second weights divide weights. */ -#define MOD_WVG_MIX_DIF 6 /* Difference between second weights and weights. */ -#define MOD_WVG_MIX_AVG 7 /* Average of both weights. */ +enum { + MOD_WVG_MIX_SET = 1, /* Second weights replace weights. */ + MOD_WVG_MIX_ADD = 2, /* Second weights are added to weights. */ + MOD_WVG_MIX_SUB = 3, /* Second weights are subtracted from weights. */ + MOD_WVG_MIX_MUL = 4, /* Second weights are multiplied with weights. */ + MOD_WVG_MIX_DIV = 5, /* Second weights divide weights. */ + MOD_WVG_MIX_DIF = 6, /* Difference between second weights and weights. */ + MOD_WVG_MIX_AVG = 7, /* Average of both weights. */ +}; /* What vertices to affect. */ -#define MOD_WVG_SET_ALL 1 /* Affect all vertices. */ -#define MOD_WVG_SET_A 2 /* Affect only vertices in first vgroup. */ -#define MOD_WVG_SET_B 3 /* Affect only vertices in second vgroup. */ -#define MOD_WVG_SET_OR 4 /* Affect only vertices in one vgroup or the other. */ -#define MOD_WVG_SET_AND 5 /* Affect only vertices in both vgroups. */ +enum { + MOD_WVG_SET_ALL = 1, /* Affect all vertices. */ + MOD_WVG_SET_A = 2, /* Affect only vertices in first vgroup. */ + MOD_WVG_SET_B = 3, /* Affect only vertices in second vgroup. */ + MOD_WVG_SET_OR = 4, /* Affect only vertices in one vgroup or the other. */ + MOD_WVG_SET_AND = 5, /* Affect only vertices in both vgroups. */ +}; typedef struct WeightVGProximityModifierData { ModifierData modifier; - /* Note: I tried to keep everything logically ordered - provided the - * alignment constraints... */ - - char defgrp_name[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ + char defgrp_name[64]; /* Name of vertex group to modify/weight. MAX_VGROUP_NAME. */ /* Proximity modes. */ - int proximity_mode; - int proximity_flags; + int proximity_mode; + int proximity_flags; /* Target object from which to calculate vertices distances. */ struct Object *proximity_ob_target; /* Masking options. */ - float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */ - /* Name of mask vertex group from which to get weight factors. */ - char mask_defgrp_name[64]; /* MAX_VGROUP_NAME */ + float mask_constant; /* The global "influence", if no vgroup nor tex is used as mask. */ + char mask_defgrp_name[64]; /* Name of mask vertex group from which to get weight factors. MAX_VGROUP_NAME */ /* Texture masking. */ - int mask_tex_use_channel; /* Which channel to use as weightf. */ - struct Tex *mask_texture; /* The texture. */ - struct Object *mask_tex_map_obj; /* Name of the map object. */ - int mask_tex_mapping; /* How to map the texture! */ - char mask_tex_uvlayer_name[64]; /* Name of the UV Map. MAX_CUSTOMDATA_LAYER_NAME. */ + int mask_tex_use_channel; /* Which channel to use as weightf. */ + struct Tex *mask_texture; /* The texture. */ + struct Object *mask_tex_map_obj; /* Name of the map object. */ + int mask_tex_mapping; /* How to map the texture! */ + char mask_tex_uvlayer_name[64]; /* Name of the UV Map. MAX_CUSTOMDATA_LAYER_NAME. */ - float min_dist, max_dist; /* Distances mapping to 0.0/1.0 weights. */ + float min_dist, max_dist; /* Distances mapping to 0.0/1.0 weights. */ /* Put here to avoid breaking existing struct... */ - short falloff_type; /* Using MOD_WVG_MAPPING_* defines. */ + short falloff_type; /* Using MOD_WVG_MAPPING_* enums. */ /* Padding... */ short pad_s1; } WeightVGProximityModifierData; /* Modes of proximity weighting. */ -/* Dist from target object to affected object. */ -#define MOD_WVG_PROXIMITY_OBJECT 1 /* source vertex to other location */ -/* Dist from target object to vertex. */ -#define MOD_WVG_PROXIMITY_GEOMETRY 2 /* source vertex to other geometry */ +enum { + MOD_WVG_PROXIMITY_OBJECT = 1, /* source vertex to other location */ + MOD_WVG_PROXIMITY_GEOMETRY = 2, /* source vertex to other geometry */ +}; /* Flags options for proximity weighting. */ -/* Use nearest vertices of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ -#define MOD_WVG_PROXIMITY_GEOM_VERTS (1 << 0) -/* Use nearest edges of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ -#define MOD_WVG_PROXIMITY_GEOM_EDGES (1 << 1) -/* Use nearest faces of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ -#define MOD_WVG_PROXIMITY_GEOM_FACES (1 << 2) +enum { + /* Use nearest vertices of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ + MOD_WVG_PROXIMITY_GEOM_VERTS = (1 << 0), + /* Use nearest edges of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ + MOD_WVG_PROXIMITY_GEOM_EDGES = (1 << 1), + /* Use nearest faces of target obj, in MOD_WVG_PROXIMITY_GEOMETRY mode. */ + MOD_WVG_PROXIMITY_GEOM_FACES = (1 << 2), +}; /* Defines common to all WeightVG modifiers. */ /* Mapping modes. */ -#define MOD_WVG_MAPPING_NONE 0 -#define MOD_WVG_MAPPING_CURVE 1 -#define MOD_WVG_MAPPING_SHARP 2 /* PROP_SHARP */ -#define MOD_WVG_MAPPING_SMOOTH 3 /* PROP_SMOOTH */ -#define MOD_WVG_MAPPING_ROOT 4 /* PROP_ROOT */ -/* PROP_LIN not used (same as NONE, here...). */ -/* PROP_CONST not used. */ -#define MOD_WVG_MAPPING_SPHERE 7 /* PROP_SPHERE */ -#define MOD_WVG_MAPPING_RANDOM 8 /* PROP_RANDOM */ -#define MOD_WVG_MAPPING_STEP 9 /* Median Step. */ +enum { + MOD_WVG_MAPPING_NONE = 0, + MOD_WVG_MAPPING_CURVE = 1, + MOD_WVG_MAPPING_SHARP = 2, /* PROP_SHARP */ + MOD_WVG_MAPPING_SMOOTH = 3, /* PROP_SMOOTH */ + MOD_WVG_MAPPING_ROOT = 4, /* PROP_ROOT */ + /* PROP_LIN not used (same as NONE, here...). */ + /* PROP_CONST not used. */ + MOD_WVG_MAPPING_SPHERE = 7, /* PROP_SPHERE */ + MOD_WVG_MAPPING_RANDOM = 8, /* PROP_RANDOM */ + MOD_WVG_MAPPING_STEP = 9, /* Median Step. */ +}; /* Tex channel to be used as mask. */ -#define MOD_WVG_MASK_TEX_USE_INT 1 -#define MOD_WVG_MASK_TEX_USE_RED 2 -#define MOD_WVG_MASK_TEX_USE_GREEN 3 -#define MOD_WVG_MASK_TEX_USE_BLUE 4 -#define MOD_WVG_MASK_TEX_USE_HUE 5 -#define MOD_WVG_MASK_TEX_USE_SAT 6 -#define MOD_WVG_MASK_TEX_USE_VAL 7 -#define MOD_WVG_MASK_TEX_USE_ALPHA 8 - -/* Dynamic paint modifier flags */ -#define MOD_DYNAMICPAINT_TYPE_CANVAS (1 << 0) -#define MOD_DYNAMICPAINT_TYPE_BRUSH (1 << 1) +enum { + MOD_WVG_MASK_TEX_USE_INT = 1, + MOD_WVG_MASK_TEX_USE_RED = 2, + MOD_WVG_MASK_TEX_USE_GREEN = 3, + MOD_WVG_MASK_TEX_USE_BLUE = 4, + MOD_WVG_MASK_TEX_USE_HUE = 5, + MOD_WVG_MASK_TEX_USE_SAT = 6, + MOD_WVG_MASK_TEX_USE_VAL = 7, + MOD_WVG_MASK_TEX_USE_ALPHA = 8, +}; typedef struct DynamicPaintModifierData { ModifierData modifier; @@ -1058,18 +1107,23 @@ typedef struct DynamicPaintModifierData { int pad; } DynamicPaintModifierData; -/* Remesh modifier */ +/* Dynamic paint modifier flags */ +enum { + MOD_DYNAMICPAINT_TYPE_CANVAS = (1 << 0), + MOD_DYNAMICPAINT_TYPE_BRUSH = (1 << 1), +}; +/* Remesh modifier */ typedef enum RemeshModifierFlags { - MOD_REMESH_FLOOD_FILL = 1, + MOD_REMESH_FLOOD_FILL = 1, MOD_REMESH_SMOOTH_SHADING = 2, } RemeshModifierFlags; typedef enum RemeshModifierMode { /* blocky */ - MOD_REMESH_CENTROID = 0, + MOD_REMESH_CENTROID = 0, /* smooth */ - MOD_REMESH_MASS_POINT = 1, + MOD_REMESH_MASS_POINT = 1, /* keeps sharp edges */ MOD_REMESH_SHARP_FEATURES = 2, } RemeshModifierMode; @@ -1077,8 +1131,7 @@ typedef enum RemeshModifierMode { typedef struct RemeshModifierData { ModifierData modifier; - /* floodfill option, controls how small components can be - * before they are removed */ + /* floodfill option, controls how small components can be before they are removed */ float threshold; /* ratio between size of model and grid */ @@ -1095,14 +1148,13 @@ typedef struct RemeshModifierData { } RemeshModifierData; /* Skin modifier */ - typedef struct SkinModifierData { ModifierData modifier; float branch_smoothing; char flag; - + char symmetry_axes; char pad[2]; @@ -1110,20 +1162,20 @@ typedef struct SkinModifierData { /* SkinModifierData.symmetry_axes */ enum { - MOD_SKIN_SYMM_X = 1, - MOD_SKIN_SYMM_Y = 2, - MOD_SKIN_SYMM_Z = 4, + MOD_SKIN_SYMM_X = (1 << 0), + MOD_SKIN_SYMM_Y = (1 << 1), + MOD_SKIN_SYMM_Z = (1 << 2), }; /* SkinModifierData.flag */ enum { - MOD_SKIN_SMOOTH_SHADING = 1 + MOD_SKIN_SMOOTH_SHADING = 1, }; /* Triangulate modifier */ - typedef struct TriangulateModifierData { ModifierData modifier; + int flag; int pad; } TriangulateModifierData; @@ -1132,39 +1184,43 @@ enum { MOD_TRIANGULATE_BEAUTY = (1 << 0), }; -/* Smooth modifier flags */ -#define MOD_LAPLACIANSMOOTH_X (1<<1) -#define MOD_LAPLACIANSMOOTH_Y (1<<2) -#define MOD_LAPLACIANSMOOTH_Z (1<<3) -#define MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME (1 << 4) -#define MOD_LAPLACIANSMOOTH_NORMALIZED (1 << 5) - typedef struct LaplacianSmoothModifierData { ModifierData modifier; + float lambda, lambda_border, pad1; - char defgrp_name[64]; /* MAX_VGROUP_NAME */ + char defgrp_name[64]; /* MAX_VGROUP_NAME */ short flag, repeat; } LaplacianSmoothModifierData; +/* Smooth modifier flags */ +enum { + MOD_LAPLACIANSMOOTH_X = (1 << 1), + MOD_LAPLACIANSMOOTH_Y = (1 << 2), + MOD_LAPLACIANSMOOTH_Z = (1 << 3), + MOD_LAPLACIANSMOOTH_PRESERVE_VOLUME = (1 << 4), + MOD_LAPLACIANSMOOTH_NORMALIZED = (1 << 5), +}; + typedef struct UVWarpModifierData { ModifierData modifier; char axis_u, axis_v; char pad[6]; - float center[2]; /* used for rotate/scale */ + float center[2]; /* used for rotate/scale */ struct Object *object_src; /* source */ - char bone_src[64]; /* optional name of bone target, MAX_ID_NAME-2 */ + char bone_src[64]; /* optional name of bone target, MAX_ID_NAME-2 */ struct Object *object_dst; /* target */ - char bone_dst[64]; /* optional name of bone target, MAX_ID_NAME-2 */ + char bone_dst[64]; /* optional name of bone target, MAX_ID_NAME-2 */ - char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ - char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ + char vgroup_name[64]; /* optional vertexgroup name, MAX_VGROUP_NAME */ + char uvlayer_name[64]; /* MAX_CUSTOMDATA_LAYER_NAME */ } UVWarpModifierData; /* cache modifier */ typedef struct MeshCacheModifierData { ModifierData modifier; + char flag; char type; /* file format */ char time_mode; @@ -1191,29 +1247,29 @@ typedef struct MeshCacheModifierData { float eval_time; float eval_factor; - char filepath[1024]; // FILE_MAX + char filepath[1024]; /* FILE_MAX */ } MeshCacheModifierData; enum { MOD_MESHCACHE_TYPE_MDD = 1, - MOD_MESHCACHE_TYPE_PC2 = 2 + MOD_MESHCACHE_TYPE_PC2 = 2, }; enum { MOD_MESHCACHE_DEFORM_OVERWRITE = 0, - MOD_MESHCACHE_DEFORM_INTEGRATE = 1 + MOD_MESHCACHE_DEFORM_INTEGRATE = 1, }; enum { - MOD_MESHCACHE_INTERP_NONE = 0, - MOD_MESHCACHE_INTERP_LINEAR = 1, - // MOD_MESHCACHE_INTERP_CARDINAL = 2 + MOD_MESHCACHE_INTERP_NONE = 0, + MOD_MESHCACHE_INTERP_LINEAR = 1, +/* MOD_MESHCACHE_INTERP_CARDINAL = 2, */ }; enum { - MOD_MESHCACHE_TIME_FRAME = 0, + MOD_MESHCACHE_TIME_FRAME = 0, MOD_MESHCACHE_TIME_SECONDS = 1, - MOD_MESHCACHE_TIME_FACTOR = 2, + MOD_MESHCACHE_TIME_FACTOR = 2, }; enum { diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index fda696f2e28..e7eb670572a 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -720,8 +720,10 @@ typedef struct NodeTexBase { typedef struct NodeTexSky { NodeTexBase base; + int sky_model; float sun_direction[3]; float turbidity; + float ground_albedo; } NodeTexSky; typedef struct NodeTexImage { @@ -937,6 +939,10 @@ typedef struct NodeShaderNormalMap { #define SHD_WAVE_BANDS 0 #define SHD_WAVE_RINGS 1 +/* sky texture */ +#define SHD_SKY_OLD 0 +#define SHD_SKY_NEW 1 + /* image/environment texture */ #define SHD_COLORSPACE_NONE 0 #define SHD_COLORSPACE_COLOR 1 @@ -965,6 +971,11 @@ typedef struct NodeShaderNormalMap { #define SHD_NORMAL_MAP_BLENDER_OBJECT 3 #define SHD_NORMAL_MAP_BLENDER_WORLD 4 +/* tangent */ +#define SHD_SUBSURFACE_COMPATIBLE 0 +#define SHD_SUBSURFACE_CUBIC 1 +#define SHD_SUBSURFACE_GAUSSIAN 2 + /* blur node */ #define CMP_NODE_BLUR_ASPECT_NONE 0 #define CMP_NODE_BLUR_ASPECT_Y 1 diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index de34f101c31..53d2ab1df07 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -41,7 +41,7 @@ #ifdef __cplusplus extern "C" { #endif - + struct Object; struct AnimData; struct Ipo; @@ -100,7 +100,10 @@ typedef struct BoundBox { } BoundBox; /* boundbox flag */ -#define OB_BB_DISABLED 1 +enum { + BOUNDBOX_DISABLED = (1 << 0), + BOUNDBOX_DIRTY = (1 << 1), +}; typedef struct Object { ID id; @@ -130,7 +133,6 @@ typedef struct Object { ListBase constraintChannels DNA_DEPRECATED; // XXX deprecated... old animation system ListBase effect DNA_DEPRECATED; // XXX deprecated... keep for readfile - ListBase disp; /* list of DispList, used by lattice, metaballs curve & surfaces */ ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */ ListBase modifiers; /* list of ModifierData structures */ @@ -276,6 +278,9 @@ typedef struct Object { struct RigidBodyCon *rigidbody_constraint; /* settings for Bullet constraint */ float ima_ofs[2]; /* offset for image empties */ + + /* Runtime valuated curve-specific data, not stored in the file */ + struct CurveCache *curve_cache; } Object; /* Warning, this is not used anymore because hooks are now modifiers */ @@ -318,26 +323,28 @@ typedef struct DupliObject { /* **************** OBJECT ********************* */ /* used many places... should be specialized */ -#define SELECT 1 +#define SELECT 1 /* type */ -#define OB_EMPTY 0 -#define OB_MESH 1 -#define OB_CURVE 2 -#define OB_SURF 3 -#define OB_FONT 4 -#define OB_MBALL 5 +enum { + OB_EMPTY = 0, + OB_MESH = 1, + OB_CURVE = 2, + OB_SURF = 3, + OB_FONT = 4, + OB_MBALL = 5, -#define OB_LAMP 10 -#define OB_CAMERA 11 + OB_LAMP = 10, + OB_CAMERA = 11, -#define OB_SPEAKER 12 + OB_SPEAKER = 12, -// #define OB_WAVE 21 -#define OB_LATTICE 22 +/* OB_WAVE = 21, */ + OB_LATTICE = 22, /* 23 and 24 are for life and sector (old file compat.) */ -#define OB_ARMATURE 25 + OB_ARMATURE = 25, +}; /* check if the object type supports materials */ #define OB_TYPE_SUPPORT_MATERIAL(_type) \ @@ -346,6 +353,8 @@ typedef struct DupliObject { (ELEM(_type, OB_MESH, OB_LATTICE)) #define OB_TYPE_SUPPORT_EDITMODE(_type) \ (ELEM7(_type, OB_MESH, OB_FONT, OB_CURVE, OB_SURF, OB_MBALL, OB_LATTICE, OB_ARMATURE)) +#define OB_TYPE_SUPPORT_PARVERT(_type) \ + (ELEM4(_type, OB_MESH, OB_SURF, OB_CURVE, OB_LATTICE)) /* is this ID type used as object data */ #define OB_DATA_SUPPORT_ID(_id_type) \ @@ -355,263 +364,300 @@ typedef struct DupliObject { ID_ME: case ID_CU: case ID_MB: case ID_LA: case ID_SPK: case ID_CA: case ID_LT: case ID_AR /* partype: first 4 bits: type */ -#define PARTYPE 15 -#define PAROBJECT 0 -#define PARCURVE 1 -#define PARKEY 2 +enum { + PARTYPE = (1 << 4) - 1, + PAROBJECT = 0, + PARCURVE = 1, + PARKEY = 2, -#define PARSKEL 4 -#define PARVERT1 5 -#define PARVERT3 6 -#define PARBONE 7 + PARSKEL = 4, + PARVERT1 = 5, + PARVERT3 = 6, + PARBONE = 7, /* slow parenting - is not threadsafe and/or may give errors after jumping */ -#define PARSLOW 16 + PARSLOW = 16, +}; /* (short) transflag */ /* flags 1 and 2 were unused or relics from past features */ -#define OB_NEG_SCALE 4 -#define OB_DUPLI (8+16+256+512+2048) -#define OB_DUPLIFRAMES 8 -#define OB_DUPLIVERTS 16 -#define OB_DUPLIROT 32 -#define OB_DUPLINOSPEED 64 -/*#define OB_POWERTRACK 128*/ /*UNUSED*/ -#define OB_DUPLIGROUP 256 -#define OB_DUPLIFACES 512 -#define OB_DUPLIFACES_SCALE 1024 -#define OB_DUPLIPARTS 2048 -#define OB_RENDER_DUPLI 4096 -#define OB_NO_CONSTRAINTS 8192 /* runtime constraints disable */ -#define OB_NO_PSYS_UPDATE 16384 /* hack to work around particle issue */ +enum { + OB_NEG_SCALE = 1 << 2, + OB_DUPLIFRAMES = 1 << 3, + OB_DUPLIVERTS = 1 << 4, + OB_DUPLIROT = 1 << 5, + OB_DUPLINOSPEED = 1 << 6, +/* OB_POWERTRACK = 1 << 7,*/ /*UNUSED*/ + OB_DUPLIGROUP = 1 << 8, + OB_DUPLIFACES = 1 << 9, + OB_DUPLIFACES_SCALE = 1 << 10, + OB_DUPLIPARTS = 1 << 11, + OB_RENDER_DUPLI = 1 << 12, + OB_NO_CONSTRAINTS = 1 << 13, /* runtime constraints disable */ + OB_NO_PSYS_UPDATE = 1 << 14, /* hack to work around particle issue */ + + OB_DUPLI = OB_DUPLIFRAMES | OB_DUPLIVERTS | OB_DUPLIGROUP | OB_DUPLIFACES | OB_DUPLIPARTS, +}; /* (short) ipoflag */ /* XXX: many old flags for features removed due to incompatibility * with new system and/or other design issues were here */ /* for stride/path editing (XXX: NEEDS REVIEW) */ -#define OB_DISABLE_PATH 1024 +#define OB_DISABLE_PATH (1 << 10) /* (short) trackflag / upflag */ -#define OB_POSX 0 -#define OB_POSY 1 -#define OB_POSZ 2 -#define OB_NEGX 3 -#define OB_NEGY 4 -#define OB_NEGZ 5 +enum { + OB_POSX = 0, + OB_POSY = 1, + OB_POSZ = 2, + OB_NEGX = 3, + OB_NEGY = 4, + OB_NEGZ = 5, +}; /* gameflag in game.h */ /* dt: no flags */ -#define OB_BOUNDBOX 1 -#define OB_WIRE 2 -#define OB_SOLID 3 -#define OB_MATERIAL 4 -#define OB_TEXTURE 5 -#define OB_RENDER 6 +enum { + OB_BOUNDBOX = 1, + OB_WIRE = 2, + OB_SOLID = 3, + OB_MATERIAL = 4, + OB_TEXTURE = 5, + OB_RENDER = 6, -#define OB_PAINT 100 /* temporary used in draw code */ + OB_PAINT = 100, /* temporary used in draw code */ +}; /* dtx: flags (short) */ -#define OB_DRAWBOUNDOX (1 << 0) -#define OB_AXIS (1 << 1) -#define OB_TEXSPACE (1 << 2) -#define OB_DRAWNAME (1 << 3) -#define OB_DRAWIMAGE (1 << 4) +enum { + OB_DRAWBOUNDOX = 1 << 0, + OB_AXIS = 1 << 1, + OB_TEXSPACE = 1 << 2, + OB_DRAWNAME = 1 << 3, + OB_DRAWIMAGE = 1 << 4, /* for solid+wire display */ -#define OB_DRAWWIRE (1 << 5) + OB_DRAWWIRE = 1 << 5, /* for overdraw s*/ -#define OB_DRAWXRAY (1 << 6) + OB_DRAWXRAY = 1 << 6, /* enable transparent draw */ -#define OB_DRAWTRANSP (1 << 7) -#define OB_DRAW_ALL_EDGES (1 << 8) /* only for meshes currently */ + OB_DRAWTRANSP = 1 << 7, + OB_DRAW_ALL_EDGES = 1 << 8, /* only for meshes currently */ +}; /* empty_drawtype: no flags */ -#define OB_ARROWS 1 -#define OB_PLAINAXES 2 -#define OB_CIRCLE 3 -#define OB_SINGLE_ARROW 4 -#define OB_CUBE 5 -#define OB_EMPTY_SPHERE 6 -#define OB_EMPTY_CONE 7 -#define OB_EMPTY_IMAGE 8 +enum { + OB_ARROWS = 1, + OB_PLAINAXES = 2, + OB_CIRCLE = 3, + OB_SINGLE_ARROW = 4, + OB_CUBE = 5, + OB_EMPTY_SPHERE = 6, + OB_EMPTY_CONE = 7, + OB_EMPTY_IMAGE = 8, +}; /* boundtype */ -#define OB_BOUND_BOX 0 -#define OB_BOUND_SPHERE 1 -#define OB_BOUND_CYLINDER 2 -#define OB_BOUND_CONE 3 -#define OB_BOUND_TRIANGLE_MESH 4 -#define OB_BOUND_CONVEX_HULL 5 -/* #define OB_BOUND_DYN_MESH 6 */ /*UNUSED*/ -#define OB_BOUND_CAPSULE 7 +enum { + OB_BOUND_BOX = 0, + OB_BOUND_SPHERE = 1, + OB_BOUND_CYLINDER = 2, + OB_BOUND_CONE = 3, + OB_BOUND_TRIANGLE_MESH = 4, + OB_BOUND_CONVEX_HULL = 5, +/* OB_BOUND_DYN_MESH = 6, */ /*UNUSED*/ + OB_BOUND_CAPSULE = 7, +}; /* **************** BASE ********************* */ -/* also needed for base!!!!! or rather, thy interfere....*/ +/* also needed for base!!!!! or rather, they interfere....*/ /* base->flag and ob->flag */ -#define BA_WAS_SEL 2 -#define BA_HAS_RECALC_OB 4 -#define BA_HAS_RECALC_DATA 8 +#define BA_WAS_SEL (1 << 1) +#define BA_HAS_RECALC_OB (1 << 2) +#define BA_HAS_RECALC_DATA (1 << 3) /* NOTE: this was used as a proper setting in past, so nullify before using */ -#define BA_TEMP_TAG 32 +#define BA_TEMP_TAG (1 << 5) -/* #define BA_FROMSET 128 */ /*UNUSED*/ +/* #define BA_FROMSET (1 << 7) */ /*UNUSED*/ -#define BA_TRANSFORM_CHILD 256 /* child of a transformed object */ -#define BA_TRANSFORM_PARENT 8192 /* parent of a transformed object */ +#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */ +#define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */ /* an initial attempt as making selection more specific! */ -#define BA_DESELECT 0 -#define BA_SELECT 1 +#define BA_DESELECT 0 +#define BA_SELECT 1 -#define OB_FROMDUPLI 512 -#define OB_DONE 1024 -// #define OB_RADIO 2048 /* deprecated */ -#define OB_FROMGROUP 4096 +#define OB_FROMDUPLI (1 << 9) +#define OB_DONE (1 << 10) +/* #define OB_RADIO (1 << 11) */ /* deprecated */ +#define OB_FROMGROUP (1 << 12) /* WARNING - when adding flags check on PSYS_RECALC */ /* ob->recalc (flag bits!) */ -#define OB_RECALC_OB (1 << 0) -#define OB_RECALC_DATA (1 << 1) +enum { + OB_RECALC_OB = 1 << 0, + OB_RECALC_DATA = 1 << 1, /* time flag is set when time changes need recalc, so baked systems can ignore it */ -#define OB_RECALC_TIME (1 << 2) + OB_RECALC_TIME = 1 << 2, /* only use for matching any flag, NOT as an argument since more flags may be added. */ -#define OB_RECALC_ALL (OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME) + OB_RECALC_ALL = OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME, +}; /* controller state */ -#define OB_MAX_STATES 30 +#define OB_MAX_STATES 30 /* collision masks */ -#define OB_MAX_COL_MASKS 8 +#define OB_MAX_COL_MASKS 8 /* ob->gameflag */ -#define OB_DYNAMIC 1 -#define OB_CHILD 2 -#define OB_ACTOR 4 -#define OB_INERTIA_LOCK_X 8 -#define OB_INERTIA_LOCK_Y 16 -#define OB_INERTIA_LOCK_Z 32 -#define OB_DO_FH 64 -#define OB_ROT_FH 128 -#define OB_ANISOTROPIC_FRICTION 256 -#define OB_GHOST 512 -#define OB_RIGID_BODY 1024 -#define OB_BOUNDS 2048 - -#define OB_COLLISION_RESPONSE 4096 -#define OB_SECTOR 8192 -#define OB_PROP 16384 -#define OB_MAINACTOR 32768 - -#define OB_COLLISION 65536 -#define OB_SOFT_BODY 0x20000 -#define OB_OCCLUDER 0x40000 -#define OB_SENSOR 0x80000 -#define OB_NAVMESH 0x100000 -#define OB_HASOBSTACLE 0x200000 -#define OB_CHARACTER 0x400000 +enum { + OB_DYNAMIC = 1 << 0, + OB_CHILD = 1 << 1, + OB_ACTOR = 1 << 2, + OB_INERTIA_LOCK_X = 1 << 3, + OB_INERTIA_LOCK_Y = 1 << 4, + OB_INERTIA_LOCK_Z = 1 << 5, + OB_DO_FH = 1 << 6, + OB_ROT_FH = 1 << 7, + OB_ANISOTROPIC_FRICTION = 1 << 8, + OB_GHOST = 1 << 9, + OB_RIGID_BODY = 1 << 10, + OB_BOUNDS = 1 << 11, + + OB_COLLISION_RESPONSE = 1 << 12, + OB_SECTOR = 1 << 13, + OB_PROP = 1 << 14, + OB_MAINACTOR = 1 << 15, + + OB_COLLISION = 1 << 16, + OB_SOFT_BODY = 1 << 17, + OB_OCCLUDER = 1 << 18, + OB_SENSOR = 1 << 19, + OB_NAVMESH = 1 << 20, + OB_HASOBSTACLE = 1 << 21, + OB_CHARACTER = 1 << 22, +}; /* ob->gameflag2 */ -#define OB_NEVER_DO_ACTIVITY_CULLING 1 -#define OB_LOCK_RIGID_BODY_X_AXIS 4 -#define OB_LOCK_RIGID_BODY_Y_AXIS 8 -#define OB_LOCK_RIGID_BODY_Z_AXIS 16 -#define OB_LOCK_RIGID_BODY_X_ROT_AXIS 32 -#define OB_LOCK_RIGID_BODY_Y_ROT_AXIS 64 -#define OB_LOCK_RIGID_BODY_Z_ROT_AXIS 128 - -/* #define OB_LIFE (OB_PROP|OB_DYNAMIC|OB_ACTOR|OB_MAINACTOR|OB_CHILD) */ +enum { + OB_NEVER_DO_ACTIVITY_CULLING = 1 << 0, + OB_LOCK_RIGID_BODY_X_AXIS = 1 << 2, + OB_LOCK_RIGID_BODY_Y_AXIS = 1 << 3, + OB_LOCK_RIGID_BODY_Z_AXIS = 1 << 4, + OB_LOCK_RIGID_BODY_X_ROT_AXIS = 1 << 5, + OB_LOCK_RIGID_BODY_Y_ROT_AXIS = 1 << 6, + OB_LOCK_RIGID_BODY_Z_ROT_AXIS = 1 << 7, + +/* OB_LIFE = OB_PROP | OB_DYNAMIC | OB_ACTOR | OB_MAINACTOR | OB_CHILD, */ +}; /* ob->body_type */ -#define OB_BODY_TYPE_NO_COLLISION 0 -#define OB_BODY_TYPE_STATIC 1 -#define OB_BODY_TYPE_DYNAMIC 2 -#define OB_BODY_TYPE_RIGID 3 -#define OB_BODY_TYPE_SOFT 4 -#define OB_BODY_TYPE_OCCLUDER 5 -#define OB_BODY_TYPE_SENSOR 6 -#define OB_BODY_TYPE_NAVMESH 7 -#define OB_BODY_TYPE_CHARACTER 8 +enum { + OB_BODY_TYPE_NO_COLLISION = 0, + OB_BODY_TYPE_STATIC = 1, + OB_BODY_TYPE_DYNAMIC = 2, + OB_BODY_TYPE_RIGID = 3, + OB_BODY_TYPE_SOFT = 4, + OB_BODY_TYPE_OCCLUDER = 5, + OB_BODY_TYPE_SENSOR = 6, + OB_BODY_TYPE_NAVMESH = 7, + OB_BODY_TYPE_CHARACTER = 8, +}; /* ob->depsflag */ -#define OB_DEPS_EXTRA_OB_RECALC 1 -#define OB_DEPS_EXTRA_DATA_RECALC 2 +enum { + OB_DEPS_EXTRA_OB_RECALC = 1 << 0, + OB_DEPS_EXTRA_DATA_RECALC = 1 << 1, +}; /* ob->scavisflag */ -#define OB_VIS_SENS 1 -#define OB_VIS_CONT 2 -#define OB_VIS_ACT 4 +enum { + OB_VIS_SENS = 1 << 0, + OB_VIS_CONT = 1 << 1, + OB_VIS_ACT = 1 << 2, +}; /* ob->scaflag */ -#define OB_SHOWSENS 64 -#define OB_SHOWACT 128 -#define OB_ADDSENS 256 -#define OB_ADDCONT 512 -#define OB_ADDACT 1024 -#define OB_SHOWCONT 2048 -#define OB_ALLSTATE 4096 -#define OB_INITSTBIT 8192 -#define OB_DEBUGSTATE 16384 -#define OB_SHOWSTATE 32768 +enum { + OB_SHOWSENS = 1 << 6, + OB_SHOWACT = 1 << 7, + OB_ADDSENS = 1 << 8, + OB_ADDCONT = 1 << 9, + OB_ADDACT = 1 << 10, + OB_SHOWCONT = 1 << 11, + OB_ALLSTATE = 1 << 12, + OB_INITSTBIT = 1 << 13, + OB_DEBUGSTATE = 1 << 14, + OB_SHOWSTATE = 1 << 15, +}; /* ob->restrictflag */ -#define OB_RESTRICT_VIEW 1 -#define OB_RESTRICT_SELECT 2 -#define OB_RESTRICT_RENDER 4 +enum { + OB_RESTRICT_VIEW = 1 << 0, + OB_RESTRICT_SELECT = 1 << 1, + OB_RESTRICT_RENDER = 1 << 2, +}; /* ob->shapeflag */ -#define OB_SHAPE_LOCK 1 -#define OB_SHAPE_TEMPLOCK 2 // deprecated -#define OB_SHAPE_EDIT_MODE 4 +enum { + OB_SHAPE_LOCK = 1 << 0, + OB_SHAPE_TEMPLOCK = 1 << 1, /* deprecated */ + OB_SHAPE_EDIT_MODE = 1 << 2, +}; /* ob->nlaflag */ - /* WARNING: flags (1<<0) and (1<<1) were from old animsys */ +enum { + /* WARNING: flags (1 << 0) and (1 << 1) were from old animsys */ /* object-channel expanded status */ -#define OB_ADS_COLLAPSED (1<<10) + OB_ADS_COLLAPSED = 1 << 10, /* object's ipo-block */ -#define OB_ADS_SHOWIPO (1<<11) + OB_ADS_SHOWIPO = 1 << 11, /* object's constraint channels */ -#define OB_ADS_SHOWCONS (1<<12) + OB_ADS_SHOWCONS = 1 << 12, /* object's material channels */ -#define OB_ADS_SHOWMATS (1<<13) + OB_ADS_SHOWMATS = 1 << 13, /* object's marticle channels */ -#define OB_ADS_SHOWPARTS (1<<14) + OB_ADS_SHOWPARTS = 1 << 14, +}; /* ob->protectflag */ -#define OB_LOCK_LOCX 1 -#define OB_LOCK_LOCY 2 -#define OB_LOCK_LOCZ 4 -#define OB_LOCK_LOC 7 -#define OB_LOCK_ROTX 8 -#define OB_LOCK_ROTY 16 -#define OB_LOCK_ROTZ 32 -#define OB_LOCK_ROT 56 -#define OB_LOCK_SCALEX 64 -#define OB_LOCK_SCALEY 128 -#define OB_LOCK_SCALEZ 256 -#define OB_LOCK_SCALE 448 -#define OB_LOCK_ROTW 512 -#define OB_LOCK_ROT4D 1024 +enum { + OB_LOCK_LOCX = 1 << 0, + OB_LOCK_LOCY = 1 << 1, + OB_LOCK_LOCZ = 1 << 2, + OB_LOCK_LOC = OB_LOCK_LOCX | OB_LOCK_LOCY | OB_LOCK_LOCZ, + OB_LOCK_ROTX = 1 << 3, + OB_LOCK_ROTY = 1 << 4, + OB_LOCK_ROTZ = 1 << 5, + OB_LOCK_ROT = OB_LOCK_ROTX | OB_LOCK_ROTY | OB_LOCK_ROTZ, + OB_LOCK_SCALEX = 1 << 6, + OB_LOCK_SCALEY = 1 << 7, + OB_LOCK_SCALEZ = 1 << 8, + OB_LOCK_SCALE = OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ, + OB_LOCK_ROTW = 1 << 9, + OB_LOCK_ROT4D = 1 << 10, +}; /* ob->mode */ typedef enum ObjectMode { - OB_MODE_OBJECT = 0, - OB_MODE_EDIT = 1, - OB_MODE_SCULPT = 2, - OB_MODE_VERTEX_PAINT = 4, - OB_MODE_WEIGHT_PAINT = 8, - OB_MODE_TEXTURE_PAINT = 16, - OB_MODE_PARTICLE_EDIT = 32, - OB_MODE_POSE = 64 + OB_MODE_OBJECT = 0, + OB_MODE_EDIT = 1 << 0, + OB_MODE_SCULPT = 1 << 1, + OB_MODE_VERTEX_PAINT = 1 << 2, + OB_MODE_WEIGHT_PAINT = 1 << 3, + OB_MODE_TEXTURE_PAINT = 1 << 4, + OB_MODE_PARTICLE_EDIT = 1 << 5, + OB_MODE_POSE = 1 << 6, } ObjectMode; /* any mode where the brush system is used */ -#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT|OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT) +#define OB_MODE_ALL_PAINT (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT) #define MAX_DUPLI_RECUR 8 diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h index 29fcaf3bf73..b7ca3066b4f 100644 --- a/source/blender/makesdna/DNA_particle_types.h +++ b/source/blender/makesdna/DNA_particle_types.h @@ -272,7 +272,9 @@ typedef struct ParticleSystem { struct DerivedMesh *hair_in_dm, *hair_out_dm; /* input/output for cloth simulation */ struct Object *target_ob; - struct Object *lattice; + + struct LatticeDeformData *lattice_deform_data; /* run-time only lattice deformation data */ + struct Object *parent; /* particles from global space -> parent space */ struct ListBase targets; /* used for keyed and boid physics */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 9d840ad13e8..ec86a4739c5 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -112,22 +112,48 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */ void *activedata; /* runtime for panel manipulation */ } Panel; -typedef struct uiList { /* some list UI data need to be saved in file */ +/* uiList dynamic data... */ +/* These two Lines with # tell makesdna this struct can be excluded. */ +# +# +typedef struct uiListDyn { + int height; /* Number of rows needed to draw all elements. */ + int visual_height; /* Actual visual height of the list (in rows). */ + int visual_height_min; /* Minimal visual height of the list (in rows). */ + + int items_len; /* Number of items in collection. */ + int items_shown; /* Number of items actually visible after filtering. */ + + /* Filtering data. */ + int *items_filter_flags; /* items_len length. */ + int *items_filter_neworder; /* org_idx -> new_idx, items_len length. */ +} uiListDyn; + +typedef struct uiList { /* some list UI data need to be saved in file */ struct uiList *next, *prev; - struct uiListType *type; /* runtime */ - void *padp; + struct uiListType *type; /* runtime */ - char list_id[64]; /* defined as UI_MAX_NAME_STR */ + char list_id[64]; /* defined as UI_MAX_NAME_STR */ - int layout_type; /* How items are layedout in the list */ - int padi; + int layout_type; /* How items are layedout in the list */ + int flag; int list_scroll; - int list_size; + int list_grip; int list_last_len; - int list_grip_size; -/* char list_search[64]; */ + int padi1; + + /* Filtering data. */ + char filter_byname[64]; /* defined as UI_MAX_NAME_STR */ + int filter_flag; + int filter_sort_flag; + + /* Custom sub-classes properties. */ + IDProperty *properties; + + /* Dynamic data (runtime). */ + uiListDyn *dyn_data; } uiList; typedef struct ScrArea { @@ -232,13 +258,38 @@ typedef struct ARegion { #define PNL_DEFAULT_CLOSED 1 #define PNL_NO_HEADER 2 -/* uilist layout_type */ +/* uiList layout_type */ enum { UILST_LAYOUT_DEFAULT = 0, UILST_LAYOUT_COMPACT = 1, UILST_LAYOUT_GRID = 2, }; +/* uiList flag */ +enum { + UILST_SCROLL_TO_ACTIVE_ITEM = 1 << 0, /* Scroll list to make active item visible. */ + UILST_RESIZING = 1 << 1, /* We are currently resizing, deactivate autosize! */ +}; + +/* uiList filter flags (dyn_data) */ +enum { + UILST_FLT_ITEM = 1 << 31, /* This item has passed the filter process successfully. */ +}; + +/* uiList filter options */ +enum { + UILST_FLT_SHOW = 1 << 0, /* Show filtering UI. */ + UILST_FLT_EXCLUDE = UILST_FLT_ITEM, /* Exclude filtered items, *must* use this same value. */ +}; + +/* uiList filter orderby type */ +enum { + UILST_FLT_SORT_ALPHA = 1 << 0, + UILST_FLT_SORT_REVERSE = 1 << 31 /* Special value, bitflag used to reverse order! */ +}; + +#define UILST_FLT_SORT_MASK (((unsigned int)UILST_FLT_SORT_REVERSE) - 1) + /* regiontype, first two are the default set */ /* Do NOT change order, append on end. Types are hardcoded needed */ enum { diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index d8cf80d047b..1b946c829fd 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -60,6 +60,7 @@ typedef struct bMouseSensor { short pad2; } bMouseSensor; +/* DEPRECATED */ typedef struct bTouchSensor { char name[64]; /* MAX_NAME */ struct Material *ma; @@ -235,7 +236,7 @@ typedef struct bJoystickSensor { /* sensor->type */ #define SENS_ALWAYS 0 -#define SENS_TOUCH 1 +#define SENS_TOUCH 1 /* DEPRECATED */ #define SENS_NEAR 2 #define SENS_KEYBOARD 3 #define SENS_PROPERTY 4 diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 85655ce09bd..0478ff567a0 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -132,8 +132,9 @@ typedef struct SpaceButs { short mainb, mainbo, mainbuser; /* context tabs */ short re_align, align; /* align for panels */ short preview; /* preview is signal to refresh */ - short texture_context; /* texture context selector (material, world, brush)*/ - char flag, pad; + /* texture context selector (material, lamp, particles, world, other)*/ + short texture_context, texture_context_prev; + char flag, pad[7]; void *path; /* runtime */ int pathflag, dataicon; /* runtime */ @@ -246,6 +247,13 @@ typedef struct SpaceOops { View2D v2d DNA_DEPRECATED; /* deprecated, copied to region */ ListBase tree; + + /* treestore is an ordered list of TreeStoreElem's from outliner tree; + * Note that treestore may contain duplicate elements if element + * is used multiple times in outliner tree (e. g. linked objects) + * Also note that BLI_mempool can not be read/written in DNA directly, + * therefore readfile.c/writefile.c linearize treestore into TreeStore structure + */ struct BLI_mempool *treestore; /* search stuff */ @@ -253,7 +261,9 @@ typedef struct SpaceOops { struct TreeStoreElem search_tse; short flag, outlinevis, storeflag, search_flags; - struct GHash *treehash; /* note, allows duplicates */ + + /* pointers to treestore elements, grouped by (id, type, nr) in hashtable for faster searching */ + void *treehash; } SpaceOops; @@ -1083,6 +1093,8 @@ typedef struct SpaceClip { int around, pad4; /* pivot point for transforms */ + float cursor[2]; /* Mask editor 2d cursor */ + MaskSpaceInfo mask_info; } SpaceClip; diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index e0c5cd5608e..1621f7c6cb6 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -286,6 +286,9 @@ typedef struct ThemeSpace { char preview_stitch_unstitchable[4]; char preview_stitch_active[4]; + char uv_shadow[4]; + char uv_others[4]; + char match[4]; /* outliner - filter match */ char selected_highlight[4]; /* outliner - selected item */ diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 70c79fa393c..f8fa625415e 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -29,6 +29,7 @@ add_definitions(-DWITH_DNA_GHASH) blender_include_dirs( ../../../../intern/guardedalloc + ../../../../intern/atomic ../../blenlib .. ) diff --git a/source/blender/makesdna/intern/SConscript b/source/blender/makesdna/intern/SConscript index c0db40dcfd2..7c3af30ee83 100644 --- a/source/blender/makesdna/intern/SConscript +++ b/source/blender/makesdna/intern/SConscript @@ -46,7 +46,9 @@ dna = env.Clone() makesdna_tool.Append(CCFLAGS = '-DBASE_HEADER="\\"source/blender/makesdna/\\"" ') makesdna_tool.Append (CPPPATH = ['#/intern/guardedalloc', - '../../makesdna', '../../bmesh']) + '#/intern/atomic', + '../../makesdna', '../../bmesh', + '../../blenlib']) if env['OURPLATFORM'] == 'linuxcross': USE_WINE = True # when cross compiling on linux 64bit this is useful diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 1225821102a..ed7f6f5d765 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -530,7 +530,7 @@ static void init_structDNA(SDNA *sdna, bool do_endian_swap) #ifdef WITH_DNA_GHASH /* create a ghash lookup to speed up */ - sdna->structs_map = BLI_ghash_str_new("init_structDNA gh"); + sdna->structs_map = BLI_ghash_str_new_ex("init_structDNA gh", sdna->nr_structs); for (nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index b18d3c83342..b6152c4a4bf 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -31,6 +31,8 @@ #include "RNA_types.h" +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif @@ -620,7 +622,6 @@ extern StructRNA RNA_ThemeWidgetStateColors; extern StructRNA RNA_TimelineMarker; extern StructRNA RNA_Timer; extern StructRNA RNA_ToolSettings; -extern StructRNA RNA_TouchSensor; extern StructRNA RNA_TrackToConstraint; extern StructRNA RNA_TransformConstraint; extern StructRNA RNA_TransformSequence; @@ -1073,10 +1074,11 @@ void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **value); void RNA_parameter_get_lookup(ParameterList *parms, const char *identifier, void **value); void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *value); void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, const void *value); -int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm); -int RNA_parameter_length_get_data(ParameterList *parms, PropertyRNA *parm, void *data); -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); +/* Only for PROP_DYNAMIC properties! */ +int RNA_parameter_dynamic_length_get(ParameterList *parms, PropertyRNA *parm); +int RNA_parameter_dynamic_length_get_data(ParameterList *parms, PropertyRNA *parm, void *data); +void RNA_parameter_dynamic_length_set(ParameterList *parms, PropertyRNA *parm, int length); +void RNA_parameter_dynamic_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); @@ -1084,17 +1086,9 @@ int RNA_function_call_lookup(struct bContext *C, struct ReportList *reports, Poi const char *identifier, ParameterList *parms); 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 -; + FunctionRNA *func, const char *format, ...) ATTR_PRINTF_FORMAT(5, 6); 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 -; + const char *identifier, const char *format, ...) ATTR_PRINTF_FORMAT(5, 6); 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, @@ -1120,11 +1114,7 @@ StructRNA *ID_code_to_RNA_type(short idcode); # define RNA_warning(format, ...) _RNA_warning("%s: " format "\n", __FUNCTION__, __VA_ARGS__) #endif -void _RNA_warning(const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 1, 2))) -#endif -; +void _RNA_warning(const char *format, ...) ATTR_PRINTF_FORMAT(1, 2); /* Equals test (skips pointers and collections) * is_strict false assumes uninitialized properties are equal */ diff --git a/source/blender/makesrna/RNA_types.h b/source/blender/makesrna/RNA_types.h index 69cb2caf058..43bf1973c33 100644 --- a/source/blender/makesrna/RNA_types.h +++ b/source/blender/makesrna/RNA_types.h @@ -69,27 +69,27 @@ typedef struct PropertyPointerRNA { /* Property */ typedef enum PropertyType { - PROP_BOOLEAN = 0, - PROP_INT = 1, - PROP_FLOAT = 2, - PROP_STRING = 3, - PROP_ENUM = 4, - PROP_POINTER = 5, - PROP_COLLECTION = 6 + PROP_BOOLEAN = 0, + PROP_INT = 1, + PROP_FLOAT = 2, + PROP_STRING = 3, + PROP_ENUM = 4, + PROP_POINTER = 5, + PROP_COLLECTION = 6, } PropertyType; /* also update rna_property_subtype_unit when you change this */ typedef enum PropertyUnit { - PROP_UNIT_NONE = (0 << 16), - PROP_UNIT_LENGTH = (1 << 16), /* m */ - PROP_UNIT_AREA = (2 << 16), /* m^2 */ - PROP_UNIT_VOLUME = (3 << 16), /* m^3 */ - PROP_UNIT_MASS = (4 << 16), /* kg */ - PROP_UNIT_ROTATION = (5 << 16), /* radians */ - PROP_UNIT_TIME = (6 << 16), /* frame */ - PROP_UNIT_VELOCITY = (7 << 16), /* m/s */ + PROP_UNIT_NONE = (0 << 16), + PROP_UNIT_LENGTH = (1 << 16), /* m */ + PROP_UNIT_AREA = (2 << 16), /* m^2 */ + PROP_UNIT_VOLUME = (3 << 16), /* m^3 */ + PROP_UNIT_MASS = (4 << 16), /* kg */ + 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_CAMERA = (9 << 16) /* mm */ + PROP_UNIT_CAMERA = (9 << 16), /* mm */ } PropertyUnit; #define RNA_SUBTYPE_UNIT(subtype) ((subtype) & 0x00FF0000) @@ -105,95 +105,101 @@ typedef enum PropertyUnit { * node socket button subtypes! */ typedef enum PropertySubType { - PROP_NONE = 0, + PROP_NONE = 0, /* strings */ - PROP_FILEPATH = 1, - PROP_DIRPATH = 2, - PROP_FILENAME = 3, - PROP_BYTESTRING = 4, /* a string which should be represented as bytes in python, still NULL terminated though. */ + PROP_FILEPATH = 1, + PROP_DIRPATH = 2, + PROP_FILENAME = 3, + PROP_BYTESTRING = 4, /* a string which should be represented as bytes in python, NULL terminated though. */ /* 5 was used by "PROP_TRANSLATE" sub-type, which is now a flag. */ - PROP_PASSWORD = 6, /* a string which should not be displayed in UI */ + PROP_PASSWORD = 6, /* a string which should not be displayed in UI */ /* numbers */ - PROP_UNSIGNED = 13, - PROP_PERCENTAGE = 14, - PROP_FACTOR = 15, - PROP_ANGLE = 16 | PROP_UNIT_ROTATION, - PROP_TIME = 17 | PROP_UNIT_TIME, + PROP_UNSIGNED = 13, + PROP_PERCENTAGE = 14, + PROP_FACTOR = 15, + PROP_ANGLE = 16 | PROP_UNIT_ROTATION, + 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, + PROP_DISTANCE = 18 | PROP_UNIT_LENGTH, + PROP_DISTANCE_CAMERA = 19 | PROP_UNIT_CAMERA, /* number arrays */ - PROP_COLOR = 20, - PROP_TRANSLATION = 21 | PROP_UNIT_LENGTH, - PROP_DIRECTION = 22, - PROP_VELOCITY = 23 | PROP_UNIT_VELOCITY, - PROP_ACCELERATION = 24 | PROP_UNIT_ACCELERATION, - PROP_MATRIX = 25, - PROP_EULER = 26 | PROP_UNIT_ROTATION, - PROP_QUATERNION = 27, - PROP_AXISANGLE = 28, - PROP_XYZ = 29, - PROP_XYZ_LENGTH = 29 | PROP_UNIT_LENGTH, - PROP_COLOR_GAMMA = 30, /* used for colors which would be color managed before display */ - PROP_COORDS = 31, /* generic array, no units applied, only that x/y/z/w are used (python vec) */ + PROP_COLOR = 20, + PROP_TRANSLATION = 21 | PROP_UNIT_LENGTH, + PROP_DIRECTION = 22, + PROP_VELOCITY = 23 | PROP_UNIT_VELOCITY, + PROP_ACCELERATION = 24 | PROP_UNIT_ACCELERATION, + PROP_MATRIX = 25, + PROP_EULER = 26 | PROP_UNIT_ROTATION, + PROP_QUATERNION = 27, + PROP_AXISANGLE = 28, + PROP_XYZ = 29, + PROP_XYZ_LENGTH = 29 | PROP_UNIT_LENGTH, + PROP_COLOR_GAMMA = 30, /* used for colors which would be color managed before display */ + PROP_COORDS = 31, /* generic array, no units applied, only that x/y/z/w are used (python vec) */ /* booleans */ - PROP_LAYER = 40, - PROP_LAYER_MEMBER = 41 + PROP_LAYER = 40, + PROP_LAYER_MEMBER = 41, } PropertySubType; -/* Make sure enums are updated with thses */ -/* HIGHEST FLAG IN USE: 1 << 29 */ +/* Make sure enums are updated with these */ +/* HIGHEST FLAG IN USE: 1 << 30 */ typedef enum PropertyFlag { /* editable means the property is editable in the user * interface, properties are editable by default except * for pointers and collections. */ - PROP_EDITABLE = (1 << 0), + PROP_EDITABLE = (1 << 0), /* this property is editable even if it is lib linked, * meaning it will get lost on reload, but it's useful * for editing. */ - PROP_LIB_EXCEPTION = (1 << 16), + PROP_LIB_EXCEPTION = (1 << 16), /* animatable means the property can be driven by some * other input, be it animation curves, expressions, .. * properties are animatable by default except for pointers * and collections */ - PROP_ANIMATABLE = (1 << 1), + PROP_ANIMATABLE = (1 << 1), /* icon */ - PROP_ICONS_CONSECUTIVE = (1 << 12), + PROP_ICONS_CONSECUTIVE = (1 << 12), /* hidden in the user interface */ - PROP_HIDDEN = (1 << 19), + PROP_HIDDEN = (1 << 19), /* do not write in presets */ - PROP_SKIP_SAVE = (1 << 28), - - /* function paramater flags */ - PROP_REQUIRED = (1 << 2), - PROP_OUTPUT = (1 << 3), - PROP_RNAPTR = (1 << 11), + PROP_SKIP_SAVE = (1 << 28), + + /* function parameter flags */ + PROP_REQUIRED = (1 << 2), + PROP_OUTPUT = (1 << 3), + PROP_RNAPTR = (1 << 11), + /* This allows for non-breaking API updates, when adding non-critical new parameter to a callback function. + * This way, old py code defining funcs without that parameter would still work. + * WARNING: any parameter after the first PYFUNC_OPTIONAL one will be considered as optional! + * NOTE: only for input parameters! + */ + PROP_PYFUNC_OPTIONAL = (1 << 30), /* registering */ - PROP_REGISTER = (1 << 4), - PROP_REGISTER_OPTIONAL = (1 << 4) | (1 << 5), + PROP_REGISTER = (1 << 4), + PROP_REGISTER_OPTIONAL = PROP_REGISTER | (1 << 5), /* pointers */ - PROP_ID_REFCOUNT = (1 << 6), + PROP_ID_REFCOUNT = (1 << 6), /* disallow assigning a variable to its self, eg an object tracking its self * only apply this to types that are derived from an ID ()*/ - PROP_ID_SELF_CHECK = (1 << 20), + PROP_ID_SELF_CHECK = (1 << 20), /* use for... * - pointers: in the UI and python so unsetting or setting to None won't work * - strings: so our internal generated get/length/set functions know to do NULL checks before access [#30865] */ - PROP_NEVER_NULL = (1 << 18), + PROP_NEVER_NULL = (1 << 18), /* currently only used for UI, this is similar to PROP_NEVER_NULL * except that the value may be NULL at times, used for ObData, where an Empty's will be NULL * but setting NULL on a mesh object is not possible. So, if its not NULL, setting NULL cant be done! */ - PROP_NEVER_UNLINK = (1 << 25), + PROP_NEVER_UNLINK = (1 << 25), /* flag contains multiple enums. * note: not to be confused with prop->enumbitflags @@ -201,33 +207,33 @@ typedef enum PropertyFlag { * * note: these can't be animated so use with care. */ - PROP_ENUM_FLAG = (1 << 21), + PROP_ENUM_FLAG = (1 << 21), /* need context for update function */ - PROP_CONTEXT_UPDATE = (1 << 22), + PROP_CONTEXT_UPDATE = (1 << 22), PROP_CONTEXT_PROPERTY_UPDATE = (1 << 22) | (1 << 27), /* Use for arrays or for any data that should not have a reference kept * most common case is functions that return arrays where the array */ - PROP_THICK_WRAP = (1 << 23), + PROP_THICK_WRAP = (1 << 23), /* Reject values outside limits, use for python api only so far * this is for use when silently clamping string length will give * bad behavior later. Could also enforce this for INT's and other types. * note: currently no support for function arguments or non utf8 paths (filepaths) */ - PROP_NEVER_CLAMP = (1 << 26), + PROP_NEVER_CLAMP = (1 << 26), /* internal flags */ - PROP_BUILTIN = (1 << 7), - PROP_EXPORT = (1 << 8), - PROP_RUNTIME = (1 << 9), - PROP_IDPROPERTY = (1 << 10), - PROP_RAW_ACCESS = (1 << 13), - PROP_RAW_ARRAY = (1 << 14), - PROP_FREE_POINTERS = (1 << 15), - PROP_DYNAMIC = (1 << 17), /* for dynamic arrays, and retvals of type string */ - PROP_ENUM_NO_CONTEXT = (1 << 24), /* for enum that shouldn't be contextual */ - PROP_ENUM_NO_TRANSLATE = (1 << 29), /* for enums that shouldn't be translated (e.g. renderlayers' names in nodes) */ + PROP_BUILTIN = (1 << 7), + PROP_EXPORT = (1 << 8), + PROP_RUNTIME = (1 << 9), + PROP_IDPROPERTY = (1 << 10), + PROP_RAW_ACCESS = (1 << 13), + PROP_RAW_ARRAY = (1 << 14), + PROP_FREE_POINTERS = (1 << 15), + PROP_DYNAMIC = (1 << 17), /* for dynamic arrays, and retvals of type string */ + PROP_ENUM_NO_CONTEXT = (1 << 24), /* for enum that shouldn't be contextual */ + PROP_ENUM_NO_TRANSLATE = (1 << 29), /* for enums not to be translated (e.g. renderlayers' names in nodes) */ } PropertyFlag; typedef struct CollectionPropertyIterator { @@ -332,23 +338,23 @@ typedef struct ParameterDynAlloc { /* Function */ typedef enum FunctionFlag { - FUNC_NO_SELF = 1, /* for static functions */ - FUNC_USE_SELF_TYPE = 2, /* for class methods, only used when FUNC_NO_SELF is set */ - FUNC_USE_MAIN = 4, - FUNC_USE_CONTEXT = 8, - FUNC_USE_REPORTS = 16, - FUNC_USE_SELF_ID = 2048, - FUNC_ALLOW_WRITE = 4096, + FUNC_NO_SELF = (1 << 0), /* for static functions */ + FUNC_USE_SELF_TYPE = (1 << 1), /* for class methods, only used when FUNC_NO_SELF is set */ + FUNC_USE_MAIN = (1 << 2), + FUNC_USE_CONTEXT = (1 << 3), + FUNC_USE_REPORTS = (1 << 4), + FUNC_USE_SELF_ID = (1 << 11), + FUNC_ALLOW_WRITE = (1 << 12), /* registering */ - FUNC_REGISTER = 32, - FUNC_REGISTER_OPTIONAL = 32 | 64, + FUNC_REGISTER = (1 << 5), + FUNC_REGISTER_OPTIONAL = FUNC_REGISTER | (1 << 6), /* internal flags */ - FUNC_BUILTIN = 128, - FUNC_EXPORT = 256, - FUNC_RUNTIME = 512, - FUNC_FREE_POINTERS = 1024 + FUNC_BUILTIN = (1 << 7), + FUNC_EXPORT = (1 << 8), + FUNC_RUNTIME = (1 << 9), + FUNC_FREE_POINTERS = (1 << 10), } FunctionFlag; typedef void (*CallFunc)(struct bContext *C, struct ReportList *reports, PointerRNA *ptr, ParameterList *parms); @@ -359,15 +365,15 @@ typedef struct FunctionRNA FunctionRNA; typedef enum StructFlag { /* indicates that this struct is an ID struct, and to use refcounting */ - STRUCT_ID = 1, - STRUCT_ID_REFCOUNT = 2, - STRUCT_UNDO = 4, /* defaults on, clear for user preferences and similar */ + STRUCT_ID = (1 << 0), + STRUCT_ID_REFCOUNT = (1 << 1), + STRUCT_UNDO = (1 << 2), /* defaults on, clear for user preferences and similar */ /* internal flags */ - STRUCT_RUNTIME = 8, - STRUCT_GENERATED = 16, - STRUCT_FREE_POINTERS = 32, - STRUCT_NO_IDPROPERTIES = 64 /* Menu's and Panels don't need properties */ + STRUCT_RUNTIME = (1 << 3), + STRUCT_GENERATED = (1 << 4), + STRUCT_FREE_POINTERS = (1 << 5), + STRUCT_NO_IDPROPERTIES = (1 << 6), /* Menu's and Panels don't need properties */ } StructFlag; typedef int (*StructValidateFunc)(struct PointerRNA *ptr, void *data, int *have_function); diff --git a/source/blender/makesrna/SConscript b/source/blender/makesrna/SConscript index 2d0c4260c97..dfe1ebb3385 100644 --- a/source/blender/makesrna/SConscript +++ b/source/blender/makesrna/SConscript @@ -36,6 +36,7 @@ incs = [ '.', './intern', '#/intern/guardedalloc', + '#/intern/atomic', '#/intern/memutil', '#/extern/glew/include', '#/intern/audaspace/intern', diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 592c518e9c0..eb0c4f7c422 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -276,6 +276,7 @@ blender_include_dirs( ../../../../intern/audaspace/intern ../../../../intern/cycles/blender ../../../../intern/guardedalloc + ../../../../intern/atomic ../../../../intern/memutil ../../../../intern/smoke/extern ) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index c158facca7c..4703e70b369 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -2273,11 +2273,12 @@ static void rna_def_function_funcs(FILE *f, StructDefRNA *dsrna, FunctionDefRNA valstr = "*"; } - /* this must be kept in sync with RNA_parameter_length_get_data, + /* this must be kept in sync with RNA_parameter_dynamic_length_get_data and RNA_parameter_get, * we could just call the function directly, but this is faster */ if (flag & PROP_DYNAMIC) { - fprintf(f, "\t%s_len = %s((int *)_data);\n", dparm->prop->identifier, pout ? "" : "*"); - data_str = "(&(((char *)_data)[sizeof(void *)]))"; + fprintf(f, "\t%s_len = %s((ParameterDynAlloc *)_data)->array_tot;\n", dparm->prop->identifier, + pout ? "(int *)&" : "(int)"); + data_str = "(&(((ParameterDynAlloc *)_data)->array))"; } else { data_str = "_data"; diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index f3e561cde0a..e935ff285b1 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -650,7 +650,7 @@ static PropertyRNA *RNA_struct_find_nested(PointerRNA *ptr, StructRNA *srna) { PropertyRNA *prop = NULL; - RNA_STRUCT_BEGIN(ptr, iprop) + RNA_STRUCT_BEGIN (ptr, iprop) { /* This assumes that there can only be one user of this nested struct */ if (RNA_property_pointer_type(ptr, iprop) == srna) { @@ -673,7 +673,7 @@ bool RNA_struct_contains_property(PointerRNA *ptr, PropertyRNA *prop_test) iterprop = RNA_struct_iterator_property(ptr->type); - RNA_PROP_BEGIN(ptr, itemptr, iterprop) + RNA_PROP_BEGIN (ptr, itemptr, iterprop) { /* PropertyRNA *prop = itemptr.data; */ if (prop_test == (PropertyRNA *)itemptr.data) { @@ -721,7 +721,7 @@ FunctionRNA *RNA_struct_find_function(StructRNA *srna, const char *identifier) func = NULL; - RNA_PROP_BEGIN(&tptr, funcptr, iterprop) + RNA_PROP_BEGIN (&tptr, funcptr, iterprop) { if (strcmp(identifier, RNA_function_identifier(funcptr.data)) == 0) { func = funcptr.data; @@ -3329,7 +3329,7 @@ static int rna_raw_access(ReportList *reports, PointerRNA *ptr, PropertyRNA *pro } /* no item property pointer, can still be id property, or * property of a type derived from the collection pointer type */ - RNA_PROP_BEGIN(ptr, itemptr, prop) + RNA_PROP_BEGIN (ptr, itemptr, prop) { if (itemptr.data) { if (itemprop) { @@ -4982,7 +4982,7 @@ static char *rna_pointer_as_string__idprop(bContext *C, PointerRNA *ptr) BLI_dynstr_append(dynstr, "{"); - RNA_STRUCT_BEGIN(ptr, prop) + RNA_STRUCT_BEGIN (ptr, prop) { propname = RNA_property_identifier(prop); @@ -5049,7 +5049,7 @@ char *RNA_pointer_as_string_keywords_ex(bContext *C, PointerRNA *ptr, PointerRNA PropertyRNA *prop_default; char *buf_default; - RNA_PROP_BEGIN(ptr, propptr, iterprop) + RNA_PROP_BEGIN (ptr, propptr, iterprop) { prop = propptr.data; @@ -5357,7 +5357,14 @@ PropertyRNA *RNA_function_get_parameter(PointerRNA *UNUSED(ptr), FunctionRNA *fu PropertyRNA *RNA_function_find_parameter(PointerRNA *UNUSED(ptr), FunctionRNA *func, const char *identifier) { - return BLI_findstring(&func->cont.properties, identifier, offsetof(PropertyRNA, identifier)); + PropertyRNA *parm; + + parm = func->cont.properties.first; + for (; parm; parm = parm->next) + if (strcmp(RNA_property_identifier(parm), identifier) == 0) + break; + + return parm; } const ListBase *RNA_function_defined_parameters(FunctionRNA *func) @@ -5529,10 +5536,19 @@ void RNA_parameter_get(ParameterList *parms, PropertyRNA *parm, void **value) if (iter.parm == parm) break; - if (iter.valid) - *value = iter.data; - else + if (iter.valid) { + if (parm->flag & PROP_DYNAMIC) { + /* for dynamic arrays and strings, data is a pointer to an array */ + ParameterDynAlloc *data_alloc = iter.data; + *value = data_alloc->array; + } + else { + *value = iter.data; + } + } + else { *value = NULL; + } RNA_parameter_list_end(&iter); } @@ -5560,8 +5576,35 @@ void RNA_parameter_set(ParameterList *parms, PropertyRNA *parm, const void *valu if (iter.parm == parm) break; - if (iter.valid) - memcpy(iter.data, value, iter.size); + if (iter.valid) { + if (parm->flag & PROP_DYNAMIC) { + /* for dynamic arrays and strings, data is a pointer to an array */ + ParameterDynAlloc *data_alloc = iter.data; + size_t size = 0; + switch (parm->type) { + case PROP_STRING: + size = sizeof(char); + break; + case PROP_INT: + case PROP_BOOLEAN: + size = sizeof(int); + break; + case PROP_FLOAT: + size = sizeof(float); + break; + default: + break; + } + size *= data_alloc->array_tot; + if (data_alloc->array) + MEM_freeN(data_alloc->array); + data_alloc->array = MEM_mallocN(size, AT); + memcpy(data_alloc->array, value, size); + } + else { + memcpy(iter.data, value, iter.size); + } + } RNA_parameter_list_end(&iter); } @@ -5579,7 +5622,7 @@ void RNA_parameter_set_lookup(ParameterList *parms, const char *identifier, cons RNA_parameter_set(parms, parm, value); } -int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm) +int RNA_parameter_dynamic_length_get(ParameterList *parms, PropertyRNA *parm) { ParameterIterator iter; int len = 0; @@ -5591,14 +5634,14 @@ int RNA_parameter_length_get(ParameterList *parms, PropertyRNA *parm) break; if (iter.valid) - len = RNA_parameter_length_get_data(parms, parm, iter.data); + len = RNA_parameter_dynamic_length_get_data(parms, parm, iter.data); RNA_parameter_list_end(&iter); return len; } -void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int length) +void RNA_parameter_dynamic_length_set(ParameterList *parms, PropertyRNA *parm, int length) { ParameterIterator iter; @@ -5609,19 +5652,24 @@ void RNA_parameter_length_set(ParameterList *parms, PropertyRNA *parm, int lengt break; if (iter.valid) - RNA_parameter_length_set_data(parms, parm, iter.data, length); + RNA_parameter_dynamic_length_set_data(parms, parm, iter.data, length); RNA_parameter_list_end(&iter); } -int RNA_parameter_length_get_data(ParameterList *UNUSED(parms), PropertyRNA *UNUSED(parm), void *data) +int RNA_parameter_dynamic_length_get_data(ParameterList *UNUSED(parms), PropertyRNA *parm, void *data) { - return *((int *)((char *)data)); + if (parm->flag & PROP_DYNAMIC) { + return (int)((ParameterDynAlloc *)data)->array_tot; + } + return 0; } -void RNA_parameter_length_set_data(ParameterList *UNUSED(parms), PropertyRNA *UNUSED(parm), void *data, int length) +void RNA_parameter_dynamic_length_set_data(ParameterList *UNUSED(parms), PropertyRNA *parm, void *data, int length) { - *((int *)data) = length; + if (parm->flag & PROP_DYNAMIC) { + ((ParameterDynAlloc *)data)->array_tot = (intptr_t)length; + } } int RNA_function_call(bContext *C, ReportList *reports, PointerRNA *ptr, FunctionRNA *func, ParameterList *parms) diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index 99053714246..d6e6786800b 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -700,7 +700,7 @@ static void rna_def_action_actuator(BlenderRNA *brna) prop = RNA_def_property(srna, "blend_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "blend_mode"); RNA_def_property_enum_items(prop, prop_blend_items); - RNA_def_property_ui_text(prop, "Blend Mode", "Determines how this layer is blended with previous layers"); + RNA_def_property_ui_text(prop, "Blend Mode", "How this layer is blended with previous layers"); RNA_def_property_update(prop, NC_LOGIC, NULL); #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index ebd06475c79..933f06cec8c 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -584,6 +584,7 @@ static void rna_ColorManagement_update(Main *UNUSED(bmain), Scene *UNUSED(scene) return; if (GS(id->name) == ID_SCE) { + DAG_id_tag_update(id, 0); WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, NULL); } } diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 05d4c5a59d2..6a1aa37d0cc 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1083,7 +1083,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); prop = RNA_def_property(srna, "offset", PROP_FLOAT, PROP_DISTANCE); - RNA_def_property_range(prop, 0.0, 100.f); + RNA_def_property_range(prop, -1000.0, 1000.0f); + RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, -1); RNA_def_property_ui_text(prop, "Offset", "Offset of floor from object origin"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); } diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c index 287d7ee2ed3..d4b1130763b 100644 --- a/source/blender/makesrna/intern/rna_define.c +++ b/source/blender/makesrna/intern/rna_define.c @@ -1321,6 +1321,26 @@ void RNA_def_property_ui_range(PropertyRNA *prop, double min, double max, double { StructRNA *srna = DefRNA.laststruct; +#ifdef DEBUG + if (min > max) { + fprintf(stderr, "%s: \"%s.%s\", min > max.\n", + __func__, srna->identifier, prop->identifier); + DefRNA.error = 1; + } + + if (step < 0 || step > 100) { + fprintf(stderr, "%s: \"%s.%s\", step outside range.\n", + __func__, srna->identifier, prop->identifier); + DefRNA.error = 1; + } + + if (precision < -1 || precision > 10) { + fprintf(stderr, "%s: \"%s.%s\", step outside range.\n", + __func__, srna->identifier, prop->identifier); + DefRNA.error = 1; + } +#endif + switch (prop->type) { case PROP_INT: { @@ -1366,6 +1386,14 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max) { StructRNA *srna = DefRNA.laststruct; +#ifdef DEBUG + if (min > max) { + fprintf(stderr, "%s: \"%s.%s\", min > max.\n", + __func__, srna->identifier, prop->identifier); + DefRNA.error = 1; + } +#endif + switch (prop->type) { case PROP_INT: { @@ -3208,7 +3236,7 @@ void RNA_def_property_duplicate_pointers(StructOrFunctionRNA *cont_, PropertyRNA if (prop->identifier) { if (cont->prophash) { prop->identifier = BLI_strdup(prop->identifier); - BLI_ghash_assign(cont->prophash, (void *)prop->identifier, prop, NULL, NULL); + BLI_ghash_reinsert(cont->prophash, (void *)prop->identifier, prop, NULL, NULL); } else { prop->identifier = BLI_strdup(prop->identifier); diff --git a/source/blender/makesrna/intern/rna_image_api.c b/source/blender/makesrna/intern/rna_image_api.c index c1769f02974..f0322bac756 100644 --- a/source/blender/makesrna/intern/rna_image_api.c +++ b/source/blender/makesrna/intern/rna_image_api.c @@ -87,7 +87,7 @@ static void rna_Image_save_render(Image *image, bContext *C, ReportList *reports else { ImBuf *write_ibuf; - write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, TRUE, TRUE, &scene->view_settings, + write_ibuf = IMB_colormanagement_imbuf_for_write(ibuf, true, true, &scene->view_settings, &scene->display_settings, &scene->r.im_format); write_ibuf->planes = scene->r.im_format.planes; diff --git a/source/blender/makesrna/intern/rna_lamp.c b/source/blender/makesrna/intern/rna_lamp.c index ffc9ac0e52e..f59f3db3652 100644 --- a/source/blender/makesrna/intern/rna_lamp.c +++ b/source/blender/makesrna/intern/rna_lamp.c @@ -26,6 +26,7 @@ #include <stdlib.h> +#include "BLI_sys_types.h" #include "BLI_math_base.h" #include "BLI_math_rotation.h" diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index fd931262904..8104fc169f6 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -361,8 +361,13 @@ Mesh *rna_Main_meshes_new_from_object( BKE_mesh_from_metaball(&disp, tmpmesh); BKE_displist_free(&disp); } - else - BKE_mesh_from_metaball(&ob->disp, tmpmesh); + else { + ListBase disp = {NULL, NULL}; + if (ob->curve_cache) { + disp = ob->curve_cache->disp; + } + BKE_mesh_from_metaball(&disp, tmpmesh); + } BKE_mesh_texspace_copy_from_object(tmpmesh, ob); diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 35d8a0fb433..1473bcd9ab8 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -575,8 +575,9 @@ static void rna_Mesh_texspace_size_get(PointerRNA *ptr, float values[3]) { Mesh *me = (Mesh *)ptr->data; - if (!me->bb) + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(me); + } copy_v3_v3(values, me->size); } @@ -585,8 +586,9 @@ static void rna_Mesh_texspace_loc_get(PointerRNA *ptr, float values[3]) { Mesh *me = (Mesh *)ptr->data; - if (!me->bb) + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(me); + } copy_v3_v3(values, me->loc); } @@ -1106,12 +1108,15 @@ static void rna_MeshPoly_vertices_set(PointerRNA *ptr, const int *values) } } +/* disabling, some importers don't know the total material count when assigning materials */ +#if 0 static void rna_MeshPoly_material_index_range(PointerRNA *ptr, int *min, int *max, int *softmin, int *softmax) { Mesh *me = rna_mesh(ptr); *min = 0; *max = max_ii(0, me->totcol - 1); } +#endif static int rna_MeshVertex_index_get(PointerRNA *ptr) { @@ -1771,7 +1776,9 @@ static void rna_def_mface(BlenderRNA *brna) prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); RNA_def_property_ui_text(prop, "Material Index", ""); +#if 0 RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); /* reuse for tessface is ok */ +#endif RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); @@ -1868,7 +1875,9 @@ static void rna_def_mpolygon(BlenderRNA *brna) prop = RNA_def_property(srna, "material_index", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "mat_nr"); RNA_def_property_ui_text(prop, "Material Index", ""); +#if 0 RNA_def_property_int_funcs(prop, NULL, NULL, "rna_MeshPoly_material_index_range"); +#endif RNA_def_property_update(prop, 0, "rna_Mesh_update_data"); prop = RNA_def_property(srna, "select", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index ad9977fef50..7fec4a1ff9c 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -57,14 +57,15 @@ static const char *rna_Mesh_unit_test_compare(struct Mesh *mesh, bContext *C, st return ret; } -void rna_Mesh_calc_smooth_groups(struct Mesh *mesh, int *r_poly_group_len, int **r_poly_group, int *r_group_total) +void rna_Mesh_calc_smooth_groups(struct Mesh *mesh, int use_bitflags, int *r_poly_group_len, + int **r_poly_group, int *r_group_total) { *r_poly_group_len = mesh->totpoly; *r_poly_group = BKE_mesh_calc_smoothgroups( mesh->medge, mesh->totedge, mesh->mpoly, mesh->totpoly, mesh->mloop, mesh->totloop, - r_group_total); + r_group_total, use_bitflags); } #else @@ -87,6 +88,7 @@ void RNA_api_mesh(StructRNA *srna) func = RNA_def_function(srna, "calc_smooth_groups", "rna_Mesh_calc_smooth_groups"); RNA_def_function_ui_description(func, "Calculate smooth groups from sharp edges"); + RNA_def_boolean(func, "use_bitflags", false, "", "Produce bitflags groups instead of simple numeric values"); /* return values */ parm = RNA_def_int_array(func, "poly_groups", 1, NULL, 0, 0, "", "Smooth Groups", 0, 0); RNA_def_property_flag(parm, PROP_DYNAMIC | PROP_OUTPUT); diff --git a/source/blender/makesrna/intern/rna_meta.c b/source/blender/makesrna/intern/rna_meta.c index 11f0e48012b..49b63933ae9 100644 --- a/source/blender/makesrna/intern/rna_meta.c +++ b/source/blender/makesrna/intern/rna_meta.c @@ -320,13 +320,13 @@ static void rna_def_metaball(BlenderRNA *brna) /* number values */ prop = RNA_def_property(srna, "resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "wiresize"); - RNA_def_property_range(prop, 0.050f, 1.0f); + RNA_def_property_range(prop, 0.005f, 10000.0f); RNA_def_property_ui_text(prop, "Wire Size", "Polygonization resolution in the 3D viewport"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); prop = RNA_def_property(srna, "render_resolution", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_sdna(prop, NULL, "rendersize"); - RNA_def_property_range(prop, 0.050f, 1.0f); + RNA_def_property_range(prop, 0.005f, 10000.0f); RNA_def_property_ui_text(prop, "Render Size", "Polygonization resolution in rendering"); RNA_def_property_update(prop, 0, "rna_MetaBall_update_data"); diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index cd6067fb7e8..7fc61c0acfd 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -667,8 +667,8 @@ static void rna_UVProjectModifier_num_projectors_set(PointerRNA *ptr, int value) UVProjectModifierData *md = (UVProjectModifierData *)ptr->data; int a; - md->num_projectors = CLAMPIS(value, 1, MOD_UVPROJECT_MAX); - for (a = md->num_projectors; a < MOD_UVPROJECT_MAX; a++) + md->num_projectors = CLAMPIS(value, 1, MOD_UVPROJECT_MAXPROJECTORS); + for (a = md->num_projectors; a < MOD_UVPROJECT_MAXPROJECTORS; a++) md->projectors[a] = NULL; } @@ -1720,7 +1720,7 @@ static void rna_def_modifier_uvproject(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "num_projectors"); RNA_def_property_ui_text(prop, "Number of Projectors", "Number of projectors to use"); RNA_def_property_int_funcs(prop, NULL, "rna_UVProjectModifier_num_projectors_set", NULL); - RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAX); + RNA_def_property_range(prop, 1, MOD_UVPROJECT_MAXPROJECTORS); RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "projectors", PROP_COLLECTION, PROP_NONE); @@ -2781,7 +2781,7 @@ static void rna_def_modifier_screw(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); prop = RNA_def_property(srna, "angle", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_ui_range(prop, 0, -M_PI * 2, M_PI * 2, 2); + RNA_def_property_ui_range(prop, -M_PI * 2, M_PI * 2, 2, -1); RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); RNA_def_property_ui_text(prop, "Angle", "Angle of revolution"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index b4576509098..eb18f791b04 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -921,22 +921,6 @@ static void rna_NodeTree_active_output_set(PointerRNA *ptr, int value) } } -static int rna_NodeTree_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) -{ - bNodeTree *ntree = (bNodeTree *)ptr->data; - bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_IN, key); - RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr); - return (sock != NULL); -} - -static int rna_NodeTree_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) -{ - bNodeTree *ntree = (bNodeTree *)ptr->data; - bNodeSocket *sock = ntreeFindSocketInterface(ntree, SOCK_OUT, key); - RNA_pointer_create(ptr->id.data, &RNA_NodeSocketInterface, sock, r_ptr); - return (sock != NULL); -} - static bNodeSocket *rna_NodeTree_inputs_new(bNodeTree *ntree, ReportList *reports, const char *type, const char *name) { bNodeSocket *sock; @@ -1563,22 +1547,6 @@ static void rna_Node_name_set(PointerRNA *ptr, const char *value) BKE_all_animdata_fix_paths_rename(NULL, "nodes", oldname, node->name); } -static int rna_Node_inputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) -{ - bNode *node = (bNode *)ptr->data; - bNodeSocket *sock = nodeFindSocket(node, SOCK_IN, key); - RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr); - return (sock != NULL); -} - -static int rna_Node_outputs_lookupstring(PointerRNA *ptr, const char *key, PointerRNA *r_ptr) -{ - bNode *node = (bNode *)ptr->data; - bNodeSocket *sock = nodeFindSocket(node, SOCK_OUT, key); - RNA_pointer_create(ptr->id.data, &RNA_NodeSocket, sock, r_ptr); - return (sock != NULL); -} - static bNodeSocket *rna_Node_inputs_new(ID *id, bNode *node, ReportList *reports, const char *type, const char *name, const char *identifier) { bNodeTree *ntree = (bNodeTree *)id; @@ -2851,6 +2819,15 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p ED_node_tag_update_nodetree(bmain, ntree); } +static void rna_ShaderNodeSubsurface_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + #else static EnumPropertyItem prop_image_layer_items[] = { @@ -3220,10 +3197,22 @@ static void def_sh_tex(StructRNA *srna) static void def_sh_tex_sky(StructRNA *srna) { + static EnumPropertyItem prop_sky_type[] = { + {SHD_SKY_OLD, "PREETHAM", 0, "Preetham", ""}, + {SHD_SKY_NEW, "HOSEK_WILKIE", 0, "Hosek / Wilkie", ""}, + {0, NULL, 0, NULL, NULL} + }; + PropertyRNA *prop; RNA_def_struct_sdna_from(srna, "NodeTexSky", "storage"); def_sh_tex(srna); + + prop = RNA_def_property(srna, "sky_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "sky_model"); + RNA_def_property_enum_items(prop, prop_sky_type); + RNA_def_property_ui_text(prop, "Sky Type", ""); + RNA_def_property_update(prop, 0, "rna_Node_update"); prop = RNA_def_property(srna, "sun_direction", PROP_FLOAT, PROP_DIRECTION); RNA_def_property_ui_text(prop, "Sun Direction", "Direction from where the sun is shining"); @@ -3231,8 +3220,14 @@ static void def_sh_tex_sky(StructRNA *srna) prop = RNA_def_property(srna, "turbidity", PROP_FLOAT, PROP_NONE); RNA_def_property_range(prop, 1.0f, 30.0f); + RNA_def_property_ui_range(prop, 1.0f, 10.0f, 10, 3); RNA_def_property_ui_text(prop, "Turbidity", "Atmospheric turbidity"); RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + + prop = RNA_def_property(srna, "ground_albedo", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "Ground Albedo", "Ground color that is subtly reflected in the sky"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } static void def_sh_tex_environment(StructRNA *srna) @@ -3640,6 +3635,25 @@ static void def_sh_tangent(StructRNA *srna) RNA_def_struct_sdna_from(srna, "bNode", NULL); } + +static void def_sh_subsurface(StructRNA *srna) +{ + static EnumPropertyItem prop_subsurface_falloff_items[] = { + {SHD_SUBSURFACE_COMPATIBLE, "COMPATIBLE", 0, "Compatible", "Subsurface scattering falloff compatible with previous versions"}, + {SHD_SUBSURFACE_CUBIC, "CUBIC", 0, "Cubic", "Simple cubic falloff function"}, + {SHD_SUBSURFACE_GAUSSIAN, "GAUSSIAN", 0, "Gaussian", "Normal distribution, multiple can be combined to fit more complex profiles"}, + {0, NULL, 0, NULL, NULL} + }; + + PropertyRNA *prop; + + prop = RNA_def_property(srna, "falloff", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, prop_subsurface_falloff_items); + RNA_def_property_ui_text(prop, "Falloff", "Function to determine how much light nearby points contribute based on their distance to the shading point"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeSubsurface_update"); +} + static void def_sh_script(StructRNA *srna) { PropertyRNA *prop; @@ -6822,16 +6836,12 @@ static void rna_def_node(BlenderRNA *brna) prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL); - RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, - "rna_Node_inputs_lookupstring", NULL); RNA_def_property_struct_type(prop, "NodeSocket"); RNA_def_property_ui_text(prop, "Inputs", ""); rna_def_node_sockets_api(brna, prop, SOCK_IN); prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL); - RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, - "rna_Node_outputs_lookupstring", NULL); RNA_def_property_struct_type(prop, "NodeSocket"); RNA_def_property_ui_text(prop, "Outputs", ""); rna_def_node_sockets_api(brna, prop, SOCK_OUT); @@ -7247,8 +7257,6 @@ static void rna_def_nodetree(BlenderRNA *brna) prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL); - RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, - "rna_NodeTree_inputs_lookupstring", NULL); RNA_def_property_struct_type(prop, "NodeSocketInterface"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Inputs", "Node tree inputs"); @@ -7261,8 +7269,6 @@ static void rna_def_nodetree(BlenderRNA *brna) prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL); - RNA_def_property_collection_funcs(prop, NULL, NULL, NULL, NULL, NULL, NULL, - "rna_NodeTree_outputs_lookupstring", NULL); RNA_def_property_struct_type(prop, "NodeSocketInterface"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Outputs", "Node tree outputs"); diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index e71d1d22c4b..9bf9bc1deac 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -465,7 +465,7 @@ static EnumPropertyItem *rna_Object_parent_type_itemf(bContext *UNUSED(C), Point RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARBONE); } - if (ELEM4(par->type, OB_MESH, OB_CURVE, OB_SURF, OB_LATTICE)) { + if (OB_TYPE_SUPPORT_PARVERT(par->type)) { RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARVERT1); RNA_enum_items_add_value(&item, &totitem, parent_type_items, PARVERT3); } @@ -903,6 +903,7 @@ static void rna_MaterialSlot_update(Main *bmain, Scene *scene, PointerRNA *ptr) { rna_Object_internal_update(bmain, scene, ptr); WM_main_add_notifier(NC_OBJECT | ND_OB_SHADING, ptr->id.data); + WM_main_add_notifier(NC_MATERIAL | ND_SHADING_LINKS, NULL); } /* why does this have to be so complicated?, can't all this crap be diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 1d2aa08e7cd..e40d0cca79e 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -861,7 +861,9 @@ static void rna_def_pointcache(BlenderRNA *brna) prop = RNA_def_property(srna, "use_library_path", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", PTCACHE_IGNORE_LIBPATH); - RNA_def_property_ui_text(prop, "Library Path", "Use this files path when library linked into another file"); + RNA_def_property_ui_text(prop, "Library Path", + "Use this files path for the disk cache when library linked into another file. " + "For local bakes per scene file, disable this option"); RNA_def_property_update(prop, NC_OBJECT, "rna_Cache_idname_change"); prop = RNA_def_property(srna, "point_caches", PROP_COLLECTION, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index 82cdfcdd631..5b809a51705 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -49,6 +49,9 @@ #include "BKE_context.h" #include "BKE_report.h" +#include "IMB_colormanagement.h" +#include "GPU_extensions.h" + /* RenderEngine Callbacks */ static void engine_tag_redraw(RenderEngine *engine) @@ -61,6 +64,23 @@ static void engine_tag_update(RenderEngine *engine) engine->flag |= RE_ENGINE_DO_UPDATE; } +static int engine_support_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene) +{ + return IMB_colormanagement_support_glsl_draw(&scene->view_settings, true); +} + +static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene *scene) +{ + IMB_colormanagement_setup_glsl_draw(&scene->view_settings, + &scene->display_settings, + false, true); +} + +static void engine_unbind_display_space_shader(RenderEngine *UNUSED(engine)) +{ + IMB_colormanagement_finish_glsl_draw(); +} + static void engine_update(RenderEngine *engine, Main *bmain, Scene *scene) { extern FunctionRNA rna_RenderEngine_update_func; @@ -342,14 +362,15 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_RNAPTR); /* tag for redraw */ - RNA_def_function(srna, "tag_redraw", "engine_tag_redraw"); + func = RNA_def_function(srna, "tag_redraw", "engine_tag_redraw"); RNA_def_function_ui_description(func, "Request redraw for viewport rendering"); /* tag for update */ - RNA_def_function(srna, "tag_update", "engine_tag_update"); + func = RNA_def_function(srna, "tag_update", "engine_tag_update"); RNA_def_function_ui_description(func, "Request update call for viewport rendering"); func = RNA_def_function(srna, "begin_result", "RE_engine_begin_result"); + RNA_def_function_ui_description(func, "Create render result to write linear floating point render layers and passes"); prop = RNA_def_int(func, "x", 0, 0, INT_MAX, "X", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_int(func, "y", 0, 0, INT_MAX, "Y", "", 0, INT_MAX); @@ -363,39 +384,61 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_function_return(func, prop); func = RNA_def_function(srna, "update_result", "RE_engine_update_result"); + RNA_def_function_ui_description(func, "Signal that pixels have been updated and can be redrawn in the user interface"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "end_result", "RE_engine_end_result"); + RNA_def_function_ui_description(func, "All pixels in the render result have been set and are final"); prop = RNA_def_pointer(func, "result", "RenderResult", "Result", ""); RNA_def_property_flag(prop, PROP_REQUIRED); RNA_def_boolean(func, "cancel", 0, "Cancel", "Don't merge back results"); func = RNA_def_function(srna, "test_break", "RE_engine_test_break"); + RNA_def_function_ui_description(func, "Test if the render operation should been cancelled, this is a fast call that should be used regularly for responsiveness"); prop = RNA_def_boolean(func, "do_break", 0, "Break", ""); RNA_def_function_return(func, prop); func = RNA_def_function(srna, "update_stats", "RE_engine_update_stats"); + RNA_def_function_ui_description(func, "Update and signal to redraw render status text"); prop = RNA_def_string(func, "stats", "", 0, "Stats", ""); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_string(func, "info", "", 0, "Info", ""); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "update_progress", "RE_engine_update_progress"); + RNA_def_function_ui_description(func, "Update progress percentage of render"); prop = RNA_def_float(func, "progress", 0, 0.0f, 1.0f, "", "Percentage of render that's done", 0.0f, 1.0f); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "update_memory_stats", "RE_engine_update_memory_stats"); + RNA_def_function_ui_description(func, "Update memory usage statistics"); RNA_def_float(func, "memory_used", 0, 0.0f, FLT_MAX, "", "Current memory usage in megabytes", 0.0f, FLT_MAX); RNA_def_float(func, "memory_peak", 0, 0.0f, FLT_MAX, "", "Peak memory usage in megabytes", 0.0f, FLT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); func = RNA_def_function(srna, "report", "RE_engine_report"); + RNA_def_function_ui_description(func, "Report info, warning or error messages"); prop = RNA_def_enum_flag(func, "type", wm_report_items, 0, "Type", ""); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_string(func, "message", "", 0, "Report Message", ""); RNA_def_property_flag(prop, PROP_REQUIRED); + func = RNA_def_function(srna, "bind_display_space_shader", "engine_bind_display_space_shader"); + RNA_def_function_ui_description(func, "Bind GLSL fragment shader that converts linear colors to display space colors using scene color management settings"); + prop = RNA_def_pointer(func, "scene", "Scene", "", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); + + func = RNA_def_function(srna, "unbind_display_space_shader", "engine_unbind_display_space_shader"); + RNA_def_function_ui_description(func, "Unbind GLSL display space shader, must always be called after binding the shader"); + + func = RNA_def_function(srna, "support_display_space_shader", "engine_support_display_space_shader"); + RNA_def_function_ui_description(func, "Test if GLSL display space shader is supported for the combination of graphics card and scene settings"); + prop = RNA_def_pointer(func, "scene", "Scene", "", ""); + RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_boolean(func, "supported", 0, "Supported", ""); + RNA_def_function_return(func, prop); + RNA_define_verify_sdna(0); prop = RNA_def_property(srna, "is_animation", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_rna.c b/source/blender/makesrna/intern/rna_rna.c index 67fc3056485..380bde90ff9 100644 --- a/source/blender/makesrna/intern/rna_rna.c +++ b/source/blender/makesrna/intern/rna_rna.c @@ -566,6 +566,12 @@ static int rna_Property_is_required_get(PointerRNA *ptr) return prop->flag & PROP_REQUIRED ? 1 : 0; } +static int rna_Property_is_argument_optional_get(PointerRNA *ptr) +{ + PropertyRNA *prop = (PropertyRNA *)ptr->data; + return prop->flag & PROP_PYFUNC_OPTIONAL ? 1 : 0; +} + static int rna_Property_is_never_none_get(PointerRNA *ptr) { PropertyRNA *prop = (PropertyRNA *)ptr->data; @@ -1171,6 +1177,12 @@ static void rna_def_property(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Property_is_required_get", NULL); RNA_def_property_ui_text(prop, "Required", "False when this property is an optional argument in an RNA function"); + prop = RNA_def_property(srna, "is_argument_optional", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_boolean_funcs(prop, "rna_Property_is_argument_optional_get", NULL); + RNA_def_property_ui_text(prop, "Optional Argument", + "True when the property is optional in a Python function implementing an RNA function"); + prop = RNA_def_property(srna, "is_never_none", PROP_BOOLEAN, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_EDITABLE); RNA_def_property_boolean_funcs(prop, "rna_Property_is_never_none_get", NULL); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 83dbd79024e..e58bf2598f7 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -487,7 +487,11 @@ static void rna_Scene_view3d_update(Main *bmain, Scene *UNUSED(scene_unused), Po static void rna_Scene_layer_update(Main *bmain, Scene *scene, PointerRNA *ptr) { rna_Scene_view3d_update(bmain, scene, ptr); - DAG_on_visible_update(bmain, FALSE); + /* XXX We would need do_time=true here, else we can have update issues like [#36289]... + * However, this has too much drawbacks (like slower layer switch, undesired updates...). + * That's TODO for future DAG updates. + */ + DAG_on_visible_update(bmain, false); } static void rna_Scene_fps_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) @@ -2690,202 +2694,202 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) RNA_def_property_pointer_funcs(prop, "rna_FreestyleLineSet_linestyle_get", "rna_FreestyleLineSet_linestyle_set", NULL, NULL); RNA_def_property_ui_text(prop, "Line Style", "Line style settings"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Line Set Name", "Line set name"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); RNA_def_struct_name_property(srna, prop); prop = RNA_def_property(srna, "show_render", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_LINESET_ENABLED); RNA_def_property_ui_text(prop, "Render", "Enable or disable this line set during stroke rendering"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_by_visibility", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_VISIBILITY); RNA_def_property_ui_text(prop, "Selection by Visibility", "Select feature edges based on visibility"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_by_edge_types", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_EDGE_TYPES); RNA_def_property_ui_text(prop, "Selection by Edge Types", "Select feature edges based on edge types"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_by_group", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_GROUP); RNA_def_property_ui_text(prop, "Selection by Group", "Select feature edges based on a group of objects"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_by_image_border", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_IMAGE_BORDER); RNA_def_property_ui_text(prop, "Selection by Image Border", "Select feature edges by image border (less memory consumption)"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_by_face_marks", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "selection", FREESTYLE_SEL_FACE_MARK); RNA_def_property_ui_text(prop, "Selection by Face Marks", "Select feature edges by face marks"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "edge_type_negation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, edge_type_negation_items); RNA_def_property_ui_text(prop, "Edge Type Negation", "Set the negation operation for conditions on feature edge types"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "edge_type_combination", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, edge_type_combination_items); RNA_def_property_ui_text(prop, "Edge Type Combination", "Set the combination operation for conditions on feature edge types"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "group", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "group"); RNA_def_property_struct_type(prop, "Group"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Group", "A group of objects based on which feature edges are selected"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "group_negation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, group_negation_items); RNA_def_property_ui_text(prop, "Group Negation", "Set the negation operation for conditions on feature edge types"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "face_mark_negation", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, face_mark_negation_items); RNA_def_property_ui_text(prop, "Face Mark Negation", "Set the negation operation for the condition on face marks"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "face_mark_condition", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "flags"); RNA_def_property_enum_items(prop, face_mark_condition_items); RNA_def_property_ui_text(prop, "Face Mark Condition", "Set a feature edge selection condition on face marks"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_silhouette", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SILHOUETTE); RNA_def_property_ui_text(prop, "Silhouette", "Select silhouette edges"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_border", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_BORDER); RNA_def_property_ui_text(prop, "Border", "Select border edges"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_crease", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CREASE); RNA_def_property_ui_text(prop, "Crease", "Select crease edges"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_ridge_valley", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_RIDGE_VALLEY); RNA_def_property_ui_text(prop, "Ridge & Valley", "Select ridges and valleys"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_suggestive_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR); RNA_def_property_ui_text(prop, "Suggestive Contour", "Select suggestive contours"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_material_boundary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY); RNA_def_property_ui_text(prop, "Material Boundary", "Select edges at material boundaries"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_CONTOUR); RNA_def_property_ui_text(prop, "Contour", "Select contours"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_external_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR); RNA_def_property_ui_text(prop, "External Contour", "Select external contours"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "select_edge_mark", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "edge_types", FREESTYLE_FE_EDGE_MARK); RNA_def_property_ui_text(prop, "Edge Mark", "Select edge marks"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_silhouette", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SILHOUETTE); RNA_def_property_ui_text(prop, "Silhouette", "Exclude silhouette edges"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_border", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_BORDER); RNA_def_property_ui_text(prop, "Border", "Exclude border edges"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_crease", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CREASE); RNA_def_property_ui_text(prop, "Crease", "Exclude crease edges"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_ridge_valley", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_RIDGE_VALLEY); RNA_def_property_ui_text(prop, "Ridge & Valley", "Exclude ridges and valleys"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_suggestive_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_SUGGESTIVE_CONTOUR); RNA_def_property_ui_text(prop, "Suggestive Contour", "Exclude suggestive contours"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_material_boundary", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_MATERIAL_BOUNDARY); RNA_def_property_ui_text(prop, "Material Boundary", "Exclude edges at material boundaries"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_CONTOUR); RNA_def_property_ui_text(prop, "Contour", "Exclude contours"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_external_contour", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EXTERNAL_CONTOUR); RNA_def_property_ui_text(prop, "External Contour", "Exclude external contours"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "exclude_edge_mark", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "exclude_edge_types", FREESTYLE_FE_EDGE_MARK); RNA_def_property_ui_text(prop, "Edge Mark", "Exclude edge marks"); RNA_def_property_ui_icon(prop, ICON_X, 0); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "visibility", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "qi"); RNA_def_property_enum_items(prop, visibility_items); RNA_def_property_ui_text(prop, "Visibility", "Determine how to use visibility for feature edge selection"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "qi_start", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "qi_start"); RNA_def_property_range(prop, 0, INT_MAX); RNA_def_property_ui_text(prop, "Start", "First QI value of the QI range"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "qi_end", PROP_INT, PROP_UNSIGNED); RNA_def_property_int_sdna(prop, NULL, "qi_end"); RNA_def_property_range(prop, 0, INT_MAX); RNA_def_property_ui_text(prop, "End", "Last QI value of the QI range"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); /* FreestyleModuleSettings */ @@ -2897,12 +2901,12 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Text"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Style Module", "Python script to define a style module"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "is_displayed", 1); RNA_def_property_ui_text(prop, "Use", "Enable or disable this style module during stroke rendering"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); /* FreestyleSettings */ @@ -2920,62 +2924,62 @@ static void rna_def_freestyle_settings(BlenderRNA *brna) RNA_def_property_enum_sdna(prop, NULL, "mode"); RNA_def_property_enum_items(prop, freestyle_ui_mode_items); RNA_def_property_ui_text(prop, "Control Mode", "Select the Freestyle control mode"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "raycasting_algorithm", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "raycasting_algorithm"); RNA_def_property_enum_items(prop, freestyle_raycasting_algorithm_items); RNA_def_property_ui_text(prop, "Raycasting Algorithm", "Select the Freestyle raycasting algorithm"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_culling", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_CULLING); RNA_def_property_ui_text(prop, "Culling", "If enabled, out-of-view edges are ignored"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_suggestive_contours", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_SUGGESTIVE_CONTOURS_FLAG); RNA_def_property_ui_text(prop, "Suggestive Contours", "Enable suggestive contours"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_ridges_and_valleys", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_RIDGES_AND_VALLEYS_FLAG); RNA_def_property_ui_text(prop, "Ridges and Valleys", "Enable ridges and valleys"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_material_boundaries", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_MATERIAL_BOUNDARIES_FLAG); RNA_def_property_ui_text(prop, "Material Boundaries", "Enable material boundaries"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_smoothness", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_FACE_SMOOTHNESS_FLAG); RNA_def_property_ui_text(prop, "Face Smoothness", "Take face smoothness into account in view map calculation"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_advanced_options", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flags", FREESTYLE_ADVANCED_OPTIONS_FLAG); RNA_def_property_ui_text(prop, "Advanced Options", "Enable advanced edge detection options (sphere radius and Kr derivative epsilon)"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "sphere_radius", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "sphere_radius"); RNA_def_property_range(prop, 0.0, 1000.0); RNA_def_property_ui_text(prop, "Sphere Radius", "Sphere radius for computing curvatures"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "kr_derivative_epsilon", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "dkr_epsilon"); RNA_def_property_range(prop, -1000.0, 1000.0); RNA_def_property_ui_text(prop, "Kr Derivative Epsilon", "Kr derivative epsilon for computing suggestive contours"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "crease_angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "crease_angle"); RNA_def_property_range(prop, 0.0, DEG2RAD(180.0)); RNA_def_property_ui_text(prop, "Crease Angle", "Angular threshold for detecting crease edges"); - RNA_def_property_update(prop, NC_SCENE, NULL); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "linesets", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "linesets", NULL); @@ -4190,12 +4194,14 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop = RNA_def_property(srna, "tile_x", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "tilex"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 8, 65536); RNA_def_property_ui_text(prop, "Tile X", "Horizontal tile size to use while rendering"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "tile_y", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "tiley"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_range(prop, 8, 65536); RNA_def_property_ui_text(prop, "Tile Y", "Vertical tile size to use while rendering"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); diff --git a/source/blender/makesrna/intern/rna_sensor.c b/source/blender/makesrna/intern/rna_sensor.c index 278dc074c50..5a3ec8f1f1d 100644 --- a/source/blender/makesrna/intern/rna_sensor.c +++ b/source/blender/makesrna/intern/rna_sensor.c @@ -58,7 +58,6 @@ EnumPropertyItem sensor_type_items[] = { {SENS_RADAR, "RADAR", 0, "Radar", ""}, {SENS_RANDOM, "RANDOM", 0, "Random", ""}, {SENS_RAY, "RAY", 0, "Ray", ""}, - {SENS_TOUCH, "TOUCH", 0, "Touch", ""}, {0, NULL, 0, NULL, NULL} }; @@ -74,8 +73,6 @@ static StructRNA *rna_Sensor_refine(struct PointerRNA *ptr) switch (sensor->type) { case SENS_ALWAYS: return &RNA_AlwaysSensor; - case SENS_TOUCH: - return &RNA_TouchSensor; case SENS_NEAR: return &RNA_NearSensor; case SENS_KEYBOARD: @@ -267,15 +264,6 @@ static void rna_Sensor_Armature_update(Main *UNUSED(bmain), Scene *UNUSED(scene) posechannel[0] = 0; constraint[0] = 0; } - -/* note: the following set functions exists only to avoid id refcounting */ -static void rna_Sensor_touch_material_set(PointerRNA *ptr, PointerRNA value) -{ - bSensor *sens = (bSensor *)ptr->data; - bTouchSensor *ts = (bTouchSensor *) sens->data; - - ts->ma = value.data; -} #else static void rna_def_sensor(BlenderRNA *brna) @@ -427,25 +415,6 @@ static void rna_def_mouse_sensor(BlenderRNA *brna) RNA_def_property_update(prop, NC_LOGIC, NULL); } -static void rna_def_touch_sensor(BlenderRNA *brna) -{ - StructRNA *srna; - PropertyRNA *prop; - - srna = RNA_def_struct(brna, "TouchSensor", "Sensor"); - RNA_def_struct_ui_text(srna, "Touch Sensor", "Sensor to detect objects colliding with the current object"); - RNA_def_struct_sdna_from(srna, "bTouchSensor", "data"); - - prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); - RNA_def_property_struct_type(prop, "Material"); - RNA_def_property_pointer_sdna(prop, NULL, "ma"); - RNA_def_property_flag(prop, PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Material", "Only look for objects with this material (blank = all objects)"); - /* note: custom set function is ONLY to avoid rna setting a user for this. */ - RNA_def_property_pointer_funcs(prop, NULL, "rna_Sensor_touch_material_set", NULL, NULL); - RNA_def_property_update(prop, NC_LOGIC, NULL); -} - static void rna_def_keyboard_sensor(BlenderRNA *brna) { StructRNA *srna; @@ -917,7 +886,6 @@ void RNA_def_sensor(BlenderRNA *brna) rna_def_always_sensor(brna); rna_def_near_sensor(brna); rna_def_mouse_sensor(brna); - rna_def_touch_sensor(brna); rna_def_keyboard_sensor(brna); rna_def_property_sensor(brna); rna_def_armature_sensor(brna); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 650453ebc69..f8e1ac094aa 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -93,6 +93,23 @@ static void meta_tmp_ref(Sequence *seq_par, Sequence *seq) } } +static void rna_SequenceElement_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + Scene *scene = (Scene *) ptr->id.data; + Editing *ed = BKE_sequencer_editing_get(scene, FALSE); + + if (ed) { + StripElem *se = (StripElem *)ptr->data; + Sequence *seq; + + /* slow but we can't avoid! */ + seq = BKE_sequencer_from_elem(&ed->seqbase, se); + if (seq) { + BKE_sequence_invalidate_cache(scene, seq); + } + } +} + static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { Scene *scene = (Scene *) ptr->id.data; @@ -1063,7 +1080,7 @@ static void rna_def_strip_element(BlenderRNA *brna) prop = RNA_def_property(srna, "filename", PROP_STRING, PROP_FILENAME); RNA_def_property_string_sdna(prop, NULL, "name"); RNA_def_property_ui_text(prop, "Filename", ""); - RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update"); + RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceElement_update"); prop = RNA_def_property(srna, "orig_width", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "orig_width"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index f7a0d865274..54012122617 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -172,6 +172,7 @@ static EnumPropertyItem buttons_texture_context_items[] = { #include "DNA_mask_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_userdef_types.h" #include "BLI_math.h" @@ -197,6 +198,9 @@ static EnumPropertyItem buttons_texture_context_items[] = { #include "IMB_imbuf_types.h" +#include "UI_interface.h" +#include "UI_view2d.h" + static StructRNA *rna_Space_refine(struct PointerRNA *ptr) { SpaceLink *space = (SpaceLink *)ptr->data; @@ -959,6 +963,14 @@ static EnumPropertyItem *rna_SpaceProperties_texture_context_itemf(bContext *C, return item; } +static void rna_SpaceProperties_texture_context_set(PointerRNA *ptr, int value) +{ + SpaceButs *sbuts = (SpaceButs *)(ptr->data); + + /* User action, no need to keep "better" value in prev here! */ + sbuts->texture_context = sbuts->texture_context_prev = value; +} + /* Space Console */ static void rna_ConsoleLine_body_get(PointerRNA *ptr, char *value) { @@ -1255,6 +1267,15 @@ static void rna_SpaceNodeEditor_show_backdrop_update(Main *UNUSED(bmain), Scene WM_main_add_notifier(NC_SCENE | ND_NODES, NULL); } +static void rna_SpaceNodeEditor_cursor_location_from_region(SpaceNode *snode, bContext *C, int x, int y) +{ + ARegion *ar = CTX_wm_region(C); + + UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]); + snode->cursor[0] /= UI_DPI_FAC; + snode->cursor[1] /= UI_DPI_FAC; +} + static void rna_SpaceClipEditor_clip_set(PointerRNA *ptr, PointerRNA value) { SpaceClip *sc = (SpaceClip *)(ptr->data); @@ -2194,7 +2215,8 @@ static void rna_def_space_buttons(BlenderRNA *brna) prop = RNA_def_property(srna, "texture_context", PROP_ENUM, PROP_NONE); RNA_def_property_enum_items(prop, buttons_texture_context_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceProperties_texture_context_itemf"); + RNA_def_property_enum_funcs(prop, NULL, "rna_SpaceProperties_texture_context_set", + "rna_SpaceProperties_texture_context_itemf"); RNA_def_property_ui_text(prop, "Texture Context", "Type of texture data to display and edit"); RNA_def_property_update(prop, NC_TEXTURE, NULL); @@ -3292,7 +3314,8 @@ static void rna_def_space_node_path_api(BlenderRNA *brna, PropertyRNA *cprop) static void rna_def_space_node(BlenderRNA *brna) { StructRNA *srna; - PropertyRNA *prop; + PropertyRNA *prop, *parm; + FunctionRNA *func; static EnumPropertyItem texture_type_items[] = { {SNODE_TEX_OBJECT, "OBJECT", ICON_OBJECT_DATA, "Object", "Edit texture nodes from Object"}, @@ -3433,6 +3456,14 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "cursor"); RNA_def_property_ui_text(prop, "Cursor Location", "Location for adding new nodes"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE_VIEW, NULL); + + func = RNA_def_function(srna, "cursor_location_from_region", "rna_SpaceNodeEditor_cursor_location_from_region"); + RNA_def_function_ui_description(func, "Set the cursor location using region coordinates"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + parm = RNA_def_int(func, "x", 0, INT_MIN, INT_MAX, "x", "Region x coordinate", -10000, 10000); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_int(func, "y", 0, INT_MIN, INT_MAX, "y", "Region y coordinate", -10000, 10000); + RNA_def_property_flag(parm, PROP_REQUIRED); } static void rna_def_space_logic(BlenderRNA *brna) @@ -3525,6 +3556,7 @@ static void rna_def_space_clip(BlenderRNA *brna) static EnumPropertyItem pivot_items[] = { {V3D_CENTER, "BOUNDING_BOX_CENTER", ICON_ROTATE, "Bounding Box Center", "Pivot around bounding box center of selected object(s)"}, + {V3D_CURSOR, "CURSOR", ICON_CURSOR, "2D Cursor", "Pivot around the 2D cursor"}, {V3D_LOCAL, "INDIVIDUAL_ORIGINS", ICON_ROTATECOLLECTION, "Individual Origins", "Pivot around each object's own origin"}, {V3D_CENTROID, "MEDIAN_POINT", ICON_ROTATECENTER, "Median Point", diff --git a/source/blender/makesrna/intern/rna_test.c b/source/blender/makesrna/intern/rna_test.c index 22b6f323647..e54e5f9bcad 100644 --- a/source/blender/makesrna/intern/rna_test.c +++ b/source/blender/makesrna/intern/rna_test.c @@ -34,6 +34,8 @@ #include "rna_internal.h" +#ifdef RNA_RUNTIME + #define ARRAY_SIZE 3 #define DYNAMIC_ARRAY_SIZE 64 #define MARRAY_DIM [3][4][5] @@ -43,8 +45,6 @@ #define DYNAMIC_MARRAY_DIM [3][4][5] #define DYNAMIC_MARRAY_SIZE(type) (sizeof(type DYNAMIC_MARRAY_DIM) / sizeof(type)) -#ifdef RNA_RUNTIME - #ifdef UNIT_TEST #define DEF_VARS(type, prefix) \ diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 1026a2c7772..fc71be75d3c 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -229,23 +229,33 @@ static void rna_trackingPlaneMarker_frame_set(PointerRNA *ptr, int value) { MovieClip *clip = (MovieClip *) ptr->id.data; MovieTracking *tracking = &clip->tracking; - MovieTrackingPlaneTrack *plane_track; MovieTrackingPlaneMarker *plane_marker = (MovieTrackingPlaneMarker *) ptr->data; - - /* TODO(sergey): Need to support editing markers from object's tracks */ - - plane_track = tracking->plane_tracks.first; - while (plane_track) { - if (plane_marker >= plane_track->markers && - plane_marker < plane_track->markers + plane_track->markersnr) + MovieTrackingObject *tracking_object; + bool found = false; + MovieTrackingPlaneTrack *plane_track = NULL; + + for (tracking_object = tracking->objects.first; + tracking_object; + tracking_object = tracking_object->next) + { + ListBase *tracksbase = BKE_tracking_object_get_plane_tracks(tracking, tracking_object); + + for (plane_track = tracksbase->first; + plane_track; + plane_track = plane_track->next) { - break; + if (plane_marker >= plane_track->markers && plane_marker < plane_track->markers + plane_track->markersnr) { + found = true; + break; + } } - plane_track = plane_track->next; + if (found) { + break; + } } - if (plane_track) { + if (found) { MovieTrackingPlaneMarker new_plane_marker = *plane_marker; new_plane_marker.framenr = value; @@ -455,19 +465,33 @@ static void rna_trackingMarker_frame_set(PointerRNA *ptr, int value) { MovieClip *clip = (MovieClip *) ptr->id.data; MovieTracking *tracking = &clip->tracking; - MovieTrackingTrack *track; MovieTrackingMarker *marker = (MovieTrackingMarker *) ptr->data; + MovieTrackingObject *tracking_object; + bool found = false; + MovieTrackingTrack *track = NULL; + + for (tracking_object = tracking->objects.first; + tracking_object; + tracking_object = tracking_object->next) + { + ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, tracking_object); + + for (track = tracksbase->first; + track; + track = track->next) + { + if (marker >= track->markers && marker < track->markers + track->markersnr) { + found = true; + break; + } + } - track = tracking->tracks.first; - while (track) { - if (marker >= track->markers && marker < track->markers + track->markersnr) { + if (found) { break; } - - track = track->next; } - if (track) { + if (found) { MovieTrackingMarker new_marker = *marker; new_marker.framenr = value; @@ -511,7 +535,8 @@ static void rna_trackingDopesheet_tagUpdate(Main *UNUSED(bmain), Scene *scene, P /* API */ -static MovieTrackingTrack *add_track_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, const char *name, int frame) +static MovieTrackingTrack *add_track_to_base(MovieClip *clip, MovieTracking *tracking, ListBase *tracksbase, + const char *name, int frame) { int width, height; MovieClipUser user = {0}; @@ -622,6 +647,44 @@ static void rna_trackingMarkers_delete_frame(MovieTrackingTrack *track, int fram WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL); } +static MovieTrackingPlaneMarker *rna_trackingPlaneMarkers_find_frame(MovieTrackingPlaneTrack *plane_track, int framenr, int exact) +{ + if (exact) + return BKE_tracking_plane_marker_get_exact(plane_track, framenr); + else + return BKE_tracking_plane_marker_get(plane_track, framenr); +} + +static MovieTrackingPlaneMarker *rna_trackingPlaneMarkers_insert_frame(MovieTrackingPlaneTrack *plane_track, int framenr) +{ + MovieTrackingPlaneMarker plane_marker, *new_plane_marker; + + memset(&plane_marker, 0, sizeof(plane_marker)); + plane_marker.framenr = framenr; + + /* a bit arbitrary, but better than creating zero markers */ + copy_v2_v2(plane_marker.corners[0], plane_track->markers[0].corners[0]); + copy_v2_v2(plane_marker.corners[1], plane_track->markers[0].corners[1]); + copy_v2_v2(plane_marker.corners[2], plane_track->markers[0].corners[2]); + copy_v2_v2(plane_marker.corners[3], plane_track->markers[0].corners[3]); + + new_plane_marker = BKE_tracking_plane_marker_insert(plane_track, &plane_marker); + + WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL); + + return new_plane_marker; +} + +static void rna_trackingPlaneMarkers_delete_frame(MovieTrackingPlaneTrack *plane_track, int framenr) +{ + if (plane_track->markersnr == 1) + return; + + BKE_tracking_plane_marker_delete(plane_track, framenr); + + WM_main_add_notifier(NC_MOVIECLIP | NA_EDITED, NULL); +} + #else static EnumPropertyItem tracker_motion_model[] = { @@ -1067,7 +1130,7 @@ static void rna_def_trackingMarkers(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_function_return(func, parm); func = RNA_def_function(srna, "insert_frame", "rna_trackingMarkers_insert_frame"); - RNA_def_function_ui_description(func, "Add a number of tracks to this movie clip"); + RNA_def_function_ui_description(func, "Insert a new marker at the specified frame"); parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", "Frame number to insert marker to", MINFRAME, MAXFRAME); RNA_def_property_flag(parm, PROP_REQUIRED); @@ -1317,7 +1380,7 @@ static void rna_def_trackingPlaneMarker(BlenderRNA *brna) RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x2); RNA_def_property_ui_range(prop, -FLT_MAX, FLT_MAX, 1, RNA_TRANSLATION_PREC_DEFAULT); RNA_def_property_ui_text(prop, "Corners", - "Array of coordinates which represents UI rectange corners in " + "Array of coordinates which represents UI rectangle corners in " "frame normalized coordinates"); RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, NULL); @@ -1331,11 +1394,38 @@ static void rna_def_trackingPlaneMarker(BlenderRNA *brna) static void rna_def_trackingPlaneMarkers(BlenderRNA *brna, PropertyRNA *cprop) { StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; RNA_def_property_srna(cprop, "MovieTrackingPlaneMarkers"); srna = RNA_def_struct(brna, "MovieTrackingPlaneMarkers", NULL); RNA_def_struct_sdna(srna, "MovieTrackingPlaneTrack"); - RNA_def_struct_ui_text(srna, "Movie Tracking Plane Markers", "Collection of markers for movie tracking plane track"); + RNA_def_struct_ui_text(srna, "Movie Tracking Plane Markers", + "Collection of markers for movie tracking plane track"); + + func = RNA_def_function(srna, "find_frame", "rna_trackingPlaneMarkers_find_frame"); + RNA_def_function_ui_description(func, "Get plane marker for specified frame"); + parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", + "Frame number to find marker for", MINFRAME, MAXFRAME); + RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "exact", TRUE, "Exact", + "Get plane marker at exact frame number rather than get estimated marker"); + parm = RNA_def_pointer(func, "plane_marker", "MovieTrackingPlaneMarker", "", "Plane marker for specified frame"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "insert_frame", "rna_trackingPlaneMarkers_insert_frame"); + RNA_def_function_ui_description(func, "Insert a new plane marker at the specified frame"); + parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", + "Frame number to insert marker to", MINFRAME, MAXFRAME); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "plane_marker", "MovieTrackingPlaneMarker", "", "Newly created plane marker"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "delete_frame", "rna_trackingPlaneMarkers_delete_frame"); + RNA_def_function_ui_description(func, "Delete plane marker at specified frame"); + parm = RNA_def_int(func, "frame", 1, MINFRAME, MAXFRAME, "Frame", + "Frame number to delete plane marker from", MINFRAME, MAXFRAME); + RNA_def_property_flag(parm, PROP_REQUIRED); } static void rna_def_trackingPlaneTrack(BlenderRNA *brna) @@ -1566,10 +1656,13 @@ static void rna_def_trackingPlaneTracks(BlenderRNA *brna) RNA_def_struct_sdna(srna, "MovieTracking"); RNA_def_struct_ui_text(srna, "Movie Plane Tracks", "Collection of movie tracking plane tracks"); + /* TODO(sergey): Add API to create new plane tracks */ + /* active plane track */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MovieTrackingPlaneTrack"); - RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", + NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); RNA_def_property_ui_text(prop, "Active Plane Track", "Active plane track in this tracking data object"); } @@ -1613,7 +1706,8 @@ static void rna_def_trackingObjectPlaneTracks(BlenderRNA *brna) /* active track */ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE); RNA_def_property_struct_type(prop, "MovieTrackingTrack"); - RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", NULL, NULL); + RNA_def_property_pointer_funcs(prop, "rna_tracking_active_plane_track_get", "rna_tracking_active_plane_track_set", + NULL, NULL); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_NEVER_UNLINK); RNA_def_property_ui_text(prop, "Active Track", "Active track in this tracking data object"); } diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c index 9efe3d9f1d6..6d521c6364f 100644 --- a/source/blender/makesrna/intern/rna_ui.c +++ b/source/blender/makesrna/intern/rna_ui.c @@ -31,6 +31,8 @@ #include "BLF_translation.h" +#include "BKE_idprop.h" + #include "RNA_define.h" #include "rna_internal.h" @@ -58,12 +60,9 @@ EnumPropertyItem operator_context_items[] = { }; EnumPropertyItem uilist_layout_type_items[] = { - {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout", - "Use the default, multi-rows layout"}, - {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout", - "Use the compact, single-row layout"}, - {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout", - "Use the grid-based layout"}, + {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout", "Use the default, multi-rows layout"}, + {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout", "Use the compact, single-row layout"}, + {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout", "Use the grid-based layout"}, {0, NULL, 0, NULL, NULL} }; @@ -269,8 +268,24 @@ static StructRNA *rna_Panel_refine(PointerRNA *ptr) } /* UIList */ +static unsigned int rna_UIList_filter_const_FILTER_ITEM_get(PointerRNA *ptr) +{ + return UILST_FLT_ITEM; +} + +static IDProperty *rna_UIList_idprops(PointerRNA *ptr, bool create) +{ + uiList *ui_list = (uiList *)ptr->data; + if (create && !ui_list->properties) { + IDPropertyTemplate val = {0}; + ui_list->properties = IDP_New(IDP_GROUP, &val, "RNA_UIList IDproperties group"); + } + + return ui_list->properties; +} + static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr, - int icon, PointerRNA *active_dataptr, const char *active_propname, int index) + int icon, PointerRNA *active_dataptr, const char *active_propname, int index, int flt_flag) { extern FunctionRNA rna_UIList_draw_item_func; @@ -290,11 +305,139 @@ static void uilist_draw_item(uiList *ui_list, bContext *C, uiLayout *layout, Poi RNA_parameter_set_lookup(&list, "active_data", active_dataptr); RNA_parameter_set_lookup(&list, "active_property", &active_propname); RNA_parameter_set_lookup(&list, "index", &index); + RNA_parameter_set_lookup(&list, "flt_flag", &flt_flag); + ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list); + + RNA_parameter_list_free(&list); +} + +static void uilist_draw_filter(uiList *ui_list, bContext *C, uiLayout *layout) +{ + extern FunctionRNA rna_UIList_draw_filter_func; + + PointerRNA ul_ptr; + ParameterList list; + FunctionRNA *func; + + RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr); + func = &rna_UIList_draw_filter_func; /* RNA_struct_find_function(&ul_ptr, "draw_filter"); */ + + RNA_parameter_list_create(&list, &ul_ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + RNA_parameter_set_lookup(&list, "layout", &layout); ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list); RNA_parameter_list_free(&list); } +static void uilist_filter_items(uiList *ui_list, bContext *C, PointerRNA *dataptr, const char *propname) +{ + extern FunctionRNA rna_UIList_filter_items_func; + + PointerRNA ul_ptr; + ParameterList list; + FunctionRNA *func; + PropertyRNA *parm; + + uiListDyn *flt_data = ui_list->dyn_data; + int *filter_flags, *filter_neworder; + void *ret1, *ret2; + int ret_len; + int len = flt_data->items_len = RNA_collection_length(dataptr, propname); + + RNA_pointer_create(&CTX_wm_screen(C)->id, ui_list->type->ext.srna, ui_list, &ul_ptr); + func = &rna_UIList_filter_items_func; /* RNA_struct_find_function(&ul_ptr, "filter_items"); */ + + RNA_parameter_list_create(&list, &ul_ptr, func); + RNA_parameter_set_lookup(&list, "context", &C); + RNA_parameter_set_lookup(&list, "data", dataptr); + RNA_parameter_set_lookup(&list, "property", &propname); + + ui_list->type->ext.call((bContext *)C, &ul_ptr, func, &list); + + parm = RNA_function_find_parameter(NULL, func, "filter_flags"); + ret_len = RNA_parameter_dynamic_length_get(&list, parm); + if (ret_len != len && ret_len != 0) { + printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", AT, + RNA_parameter_dynamic_length_get(&list, parm), "filter_flags", len); + RNA_parameter_list_free(&list); + return; + } + RNA_parameter_get(&list, parm, &ret1); + filter_flags = (int *)ret1; + + parm = RNA_function_find_parameter(NULL, func, "filter_neworder"); + ret_len = RNA_parameter_dynamic_length_get(&list, parm); + if (ret_len != len && ret_len != 0) { + printf("%s: Error, py func returned %d items in %s, %d or none were expected.\n", AT, + RNA_parameter_dynamic_length_get(&list, parm), "filter_neworder", len); + RNA_parameter_list_free(&list); + return; + } + RNA_parameter_get(&list, parm, &ret2); + filter_neworder = (int *)ret2; + + /* We have to do some final checks and transforms... */ + { + int i, filter_exclude = ui_list->filter_flag & UILST_FLT_EXCLUDE; + if (filter_flags) { + flt_data->items_filter_flags = MEM_mallocN(sizeof(int) * len, AT); + memcpy(flt_data->items_filter_flags, filter_flags, sizeof(int) * len); + + if (filter_neworder) { + /* For sake of simplicity, py filtering is expected to filter all items, but we actually only want + * reordering data for shown items! + */ + int items_shown, shown_idx; + int t_idx, t_ni, prev_ni; + flt_data->items_shown = 0; + for (i = 0, shown_idx = 0; i < len; i++) { + if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { + filter_neworder[shown_idx++] = filter_neworder[i]; + } + } + items_shown = flt_data->items_shown = shown_idx; + flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * items_shown, AT); + /* And now, bring back new indices into the [0, items_shown[ range! + * XXX This is O(N²)... :/ + */ + for (shown_idx = 0, prev_ni = -1; shown_idx < items_shown; shown_idx++) { + for (i = 0, t_ni = len, t_idx = -1; i < items_shown; i++) { + int ni = filter_neworder[i]; + if (ni > prev_ni && ni < t_ni) { + t_idx = i; + t_ni = ni; + } + } + if (t_idx >= 0) { + prev_ni = t_ni; + flt_data->items_filter_neworder[t_idx] = shown_idx; + } + } + } + else { + /* we still have to set flt_data->items_shown... */ + flt_data->items_shown = 0; + for (i = 0; i < len; i++) { + if ((filter_flags[i] & UILST_FLT_ITEM) ^ filter_exclude) { + flt_data->items_shown++; + } + } + } + } + else { + flt_data->items_shown = len; + + if (filter_neworder) { + flt_data->items_filter_neworder = MEM_mallocN(sizeof(int) * len, AT); + memcpy(flt_data->items_filter_neworder, filter_neworder, sizeof(int) * len); + } + } + } + + RNA_parameter_list_free(&list); +} + static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type) { uiListType *ult = RNA_struct_blender_type_get(type); @@ -318,7 +461,7 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da uiListType *ult, dummyult = {NULL}; uiList dummyuilist = {NULL}; PointerRNA dummyul_ptr; - int have_function[1]; + int have_function[3]; size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */ /* setup dummy menu & menu type to store static properties in */ @@ -349,9 +492,10 @@ static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *da ult->ext.call = call; ult->ext.free = free; RNA_struct_blender_type_set(ult->ext.srna, ult); - RNA_def_struct_flag(ult->ext.srna, STRUCT_NO_IDPROPERTIES); ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL; + ult->draw_filter = (have_function[1]) ? uilist_draw_filter : NULL; + ult->filter_items = (have_function[2]) ? uilist_filter_items : NULL; WM_uilisttype_add(ult); @@ -874,8 +1018,46 @@ static void rna_def_uilist(BlenderRNA *brna) RNA_def_struct_sdna(srna, "uiList"); RNA_def_struct_refine_func(srna, "rna_UIList_refine"); RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL); + RNA_def_struct_idprops_func(srna, "rna_UIList_idprops"); - /* draw */ + /* Registration */ + prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "type->idname"); + RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP); + RNA_def_property_ui_text(prop, "ID Name", + "If this is set, the uilist gets a custom ID, otherwise it takes the " + "name of the class used to define the uilist (for example, if the " + "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the " + "script, then bl_idname = \"OBJECT_UL_vgroups\")"); + + /* Data */ + prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, uilist_layout_type_items); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + + /* Filter options */ + prop = RNA_def_property(srna, "use_filter_show", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_SHOW); + RNA_def_property_ui_text(prop, "Show Filter", "Show filtering options"); + + prop = RNA_def_property(srna, "filter_name", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "filter_byname"); + RNA_def_property_ui_text(prop, "Filter by Name", "Only show items matching this name (use '*' as wildcard)"); + + prop = RNA_def_property(srna, "use_filter_invert", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter_flag", UILST_FLT_EXCLUDE); + RNA_def_property_ui_text(prop, "Invert", "Invert filtering (show hidden items, and vice-versa)"); + + prop = RNA_def_property(srna, "use_filter_sort_alpha", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_ALPHA); + RNA_def_property_ui_icon(prop, ICON_SORTALPHA, 0); + RNA_def_property_ui_text(prop, "Sort by Name", "Sort items by their name"); + + prop = RNA_def_property(srna, "use_filter_sort_reverse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "filter_sort_flag", UILST_FLT_SORT_REVERSE); + RNA_def_property_ui_text(prop, "Invert", "Invert the order of shown items"); + + /* draw_item */ func = RNA_def_function(srna, "draw_item", NULL); RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item " "function, you may want to check given 'item' is of the right type...)"); @@ -897,21 +1079,52 @@ static void rna_def_uilist(BlenderRNA *brna) "Identifier of property in active_data, for the active element"); RNA_def_property_flag(parm, PROP_REQUIRED); RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_PYFUNC_OPTIONAL); + prop = RNA_def_property(func, "flt_flag", PROP_INT, PROP_UNSIGNED); + RNA_def_property_ui_text(prop, "", "The filter-flag result for this item"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_PYFUNC_OPTIONAL); + + /* draw_filter */ + func = RNA_def_function(srna, "draw_filter", NULL); + RNA_def_function_ui_description(func, "Draw filtering options"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + parm = RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL); - prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE); - RNA_def_property_enum_items(prop, uilist_layout_type_items); - RNA_def_property_clear_flag(prop, PROP_EDITABLE); + /* filter */ + func = RNA_def_function(srna, "filter_items", NULL); + RNA_def_function_ui_description(func, "Filter and/or re-order items of the collection (output filter results in " + "filter_flags, and reorder results in filter_neworder arrays)"); + RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_property_flag(parm, PROP_REQUIRED); + parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property"); + RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR); + parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data, for the collection"); + RNA_def_property_flag(parm, PROP_REQUIRED); + prop = RNA_def_property(func, "filter_flags", PROP_INT, PROP_UNSIGNED); + RNA_def_property_flag(prop, PROP_REQUIRED | PROP_DYNAMIC); + RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */ + RNA_def_property_ui_text(prop, "", "An array of filter flags, one for each item in the collection (NOTE: " + "FILTER_ITEM bit is reserved, it defines whether the item is shown or not)"); + RNA_def_function_output(func, prop); + prop = RNA_def_property(func, "filter_neworder", PROP_INT, PROP_UNSIGNED); + RNA_def_property_flag(prop, PROP_REQUIRED | PROP_DYNAMIC); + RNA_def_property_array(prop, 1); /* XXX Dummy value, default 0 does not work */ + RNA_def_property_ui_text(prop, "", "An array of indices, one for each item in the collection, mapping the org " + "index to the new one"); + RNA_def_function_output(func, prop); + + /* "Constants"! */ + RNA_define_verify_sdna(0); /* not in sdna */ - /* registration */ - prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "type->idname"); - RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP); - RNA_def_property_ui_text(prop, "ID Name", - "If this is set, the uilist gets a custom ID, otherwise it takes the " - "name of the class used to define the uilist (for example, if the " - "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the " - "script, then bl_idname = \"OBJECT_UL_vgroups\")"); + prop = RNA_def_property(srna, "bitflag_filter_item", PROP_INT, PROP_UNSIGNED); + RNA_def_property_ui_text(prop, "FILTER_ITEM", + "The value of the reserved bitfalg 'FILTER_ITEM' (in filter_flags values)"); + RNA_def_property_int_funcs(prop, "rna_UIList_filter_const_FILTER_ITEM_get", NULL, NULL); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_header(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 2d89317b4ae..d79a40aa615 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -428,7 +428,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Sub-layout. Items placed in this sublayout are placed next to each other " "in a row"); - RNA_def_boolean(func, "align", 0, "", "Align buttons to each other"); + RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); func = RNA_def_function(srna, "column", "uiLayoutColumn"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); @@ -436,13 +436,13 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Sub-layout. Items placed in this sublayout are placed under each other " "in a column"); - RNA_def_boolean(func, "align", 0, "", "Align buttons to each other"); + RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); func = RNA_def_function(srna, "column_flow", "uiLayoutColumnFlow"); RNA_def_int(func, "columns", 0, 0, INT_MAX, "", "Number of columns, 0 is automatic", 0, INT_MAX); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); - RNA_def_boolean(func, "align", 0, "", "Align buttons to each other"); + RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); /* box layout */ func = RNA_def_function(srna, "box", "uiLayoutBox"); @@ -456,7 +456,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f); - RNA_def_boolean(func, "align", 0, "", "Align buttons to each other"); + RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); /* Icon of a rna pointer */ func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon"); @@ -501,13 +501,13 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Item. Exposes an RNA item and places it into the layout"); api_ui_item_rna_common(func); api_ui_item_common(func); - RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail"); - RNA_def_boolean(func, "slider", 0, "", "Use slider widget for numeric values"); - RNA_def_boolean(func, "toggle", 0, "", "Use toggle widget for boolean values"); - RNA_def_boolean(func, "icon_only", 0, "", "Draw only icons in buttons, no text"); - RNA_def_boolean(func, "event", 0, "", "Use button to input key events"); - RNA_def_boolean(func, "full_event", 0, "", "Use button to input full events including modifiers"); - RNA_def_boolean(func, "emboss", 1, "", "Draw the button itself, just the icon/text"); + RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail"); + RNA_def_boolean(func, "slider", false, "", "Use slider widget for numeric values"); + RNA_def_boolean(func, "toggle", false, "", "Use toggle widget for boolean values"); + RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in buttons, no text"); + RNA_def_boolean(func, "event", false, "", "Use button to input key events"); + RNA_def_boolean(func, "full_event", false, "", "Use button to input full events including modifiers"); + RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text"); RNA_def_int(func, "index", -1, -2, INT_MAX, "", "The index of this button, when set a single member of an array can be accessed, " "when set to -1 all array members are used", -2, INT_MAX); /* RNA_NO_INDEX == -1 */ @@ -535,7 +535,7 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "operator", "rna_uiItemO"); api_ui_item_op_common(func); - RNA_def_boolean(func, "emboss", 1, "", "Draw the button itself, just the icon/text"); + RNA_def_boolean(func, "emboss", true, "", "Draw the button itself, just the icon/text"); parm = RNA_def_pointer(func, "properties", "OperatorProperties", "", "Operator properties to fill in, return when 'properties' is set to true"); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR); @@ -569,7 +569,7 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_op_common(func); parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in operator"); RNA_def_property_flag(parm, PROP_REQUIRED); - parm = RNA_def_boolean(func, "value", 0, "", "Value of the property to call the operator with"); + parm = RNA_def_boolean(func, "value", false, "", "Value of the property to call the operator with"); RNA_def_property_flag(parm, PROP_REQUIRED); */ func = RNA_def_function(srna, "operator_int", "uiItemIntO"); @@ -623,7 +623,7 @@ void RNA_api_ui_layout(StructRNA *srna) /* templates */ func = RNA_def_function(srna, "template_header", "uiTemplateHeader"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); - RNA_def_boolean(func, "menus", 1, "", "The header has menus, and should show menu expander"); + RNA_def_boolean(func, "menus", true, "", "The header has menus, and should show menu expander"); func = RNA_def_function(srna, "template_ID", "uiTemplateID"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -679,7 +679,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Item. A preview window for materials, textures, lamps, etc"); parm = RNA_def_pointer(func, "id", "ID", "", "ID datablock"); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_boolean(func, "show_buttons", 1, "", "Show preview buttons?"); + RNA_def_boolean(func, "show_buttons", true, "", "Show preview buttons?"); RNA_def_pointer(func, "parent", "ID", "", "ID datablock"); RNA_def_pointer(func, "slot", "TextureSlot", "", "Texture slot"); @@ -687,13 +687,13 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Item. A curve mapping widget used for e.g falloff curves for lamps"); api_ui_item_rna_common(func); RNA_def_enum(func, "type", curve_type_items, 0, "Type", "Type of curves to display"); - RNA_def_boolean(func, "levels", 0, "", "Show black/white levels"); - RNA_def_boolean(func, "brush", 0, "", "Show brush options"); + RNA_def_boolean(func, "levels", false, "", "Show black/white levels"); + RNA_def_boolean(func, "brush", false, "", "Show brush options"); func = RNA_def_function(srna, "template_color_ramp", "uiTemplateColorRamp"); RNA_def_function_ui_description(func, "Item. A color ramp widget"); api_ui_item_rna_common(func); - RNA_def_boolean(func, "expand", 0, "", "Expand button to show more detail"); + RNA_def_boolean(func, "expand", false, "", "Expand button to show more detail"); func = RNA_def_function(srna, "template_icon_view", "uiTemplateIconView"); RNA_def_function_ui_description(func, "Enum. Large widget showing Icon previews"); @@ -723,10 +723,10 @@ void RNA_api_ui_layout(StructRNA *srna) func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker"); RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors"); api_ui_item_rna_common(func); - RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel"); - RNA_def_boolean(func, "lock", 0, "", "Lock the color wheel display to value 1.0 regardless of actual color"); - RNA_def_boolean(func, "lock_luminosity", 0, "", "Keep the color at its original vector length"); - RNA_def_boolean(func, "cubic", 1, "", "Cubic saturation for picking values close to white"); + RNA_def_boolean(func, "value_slider", false, "", "Display the value slider to the right of the color wheel"); + RNA_def_boolean(func, "lock", false, "", "Lock the color wheel display to value 1.0 regardless of actual color"); + RNA_def_boolean(func, "lock_luminosity", false, "", "Keep the color at its original vector length"); + RNA_def_boolean(func, "cubic", true, "", "Cubic saturation for picking values close to white"); func = RNA_def_function(srna, "template_image_layers", "uiTemplateImageLayers"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -741,19 +741,19 @@ void RNA_api_ui_layout(StructRNA *srna) api_ui_item_rna_common(func); parm = RNA_def_pointer(func, "image_user", "ImageUser", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); - RNA_def_boolean(func, "compact", 0, "", "Use more compact layout"); + RNA_def_boolean(func, "compact", false, "", "Use more compact layout"); func = RNA_def_function(srna, "template_image_settings", "uiTemplateImageSettings"); RNA_def_function_ui_description(func, "User interface for setting image format options"); parm = RNA_def_pointer(func, "image_settings", "ImageFormatSettings", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); - RNA_def_boolean(func, "color_management", 0, "", "Show color management settings"); + RNA_def_boolean(func, "color_management", false, "", "Show color management settings"); func = RNA_def_function(srna, "template_movieclip", "uiTemplateMovieClip"); RNA_def_function_ui_description(func, "Item(s). User interface for selecting movie clips and their source paths"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); - RNA_def_boolean(func, "compact", 0, "", "Use more compact layout"); + RNA_def_boolean(func, "compact", false, "", "Use more compact layout"); func = RNA_def_function(srna, "template_track", "uiTemplateTrack"); RNA_def_function_ui_description(func, "Item. A movie-track widget to preview tracking image."); @@ -766,7 +766,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); parm = RNA_def_pointer(func, "track", "MovieTrackingTrack", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL); - RNA_def_boolean(func, "compact", 0, "", "Use more compact layout"); + RNA_def_boolean(func, "compact", false, "", "Use more compact layout"); func = RNA_def_function(srna, "template_movieclip_information", "uiTemplateMovieclipInformation"); RNA_def_function_ui_description(func, "Item. Movie clip information data."); @@ -796,9 +796,10 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_string(func, "active_propname", "", 0, "", "Identifier of the integer property in active_data, index of the active item"); RNA_def_property_flag(parm, PROP_REQUIRED); - RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display", 0, INT_MAX); - RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display", 0, INT_MAX); + RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Default and minimum number of rows to display", 0, INT_MAX); + RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Default maximum number of rows to display", 0, INT_MAX); RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use"); + RNA_def_int(func, "columns", 9, 0, INT_MAX, "", "Number of items to display per row, for GRID layout", 0, INT_MAX); func = RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs"); RNA_def_function_flag(func, FUNC_USE_CONTEXT); @@ -859,7 +860,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_ui_description(func, "Item. A widget to control color managed view settings settings."); RNA_def_function_flag(func, FUNC_USE_CONTEXT); api_ui_item_rna_common(func); - /* RNA_def_boolean(func, "show_global_settings", 0, "", "Show widgets to control global color management settings"); */ + /* RNA_def_boolean(func, "show_global_settings", false, "", "Show widgets to control global color management settings"); */ /* node socket icon */ func = RNA_def_function(srna, "template_node_socket", "uiTemplateNodeSocket"); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index f34366a23c7..3b609b69374 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2134,6 +2134,18 @@ static void rna_def_userdef_theme_space_image(BlenderRNA *brna) RNA_def_property_array(prop, 4); RNA_def_property_ui_text(prop, "Stitch preview active island", ""); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "uv_shadow", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "uv_shadow"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Texture paint/Modifier UVs", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "uv_others", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "uv_others"); + RNA_def_property_array(prop, 4); + RNA_def_property_ui_text(prop, "Other Object UVs", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_seq(BlenderRNA *brna) diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index e09fa18ffc5..7c47fd5862e 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -50,6 +50,7 @@ #include "BKE_cdderivedmesh.h" #include "BKE_displist.h" +#include "BKE_curve.h" #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -198,7 +199,7 @@ static int *find_doubles_index_map(BMesh *bm, BMOperator *dupe_op, /*element type argument doesn't do anything here*/ BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { - v2 = BMO_iter_map_value_p(&oiter); + v2 = BMO_iter_map_value_ptr(&oiter); index_map[BM_elem_index_get(v)] = BM_elem_index_get(v2) + 1; } @@ -271,7 +272,7 @@ static void bm_merge_dm_transform(BMesh *bm, DerivedMesh *dm, float mat[4][4], /* add new merge targets to weld operator */ BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { - v2 = BMO_iter_map_value_p(&oiter); + v2 = BMO_iter_map_value_ptr(&oiter); /* check in case the target vertex (v2) is already marked * for merging */ while ((v3 = BMO_slot_map_elem_get(slot_targetmap, v2))) { @@ -318,8 +319,10 @@ static void merge_first_last(BMesh *bm, /* add new merge targets to weld operator */ slot_targetmap = BMO_slot_get(weld_op->slots_in, "targetmap"); BMO_ITER (v, &oiter, find_op.slots_out, "targetmap.out", 0) { - v2 = BMO_iter_map_value_p(&oiter); - BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); + if (!BMO_slot_map_contains(slot_targetmap, v)) { + v2 = BMO_iter_map_value_ptr(&oiter); + BMO_slot_map_elem_insert(weld_op, slot_targetmap, v, v2); + } } BMO_op_finish(bm, &find_op); @@ -343,7 +346,7 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, int *indexMap = NULL; DerivedMesh *start_cap = NULL, *end_cap = NULL; MVert *src_mvert; - BMOpSlot *slot_targetmap = NULL; /* for weldop */ + BMOpSlot *slot_targetmap = NULL; /* for weld_op */ /* need to avoid infinite recursion here */ if (amd->start_cap && amd->start_cap != ob && amd->start_cap->type == OB_MESH) @@ -387,19 +390,19 @@ static DerivedMesh *arrayModifier_doArray(ArrayModifierData *amd, BKE_object_to_mat3(amd->curve_ob, tmp_mat); scale = mat3_to_scale(tmp_mat); - if (!cu->path) { + if (!amd->curve_ob->curve_cache || !amd->curve_ob->curve_cache->path) { cu->flag |= CU_PATH; // needed for path & bevlist BKE_displist_make_curveTypes(scene, amd->curve_ob, 0); } - if (cu->path) - length = scale * cu->path->totdist; + if (amd->curve_ob->curve_cache->path) + length = scale * amd->curve_ob->curve_cache->path->totdist; } } /* calculate the maximum number of copies which will fit within the * prescribed length */ if (amd->fit_type == MOD_ARR_FITLENGTH || amd->fit_type == MOD_ARR_FITCURVE) { - float dist = sqrt(dot_v3v3(offset[3], offset[3])); + float dist = len_v3(offset[3]); if (dist > 1e-6f) /* this gives length = first copy start to last copy end diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index 01b14abfb1f..326ffba3e2e 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -46,6 +46,7 @@ #include "MOD_util.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "MEM_guardedalloc.h" diff --git a/source/blender/modifiers/intern/MOD_boolean_util.c b/source/blender/modifiers/intern/MOD_boolean_util.c index 98fab9c06ff..9c8109c7856 100644 --- a/source/blender/modifiers/intern/MOD_boolean_util.c +++ b/source/blender/modifiers/intern/MOD_boolean_util.c @@ -266,44 +266,6 @@ static void FaceIt_Construct( output->it = it; } -static Object *AddNewBlenderMesh(Scene *scene, Base *base) -{ - /* This little function adds a new mesh object to the blender object list - * It uses ob to duplicate data as this seems to be easier than creating - * a new one. This new oject contains no faces nor vertices. */ - Mesh *old_me; - Base *basen; - Object *ob_new; - - /* now create a new blender object. - * duplicating all the settings from the previous object - * to the new one. */ - ob_new = BKE_object_copy(base->object); - - /* Ok we don't want to use the actual data from the - * last object, the above function incremented the - * number of users, so decrement it here. */ - old_me = ob_new->data; - old_me->id.us--; - - /* Now create a new base to add into the linked list of - * vase objects. */ - - basen = MEM_mallocN(sizeof(Base), "duplibase"); - *basen = *base; - BLI_addhead(&scene->base, basen); /* addhead: anders oneindige lus */ - basen->object = ob_new; - basen->flag &= ~SELECT; - - /* Initialize the mesh data associated with this object. */ - ob_new->data = BKE_mesh_add(G.main, "Mesh"); - - /* Finally assign the object type. */ - ob_new->type = OB_MESH; - - return ob_new; -} - static void InterpCSGFace( DerivedMesh *dm, DerivedMesh *orig_dm, int index, int orig_index, int nr, float mapmat[4][4]) @@ -509,9 +471,9 @@ static void FreeMeshDescriptors( FaceIt_Destruct(face_it); } -static DerivedMesh *NewBooleanDerivedMesh_intern( +DerivedMesh *NewBooleanDerivedMesh( DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, - int int_op_type, Material **mat, int *totmat) + int int_op_type) { float inv_mat[4][4]; @@ -567,7 +529,7 @@ static DerivedMesh *NewBooleanDerivedMesh_intern( /* iterate through results of operation and insert * into new object */ result = ConvertCSGDescriptorsToDerivedMesh( - &fd_o, &vd_o, inv_mat, map_mat, mat, totmat, dm_select, ob_select, dm, ob); + &fd_o, &vd_o, inv_mat, map_mat, NULL, NULL, dm_select, ob_select, dm, ob); /* free up the memory */ CSG_FreeVertexDescriptor(&vd_o); @@ -584,67 +546,3 @@ static DerivedMesh *NewBooleanDerivedMesh_intern( return result; } - -int NewBooleanMesh(Scene *scene, Base *base, Base *base_select, int int_op_type) -{ - Mesh *me_new; - int a, maxmat, totmat = 0; - Object *ob_new, *ob, *ob_select; - Material **mat; - DerivedMesh *result; - DerivedMesh *dm_select; - DerivedMesh *dm; - - ob = base->object; - ob_select = base_select->object; - - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); - dm_select = mesh_create_derived_view(scene, ob_select, 0); // no modifiers in editmode ?? - - maxmat = ob->totcol + ob_select->totcol; - mat = (Material **)MEM_mallocN(sizeof(Material *) * maxmat, "NewBooleanMeshMat"); - - /* put some checks in for nice user feedback */ - if (dm == NULL || dm_select == NULL) { - return 0; - } - - if (!dm->getNumTessFaces(dm) || !dm_select->getNumTessFaces(dm_select)) { - MEM_freeN(mat); - return -1; - } - - result = NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, mat, &totmat); - - if (result == NULL) { - MEM_freeN(mat); - return 0; - } - - /* create a new blender mesh object - using 'base' as a template */ - ob_new = AddNewBlenderMesh(scene, base_select); - me_new = ob_new->data; - - DM_to_mesh(result, me_new, ob_new, CD_MASK_MESH); - result->release(result); - - dm->release(dm); - dm_select->release(dm_select); - - /* add materials to object */ - for (a = 0; a < totmat; a++) - assign_material(ob_new, mat[a], a + 1, BKE_MAT_ASSIGN_USERPREF); - - MEM_freeN(mat); - - /* update dag */ - DAG_id_tag_update(&ob_new->id, OB_RECALC_DATA); - - return 1; -} - -DerivedMesh *NewBooleanDerivedMesh(DerivedMesh *dm, struct Object *ob, DerivedMesh *dm_select, struct Object *ob_select, - int int_op_type) -{ - return NewBooleanDerivedMesh_intern(dm, ob, dm_select, ob_select, int_op_type, NULL, NULL); -} diff --git a/source/blender/modifiers/intern/MOD_boolean_util.h b/source/blender/modifiers/intern/MOD_boolean_util.h index 209db60f0c9..04d76d45652 100644 --- a/source/blender/modifiers/intern/MOD_boolean_util.h +++ b/source/blender/modifiers/intern/MOD_boolean_util.h @@ -39,12 +39,6 @@ struct Base; struct DerivedMesh; /* Performs a boolean between two mesh objects, it is assumed that both objects - * are in fact a mesh object. On success returns 1 and creates a new mesh object - * into blender data structures. On failure returns 0 and reports an error. */ -int NewBooleanMesh(struct Scene *scene, struct Base *base, struct Base *base_select, int op); - - -/* Performs a boolean between two mesh objects, it is assumed that both objects * are in fact mesh object. On success returns a DerivedMesh. On failure * returns NULL and reports an error. */ diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index 9fdb40e71dc..a3569cbde68 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -49,11 +49,13 @@ #include "BKE_cdderivedmesh.h" #include "bmesh.h" +#include "bmesh_tools.h" // #define USE_TIMEIT #ifdef USE_TIMEIT # include "PIL_time.h" +# include "PIL_time_utildefines.h" #endif #include "MOD_util.h" diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index b3d3e65e120..d55ebdad939 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -44,6 +44,7 @@ #include "BKE_modifier.h" #include "bmesh.h" +#include "bmesh_tools.h" #include "DNA_object_types.h" diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index fe680041197..f6b882c5a69 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -568,7 +568,7 @@ static DerivedMesh *cutEdges(ExplodeModifierData *emd, DerivedMesh *dm) int numlayer; unsigned int ed_v1, ed_v2; - edgehash = BLI_edgehash_new(); + edgehash = BLI_edgehash_new(__func__); /* recreate vertpa from facepa calculation */ for (i = 0, mf = mface; i < totface; i++, mf++) { @@ -821,7 +821,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd, cfra = BKE_scene_frame_get(scene); /* hash table for vertice <-> particle relations */ - vertpahash = BLI_edgehash_new(); + vertpahash = BLI_edgehash_new(__func__); for (i = 0; i < totface; i++) { if (facepa[i] != totpart) { @@ -869,7 +869,7 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ invert_m4_m4(imat, ob->obmat); - psmd->psys->lattice = psys_get_lattice(&sim); + psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* duplicate & displace vertices */ ehi = BLI_edgehashIterator_new(vertpahash); @@ -973,9 +973,9 @@ static DerivedMesh *explodeMesh(ExplodeModifierData *emd, CDDM_tessfaces_to_faces(explode); explode->dirty |= DM_DIRTY_NORMALS; - if (psmd->psys->lattice) { - end_latt_deform(psmd->psys->lattice); - psmd->psys->lattice = NULL; + if (psmd->psys->lattice_deform_data) { + end_latt_deform(psmd->psys->lattice_deform_data); + psmd->psys->lattice_deform_data = NULL; } return explode; diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index e846ce11262..c51fa329df2 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -261,7 +261,7 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, maxloop += totloop; } - psys->lattice = psys_get_lattice(&sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) { float min_r[3], max_r[3]; @@ -378,9 +378,9 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, CDDM_calc_edges(result); - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice = NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } if (size) diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 83ac9f34df3..09e0ac966d0 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -933,7 +933,6 @@ static void add_poly(SkinOutput *so, BMVert *v4) { BMVert *verts[4] = {v1, v2, v3, v4}; - BMEdge *edges[4]; BMFace *f; BLI_assert(v1 != v2 && v1 != v3 && v1 != v4); @@ -941,18 +940,7 @@ static void add_poly(SkinOutput *so, BLI_assert(v3 != v4); BLI_assert(v1 && v2 && v3); - edges[0] = BM_edge_create(so->bm, v1, v2, NULL, BM_CREATE_NO_DOUBLE); - edges[1] = BM_edge_create(so->bm, v2, v3, NULL, BM_CREATE_NO_DOUBLE); - if (v4) { - edges[2] = BM_edge_create(so->bm, v3, v4, NULL, BM_CREATE_NO_DOUBLE); - edges[3] = BM_edge_create(so->bm, v4, v1, NULL, BM_CREATE_NO_DOUBLE); - } - else { - edges[2] = BM_edge_create(so->bm, v3, v1, NULL, BM_CREATE_NO_DOUBLE); - edges[3] = NULL; - } - - f = BM_face_create(so->bm, verts, edges, v4 ? 4 : 3, BM_CREATE_NO_DOUBLE); + f = BM_face_create_verts(so->bm, verts, v4 ? 4 : 3, NULL, BM_CREATE_NO_DOUBLE, true); if (so->smd->flag & MOD_SKIN_SMOOTH_SHADING) BM_elem_flag_enable(f, BM_ELEM_SMOOTH); f->mat_nr = so->mat_nr; @@ -996,7 +984,7 @@ static void output_frames(BMesh *bm, f = &sn->frames[i]; for (j = 0; j < 4; j++) { if (!f->merge[j].frame) { - BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, 0); + BMVert *v = f->verts[j] = BM_vert_create(bm, f->co[j], NULL, BM_CREATE_NOP); if (input_dvert) { MDeformVert *dv; @@ -1310,7 +1298,7 @@ static void skin_hole_detach_partially_attached_frame(BMesh *bm, Frame *frame) /* Detach everything */ for (i = 0; i < totattached; i++) { BMVert **av = &frame->verts[attached[i]]; - (*av) = BM_vert_create(bm, (*av)->co, *av, 0); + (*av) = BM_vert_create(bm, (*av)->co, *av, BM_CREATE_NOP); } } diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 9155aa0044b..ffc813068b8 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -33,6 +33,9 @@ #include "BKE_modifier.h" #include "BKE_editmesh.h" +#include "bmesh.h" +#include "bmesh_tools.h" + static DerivedMesh *triangulate_dm(DerivedMesh *dm, const int flag) { DerivedMesh *result; diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 63267538528..67168e52949 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -28,18 +28,12 @@ * \ingroup modifiers */ -#define DO_PROFILE 0 - #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_math.h" #include "BLI_string.h" #include "BLI_rand.h" -#if DO_PROFILE - #include "PIL_time.h" -#endif - #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -58,6 +52,13 @@ #include "MOD_util.h" #include "MOD_weightvg_util.h" +// #define USE_TIMEIT + +#ifdef USE_TIMEIT +# include "PIL_time.h" +# include "PIL_time_utildefines.h" +#endif + /************************************** * Util functions. * **************************************/ @@ -382,8 +383,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der int do_prev = (wmd->modifier.mode & eModifierMode_DoWeightPreview); #endif -#if DO_PROFILE - TIMEIT_START(perf) +#ifdef USE_TIMEIT + TIMEIT_START(perf); #endif /* Get number of verts. */ @@ -548,8 +549,8 @@ static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *der MEM_freeN(indices); MEM_freeN(v_cos); -#if DO_PROFILE - TIMEIT_END(perf) +#ifdef USE_TIMEIT + TIMEIT_END(perf); #endif /* Return the vgroup-modified mesh. */ diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index 4320e0436ce..78265154125 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -42,8 +42,6 @@ extern struct bNodeTreeType *ntreeType_Composite; void register_node_tree_type_cmp(void); void register_node_type_cmp_group(void); -void register_node_type_cmp_forloop(void); -void register_node_type_cmp_whileloop(void); void register_node_type_cmp_rlayers(void); void register_node_type_cmp_image(void); diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index ec39d81618d..e5d20f7dc73 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -43,8 +43,6 @@ extern struct bNodeTreeType *ntreeType_Shader; void register_node_tree_type_sh(void); void register_node_type_sh_group(void); -void register_node_type_sh_forloop(void); -void register_node_type_sh_whileloop(void); void register_node_type_sh_output(void); void register_node_type_sh_material(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index eeec40c911f..6e2c30f98cf 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -86,7 +86,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BS DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_TOON, def_toon, "BSDF_TOON", BsdfToon, "Toon BSDF", "" ) -DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, 0, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","") +DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, def_sh_subsurface, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","") DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume","" ) DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" ) DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" ) diff --git a/source/blender/nodes/NOD_texture.h b/source/blender/nodes/NOD_texture.h index ea003f23960..378c96d5882 100644 --- a/source/blender/nodes/NOD_texture.h +++ b/source/blender/nodes/NOD_texture.h @@ -42,8 +42,6 @@ extern struct bNodeTreeType *ntreeType_Texture; void register_node_tree_type_tex(void); void register_node_type_tex_group(void); -void register_node_type_tex_forloop(void); -void register_node_type_tex_whileloop(void); void register_node_type_tex_math(void); void register_node_type_tex_mix_rgb(void); diff --git a/source/blender/nodes/intern/node_util.c b/source/blender/nodes/intern/node_util.c index f9a450174a3..e77f0a08331 100644 --- a/source/blender/nodes/intern/node_util.c +++ b/source/blender/nodes/intern/node_util.c @@ -112,86 +112,54 @@ const char *node_filter_label(bNode *node) void node_update_internal_links_default(bNodeTree *ntree, bNode *node) { - bNodeSocket *fromsock_first = NULL, *tosock_first = NULL; /* used for fallback link if no other reconnections are found */ - int datatype; - int num_links_in = 0, num_links_out = 0, num_reconnect = 0; + bNodeLink *link; + bNodeSocket *output, *input, *selected; - /* Security check! */ + /* sanity check */ if (!ntree) return; - for (datatype = 0; datatype < NUM_SOCKET_TYPES; ++datatype) { - bNodeSocket *fromsock, *tosock; - int fromindex, toindex; - bNodeLink *link; - - /* Connect the first input of each type with outputs of the same type. */ + /* use link pointer as a tag for handled sockets (for outputs is unused anyway) */ + for (output = node->outputs.first; output; output = output->next) + output->link = NULL; + + for (link = ntree->links.first; link; link = link->next) { + output = link->fromsock; + if (link->fromnode != node || output->link) + continue; + output->link = link; /* not really used, just for tagging handled sockets */ - fromindex = INT_MAX; - fromsock = NULL; - for (link = ntree->links.first; link; link = link->next) { - if (nodeLinkIsHidden(link)) - continue; - if (link->tonode == node && link->tosock->type == datatype) { - int index = BLI_findindex(&node->inputs, link->tosock); - if (index < fromindex) { - fromindex = index; - fromsock = link->tosock; + /* look for suitable input */ + selected = NULL; + for (input = node->inputs.first; input; input = input->next) { + /* only use if same type */ + if (input->type == output->type) { + if (!selected) { + selected = input; } - } - } - if (fromsock) { - ++num_links_in; - if (!fromsock_first) - fromsock_first = fromsock; - } - - toindex = INT_MAX; - tosock = NULL; - for (link = ntree->links.first; link; link = link->next) { - if (nodeLinkIsHidden(link)) - continue; - if (link->fromnode == node && link->fromsock->type == datatype) { - int index = BLI_findindex(&node->outputs, link->fromsock); - if (index < toindex) { - toindex = index; - tosock = link->fromsock; + else { + /* linked inputs preferred */ + if (input->link && !selected->link) + selected = input; } } } - if (tosock) { - ++num_links_out; - if (!tosock_first) - tosock_first = tosock; - - if (fromsock) { - bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link"); - ilink->fromnode = node; - ilink->fromsock = fromsock; - ilink->tonode = node; - ilink->tosock = tosock; - /* internal link is always valid */ - ilink->flag |= NODE_LINK_VALID; - BLI_addtail(&node->internal_links, ilink); - - ++num_reconnect; - } + + if (selected) { + bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link"); + ilink->fromnode = node; + ilink->fromsock = selected; + ilink->tonode = node; + ilink->tosock = output; + /* internal link is always valid */ + ilink->flag |= NODE_LINK_VALID; + BLI_addtail(&node->internal_links, ilink); } } - /* if there is one input and one output link, but no reconnections by type, - * simply connect those two sockets. - */ - if ((num_reconnect == 0) && (num_links_in == 1) && (num_links_out == 1)) { - bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link"); - ilink->fromnode = node; - ilink->fromsock = fromsock_first; - ilink->tonode = node; - ilink->tosock = tosock_first; - /* internal link is always valid */ - ilink->flag |= NODE_LINK_VALID; - BLI_addtail(&node->internal_links, ilink); - } + /* clean up */ + for (output = node->outputs.first; output; output = output->next) + output->link = NULL; } float node_socket_get_float(bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock) diff --git a/source/blender/nodes/shader/node_shader_tree.c b/source/blender/nodes/shader/node_shader_tree.c index 134a5c9575f..1e828ea321c 100644 --- a/source/blender/nodes/shader/node_shader_tree.c +++ b/source/blender/nodes/shader/node_shader_tree.c @@ -189,13 +189,16 @@ void register_node_tree_type_sh(void) void ntreeGPUMaterialNodes(bNodeTree *ntree, GPUMaterial *mat) { + /* localize tree to create links for reroute and mute */ + bNodeTree *localtree = ntreeLocalize(ntree); bNodeTreeExec *exec; - exec = ntreeShaderBeginExecTree(ntree); - + exec = ntreeShaderBeginExecTree(localtree); ntreeExecGPUNodes(exec, mat, 1); - ntreeShaderEndExecTree(exec); + + ntreeFreeTree_ex(localtree, false); + MEM_freeN(localtree); } /* **************** call to switch lamploop for material node ************ */ diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index f6ecb3e0b72..aed8a0224f1 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -195,25 +195,28 @@ static void data_from_gpu_stack_list(ListBase *sockets, bNodeStack **ns, GPUNode bNode *nodeGetActiveTexture(bNodeTree *ntree) { /* this is the node we texture paint and draw in textured draw */ - bNode *node, *tnode; + bNode *node, *tnode, *inactivenode = NULL; if (!ntree) return NULL; - for (node = ntree->nodes.first; node; node = node->next) + for (node = ntree->nodes.first; node; node = node->next) { if (node->flag & NODE_ACTIVE_TEXTURE) return node; + else if (!inactivenode && node->typeinfo->nclass == NODE_CLASS_TEXTURE) + inactivenode = node; + } /* node active texture node in this tree, look inside groups */ for (node = ntree->nodes.first; node; node = node->next) { if (node->type == NODE_GROUP) { tnode = nodeGetActiveTexture((bNodeTree *)node->id); - if (tnode) + if (tnode && ((tnode->flag & NODE_ACTIVE_TEXTURE) || !inactivenode)) return tnode; } } - return NULL; + return inactivenode; } void ntreeExecGPUNodes(bNodeTreeExec *exec, GPUMaterial *mat, int do_outputs) diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c index 3bdc3813fd7..fd864f1c7c6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c @@ -30,11 +30,12 @@ /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = { - { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, - { SOCK_FLOAT, 1, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, - { SOCK_VECTOR, 1, N_("Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f}, - //{ SOCK_FLOAT, 1, N_("IOR"), 1.3f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f}, - { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f}, + { SOCK_VECTOR, 1, N_("Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f}, + { SOCK_FLOAT, 1, N_("Sharpness"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_FLOAT, 1, N_("Texture Blur"), 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, PROP_FACTOR}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; @@ -43,6 +44,20 @@ static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = { { -1, 0, "" } }; +static void node_shader_init_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) +{ + /*bNodeSocket *sock;*/ + + node->custom1 = SHD_SUBSURFACE_CUBIC; + + /*for (sock = node->inputs.first; sock; sock = sock->next) { + if (strcmp(sock->name, "Sharpness") == 0) { + bNodeSocketValueFloat *dval = sock->default_value; + dval->value = 0.0f; + } + }*/ +} + static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) { if (!in[1].link) @@ -51,6 +66,22 @@ static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED return GPU_stack_link(mat, "node_subsurface_scattering", in, out); } +static void node_shader_update_subsurface_scattering(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sock; + int falloff = node->custom1; + + for (sock = node->inputs.first; sock; sock = sock->next) { + if (strcmp(sock->name, "Sharpness") == 0) { + if (falloff == SHD_SUBSURFACE_CUBIC) + sock->flag &= ~SOCK_UNAVAIL; + else + sock->flag |= SOCK_UNAVAIL; + + } + } +} + /* node type definition */ void register_node_type_sh_subsurface_scattering(void) { @@ -60,9 +91,10 @@ void register_node_type_sh_subsurface_scattering(void) node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_subsurface_scattering_in, sh_node_subsurface_scattering_out); node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); - node_type_init(&ntype, NULL); + node_type_init(&ntype, node_shader_init_subsurface_scattering); node_type_storage(&ntype, "", NULL, NULL); node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering); + node_type_update(&ntype, node_shader_update_subsurface_scattering, NULL); nodeRegisterType(&ntype); } diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c index f9cd4b72912..c80b5282de3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_sky.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_sky.c @@ -48,6 +48,8 @@ static void node_shader_init_tex_sky(bNodeTree *UNUSED(ntree), bNode *node) tex->sun_direction[1] = 0.0f; tex->sun_direction[2] = 1.0f; tex->turbidity = 2.2f; + tex->ground_albedo = 0.3f; + tex->sky_model = SHD_SKY_NEW; node->storage = tex; } @@ -70,6 +72,7 @@ void register_node_type_sh_tex_sky(void) sh_node_type_base(&ntype, SH_NODE_TEX_SKY, "Sky Texture", NODE_CLASS_TEXTURE, 0); node_type_compatibility(&ntype, NODE_NEW_SHADING); node_type_socket_templates(&ntype, sh_node_tex_sky_in, sh_node_tex_sky_out); + node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); node_type_init(&ntype, node_shader_init_tex_sky); node_type_storage(&ntype, "NodeTexSky", node_free_standard_storage, node_copy_standard_storage); node_type_gpu(&ntype, node_shader_gpu_tex_sky); diff --git a/source/blender/python/bmesh/bmesh_py_ops_call.c b/source/blender/python/bmesh/bmesh_py_ops_call.c index 6c7fc686cc0..ec9f2865582 100644 --- a/source/blender/python/bmesh/bmesh_py_ops_call.c +++ b/source/blender/python/bmesh/bmesh_py_ops_call.c @@ -581,11 +581,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) item = PyDict_New(); if (slot_hash) { GHASH_ITER (hash_iter, slot_hash) { - BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); - BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + void *ele_val = BLI_ghashIterator_getValue(&hash_iter); - PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); - PyObject *py_val = BPy_BMElem_CreatePyObject(bm, *(void **)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); + PyObject *py_val = BPy_BMElem_CreatePyObject(bm, ele_val); PyDict_SetItem(item, py_key, py_val); Py_DECREF(py_key); @@ -599,11 +599,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) item = PyDict_New(); if (slot_hash) { GHASH_ITER (hash_iter, slot_hash) { - BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); - BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + void *ele_val = BLI_ghashIterator_getValue(&hash_iter); PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); - PyObject *py_val = PyFloat_FromDouble(*(float *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + PyObject *py_val = PyFloat_FromDouble(*(float *)&ele_val); PyDict_SetItem(item, py_key, py_val); Py_DECREF(py_key); @@ -617,11 +617,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) item = PyDict_New(); if (slot_hash) { GHASH_ITER (hash_iter, slot_hash) { - BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); - BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + void *ele_val = BLI_ghashIterator_getValue(&hash_iter); PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); - PyObject *py_val = PyLong_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + PyObject *py_val = PyLong_FromLong(*(int *)&ele_val); PyDict_SetItem(item, py_key, py_val); Py_DECREF(py_key); @@ -635,11 +635,11 @@ static PyObject *bpy_slot_to_py(BMesh *bm, BMOpSlot *slot) item = PyDict_New(); if (slot_hash) { GHASH_ITER (hash_iter, slot_hash) { - BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); - BMOElemMapping *ele_val = BLI_ghashIterator_getValue(&hash_iter); + BMHeader *ele_key = BLI_ghashIterator_getKey(&hash_iter); + void *ele_val = BLI_ghashIterator_getValue(&hash_iter); PyObject *py_key = BPy_BMElem_CreatePyObject(bm, ele_key); - PyObject *py_val = PyBool_FromLong(*(int *)BMO_OP_SLOT_MAPPING_DATA(ele_val)); + PyObject *py_val = PyBool_FromLong(*(int *)&ele_val); PyDict_SetItem(item, py_key, py_val); Py_DECREF(py_key); diff --git a/source/blender/python/bmesh/bmesh_py_types.c b/source/blender/python/bmesh/bmesh_py_types.c index 0e2fbe8a526..92fb506497f 100644 --- a/source/blender/python/bmesh/bmesh_py_types.c +++ b/source/blender/python/bmesh/bmesh_py_types.c @@ -122,12 +122,12 @@ static int bpy_bm_elem_hflag_set(BPy_BMElem *self, PyObject *value, void *flag) param = PyLong_AsLong(value); - if (param == true) { - BM_elem_flag_enable(self->ele, hflag); - return 0; - } - else if (param == false) { - BM_elem_flag_disable(self->ele, hflag); + if ((unsigned int)param <= 1) { + if (hflag == BM_ELEM_SELECT) + BM_elem_select_set(self->bm, self->ele, param); + else + BM_elem_flag_set(self->ele, hflag, param); + return 0; } else { @@ -1047,6 +1047,8 @@ static PyObject *bpy_bmesh_from_mesh(BPy_BMesh *self, PyObject *args, PyObject * int use_shape_key = false; int shape_key_index = 0; + BPY_BM_CHECK_OBJ(self); + if (!PyArg_ParseTupleAndKeywords(args, kw, "O|iii:from_mesh", (char **)kwlist, &py_mesh, &use_fnorm, &use_shape_key, &shape_key_index) || !(me = PyC_RNA_AsPointer(py_mesh, "Mesh"))) @@ -1871,7 +1873,7 @@ static PyObject *bpy_bmvertseq_new(BPy_BMElemSeq *self, PyObject *args) return NULL; } - v = BM_vert_create(bm, co, NULL, 0); + v = BM_vert_create(bm, co, NULL, BM_CREATE_NOP); if (v == NULL) { PyErr_SetString(PyExc_ValueError, @@ -1940,7 +1942,7 @@ static PyObject *bpy_bmedgeseq_new(BPy_BMElemSeq *self, PyObject *args) goto cleanup; } - e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, 0); + e = BM_edge_create(bm, vert_array[0], vert_array[1], NULL, BM_CREATE_NOP); if (e == NULL) { PyErr_SetString(PyExc_ValueError, @@ -2020,7 +2022,8 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) /* Go ahead and make the face! * --------------------------- */ - f_new = BM_face_create_ngon_verts(bm, vert_array, vert_seq_len, 0, false, true); + f_new = BM_face_create_verts(bm, vert_array, vert_seq_len, + py_face_example ? py_face_example->f : NULL, BM_CREATE_NOP, true); if (UNLIKELY(f_new == NULL)) { PyErr_SetString(PyExc_ValueError, @@ -2028,10 +2031,6 @@ static PyObject *bpy_bmfaceseq_new(BPy_BMElemSeq *self, PyObject *args) goto cleanup; } - if (py_face_example) { - BM_elem_attrs_copy(py_face_example->bm, bm, py_face_example->f, f_new); - } - ret = BPy_BMFace_CreatePyObject(bm, f_new); /* pass through */ @@ -2921,7 +2920,8 @@ static void bpy_bmvert_dealloc(BPy_BMElem *self) BMesh *bm = self->bm; if (bm) { void **ptr = CustomData_bmesh_get(&bm->vdata, self->ele->head.data, CD_BM_ELEM_PYPTR); - *ptr = NULL; + if (ptr) + *ptr = NULL; } PyObject_DEL(self); } @@ -2931,7 +2931,8 @@ static void bpy_bmedge_dealloc(BPy_BMElem *self) BMesh *bm = self->bm; if (bm) { void **ptr = CustomData_bmesh_get(&bm->edata, self->ele->head.data, CD_BM_ELEM_PYPTR); - *ptr = NULL; + if (ptr) + *ptr = NULL; } PyObject_DEL(self); } @@ -2941,7 +2942,8 @@ static void bpy_bmface_dealloc(BPy_BMElem *self) BMesh *bm = self->bm; if (bm) { void **ptr = CustomData_bmesh_get(&bm->pdata, self->ele->head.data, CD_BM_ELEM_PYPTR); - *ptr = NULL; + if (ptr) + *ptr = NULL; } PyObject_DEL(self); } @@ -2951,7 +2953,8 @@ static void bpy_bmloop_dealloc(BPy_BMElem *self) BMesh *bm = self->bm; if (bm) { void **ptr = CustomData_bmesh_get(&bm->ldata, self->ele->head.data, CD_BM_ELEM_PYPTR); - *ptr = NULL; + if (ptr) + *ptr = NULL; } PyObject_DEL(self); } diff --git a/source/blender/python/bmesh/bmesh_py_types_customdata.c b/source/blender/python/bmesh/bmesh_py_types_customdata.c index b0604fa2dbc..30902c615a1 100644 --- a/source/blender/python/bmesh/bmesh_py_types_customdata.c +++ b/source/blender/python/bmesh/bmesh_py_types_customdata.c @@ -32,6 +32,7 @@ #include <Python.h> +#include "BLI_utildefines.h" #include "BLI_string.h" #include "BLI_math_vector.h" diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c index 90a0444ceae..959e4a788dd 100644 --- a/source/blender/python/intern/bpy_app_handlers.c +++ b/source/blender/python/intern/bpy_app_handlers.c @@ -57,6 +57,8 @@ static PyStructSequence_Field app_cb_info_fields[] = { {(char *)"save_post", (char *)"Callback list - on saving a blend file (after)"}, {(char *)"scene_update_pre", (char *)"Callback list - on updating the scenes data (before)"}, {(char *)"scene_update_post", (char *)"Callback list - on updating the scenes data (after)"}, + {(char *)"game_pre", (char *)"Callback list - on starting the game engine"}, + {(char *)"game_post", (char *)"Callback list - on ending the game engine"}, /* sets the permanent tag */ # define APP_CB_OTHER_FIELDS 1 diff --git a/source/blender/python/intern/bpy_interface.c b/source/blender/python/intern/bpy_interface.c index feffea20553..dc1f5828c15 100644 --- a/source/blender/python/intern/bpy_interface.c +++ b/source/blender/python/intern/bpy_interface.c @@ -821,8 +821,12 @@ int BPY_context_member_get(bContext *C, const char *member, bContextDataResult * } if (done == false) { - if (item) printf("PyContext '%s' not a valid type\n", member); - else printf("PyContext '%s' not found\n", member); + if (item) { + printf("PyContext '%s' not a valid type\n", member); + } + else { + printf("PyContext '%s' not found\n", member); + } } else { if (G.debug & G_DEBUG_PYTHON) { diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 3cd030e9b08..29f2d308367 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -6875,7 +6875,7 @@ int pyrna_deferred_register_class(StructRNA *srna, PyTypeObject *py_class) /*-------------------- Type Registration ------------------------*/ -static int rna_function_arg_count(FunctionRNA *func) +static int rna_function_arg_count(FunctionRNA *func, int *min_count) { const ListBase *lb = RNA_function_defined_parameters(func); PropertyRNA *parm; @@ -6883,13 +6883,23 @@ static int rna_function_arg_count(FunctionRNA *func) int flag = RNA_function_flag(func); int is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); int count = is_staticmethod ? 0 : 1; + bool done_min_count = false; for (link = lb->first; link; link = link->next) { parm = (PropertyRNA *)link; - if (!(RNA_property_flag(parm) & PROP_OUTPUT)) + if (!(RNA_property_flag(parm) & PROP_OUTPUT)) { + if (!done_min_count && (RNA_property_flag(parm) & PROP_PYFUNC_OPTIONAL)) { + /* From now on, following parameters are optional in py func */ + if (min_count) + *min_count = count; + done_min_count = true; + } count++; + } } + if (!done_min_count && min_count) + *min_count = count; return count; } @@ -6904,7 +6914,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v PyObject *py_class = (PyObject *)py_data; PyObject *base_class = RNA_struct_py_type_get(srna); PyObject *item; - int i, flag, is_staticmethod, arg_count, func_arg_count; + int i, flag, is_staticmethod, arg_count, func_arg_count, func_arg_min_count = 0; const char *py_class_name = ((PyTypeObject *)py_class)->tp_name; /* __name__ */ if (srna_base) { @@ -6968,7 +6978,7 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v } } - func_arg_count = rna_function_arg_count(func); + func_arg_count = rna_function_arg_count(func, &func_arg_min_count); if (func_arg_count >= 0) { /* -1 if we don't care*/ arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; @@ -6976,14 +6986,25 @@ static int bpy_class_validate_recursive(PointerRNA *dummyptr, StructRNA *srna, v /* note, the number of args we check for and the number of args we give to * @staticmethods are different (quirk of python), * this is why rna_function_arg_count() doesn't return the value -1*/ - if (is_staticmethod) + if (is_staticmethod) { func_arg_count++; + func_arg_min_count++; + } - if (arg_count != func_arg_count) { - PyErr_Format(PyExc_ValueError, - "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", - class_type, py_class_name, RNA_function_identifier(func), - func_arg_count, arg_count); + if (arg_count < func_arg_min_count || arg_count > func_arg_count) { + if (func_arg_min_count != func_arg_count) { + PyErr_Format(PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have between %d and %d " + "args, found %d", + class_type, py_class_name, RNA_function_identifier(func), + func_arg_count, func_arg_min_count, arg_count); + } + else { + PyErr_Format(PyExc_ValueError, + "expected %.200s, %.200s class \"%.200s\" function to have %d args, found %d", + class_type, py_class_name, RNA_function_identifier(func), + func_arg_count, arg_count); + } return -1; } } @@ -7063,7 +7084,7 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param PropertyRNA *parm; ParameterIterator iter; PointerRNA funcptr; - int err = 0, i, ret_len = 0; + int err = 0, i, ret_len = 0, arg_count; int flag = RNA_function_flag(func); const char is_staticmethod = (flag & FUNC_NO_SELF) && !(flag & FUNC_USE_SELF_TYPE); const char is_classmethod = (flag & FUNC_NO_SELF) && (flag & FUNC_USE_SELF_TYPE); @@ -7198,7 +7219,15 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param if (item) { RNA_pointer_create(NULL, &RNA_Function, func, &funcptr); - args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ + if (is_staticmethod) { + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(((PyMethodObject *)item)->im_func))->co_argcount - 1; + } + else { + arg_count = ((PyCodeObject *)PyFunction_GET_CODE(item))->co_argcount; + } +// args = PyTuple_New(rna_function_arg_count(func)); /* first arg is included in 'item' */ + args = PyTuple_New(arg_count); /* first arg is included in 'item' */ + if (is_staticmethod) { i = 0; @@ -7230,9 +7259,11 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param continue; } - parmitem = pyrna_param_to_py(&funcptr, parm, iter.data); - PyTuple_SET_ITEM(args, i, parmitem); - i++; + if (i < arg_count) { + parmitem = pyrna_param_to_py(&funcptr, parm, iter.data); + PyTuple_SET_ITEM(args, i, parmitem); + i++; + } } #ifdef USE_PEDANTIC_WRITE diff --git a/source/blender/python/intern/bpy_rna_anim.c b/source/blender/python/intern/bpy_rna_anim.c index 6e78a543481..e473af9fac8 100644 --- a/source/blender/python/intern/bpy_rna_anim.c +++ b/source/blender/python/intern/bpy_rna_anim.c @@ -312,7 +312,8 @@ PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args) BKE_reports_init(&reports, RPT_STORE); - result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON); + result = ANIM_add_driver(&reports, (ID *)self->ptr.id.data, path_full, index, + CREATEDRIVER_WITH_FMODIFIER, DRIVER_TYPE_PYTHON); if (BPy_reports_to_error(&reports, PyExc_RuntimeError, true) == -1) return NULL; diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index d44bce502ca..19ffc7f06ef 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -1165,7 +1165,7 @@ static PyObject *Vector_lerp(VectorObject *self, PyObject *args) PyDoc_STRVAR(Vector_rotate_doc, ".. function:: rotate(other)\n" "\n" -" Return vector by a rotation value.\n" +" Rotate the vector by a rotation value.\n" "\n" " :arg other: rotation component of mathutils value\n" " :type other: :class:`Euler`, :class:`Quaternion` or :class:`Matrix`\n" diff --git a/source/blender/python/mathutils/mathutils_geometry.c b/source/blender/python/mathutils/mathutils_geometry.c index 8509c46b395..b69e3eb23f8 100644 --- a/source/blender/python/mathutils/mathutils_geometry.c +++ b/source/blender/python/mathutils/mathutils_geometry.c @@ -568,22 +568,19 @@ PyDoc_STRVAR(M_Geometry_intersect_line_plane_doc, " :type plane_co: :class:`mathutils.Vector`\n" " :arg plane_no: The direction the plane is facing\n" " :type plane_no: :class:`mathutils.Vector`\n" -" :arg no_flip: Always return an intersection on the directon defined bt line_a -> line_b\n" -" :type no_flip: :boolean\n" " :return: The point of intersection or None when not found\n" " :rtype: :class:`mathutils.Vector` or None\n" ); static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObject *args) { VectorObject *line_a, *line_b, *plane_co, *plane_no; - int no_flip = 0; float isect[3]; + if (!PyArg_ParseTuple(args, "O!O!O!O!|i:intersect_line_plane", &vector_Type, &line_a, &vector_Type, &line_b, &vector_Type, &plane_co, - &vector_Type, &plane_no, - &no_flip)) + &vector_Type, &plane_no)) { return NULL; } @@ -603,7 +600,7 @@ static PyObject *M_Geometry_intersect_line_plane(PyObject *UNUSED(self), PyObjec return NULL; } - if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec, no_flip) == 1) { + if (isect_line_plane_v3(isect, line_a->vec, line_b->vec, plane_co->vec, plane_no->vec) == 1) { return Vector_CreatePyObject(isect, 3, Py_NEW, NULL); } else { @@ -980,24 +977,35 @@ PyDoc_STRVAR(M_Geometry_distance_point_to_plane_doc, ); static PyObject *M_Geometry_distance_point_to_plane(PyObject *UNUSED(self), PyObject *args) { - VectorObject *pt, *plene_co, *plane_no; + VectorObject *pt, *plane_co, *plane_no; + float plane[4]; if (!PyArg_ParseTuple(args, "O!O!O!:distance_point_to_plane", &vector_Type, &pt, - &vector_Type, &plene_co, + &vector_Type, &plane_co, &vector_Type, &plane_no)) { return NULL; } + if (pt->size != 3 || + plane_co->size != 3 || + plane_no->size != 3) + { + PyErr_SetString(PyExc_ValueError, + "One of more of the vector arguments wasn't a 3D vector"); + return NULL; + } + if (BaseMath_ReadCallback(pt) == -1 || - BaseMath_ReadCallback(plene_co) == -1 || + BaseMath_ReadCallback(plane_co) == -1 || BaseMath_ReadCallback(plane_no) == -1) { return NULL; } - return PyFloat_FromDouble(dist_to_plane_v3(pt->vec, plene_co->vec, plane_no->vec)); + plane_from_point_normal_v3(plane, plane_co->vec, plane_no->vec); + return PyFloat_FromDouble(dist_to_plane_v3(pt->vec, plane)); } PyDoc_STRVAR(M_Geometry_barycentric_transform_doc, @@ -1054,6 +1062,17 @@ static PyObject *M_Geometry_barycentric_transform(PyObject *UNUSED(self), PyObje return NULL; } + if (BaseMath_ReadCallback(vec_pt) == -1 || + BaseMath_ReadCallback(vec_t1_src) == -1 || + BaseMath_ReadCallback(vec_t2_src) == -1 || + BaseMath_ReadCallback(vec_t3_src) == -1 || + BaseMath_ReadCallback(vec_t1_tar) == -1 || + BaseMath_ReadCallback(vec_t2_tar) == -1 || + BaseMath_ReadCallback(vec_t3_tar) == -1) + { + return NULL; + } + barycentric_transform(vec, vec_pt->vec, vec_t1_tar->vec, vec_t2_tar->vec, vec_t3_tar->vec, vec_t1_src->vec, vec_t2_src->vec, vec_t3_src->vec); @@ -1099,7 +1118,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a /* python */ PyObject *py_verts = PyList_New(0); - PyObject *py_plene_index = PyList_New(0); + PyObject *py_plane_index = PyList_New(0); memset(planes_used, 0, sizeof(char) * len); @@ -1151,7 +1170,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a for (i = 0; i < len; i++) { if (planes_used[i]) { PyObject *item = PyLong_FromLong(i); - PyList_Append(py_plene_index, item); + PyList_Append(py_plane_index, item); Py_DECREF(item); } } @@ -1160,7 +1179,7 @@ static PyObject *M_Geometry_points_in_planes(PyObject *UNUSED(self), PyObject *a { PyObject *ret = PyTuple_New(2); PyTuple_SET_ITEM(ret, 0, py_verts); - PyTuple_SET_ITEM(ret, 1, py_plene_index); + PyTuple_SET_ITEM(ret, 1, py_plane_index); return ret; } } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index ab888ba198b..a0104a30d0e 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -1741,7 +1741,7 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem } if (path_nbr == 0) - psys->lattice = psys_get_lattice(&sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* 3. start creating renderable things */ for (a=0, pa=pars; a<totpart+totchild; a++, pa++, seed++) { @@ -2094,9 +2094,9 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem psys->flag &= ~PSYS_DRAWING; - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice= NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } if (path_nbr && (ma->mode_l & MA_TANGENT_STR)==0) @@ -3279,7 +3279,7 @@ static EdgeHash *make_freestyle_edge_mark_hash(Mesh *me, DerivedMesh *dm) index = dm->getEdgeDataArray(dm, CD_ORIGINDEX); fed = CustomData_get_layer(&me->edata, CD_FREESTYLE_EDGE); if (fed) { - edge_hash = BLI_edgehash_new(); + edge_hash = BLI_edgehash_new(__func__); if (!index) { if (me->totedge == totedge) { for (a = 0; a < me->totedge; a++) { diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 899c9b335be..8ac69b101f4 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -630,6 +630,22 @@ void RE_InitState(Render *re, Render *source, RenderData *rd, SceneRenderLayer * RE_init_threadcount(re); } +/* update some variables that can be animated, and otherwise wouldn't be due to + * RenderData getting copied once at the start of animation render */ +static void render_update_anim_renderdata(Render *re, RenderData *rd) +{ + /* filter */ + re->r.gauss = rd->gauss; + + /* motion blur */ + re->r.mblur_samples = rd->mblur_samples; + re->r.blurfac = rd->blurfac; + + /* freestyle */ + re->r.line_thickness_mode = rd->line_thickness_mode; + re->r.unit_line_thickness = rd->unit_line_thickness; +} + void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) { /* re->ok flag? */ @@ -1697,12 +1713,17 @@ static void composite_freestyle_renders(Render *re, int sample) for (srl= (SceneRenderLayer *)re->r.layers.first; srl; srl= srl->next) { if ((re->r.scemode & R_SINGLE_LAYER) && srl != actsrl) continue; + if (FRS_is_freestyle_enabled(srl)) { freestyle_render = (Render *)link->data; - render_result_exr_file_read(freestyle_render, sample); - FRS_composite_result(re, srl, freestyle_render); - RE_FreeRenderResult(freestyle_render->result); - freestyle_render->result = NULL; + + /* may be NULL in case of empty render layer */ + if (freestyle_render) { + render_result_exr_file_read(freestyle_render, sample); + FRS_composite_result(re, srl, freestyle_render); + RE_FreeRenderResult(freestyle_render->result); + freestyle_render->result = NULL; + } } link = link->next; } @@ -1717,8 +1738,9 @@ static void free_all_freestyle_renders(void) for (re1= RenderGlobal.renderlist.first; re1; re1= re1->next) { for (link = (LinkData *)re1->freestyle_renders.first; link; link = link->next) { - if (link->data) { - freestyle_render = (Render *)link->data; + freestyle_render = (Render *)link->data; + + if (freestyle_render) { freestyle_scene = freestyle_render->scene; RE_FreeRender(freestyle_render); BKE_scene_unlink(&re1->freestyle_bmain, freestyle_scene, NULL); @@ -1752,6 +1774,7 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) rectf = MEM_mapallocN(re->rectx * re->recty * sizeof(float) * 4, "fullsample rgba"); for (sample = 0; sample < re->r.osa; sample++) { + Scene *sce; Render *re1; RenderResult rres; int mask; @@ -1763,9 +1786,11 @@ static void do_merge_fullsample(Render *re, bNodeTree *ntree) /* also function below assumes this */ tag_scenes_for_render(re); - for (re1 = RenderGlobal.renderlist.first; re1; re1 = re1->next) { - if (re1->scene->id.flag & LIB_DOIT) { - if (re1->r.scemode & R_FULL_SAMPLE) { + for (sce = re->main->scene.first; sce; sce = sce->id.next) { + if (sce->id.flag & LIB_DOIT) { + re1 = RE_GetRender(sce->id.name); + + if (re1 && (re1->r.scemode & R_FULL_SAMPLE)) { if (sample) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_read(re1, sample); @@ -2399,6 +2424,7 @@ static int render_initialize_from_main(Render *re, Main *bmain, Scene *scene, Sc /* not too nice, but it survives anim-border render */ if (anim) { + render_update_anim_renderdata(re, &scene->r); re->disprect = disprect; return 1; } @@ -2516,7 +2542,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie } - IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &scene->r.im_format); ok = mh->append_movie(&re->r, scene->r.sfra, scene->r.cfra, (int *) ibuf->rect, @@ -2547,7 +2573,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie else { ImBuf *ibuf = render_result_rect_to_ibuf(&rres, &scene->r); - IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &scene->r.im_format); ok = BKE_imbuf_write_stamp(scene, camera, ibuf, name, &scene->r.im_format); @@ -2567,7 +2593,7 @@ static int do_write_image_or_movie(Render *re, Main *bmain, Scene *scene, bMovie BKE_add_image_extension(name, &imf); ibuf->planes = 24; - IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf); BKE_imbuf_write_stamp(scene, camera, ibuf, name, &imf); @@ -2909,7 +2935,7 @@ int RE_WriteEnvmapResult(struct ReportList *reports, Scene *scene, EnvMap *env, return 0; } - IMB_colormanagement_imbuf_for_write(ibuf, TRUE, FALSE, &scene->view_settings, &scene->display_settings, &imf); + IMB_colormanagement_imbuf_for_write(ibuf, true, false, &scene->view_settings, &scene->display_settings, &imf); /* to save, we first get absolute path */ BLI_strncpy(filepath, relpath, sizeof(filepath)); diff --git a/source/blender/render/intern/source/pointdensity.c b/source/blender/render/intern/source/pointdensity.c index d4d6bfa5b7f..ce87888b6a0 100644 --- a/source/blender/render/intern/source/pointdensity.c +++ b/source/blender/render/intern/source/pointdensity.c @@ -140,7 +140,7 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa invert_m4_m4(ob->imat, ob->obmat); total_particles = psys->totpart+psys->totchild; - psys->lattice=psys_get_lattice(&sim); + psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); alloc_point_data(pd, total_particles, data_used); @@ -215,9 +215,9 @@ static void pointdensity_cache_psys(Render *re, PointDensity *pd, Object *ob, Pa BLI_bvhtree_balance(pd->point_tree); dm->release(dm); - if (psys->lattice) { - end_latt_deform(psys->lattice); - psys->lattice = NULL; + if (psys->lattice_deform_data) { + end_latt_deform(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; } psys_render_restore(ob, psys); diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 7ae64d499fa..838f73b5e83 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -734,6 +734,15 @@ static void traceray(ShadeInput *origshi, ShadeResult *origshr, short depth, con ShadeInput shi = {NULL}; Isect isec; float dist_mir = origshi->mat->dist_mir; + + /* with high depth the number of rays can explode due to the path splitting + * in two each time, giving 2^depth rays. we need to be able to cancel such + * a render to avoid hanging, a better solution would be random picking + * between directions and russian roulette termination */ + if(R.test_break(R.tbh)) { + zero_v4(col); + return; + } copy_v3_v3(isec.start, start); copy_v3_v3(isec.dir, dir); diff --git a/source/blender/render/intern/source/render_result.c b/source/blender/render/intern/source/render_result.c index 1f740e3f483..37587d89ce0 100644 --- a/source/blender/render/intern/source/render_result.c +++ b/source/blender/render/intern/source/render_result.c @@ -1191,7 +1191,7 @@ void render_result_rect_get_pixels(RenderResult *rr, unsigned int *rect, int rec } else if (rr->rectf) { IMB_display_buffer_transform_apply((unsigned char *) rect, rr->rectf, rr->rectx, rr->recty, 4, - view_settings, display_settings, TRUE); + view_settings, display_settings, true); } else /* else fill with black */ diff --git a/source/blender/render/intern/source/rendercore.c b/source/blender/render/intern/source/rendercore.c index fa3cf1cef87..982e9b1a410 100644 --- a/source/blender/render/intern/source/rendercore.c +++ b/source/blender/render/intern/source/rendercore.c @@ -1957,36 +1957,38 @@ void add_halo_flare(Render *re) RenderResult *rr= re->result; RenderLayer *rl; HaloRen *har; - int a, mode, do_draw = FALSE; + int a, mode; /* for now, we get the first renderlayer in list with halos set */ - for (rl= rr->layers.first; rl; rl= rl->next) - if (rl->layflag & SCE_LAY_HALO) - break; - - if (rl==NULL || rl->rectf==NULL) - return; - - mode= R.r.mode; - R.r.mode &= ~R_PANORAMA; - - project_renderdata(&R, projectverto, 0, 0, 0); - - for (a=0; a<R.tothalo; a++) { - har= R.sortedhalos[a]; + for (rl= rr->layers.first; rl; rl= rl->next) { + int do_draw = FALSE; + + if ((rl->layflag & SCE_LAY_HALO) == 0) + continue; + if (rl->rectf==NULL) + continue; - if (har->flarec) { - do_draw = TRUE; - renderflare(rr, rl->rectf, har); + mode= R.r.mode; + R.r.mode &= ~R_PANORAMA; + + project_renderdata(&R, projectverto, 0, 0, 0); + + for (a=0; a<R.tothalo; a++) { + har= R.sortedhalos[a]; + + if (har->flarec && (har->lay & rl->lay)) { + do_draw = TRUE; + renderflare(rr, rl->rectf, har); + } + } + + if (do_draw) { + /* weak... the display callback wants an active renderlayer pointer... */ + rr->renlay= rl; + re->display_draw(re->ddh, rr, NULL); } - } - if (do_draw) { - /* weak... the display callback wants an active renderlayer pointer... */ - rr->renlay= rl; - re->display_draw(re->ddh, rr, NULL); + R.r.mode= mode; } - - R.r.mode= mode; } diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 178d304eca2..114961394c4 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1191,8 +1191,8 @@ float lamp_get_visibility(LampRen *lar, const float co[3], float lv[3], float *d float visifac= 1.0f, t; sub_v3_v3v3(lv, co, lar->co); - *dist= sqrtf(dot_v3v3(lv, lv)); - t= 1.0f/dist[0]; + *dist = len_v3(lv); + t = 1.0f / (*dist); mul_v3_fl(lv, t); /* area type has no quad or sphere option */ diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index d65db9d47f8..a8ccd1f362f 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -911,7 +911,7 @@ void hoco_to_zco(ZSpan *zspan, float zco[3], const float hoco[4]) void zbufclipwire(ZSpan *zspan, int obi, int zvlnr, int ec, const float ho1[4], const float ho2[4], const float ho3[4], const float ho4[4], - int c1, int c2, int c3, int c4) + const int c1, const int c2, const int c3, const int c4) { float vez[20]; int and, or; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 8894be111e7..4480b8ab158 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -40,6 +40,7 @@ /* dna-savable wmStructs here */ #include "DNA_windowmanager_types.h" #include "WM_keymap.h" +#include "BLI_compiler_attrs.h" #ifdef __cplusplus extern "C" { @@ -76,17 +77,9 @@ void WM_init_native_pixels(bool do_it); void WM_init (struct bContext *C, int argc, const char **argv); void WM_exit_ext (struct bContext *C, const short do_python); -void WM_exit (struct bContext *C) -#if defined(__GNUC__) || defined(__clang__) -__attribute__((noreturn)) -#endif -; +void WM_exit (struct bContext *C) ATTR_NORETURN; -void WM_main (struct bContext *C) -#if defined(__GNUC__) || defined(__clang__) -__attribute__((noreturn)) -#endif -; +void WM_main (struct bContext *C) ATTR_NORETURN; bool WM_init_game (struct bContext *C); void WM_init_splash (struct bContext *C); @@ -151,9 +144,9 @@ struct wmEventHandler *WM_event_add_keymap_handler_priority(ListBase *handlers, void WM_event_remove_keymap_handler(ListBase *handlers, wmKeyMap *keymap); struct wmEventHandler *WM_event_add_ui_handler( - const struct bContext *C, ListBase *handlers, - int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata), - void (*remove)(struct bContext *C, void *userdata), void *userdata); + const struct bContext *C, ListBase *handlers, + int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata), + void (*remove)(struct bContext *C, void *userdata), void *userdata); void WM_event_remove_ui_handler(ListBase *handlers, int (*func)(struct bContext *C, const struct wmEvent *event, void *userdata), @@ -180,11 +173,7 @@ void WM_main_remove_notifier_reference(const void *reference); /* reports */ void WM_report(const struct bContext *C, ReportType type, const char *message); -void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...) -#ifdef __GNUC__ -__attribute__ ((format(printf, 3, 4))) -#endif -; +void WM_reportf(const struct bContext *C, ReportType type, const char *format, ...) ATTR_PRINTF_FORMAT(3, 4); void wm_event_add(struct wmWindow *win, const struct wmEvent *event_to_add); void wm_event_init_from_window(struct wmWindow *win, struct wmEvent *event); @@ -386,6 +375,7 @@ struct wmJob *WM_jobs_get(struct wmWindowManager *wm, struct wmWindow *win, void int WM_jobs_test(struct wmWindowManager *wm, void *owner, int job_type); float WM_jobs_progress(struct wmWindowManager *wm, void *owner); char *WM_jobs_name(struct wmWindowManager *wm, void *owner); +void *WM_jobs_customdata(struct wmWindowManager *wm, void *owner); int WM_jobs_is_running(struct wmJob *); void *WM_jobs_customdata_get(struct wmJob *); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index f1932c8aa97..e6b6df11d7d 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -115,6 +115,7 @@ struct ImBuf; #include "RNA_types.h" #include "DNA_listBase.h" +#include "BLI_compiler_attrs.h" /* exported types for WM */ #include "wm_cursors.h" @@ -522,12 +523,8 @@ typedef struct wmOperatorType { * parameters may be provided through operator properties. cannot use * any interface code or input device state. * - see defines below for return values */ - int (*exec)(struct bContext *, struct wmOperator *) -#ifdef __GNUC__ - __attribute__((warn_unused_result)) -#endif - ; - + int (*exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT; + /* this callback executes on a running operator whenever as property * is changed. It can correct its own properties or report errors for * invalid settings in exceptional cases. @@ -538,25 +535,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 *, const struct wmEvent *) -#ifdef __GNUC__ - __attribute__((warn_unused_result)) -#endif - ; + int (*invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT; int (*cancel)(struct bContext *, struct wmOperator *); - int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) -#ifdef __GNUC__ - __attribute__((warn_unused_result)) -#endif - ; + int (*modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT; /* verify if the operator can be executed in the current context, note * that the operator might still fail to execute even if this return true */ - int (*poll)(struct bContext *) -#ifdef __GNUC__ - __attribute__((warn_unused_result)) -#endif - ; + int (*poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT; /* optional panel for redo and repeat, autogenerated if not set */ void (*ui)(struct bContext *, struct wmOperator *); @@ -580,11 +565,7 @@ typedef struct wmOperatorType { /* only used for operators defined with python * use to store pointers to python functions */ void *pyop_data; - int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) -#ifdef __GNUC__ - __attribute__((warn_unused_result)) -#endif - ; + int (*pyop_poll)(struct bContext *, struct wmOperatorType *ot) ATTR_WARN_UNUSED_RESULT; /* RNA integration */ ExtensionRNA ext; diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 89c0cde2e88..74c066d1d86 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -156,8 +156,7 @@ void WM_operator_stack_clear(wmWindowManager *wm) { wmOperator *op; - while ((op = wm->operators.first)) { - BLI_remlink(&wm->operators, op); + while ((op = BLI_pophead(&wm->operators))) { WM_operator_free(op); } @@ -226,7 +225,7 @@ void WM_uilisttype_freelink(uiListType *ult) /* called on initialize WM_init() */ void WM_uilisttype_init(void) { - uilisttypes_hash = BLI_ghash_str_new("uilisttypes_hash gh"); + uilisttypes_hash = BLI_ghash_str_new_ex("uilisttypes_hash gh", 16); } void WM_uilisttype_free(void) @@ -279,7 +278,8 @@ void WM_menutype_freelink(MenuType *mt) /* called on initialize WM_init() */ void WM_menutype_init(void) { - menutypes_hash = BLI_ghash_str_new("menutypes_hash gh"); + /* reserve size is set based on blender default setup */ + menutypes_hash = BLI_ghash_str_new_ex("menutypes_hash gh", 512); } void WM_menutype_free(void) @@ -413,20 +413,17 @@ void wm_close_and_free(bContext *C, wmWindowManager *wm) if (wm->autosavetimer) wm_autosave_timer_ended(wm); - while ((win = wm->windows.first)) { - BLI_remlink(&wm->windows, win); + while ((win = BLI_pophead(&wm->windows))) { win->screen = NULL; /* prevent draw clear to use screen */ wm_draw_window_clear(win); wm_window_free(C, wm, win); } - while ((op = wm->operators.first)) { - BLI_remlink(&wm->operators, op); + while ((op = BLI_pophead(&wm->operators))) { WM_operator_free(op); } - while ((keyconf = wm->keyconfigs.first)) { - BLI_remlink(&wm->keyconfigs, keyconf); + while ((keyconf = BLI_pophead(&wm->keyconfigs))) { WM_keyconfig_free(keyconf); } diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index 515f80b0ade..e76d38dd0e2 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -49,6 +49,7 @@ #include "WM_types.h" #include "WM_api.h" #include "wm_cursors.h" +#include "wm_window.h" /* XXX this still is mess from old code */ @@ -233,25 +234,32 @@ void WM_cursor_grab_disable(wmWindow *win, int mouse_ungrab_xy[2]) } } +static void wm_cursor_warp_relative(wmWindow *win, int x, int y) +{ + /* note: don't use wmEvent coords because of continuous grab [#36409] */ + int cx, cy; + wm_get_cursor_position(win, &cx, &cy); + WM_cursor_warp(win, cx + x, cy + y); +} + /* give it a modal keymap one day? */ int wm_cursor_arrow_move(wmWindow *win, wmEvent *event) { if (win && event->val == KM_PRESS) { - if (event->type == UPARROWKEY) { - WM_cursor_warp(win, event->x, event->y + 1); + wm_cursor_warp_relative(win, 0, 1); return 1; } else if (event->type == DOWNARROWKEY) { - WM_cursor_warp(win, event->x, event->y - 1); + wm_cursor_warp_relative(win, 0, -1); return 1; } else if (event->type == LEFTARROWKEY) { - WM_cursor_warp(win, event->x - 1, event->y); + wm_cursor_warp_relative(win, -1, 0); return 1; } else if (event->type == RIGHTARROWKEY) { - WM_cursor_warp(win, event->x + 1, event->y); + wm_cursor_warp_relative(win, 1, 0); return 1; } } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b4f193bdbe6..72cd794489b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -85,10 +85,11 @@ # include "RNA_enum_types.h" #endif +static void wm_notifier_clear(wmNotifier *note); static void update_tablet_data(wmWindow *win, wmEvent *event); static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, - short context, short poll_only); + const short context, const bool poll_only); /* ************ event management ************** */ @@ -126,8 +127,7 @@ void wm_event_free_all(wmWindow *win) { wmEvent *event; - while ((event = win->queue.first)) { - BLI_remlink(&win->queue, event); + while ((event = BLI_pophead(&win->queue))) { wm_event_free(event); } } @@ -218,19 +218,18 @@ void WM_main_remove_notifier_reference(const void *reference) note_next = note->next; if (note->reference == reference) { - BLI_remlink(&wm->queue, note); - MEM_freeN(note); + /* don't remove because this causes problems for #wm_event_do_notifiers + * which may be looping on the data (deleting screens) */ + wm_notifier_clear(note); } } } } -static wmNotifier *wm_notifier_next(wmWindowManager *wm) +static void wm_notifier_clear(wmNotifier *note) { - wmNotifier *note = wm->queue.first; - - if (note) BLI_remlink(&wm->queue, note); - return note; + /* NULL the entire notifier, only leaving (next, prev) members intact */ + memset(((char *)note) + sizeof(Link), 0, sizeof(*note) - sizeof(Link)); } /* called in mainloop */ @@ -308,7 +307,7 @@ void wm_event_do_notifiers(bContext *C) } /* the notifiers are sent without context, to keep it clean */ - while ( (note = wm_notifier_next(wm)) ) { + while ((note = BLI_pophead(&wm->queue))) { for (win = wm->windows.first; win; win = win->next) { /* filter out notifiers */ @@ -964,9 +963,8 @@ int WM_operator_last_properties_store(wmOperator *UNUSED(op)) #endif static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, - PointerRNA *properties, ReportList *reports, short poll_only) + PointerRNA *properties, ReportList *reports, const bool poll_only) { - wmWindowManager *wm = CTX_wm_manager(C); int retval = OPERATOR_PASS_THROUGH; /* this is done because complicated setup is done to call this function that is better not duplicated */ @@ -974,6 +972,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, return WM_operator_poll(C, ot); if (WM_operator_poll(C, ot)) { + wmWindowManager *wm = CTX_wm_manager(C); wmOperator *op = wm_operator_create(wm, ot, properties, reports); /* if reports == NULL, they'll be initialized */ const short is_nested_call = (wm->op_undo_depth != 0); @@ -1102,9 +1101,8 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, * * invokes operator in context */ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA *properties, ReportList *reports, - short context, short poll_only) + const short context, const bool poll_only) { - wmWindow *window = CTX_wm_window(C); wmEvent *event; int retval; @@ -1113,16 +1111,23 @@ static int wm_operator_call_internal(bContext *C, wmOperatorType *ot, PointerRNA /* dummie test */ if (ot && C) { + wmWindow *window = CTX_wm_window(C); + switch (context) { case WM_OP_INVOKE_DEFAULT: case WM_OP_INVOKE_REGION_WIN: case WM_OP_INVOKE_AREA: case WM_OP_INVOKE_SCREEN: /* window is needed for invoke, cancel operator */ - if (window == NULL) + if (window == NULL) { + if (poll_only) { + CTX_wm_operator_poll_msg_set(C, "missing 'window' in context"); + } return 0; - else + } + else { event = window->eventstate; + } break; default: event = NULL; @@ -1323,9 +1328,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) wmWindowManager *wm = CTX_wm_manager(C); /* C is zero on freeing database, modal handlers then already were freed */ - while ((handler = handlers->first)) { - BLI_remlink(handlers, handler); - + while ((handler = BLI_pophead(handlers))) { if (handler->op) { if (handler->op->type->cancel) { ScrArea *area = CTX_wm_area(C); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index f4b50667b2f..abda68d8b24 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -810,15 +810,14 @@ int write_crash_blend(void) } } -int wm_file_write(bContext *C, const char *target, int fileflags, ReportList *reports) +int wm_file_write(bContext *C, const char *filepath, int fileflags, ReportList *reports) { Library *li; int len; - char filepath[FILE_MAX]; int *thumb = NULL; ImBuf *ibuf_thumb = NULL; - len = strlen(target); + len = strlen(filepath); if (len == 0) { BKE_report(reports, RPT_ERROR, "Path is empty, cannot save"); @@ -830,9 +829,9 @@ int wm_file_write(bContext *C, const char *target, int fileflags, ReportList *re return -1; } - BLI_strncpy(filepath, target, FILE_MAX); - BLI_replace_extension(filepath, FILE_MAX, ".blend"); - /* don't use 'target' anymore */ + /* note: used to replace the file extension (to ensure '.blend'), + * no need to now because the operator ensures, + * its handy for scripts to save to a predefined name without blender editing it */ /* send the OnSave event */ for (li = G.main->library.first; li; li = li->id.next) { diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 63cf1eeb40d..4e9b849af40 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -51,6 +51,7 @@ #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" #include "BKE_blender.h" @@ -510,6 +511,8 @@ void WM_exit_ext(bContext *C, const short do_python) GHOST_DisposeSystemPaths(); + BLI_threadapi_exit(); + if (MEM_get_memory_blocks_in_use() != 0) { printf("Error: Not freed memory blocks: %d\n", MEM_get_memory_blocks_in_use()); MEM_printmemlist(); diff --git a/source/blender/windowmanager/intern/wm_jobs.c b/source/blender/windowmanager/intern/wm_jobs.c index c6e067dc2f9..188ad251b8a 100644 --- a/source/blender/windowmanager/intern/wm_jobs.c +++ b/source/blender/windowmanager/intern/wm_jobs.c @@ -255,6 +255,17 @@ char *WM_jobs_name(wmWindowManager *wm, void *owner) return NULL; } +void *WM_jobs_customdata(wmWindowManager *wm, void *owner) +{ + wmJob *wm_job = wm_job_find(wm, owner, WM_JOB_TYPE_ANY); + + if (wm_job) + return WM_jobs_customdata_get(wm_job); + + return NULL; + +} + int WM_jobs_is_running(wmJob *wm_job) { return wm_job->running; diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index f1a9f6dc007..62b29266c5c 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -796,7 +796,7 @@ void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, con void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context) { - RNA_STRUCT_BEGIN(ptr, prop) + RNA_STRUCT_BEGIN (ptr, prop) { switch (RNA_property_type(prop)) { case PROP_ENUM: @@ -833,7 +833,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context) int WM_operator_properties_default(PointerRNA *ptr, const bool do_update) { int is_change = FALSE; - RNA_STRUCT_BEGIN(ptr, prop) + RNA_STRUCT_BEGIN (ptr, prop) { switch (RNA_property_type(prop)) { case PROP_POINTER: @@ -866,7 +866,7 @@ void WM_operator_properties_reset(wmOperator *op) PropertyRNA *iterprop; iterprop = RNA_struct_iterator_property(op->type->srna); - RNA_PROP_BEGIN(op->ptr, itemptr, iterprop) + RNA_PROP_BEGIN (op->ptr, itemptr, iterprop) { PropertyRNA *prop = itemptr.data; @@ -901,7 +901,7 @@ int WM_operator_view3d_distance_invoke(struct bContext *C, struct wmOperator *op /* always run, so the values are initialized, * otherwise we may get differ behavior when (dia != 1.0) */ - RNA_STRUCT_BEGIN(op->ptr, prop) + RNA_STRUCT_BEGIN (op->ptr, prop) { if (RNA_property_type(prop) == PROP_FLOAT) { PropertySubType pstype = RNA_property_subtype(prop); @@ -1137,10 +1137,16 @@ void WM_operator_properties_select_all(wmOperatorType *ot) void WM_operator_properties_border(wmOperatorType *ot) { - RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); + PropertyRNA *prop; + + prop = RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect) @@ -1171,14 +1177,18 @@ void WM_operator_properties_mouse_select(wmOperatorType *ot) void WM_operator_properties_gesture_straightline(wmOperatorType *ot, int cursor) { - RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX); - RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX); + PropertyRNA *prop; + + prop = RNA_def_int(ot->srna, "xstart", 0, INT_MIN, INT_MAX, "X Start", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "xend", 0, INT_MIN, INT_MAX, "X End", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "ystart", 0, INT_MIN, INT_MAX, "Y Start", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_int(ot->srna, "yend", 0, INT_MIN, INT_MAX, "Y End", "", INT_MIN, INT_MAX); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); if (cursor) { - PropertyRNA *prop; - prop = RNA_def_int(ot->srna, "cursor", cursor, 0, INT_MAX, "Cursor", "Mouse cursor style to use during the modal operator", 0, INT_MAX); RNA_def_property_flag(prop, PROP_HIDDEN); @@ -1553,7 +1563,7 @@ static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg static uiBlock *wm_block_create_splash(bContext *C, ARegion *ar, void *arg_unused); -/* XXX: hack to refresh splash screen with updated prest menu name, +/* XXX: hack to refresh splash screen with updated preset menu name, * since popup blocks don't get regenerated like panels do */ static void wm_block_splash_refreshmenu(bContext *UNUSED(C), void *UNUSED(arg_block), void *UNUSED(arg)) { @@ -2253,7 +2263,7 @@ static int wm_link_append_exec(bContext *C, wmOperator *op) BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag); } else { - RNA_BEGIN(op->ptr, itemptr, "files") + RNA_BEGIN (op->ptr, itemptr, "files") { RNA_string_get(&itemptr, "name", name); BLO_library_append_named_part_ex(C, mainl, &bh, name, idcode, flag); @@ -2419,15 +2429,10 @@ static void WM_OT_recover_auto_save(wmOperatorType *ot) /* *************** save file as **************** */ -static void untitled(char *filepath) +static void wm_filepath_default(char *filepath) { - if (G.save_over == 0 && strlen(filepath) < FILE_MAX - 16) { - char *c = (char *)BLI_last_slash(filepath); - - if (c) - strcpy(&c[1], "untitled.blend"); - else - strcpy(filepath, "untitled.blend"); + if (G.save_over == false) { + BLI_ensure_filename(filepath, FILE_MAX, "untitled.blend"); } } @@ -2455,7 +2460,7 @@ static int wm_save_as_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent else BLI_strncpy(name, G.main->name, FILE_MAX); - untitled(name); + wm_filepath_default(name); RNA_string_set(op->ptr, "filepath", name); WM_event_add_fileselect(C, op); @@ -2471,11 +2476,12 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op) save_set_compress(op); - if (RNA_struct_property_is_set(op->ptr, "filepath")) + if (RNA_struct_property_is_set(op->ptr, "filepath")) { RNA_string_get(op->ptr, "filepath", path); + } else { BLI_strncpy(path, G.main->name, FILE_MAX); - untitled(path); + wm_filepath_default(path); } fileflags = G.fileflags & ~G_FILE_USERPREFS; @@ -2566,7 +2572,7 @@ static int wm_save_mainfile_invoke(bContext *C, wmOperator *op, const wmEvent *U else BLI_strncpy(name, G.main->name, FILE_MAX); - untitled(name); + wm_filepath_default(name); RNA_string_set(op->ptr, "filepath", name); @@ -3199,7 +3205,7 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, int i = 0; mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__); - RNA_PROP_BEGIN(op->ptr, itemptr, prop) + RNA_PROP_BEGIN (op->ptr, itemptr, prop) { float loc[2]; @@ -3225,7 +3231,7 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, static int gesture_lasso_exec(bContext *C, wmOperator *op) { - RNA_BEGIN(op->ptr, itemptr, "path") + RNA_BEGIN (op->ptr, itemptr, "path") { float loc[2]; @@ -3385,6 +3391,7 @@ typedef struct { int initial_mouse[2]; unsigned int gltex; ListBase orig_paintcursors; + bool use_secondary_tex; void *cursor; } RadialControl; @@ -3428,7 +3435,7 @@ static void radial_control_set_tex(RadialControl *rc) switch (RNA_type_to_ID_code(rc->image_id_ptr.type)) { case ID_BR: - if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data))) { + if ((ibuf = BKE_brush_gen_radial_control_imbuf(rc->image_id_ptr.data, rc->use_secondary_tex))) { glGenTextures(1, &rc->gltex); glBindTexture(GL_TEXTURE_2D, rc->gltex); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, ibuf->x, ibuf->y, 0, @@ -3701,6 +3708,8 @@ static int radial_control_get_properties(bContext *C, wmOperator *op) } } + rc->use_secondary_tex = RNA_boolean_get(op->ptr, "secondary_tex"); + return 1; } @@ -3894,6 +3903,7 @@ static void WM_OT_radial_control(wmOperatorType *ot) RNA_def_string(ot->srna, "fill_color_path", "", 0, "Fill Color Path", "Path of property used to set the fill color of the control"); RNA_def_string(ot->srna, "zoom_path", "", 0, "Zoom Path", "Path of property used to set the zoom level for the control"); RNA_def_string(ot->srna, "image_id", "", 0, "Image ID", "Path of ID that is used to generate an image for the control"); + RNA_def_boolean(ot->srna, "secondary_tex", 0, "Secondary Texture", "Tweak brush secondary/mask texture"); } /* ************************** timer for testing ***************** */ @@ -4142,7 +4152,8 @@ void wm_operatortype_free(void) /* called on initialize WM_init() */ void wm_operatortype_init(void) { - global_ops_hash = BLI_ghash_str_new("wm_operatortype_init gh"); + /* reserve size is set based on blender default setup */ + global_ops_hash = BLI_ghash_str_new_ex("wm_operatortype_init gh", 2048); WM_operatortype_append(WM_OT_window_duplicate); WM_operatortype_append(WM_OT_read_history); @@ -4259,6 +4270,7 @@ static void gesture_straightline_modal_keymap(wmKeyConfig *keyconf) /* assign map to operators */ WM_modalkeymap_assign(keymap, "IMAGE_OT_sample_line"); WM_modalkeymap_assign(keymap, "PAINT_OT_weight_gradient"); + WM_modalkeymap_assign(keymap, "MESH_OT_bisect"); } |