diff options
Diffstat (limited to 'source')
915 files changed, 25844 insertions, 15346 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index f6f1393bd21..ddb88cf61ed 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -117,9 +117,11 @@ void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2); int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2); typedef bool (*BLF_GlyphBoundsFn)(const char *str, - const size_t str_ofs, - const struct rcti *glyph_bounds, + const size_t str_step_ofs, + const struct rcti *glyph_step_bounds, const int glyph_advance_x, + const struct rctf *glyph_bounds, + const int glyph_bearing[2], void *user_data); void BLF_boundbox_foreach_glyph_ex(int fontid, diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 394704e1c20..2f7d5a60a6f 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -946,8 +946,8 @@ void BLF_buffer(int fontid, if (font) { font->buf_info.fbuf = fbuf; font->buf_info.cbuf = cbuf; - font->buf_info.w = w; - font->buf_info.h = h; + font->buf_info.dims[0] = w; + font->buf_info.dims[1] = h; font->buf_info.ch = nch; font->buf_info.display = display; } diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index ed92e9aaff2..e5e03418073 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -613,28 +613,28 @@ static void blf_font_draw_buffer_ex(FontBLF *font, BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x); } - chx = pen_x + ((int)g->pos_x); - chy = pen_y_basis + g->height; + chx = pen_x + ((int)g->pos[0]); + chy = pen_y_basis + g->dims[1]; if (g->pitch < 0) { - pen_y = pen_y_basis + (g->height - (int)g->pos_y); + pen_y = pen_y_basis + (g->dims[1] - g->pos[1]); } else { - pen_y = pen_y_basis - (g->height - (int)g->pos_y); + pen_y = pen_y_basis - (g->dims[1] - g->pos[1]); } - if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && - pen_y < buf_info->h) { + if ((chx + g->dims[0]) >= 0 && chx < buf_info->dims[0] && (pen_y + g->dims[1]) >= 0 && + pen_y < buf_info->dims[1]) { /* don't draw beyond the buffer bounds */ - int width_clip = g->width; - int height_clip = g->height; - int yb_start = g->pitch < 0 ? 0 : g->height - 1; + int width_clip = g->dims[0]; + int height_clip = g->dims[1]; + int yb_start = g->pitch < 0 ? 0 : g->dims[1] - 1; - if (width_clip + chx > buf_info->w) { - width_clip -= chx + width_clip - buf_info->w; + if (width_clip + chx > buf_info->dims[0]) { + width_clip -= chx + width_clip - buf_info->dims[0]; } - if (height_clip + pen_y > buf_info->h) { - height_clip -= pen_y + height_clip - buf_info->h; + if (height_clip + pen_y > buf_info->dims[1]) { + height_clip -= pen_y + height_clip - buf_info->dims[1]; } /* drawing below the image? */ @@ -652,7 +652,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, if (a_byte) { const float a = (a_byte / 255.0f) * b_col_float[3]; const size_t buf_ofs = (((size_t)(chx + x) + - ((size_t)(pen_y + y) * (size_t)buf_info->w)) * + ((size_t)(pen_y + y) * (size_t)buf_info->dims[0])) * (size_t)buf_info->ch); float *fbuf = buf_info->fbuf + buf_ofs; @@ -689,7 +689,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, if (a_byte) { const float a = (a_byte / 255.0f) * b_col_float[3]; const size_t buf_ofs = (((size_t)(chx + x) + - ((size_t)(pen_y + y) * (size_t)buf_info->w)) * + ((size_t)(pen_y + y) * (size_t)buf_info->dims[0])) * (size_t)buf_info->ch); unsigned char *cbuf = buf_info->cbuf + buf_ofs; @@ -1246,13 +1246,13 @@ static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font, } gbox.xmin = pen_x; - gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->width); + gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->dims[0]); gbox.ymin = pen_y; - gbox.ymax = gbox.ymin - g->height; + gbox.ymax = gbox.ymin - g->dims[1]; pen_x += g->advance_i; - if (user_fn(str, i_curr, &gbox, g->advance_i, user_data) == false) { + if (user_fn(str, i_curr, &gbox, g->advance_i, &g->box, g->pos, user_data) == false) { break; } @@ -1365,8 +1365,8 @@ static void blf_font_fill(FontBLF *font) font->buf_info.fbuf = NULL; font->buf_info.cbuf = NULL; - font->buf_info.w = 0; - font->buf_info.h = 0; + font->buf_info.dims[0] = 0; + font->buf_info.dims[1] = 0; font->buf_info.ch = 0; font->buf_info.col_init[0] = 0; font->buf_info.col_init[1] = 0; diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index a38cb323777..ce17069e53f 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -212,7 +212,7 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc) GlyphBLF *g; unsigned int i; - for (i = 0; i < 257; i++) { + for (i = 0; i < ARRAY_SIZE(gc->bucket); i++) { while ((g = BLI_pophead(&gc->bucket[i]))) { blf_glyph_free(g); } @@ -327,26 +327,27 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un g->c = c; g->idx = (FT_UInt)index; bitmap = slot->bitmap; - g->width = (int)bitmap.width; - g->height = (int)bitmap.rows; + g->dims[0] = (int)bitmap.width; + g->dims[1] = (int)bitmap.rows; - if (g->width && g->height) { + const int buffer_size = g->dims[0] * g->dims[1]; + + if (buffer_size != 0) { if (font->flags & BLF_MONOCHROME) { /* 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++) { + for (int i = 0; i < buffer_size; i++) { bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0; } } - g->bitmap = (unsigned char *)MEM_mallocN((size_t)g->width * (size_t)g->height, "glyph bitmap"); - memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)g->width * (size_t)g->height); + g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap"); + memcpy(g->bitmap, bitmap.buffer, (size_t)buffer_size); } g->advance = ((float)slot->advance.x) / 64.0f; g->advance_i = (int)g->advance; - g->pos_x = (float)slot->bitmap_left; - g->pos_y = (float)slot->bitmap_top; + g->pos[0] = slot->bitmap_left; + g->pos[1] = slot->bitmap_top; g->pitch = slot->bitmap.pitch; FT_Outline_Get_CBox(&(slot->outline), &bbox); @@ -431,10 +432,10 @@ static void blf_texture3_draw(const unsigned char color_in[4], static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y) { - rect->xmin = floorf(x + g->pos_x); - rect->xmax = rect->xmin + (float)g->width; - rect->ymin = floorf(y + g->pos_y); - rect->ymax = rect->ymin - (float)g->height; + rect->xmin = floorf(x + (float)g->pos[0]); + rect->xmax = rect->xmin + (float)g->dims[0]; + rect->ymin = floorf(y + (float)g->pos[1]); + rect->ymax = rect->ymin - (float)g->dims[1]; } static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y) @@ -443,9 +444,9 @@ static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y) * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ rect->xmin = floorf(x); - rect->xmax = rect->xmin + MIN2(g->advance, (float)g->width); + rect->xmax = rect->xmin + MIN2(g->advance, (float)g->dims[0]); rect->ymin = floorf(y); - rect->ymax = rect->ymin - (float)g->height; + rect->ymax = rect->ymin - (float)g->dims[1]; } static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y, FontBLF *font) @@ -455,7 +456,7 @@ static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y) { - if ((!g->width) || (!g->height)) { + if ((!g->dims[0]) || (!g->dims[1])) { return; } @@ -466,7 +467,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl g->offset = gc->bitmap_len; - int buff_size = g->width * g->height; + int buff_size = g->dims[0] * g->dims[1]; int bitmap_len = gc->bitmap_len + buff_size; if (bitmap_len > gc->bitmap_len_alloc) { @@ -514,7 +515,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl if (font->shadow == 0) { blf_texture_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -523,7 +524,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else if (font->shadow <= 4) { blf_texture3_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -532,7 +533,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else { blf_texture5_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -547,39 +548,18 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl #if BLF_BLUR_ENABLE switch (font->blur) { case 3: - blf_texture3_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture3_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; case 5: - blf_texture5_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture5_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; default: - blf_texture_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } #else - blf_texture_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture_draw(font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); #endif } diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 98ada87d16d..4ae592d323f 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -103,9 +103,11 @@ void blf_font_boundbox_foreach_glyph(struct FontBLF *font, const char *str, size_t len, bool (*user_fn)(const char *str, - const size_t str_ofs, - const struct rcti *glyph_bounds, + const size_t str_step_ofs, + const struct rcti *glyph_step_bounds, const int glyph_advance_x, + const struct rctf *glyph_bounds, + const int glyph_bearing[2], void *user_data), void *user_data, struct ResultBLF *r_info); diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 6fae3eb4376..362cbf6730f 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -119,17 +119,16 @@ typedef struct GlyphBLF { */ unsigned char *bitmap; - /* glyph width and height. */ - int width; - int height; + /* Glyph width and height. */ + int dims[2]; int pitch; - /* X and Y bearing of the glyph. + /** + * X and Y bearing of the glyph. * The X bearing is from the origin to the glyph left bbox edge. * The Y bearing is from the baseline to the top of the glyph edge. */ - float pos_x; - float pos_y; + int pos[2]; struct GlyphCacheBLF *glyph_cache; } GlyphBLF; @@ -141,9 +140,8 @@ typedef struct FontBufInfoBLF { /* the same but unsigned char */ unsigned char *cbuf; - /* buffer size, keep signed so comparisons with negative values work */ - int w; - int h; + /** Buffer size, keep signed so comparisons with negative values work. */ + int dims[2]; /* number of channels. */ int ch; diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index b7308d47d71..37eed29f6fe 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -78,8 +78,8 @@ void BLF_thumb_preview(const char *filename, /* Would be done via the BLF API, but we're not using a fontid here */ font->buf_info.cbuf = buf; font->buf_info.ch = channels; - font->buf_info.w = w; - font->buf_info.h = h; + font->buf_info.dims[0] = w; + font->buf_info.dims[1] = h; /* Always create the image with a white font, * the caller can theme how it likes */ diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 5f4f3f35b82..104582be932 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -25,12 +25,12 @@ * \brief Blender kernel action and pose functionality. */ +#include "DNA_listBase.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_listBase.h" - /* The following structures are defined in DNA_action_types.h, and DNA_anim_types.h */ struct FCurve; struct Main; diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h index 071254be783..8809fadd55c 100644 --- a/source/blender/blenkernel/BKE_anim_data.h +++ b/source/blender/blenkernel/BKE_anim_data.h @@ -24,12 +24,12 @@ * \ingroup bke */ +#include "BLI_sys_types.h" /* for bool */ + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" /* for bool */ - struct AnimData; struct ID; struct Main; diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a8915c178d4..4a2ad28f90f 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -24,12 +24,12 @@ * \ingroup bke */ +#include "BLI_sys_types.h" /* for bool */ + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" /* for bool */ - struct AnimData; struct Depsgraph; struct FCurve; @@ -207,17 +207,15 @@ bool BKE_animsys_read_rna_setting(struct PathResolvedRNA *anim_rna, float *r_val bool BKE_animsys_write_rna_setting(struct PathResolvedRNA *anim_rna, const float value); /* Evaluation loop for evaluating animation data */ -void BKE_animsys_evaluate_animdata(struct Scene *scene, - struct ID *id, +void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, float ctime, - short recalc, + eAnimData_Recalc recalc, const bool flush_to_original); /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only */ void BKE_animsys_evaluate_all_animation(struct Main *main, struct Depsgraph *depsgraph, - struct Scene *scene, float ctime); /* ------------ Specialized API --------------- */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 6c383ae5011..5238853a105 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -22,6 +22,7 @@ /** \file * \ingroup bke */ +#include "BLI_listbase.h" #ifdef __cplusplus extern "C" { diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 52a603ede72..852549f22d4 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -16,6 +16,10 @@ #ifndef __BKE_BLENDER_VERSION_H__ #define __BKE_BLENDER_VERSION_H__ +#ifdef __cplusplus +extern "C" { +#endif + /** \file * \ingroup bke */ @@ -26,8 +30,8 @@ * * \note Use #STRINGIFY() rather than defining with quotes. */ -#define BLENDER_VERSION 283 -#define BLENDER_SUBVERSION 16 +#define BLENDER_VERSION 290 +#define BLENDER_SUBVERSION 1 /** Several breakages with 280, e.g. collections vs layers. */ #define BLENDER_MINVERSION 280 #define BLENDER_MINSUBVERSION 0 @@ -36,11 +40,15 @@ /** Can be left blank, otherwise a,b,c... etc with no quotes. */ #define BLENDER_VERSION_CHAR /** alpha/beta/rc/release, docs use this. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /** Optionally set to 1,2,... for example to get alpha1 or rc2. */ #define BLENDER_VERSION_CYCLE_NUMBER /** Defined in from blender.c */ extern char versionstr[]; +#ifdef __cplusplus +} +#endif + #endif /* __BKE_BLENDER_VERSION_H__ */ diff --git a/source/blender/blenkernel/BKE_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 1d6db319eb7..dd7d20c0407 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index c4fb19ea355..70ca29d5795 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -25,6 +25,7 @@ */ #include "DNA_listBase.h" +#include "DNA_object_enums.h" #include "RNA_types.h" #ifdef __cplusplus @@ -66,8 +67,6 @@ struct bScreen; struct wmWindow; struct wmWindowManager; -#include "DNA_object_enums.h" - /* Structs */ struct bContext; diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 164867b228b..2b17cb7a875 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -23,12 +23,12 @@ * \ingroup bke */ +#include "DNA_scene_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_scene_types.h" - struct BezTriple; struct Curve; struct Depsgraph; @@ -111,6 +111,8 @@ void BKE_curve_material_index_clear(struct Curve *cu); bool BKE_curve_material_index_validate(struct Curve *cu); void BKE_curve_material_remap(struct Curve *cu, const unsigned int *remap, unsigned int remap_len); +void BKE_curve_smooth_flag_set(struct Curve *cu, const bool use_smooth); + ListBase *BKE_curve_nurbs_get(struct Curve *cu); int BKE_curve_nurb_vert_index_get(const struct Nurb *nu, const void *vert); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index a4a36343ca3..42beda352f5 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. @@ -25,15 +25,15 @@ #ifndef __BKE_CUSTOMDATA_H__ #define __BKE_CUSTOMDATA_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_sys_types.h" #include "BLI_utildefines.h" #include "DNA_customdata_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct BMesh; struct CustomData; struct CustomData_MeshMasks; diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index 79ef512bc1f..a723a9ed38c 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -10,7 +10,7 @@ * 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, + * 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) 2014 Blender Foundation. @@ -24,12 +24,12 @@ #ifndef __BKE_DATA_TRANSFER_H__ #define __BKE_DATA_TRANSFER_H__ +#include "BKE_customdata.h" + #ifdef __cplusplus extern "C" { #endif -#include "BKE_customdata.h" - struct Depsgraph; struct Object; struct ReportList; diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index 0dc133e34b3..5e3603a8339 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -21,12 +21,12 @@ * \ingroup bke */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - struct Depsgraph; struct DynamicPaintCanvasSettings; struct DynamicPaintModifierData; diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index d389b557503..21a9b7b8b04 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -24,13 +24,13 @@ * \ingroup bke */ +#include "DNA_curve_types.h" + #ifdef __cplusplus extern "C" { #endif struct ChannelDriver; -struct DriverTarget; -struct DriverVar; struct FCM_EnvelopeData; struct FCurve; struct FModifier; @@ -44,8 +44,6 @@ struct StructRNA; struct bAction; struct bContext; -#include "DNA_curve_types.h" - /* ************** Keyframe Tools ***************** */ typedef struct CfraElem { @@ -56,67 +54,6 @@ typedef struct CfraElem { void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt); -/* ************** F-Curve Drivers ***************** */ - -/* With these iterators for convenience, the variables "tarIndex" and "dtar" can be - * accessed directly from the code using them, but it is not recommended that their - * values be changed to point at other slots... - */ - -/* convenience looper over ALL driver targets for a given variable (even the unused ones) */ -#define DRIVER_TARGETS_LOOPER_BEGIN(dvar) \ - { \ - DriverTarget *dtar = &dvar->targets[0]; \ - int tarIndex = 0; \ - for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++) - -/* convenience looper over USED driver targets only */ -#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar) \ - { \ - DriverTarget *dtar = &dvar->targets[0]; \ - int tarIndex = 0; \ - for (; tarIndex < dvar->num_targets; tarIndex++, dtar++) - -/* tidy up for driver targets loopers */ -#define DRIVER_TARGETS_LOOPER_END \ - } \ - ((void)0) - -/* ---------------------- */ - -void fcurve_free_driver(struct FCurve *fcu); -struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); - -void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars); - -void BKE_driver_target_matrix_to_rot_channels( - float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]); - -void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar); -void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar); - -void driver_change_variable_type(struct DriverVar *dvar, int type); -void driver_variable_name_validate(struct DriverVar *dvar); -struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver); - -float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar); -bool driver_get_variable_property(struct ChannelDriver *driver, - struct DriverTarget *dtar, - struct PointerRNA *r_ptr, - struct PropertyRNA **r_prop, - int *r_index); - -bool BKE_driver_has_simple_expression(struct ChannelDriver *driver); -bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver); -void BKE_driver_invalidate_expression(struct ChannelDriver *driver, - bool expr_changed, - bool varname_changed); - -float evaluate_driver(struct PathResolvedRNA *anim_rna, - struct ChannelDriver *driver, - struct ChannelDriver *driver_orig, - const float evaltime); - /* ************** F-Curve Modifiers *************** */ /* F-Curve Modifier Type-Info (fmi): diff --git a/source/blender/blenkernel/BKE_fcurve_driver.h b/source/blender/blenkernel/BKE_fcurve_driver.h new file mode 100644 index 00000000000..563ed408ed7 --- /dev/null +++ b/source/blender/blenkernel/BKE_fcurve_driver.h @@ -0,0 +1,106 @@ +/* + * 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + */ + +#ifndef __BKE_FCURVE_DRIVER_H__ +#define __BKE_FCURVE_DRIVER_H__ + +/** \file + * \ingroup bke + */ + +#include "DNA_curve_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ChannelDriver; +struct DriverTarget; +struct DriverVar; +struct FCurve; +struct PathResolvedRNA; +struct PointerRNA; +struct PropertyRNA; + +/* ************** F-Curve Drivers ***************** */ + +/* With these iterators for convenience, the variables "tarIndex" and "dtar" can be + * accessed directly from the code using them, but it is not recommended that their + * values be changed to point at other slots... + */ + +/* convenience looper over ALL driver targets for a given variable (even the unused ones) */ +#define DRIVER_TARGETS_LOOPER_BEGIN(dvar) \ + { \ + DriverTarget *dtar = &dvar->targets[0]; \ + int tarIndex = 0; \ + for (; tarIndex < MAX_DRIVER_TARGETS; tarIndex++, dtar++) + +/* convenience looper over USED driver targets only */ +#define DRIVER_TARGETS_USED_LOOPER_BEGIN(dvar) \ + { \ + DriverTarget *dtar = &dvar->targets[0]; \ + int tarIndex = 0; \ + for (; tarIndex < dvar->num_targets; tarIndex++, dtar++) + +/* tidy up for driver targets loopers */ +#define DRIVER_TARGETS_LOOPER_END \ + } \ + ((void)0) + +/* ---------------------- */ + +void fcurve_free_driver(struct FCurve *fcu); +struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver); + +void driver_variables_copy(struct ListBase *dst_vars, const struct ListBase *src_vars); + +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]); + +void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar); +void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar); + +void driver_change_variable_type(struct DriverVar *dvar, int type); +void driver_variable_name_validate(struct DriverVar *dvar); +struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver); + +float driver_get_variable_value(struct ChannelDriver *driver, struct DriverVar *dvar); +bool driver_get_variable_property(struct ChannelDriver *driver, + struct DriverTarget *dtar, + struct PointerRNA *r_ptr, + struct PropertyRNA **r_prop, + int *r_index); + +bool BKE_driver_has_simple_expression(struct ChannelDriver *driver); +bool BKE_driver_expression_depends_on_time(struct ChannelDriver *driver); +void BKE_driver_invalidate_expression(struct ChannelDriver *driver, + bool expr_changed, + bool varname_changed); + +float evaluate_driver(struct PathResolvedRNA *anim_rna, + struct ChannelDriver *driver, + struct ChannelDriver *driver_orig, + const float evaltime); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_FCURVE_DRIVER_H__*/ diff --git a/source/blender/blenkernel/BKE_gpencil_curve.h b/source/blender/blenkernel/BKE_gpencil_curve.h new file mode 100644 index 00000000000..cf6f9074bda --- /dev/null +++ b/source/blender/blenkernel/BKE_gpencil_curve.h @@ -0,0 +1,47 @@ +/* + * 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) 2008, Blender Foundation + * This is a new part of Blender + */ + +#ifndef __BKE_GPENCIL_CURVE_H__ +#define __BKE_GPENCIL_CURVE_H__ + +/** \file + * \ingroup bke + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Main; +struct Object; +struct Scene; + +void BKE_gpencil_convert_curve(struct Main *bmain, + struct Scene *scene, + struct Object *ob_gp, + struct Object *ob_cu, + const bool gpencil_lines, + const bool use_collections, + const bool only_stroke); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_GPENCIL_CURVE_H__ */ diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h index 8c52e6d458b..b26016aa26c 100644 --- a/source/blender/blenkernel/BKE_gpencil_geom.h +++ b/source/blender/blenkernel/BKE_gpencil_geom.h @@ -98,14 +98,6 @@ bool BKE_gpencil_stroke_shrink(struct bGPDstroke *gps, const float dist); float BKE_gpencil_stroke_length(const struct bGPDstroke *gps, bool use_3d); -void BKE_gpencil_convert_curve(struct Main *bmain, - struct Scene *scene, - struct Object *ob_gp, - struct Object *ob_cu, - const bool gpencil_lines, - const bool use_collections, - const bool only_stroke); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_gpencil_modifier.h b/source/blender/blenkernel/BKE_gpencil_modifier.h index b48a6284567..966d3a98234 100644 --- a/source/blender/blenkernel/BKE_gpencil_modifier.h +++ b/source/blender/blenkernel/BKE_gpencil_modifier.h @@ -260,28 +260,28 @@ typedef struct GpencilModifierTypeInfo { /* Initialize modifier's global data (type info and some common global storages). */ void BKE_gpencil_modifier_init(void); -const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type); +const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type); struct GpencilModifierData *BKE_gpencil_modifier_new(int type); void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, const int flag); void BKE_gpencil_modifier_free(struct GpencilModifierData *md); bool BKE_gpencil_modifier_unique_name(struct ListBase *modifiers, struct GpencilModifierData *gmd); -bool BKE_gpencil_modifier_dependsOnTime(struct GpencilModifierData *md); -struct GpencilModifierData *BKE_gpencil_modifiers_findByType(struct Object *ob, - GpencilModifierType type); -struct GpencilModifierData *BKE_gpencil_modifiers_findByName(struct Object *ob, const char *name); -void BKE_gpencil_modifier_copyData_generic(const struct GpencilModifierData *md_src, +bool BKE_gpencil_modifier_depends_ontime(struct GpencilModifierData *md); +struct GpencilModifierData *BKE_gpencil_modifiers_findby_type(struct Object *ob, + GpencilModifierType type); +struct GpencilModifierData *BKE_gpencil_modifiers_findby_name(struct Object *ob, const char *name); +void BKE_gpencil_modifier_copydata_generic(const struct GpencilModifierData *md_src, struct GpencilModifierData *md_dst); -void BKE_gpencil_modifier_copyData(struct GpencilModifierData *md, +void BKE_gpencil_modifier_copydata(struct GpencilModifierData *md, struct GpencilModifierData *target); -void BKE_gpencil_modifier_copyData_ex(struct GpencilModifierData *md, +void BKE_gpencil_modifier_copydata_ex(struct GpencilModifierData *md, struct GpencilModifierData *target, const int flag); -void BKE_gpencil_modifiers_foreachIDLink(struct Object *ob, - GreasePencilIDWalkFunc walk, - void *userData); -void BKE_gpencil_modifiers_foreachTexLink(struct Object *ob, - GreasePencilTexWalkFunc walk, - void *userData); +void BKE_gpencil_modifiers_foreach_ID_link(struct Object *ob, + GreasePencilIDWalkFunc walk, + void *userData); +void BKE_gpencil_modifiers_foreach_tex_link(struct Object *ob, + GreasePencilTexWalkFunc walk, + void *userData); bool BKE_gpencil_has_geometry_modifiers(struct Object *ob); bool BKE_gpencil_has_time_modifiers(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h index 05545216217..b6dfadd3b2a 100644 --- a/source/blender/blenkernel/BKE_idtype.h +++ b/source/blender/blenkernel/BKE_idtype.h @@ -33,6 +33,7 @@ extern "C" { #endif struct ID; +struct LibraryForeachIDData; struct Main; /** IDTypeInfo.flags. */ @@ -60,6 +61,8 @@ typedef void (*IDTypeFreeDataFunction)(struct ID *id); /** \param flag: See BKE_lib_id.h's LIB_ID_MAKELOCAL_... flags. */ typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const int flags); +typedef void (*IDTypeForeachIDFunction)(struct ID *id, struct LibraryForeachIDData *data); + typedef struct IDTypeInfo { /* ********** General IDType data. ********** */ @@ -121,6 +124,12 @@ typedef struct IDTypeInfo { * `BKE_lib_id_make_local_generic()` is enough. */ IDTypeMakeLocalFunction make_local; + + /** + * Called by `BKE_library_foreach_ID_link()` to apply a callback over all other ID usages (ID + * pointers) of given data-block. + */ + IDTypeForeachIDFunction foreach_id; } IDTypeInfo; /* ********** Declaration of each IDTypeInfo. ********** */ @@ -165,6 +174,7 @@ extern IDTypeInfo IDType_ID_LP; extern IDTypeInfo IDType_ID_HA; extern IDTypeInfo IDType_ID_PT; extern IDTypeInfo IDType_ID_VO; +extern IDTypeInfo IDType_ID_SIM; extern IDTypeInfo IDType_ID_LINK_PLACEHOLDER; diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 0d8b6efb4b1..1e5573ab014 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -23,12 +23,12 @@ * \ingroup bke */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - struct Depsgraph; struct ID; struct ImBuf; @@ -318,7 +318,7 @@ bool BKE_image_fill_tile(struct Image *ima, bool is_float); struct ImageTile *BKE_image_get_tile(struct Image *ima, int tile_number); -struct ImageTile *BKE_image_get_tile_from_iuser(struct Image *ima, struct ImageUser *iuser); +struct ImageTile *BKE_image_get_tile_from_iuser(struct Image *ima, const struct ImageUser *iuser); int BKE_image_get_tile_from_pos(struct Image *ima, const float uv[2], diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index 980d5ebc43a..18ca5629d07 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -46,12 +46,12 @@ * specific cases requiring advanced (and potentially dangerous) handling. */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct GHash; struct ID; struct Library; diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h index 3aa27bf557c..353ee3bbf5a 100644 --- a/source/blender/blenkernel/BKE_lib_query.h +++ b/source/blender/blenkernel/BKE_lib_query.h @@ -40,6 +40,7 @@ extern "C" { #endif struct ID; +struct IDProperty; struct Main; /* Tips for the callback for cases it's gonna to modify the pointer. */ @@ -126,6 +127,33 @@ enum { IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */ }; +typedef struct LibraryForeachIDData LibraryForeachIDData; + +bool BKE_lib_query_foreachid_process(struct LibraryForeachIDData *data, + struct ID **id_pp, + int cb_flag); + +#define BKE_LIB_FOREACHID_PROCESS_ID(_data, _id, _cb_flag) \ + { \ + CHECK_TYPE_ANY((_id), ID *, void *); \ + if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id), (_cb_flag))) { \ + return; \ + } \ + } \ + ((void)0) + +#define BKE_LIB_FOREACHID_PROCESS(_data, _id_super, _cb_flag) \ + { \ + CHECK_TYPE(&((_id_super)->id), ID *); \ + if (!BKE_lib_query_foreachid_process((_data), (ID **)&(_id_super), (_cb_flag))) { \ + return; \ + } \ + } \ + ((void)0) + +bool BKE_library_foreach_ID_embedded(struct LibraryForeachIDData *data, struct ID **id_pp); +void BKE_lib_query_idpropertiesForeachIDLink_callback(struct IDProperty *id_prop, void *user_data); + /* Loop over all of the ID's this datablock links to. */ void BKE_library_foreach_ID_link( struct Main *bmain, struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag); diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h index 72c5f1d1b0e..8129b9dbafb 100644 --- a/source/blender/blenkernel/BKE_lib_remap.h +++ b/source/blender/blenkernel/BKE_lib_remap.h @@ -33,12 +33,12 @@ * - `BKE_lib_remap_callback_` should be used for functions managing remapping callbacks. */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct wmWindowManager; /* BKE_libblock_free, delete are declared in BKE_lib_id.h for convenience. */ diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 5bc3d50bf8d..7883d740b0a 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -25,12 +25,12 @@ * API to manage `Library` data-blocks. */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct Library; struct Main; diff --git a/source/blender/blenkernel/BKE_light.h b/source/blender/blenkernel/BKE_light.h index a6f0fdbc8a3..17f7a8596bf 100644 --- a/source/blender/blenkernel/BKE_light.h +++ b/source/blender/blenkernel/BKE_light.h @@ -24,12 +24,13 @@ * \ingroup bke * \brief General operations, lookup, etc. for blender lights. */ + +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct Light; struct Main; diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index ed1f67350c3..b2472e862ec 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -147,6 +147,7 @@ typedef struct Main { ListBase hairs; ListBase pointclouds; ListBase volumes; + ListBase simulations; /** * Must be generated, used and freed by same code - never assume this is valid data unless you @@ -220,7 +221,7 @@ const char *BKE_main_blendfile_path_from_global(void); struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 40 +#define MAX_LIBARRAY 41 int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); #define MAIN_VERSION_ATLEAST(main, ver, subver) \ diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index c37e56149eb..a4bf86f61f3 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -100,7 +100,7 @@ typedef enum { /* For modifiers that use CD_PREVIEW_MCOL for preview. */ eModifierTypeFlag_UsesPreview = (1 << 9), - eModifierTypeFlag_AcceptsLattice = (1 << 10), + eModifierTypeFlag_AcceptsVertexCosOnly = (1 << 10), } ModifierTypeFlag; /* IMPORTANT! Keep ObjectWalkFunc and IDWalkFunc signatures compatible. */ @@ -211,18 +211,28 @@ typedef struct ModifierTypeInfo { /********************* Non-deform modifier functions *********************/ - /* For non-deform types: apply the modifier and return a mesh object. + /* For non-deform types: apply the modifier and return a mesh datablock. * - * The mesh argument should always be non-NULL; the modifier - * should read the object data from the mesh object instead of the - * actual object data. + * The mesh argument should always be non-NULL; the modifier should use the + * passed in mesh datablock rather than object->data, as it contains the mesh + * with modifier applied up to this point. * - * The modifier may reuse the mesh argument (i.e. return it in - * modified form), but must not release it. + * The modifier may modify and return the mesh argument, but must not free it + * and must ensure any referenced data layers are converted to non-referenced + * before modification. */ - struct Mesh *(*applyModifier)(struct ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *mesh); + struct Mesh *(*modifyMesh)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Mesh *mesh); + struct Hair *(*modifyHair)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Hair *hair); + struct PointCloud *(*modifyPointCloud)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct PointCloud *pointcloud); + struct Volume *(*modifyVolume)(struct ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Volume *volume); /********************* Optional functions *********************/ @@ -343,60 +353,64 @@ typedef struct ModifierTypeInfo { /* Initialize modifier's global data (type info and some common global storages). */ void BKE_modifier_init(void); -const ModifierTypeInfo *modifierType_getInfo(ModifierType type); +const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type); /* Modifier utility calls, do call through type pointer and return * default values if pointer is optional. */ -struct ModifierData *modifier_new(int type); -void modifier_free_ex(struct ModifierData *md, const int flag); -void modifier_free(struct ModifierData *md); - -bool modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md); - -void modifier_copyData_generic(const struct ModifierData *md, - struct ModifierData *target, - const int flag); -void modifier_copyData(struct ModifierData *md, struct ModifierData *target); -void modifier_copyData_ex(struct ModifierData *md, struct ModifierData *target, const int flag); -bool modifier_dependsOnTime(struct ModifierData *md); -bool modifier_supportsMapping(struct ModifierData *md); -bool modifier_supportsCage(struct Scene *scene, struct ModifierData *md); -bool modifier_couldBeCage(struct Scene *scene, struct ModifierData *md); -bool modifier_isCorrectableDeformed(struct ModifierData *md); -bool modifier_isSameTopology(ModifierData *md); -bool modifier_isNonGeometrical(ModifierData *md); -bool modifier_isEnabled(const struct Scene *scene, struct ModifierData *md, int required_mode); -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, ObjectWalkFunc walk, void *userData); -void modifiers_foreachIDLink(struct Object *ob, IDWalkFunc walk, void *userData); -void modifiers_foreachTexLink(struct Object *ob, TexWalkFunc walk, void *userData); - -struct ModifierData *modifiers_findByType(struct Object *ob, ModifierType type); -struct ModifierData *modifiers_findByName(struct Object *ob, const char *name); -void modifiers_clearErrors(struct Object *ob); -int modifiers_getCageIndex(struct Scene *scene, - struct Object *ob, - int *r_lastPossibleCageIndex, - bool is_virtual); - -bool modifiers_isModifierEnabled(struct Object *ob, int modifierType); -bool modifiers_isSoftbodyEnabled(struct Object *ob); -bool modifiers_isClothEnabled(struct Object *ob); -bool modifiers_isParticleEnabled(struct Object *ob); - -struct Object *modifiers_isDeformedByArmature(struct Object *ob); -struct Object *modifiers_isDeformedByMeshDeform(struct Object *ob); -struct Object *modifiers_isDeformedByLattice(struct Object *ob); -struct Object *modifiers_isDeformedByCurve(struct Object *ob); -bool modifiers_usesMultires(struct Object *ob); -bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm); -bool modifiers_usesSubsurfFacedots(struct Scene *scene, struct Object *ob); -bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob); -void modifier_freeTemporaryData(struct ModifierData *md); -bool modifiers_isPreview(struct Object *ob); +struct ModifierData *BKE_modifier_new(int type); +void BKE_modifier_free_ex(struct ModifierData *md, const int flag); +void BKE_modifier_free(struct ModifierData *md); + +bool BKE_modifier_unique_name(struct ListBase *modifiers, struct ModifierData *md); + +void BKE_modifier_copydata_generic(const struct ModifierData *md, + struct ModifierData *target, + const int flag); +void BKE_modifier_copydata(struct ModifierData *md, struct ModifierData *target); +void BKE_modifier_copydata_ex(struct ModifierData *md, + struct ModifierData *target, + const int flag); +bool BKE_modifier_depends_ontime(struct ModifierData *md); +bool BKE_modifier_supports_mapping(struct ModifierData *md); +bool BKE_modifier_supports_cage(struct Scene *scene, struct ModifierData *md); +bool BKE_modifier_couldbe_cage(struct Scene *scene, struct ModifierData *md); +bool BKE_modifier_is_correctable_deformed(struct ModifierData *md); +bool BKE_modifier_is_same_topology(ModifierData *md); +bool BKE_modifier_is_non_geometrical(ModifierData *md); +bool BKE_modifier_is_enabled(const struct Scene *scene, + struct ModifierData *md, + int required_mode); +void BKE_modifier_set_error(struct ModifierData *md, const char *format, ...) + ATTR_PRINTF_FORMAT(2, 3); +bool BKE_modifier_is_preview(struct ModifierData *md); + +void BKE_modifiers_foreach_object_link(struct Object *ob, ObjectWalkFunc walk, void *userData); +void BKE_modifiers_foreach_ID_link(struct Object *ob, IDWalkFunc walk, void *userData); +void BKE_modifiers_foreach_tex_link(struct Object *ob, TexWalkFunc walk, void *userData); + +struct ModifierData *BKE_modifiers_findby_type(struct Object *ob, ModifierType type); +struct ModifierData *BKE_modifiers_findny_name(struct Object *ob, const char *name); +void BKE_modifiers_clear_errors(struct Object *ob); +int BKE_modifiers_get_cage_index(struct Scene *scene, + struct Object *ob, + int *r_lastPossibleCageIndex, + bool is_virtual); + +bool BKE_modifiers_is_modifier_enabled(struct Object *ob, int modifierType); +bool BKE_modifiers_is_softbody_enabled(struct Object *ob); +bool BKE_modifiers_is_cloth_enabled(struct Object *ob); +bool BKE_modifiers_is_particle_enabled(struct Object *ob); + +struct Object *BKE_modifiers_is_deformed_by_armature(struct Object *ob); +struct Object *BKE_modifiers_is_deformed_by_meshdeform(struct Object *ob); +struct Object *BKE_modifiers_is_deformed_by_lattice(struct Object *ob); +struct Object *BKE_modifiers_is_deformed_by_curve(struct Object *ob); +bool BKE_modifiers_uses_multires(struct Object *ob); +bool BKE_modifiers_uses_armature(struct Object *ob, struct bArmature *arm); +bool BKE_modifiers_uses_subsurf_facedots(struct Scene *scene, struct Object *ob); +bool BKE_modifiers_is_correctable_deformed(struct Scene *scene, struct Object *ob); +void BKE_modifier_free_temporary_data(struct ModifierData *md); typedef struct CDMaskLink { struct CDMaskLink *next; @@ -408,16 +422,16 @@ typedef struct CDMaskLink { * pointed to by md for correct evaluation, assuming the data indicated by * final_datamask is required at the end of the stack. */ -struct CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, - struct Object *ob, - struct ModifierData *md, - struct CustomData_MeshMasks *final_datamask, - int required_mode, - ModifierData *previewmd, - const struct CustomData_MeshMasks *previewmask); -struct ModifierData *modifiers_getLastPreview(struct Scene *scene, - struct ModifierData *md, - int required_mode); +struct CDMaskLink *BKE_modifier_calc_data_masks(struct Scene *scene, + struct Object *ob, + struct ModifierData *md, + struct CustomData_MeshMasks *final_datamask, + int required_mode, + ModifierData *previewmd, + const struct CustomData_MeshMasks *previewmask); +struct ModifierData *BKE_modifier_get_last_preview(struct Scene *scene, + struct ModifierData *md, + int required_mode); typedef struct VirtualModifierData { ArmatureModifierData amd; @@ -426,46 +440,46 @@ typedef struct VirtualModifierData { ShapeKeyModifierData smd; } VirtualModifierData; -struct ModifierData *modifiers_getVirtualModifierList(const struct Object *ob, - struct VirtualModifierData *data); +struct ModifierData *BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, + struct VirtualModifierData *data); /* ensure modifier correctness when changing ob->data */ -void test_object_modifiers(struct Object *ob); +void BKE_modifiers_test_object(struct Object *ob); /* here for do_versions */ -void modifier_mdef_compact_influences(struct ModifierData *md); +void BKE_modifier_mdef_compact_influences(struct ModifierData *md); -void modifier_path_init(char *path, int path_maxlen, const char *name); -const char *modifier_path_relbase(struct Main *bmain, struct Object *ob); -const char *modifier_path_relbase_from_global(struct Object *ob); +void BKE_modifier_path_init(char *path, int path_maxlen, const char *name); +const char *BKE_modifier_path_relbase(struct Main *bmain, struct Object *ob); +const char *BKE_modifier_path_relbase_from_global(struct Object *ob); /* Accessors of original/evaluated modifiers. */ /* For a given modifier data, get corresponding original one. * If the modifier data is already original, return it as-is. */ -struct ModifierData *modifier_get_original(struct ModifierData *md); -struct ModifierData *modifier_get_evaluated(struct Depsgraph *depsgraph, - struct Object *object, - struct ModifierData *md); +struct ModifierData *BKE_modifier_get_original(struct ModifierData *md); +struct ModifierData *BKE_modifier_get_evaluated(struct Depsgraph *depsgraph, + struct Object *object, + struct ModifierData *md); /* wrappers for modifier callbacks that ensure valid normals */ -struct Mesh *modwrap_applyModifier(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *me); - -void modwrap_deformVerts(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *me, - float (*vertexCos)[3], - int numVerts); - -void modwrap_deformVertsEM(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct BMEditMesh *em, - struct Mesh *me, - float (*vertexCos)[3], - int numVerts); +struct Mesh *BKE_modifier_modify_mesh(ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Mesh *me); + +void BKE_modifier_deform_verts(ModifierData *md, + const struct ModifierEvalContext *ctx, + struct Mesh *me, + float (*vertexCos)[3], + int numVerts); + +void BKE_modifier_deform_vertsEM(ModifierData *md, + const struct ModifierEvalContext *ctx, + struct BMEditMesh *em, + struct Mesh *me, + float (*vertexCos)[3], + int numVerts); struct Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(struct Object *ob_eval, const bool get_cage_mesh); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index fe5b8cff31c..15ba72ef5b5 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2007 by Nicholas Bishop @@ -110,6 +110,11 @@ void multiresModifier_del_levels(struct MultiresModifierData *mmd, void multiresModifier_base_apply(struct Depsgraph *depsgraph, struct Object *object, struct MultiresModifierData *mmd); +int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, + struct Object *object, + struct MultiresModifierData *mmd, + int rebuild_limit, + bool switch_view_to_lower_level); void multiresModifier_subdivide_legacy(struct MultiresModifierData *mmd, struct Scene *scene, struct Object *ob, @@ -175,13 +180,25 @@ bool multiresModifier_reshapeFromCCG(const int tot_level, struct SubdivCCG *subdiv_ccg); /* Subdivide multires displacement once. */ -void multiresModifier_subdivide(struct Object *object, struct MultiresModifierData *mmd); + +typedef enum eMultiresSubdivideModeType { + MULTIRES_SUBDIVIDE_CATMULL_CLARK, + MULTIRES_SUBDIVIDE_SIMPLE, + MULTIRES_SUBDIVIDE_LINEAR, +} eMultiresSubdivideModeType; + +void multiresModifier_subdivide(struct Object *object, + struct MultiresModifierData *mmd, + const eMultiresSubdivideModeType mode); +void multires_subdivide_create_tangent_displacement_linear_grids(struct Object *object, + struct MultiresModifierData *mmd); /* Subdivide displacement to the given level. * If level is lower than the current top level nothing happens. */ void multiresModifier_subdivide_to_level(struct Object *object, struct MultiresModifierData *mmd, - const int top_level); + const int top_level, + const eMultiresSubdivideModeType mode); /* Subdivision integration, defined in multires_subdiv.c */ @@ -213,8 +230,6 @@ BLI_INLINE void BKE_multires_construct_tangent_matrix(float tangent_matrix[3][3] const float dPdv[3], const int corner); -int BKE_multires_sculpt_level_get(const struct MultiresModifierData *mmd); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 38fe974c228..536d04f8bd3 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -385,8 +385,8 @@ struct bNodeTree *ntreeAddTree(struct Main *bmain, const char *name, const char /* copy/free funcs, need to manage ID users */ void ntreeFreeTree(struct bNodeTree *ntree); -/* Free tree which is owned byt another datablock. */ -void ntreeFreeNestedTree(struct bNodeTree *ntree); +/* Free tree which is embedded into another datablock. */ +void ntreeFreeEmbeddedTree(struct bNodeTree *ntree); struct bNodeTree *ntreeCopyTree_ex(const struct bNodeTree *ntree, struct Main *bmain, const bool do_id_user); @@ -852,6 +852,7 @@ struct NodeTreeIterStore { struct Light *light; struct World *world; struct FreestyleLineStyle *linestyle; + struct Simulation *simulation; }; void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *bmain); @@ -1275,13 +1276,44 @@ int ntreeTexExecTree(struct bNodeTree *ntree, float dyt[3], int osatex, const short thread, - struct Tex *tex, + const struct Tex *tex, short which_output, int cfra, int preview, struct MTex *mtex); /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Simulation Nodes + * \{ */ + +#define SIM_NODE_PARTICLE_SIMULATION 1000 +#define SIM_NODE_FORCE 1001 +#define SIM_NODE_SET_PARTICLE_ATTRIBUTE 1002 +#define SIM_NODE_PARTICLE_BIRTH_EVENT 1003 +#define SIM_NODE_PARTICLE_TIME_STEP_EVENT 1004 +#define SIM_NODE_EXECUTE_CONDITION 1005 +#define SIM_NODE_MULTI_EXECUTE 1006 +#define SIM_NODE_PARTICLE_MESH_EMITTER 1007 +#define SIM_NODE_PARTICLE_MESH_COLLISION_EVENT 1008 +#define SIM_NODE_EMIT_PARTICLES 1009 +#define SIM_NODE_TIME 1010 +#define SIM_NODE_PARTICLE_ATTRIBUTE 1011 + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Function Nodes + * \{ */ + +#define FN_NODE_BOOLEAN_MATH 1200 +#define FN_NODE_SWITCH 1201 +#define FN_NODE_FLOAT_COMPARE 1202 +#define FN_NODE_GROUP_INSTANCE_ID 1203 +#define FN_NODE_COMBINE_STRINGS 1204 + +/** \} */ + void init_nodesystem(void); void free_nodesystem(void); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 70a44d6d8ce..3710ec810ce 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -21,12 +21,15 @@ * \ingroup bke * \brief General operations, lookup, etc. for blender objects. */ + +#include "BLI_compiler_attrs.h" + +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - struct Base; struct BoundBox; struct Depsgraph; @@ -46,8 +49,6 @@ struct ShaderFxData; struct View3D; struct ViewLayer; -#include "DNA_object_enums.h" - void BKE_object_workob_clear(struct Object *workob); void BKE_object_workob_calc_parent(struct Depsgraph *depsgraph, struct Scene *scene, diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index a354cb52f59..a7ece2e3167 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -10,7 +10,7 @@ * 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, + * 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) 2009 by Nicholas Bishop @@ -24,6 +24,9 @@ * \ingroup bke */ +#include "BLI_utildefines.h" +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -65,9 +68,6 @@ struct tPaletteColorHSV; enum eOverlayFlags; -#include "BLI_utildefines.h" -#include "DNA_object_enums.h" - extern const char PAINT_CURSOR_SCULPT[3]; extern const char PAINT_CURSOR_VERTEX_PAINT[3]; extern const char PAINT_CURSOR_WEIGHT_PAINT[3]; diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index 94f0e544a6b..35dd241c173 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -48,6 +48,7 @@ struct Mesh; struct PBVH; struct PBVHNode; struct SubdivCCG; +struct TaskParallelSettings; struct TaskParallelTLS; typedef struct PBVH PBVH; @@ -456,30 +457,10 @@ bool pbvh_has_face_sets(PBVH *bvh); void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets); /* Parallelization */ -typedef void (*PBVHParallelRangeFunc)(void *__restrict userdata, - const int iter, - const struct TaskParallelTLS *__restrict tls); -typedef void (*PBVHParallelReduceFunc)(const void *__restrict userdata, - void *__restrict chunk_join, - void *__restrict chunk); - -typedef struct PBVHParallelSettings { - bool use_threading; - void *userdata_chunk; - size_t userdata_chunk_size; - PBVHParallelReduceFunc func_reduce; -} PBVHParallelSettings; - -void BKE_pbvh_parallel_range_settings(struct PBVHParallelSettings *settings, +void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings, bool use_threading, int totnode); -void BKE_pbvh_parallel_range(const int start, - const int stop, - void *userdata, - PBVHParallelRangeFunc func, - const struct PBVHParallelSettings *settings); - struct MVert *BKE_pbvh_get_verts(const PBVH *bvh); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index c2fad6db314..164783f4d14 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/BKE_report.h b/source/blender/blenkernel/BKE_report.h index d7ce9625548..063c0831a0d 100644 --- a/source/blender/blenkernel/BKE_report.h +++ b/source/blender/blenkernel/BKE_report.h @@ -21,16 +21,16 @@ * \ingroup bke */ -#ifdef __cplusplus -extern "C" { -#endif - #include <stdio.h> #include "BLI_compiler_attrs.h" #include "BLI_utildefines.h" #include "DNA_windowmanager_types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* Reporting Information and Errors * * These functions also accept NULL in case no error reporting diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index dc1c80bb0f5..a50f9b24c61 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -219,6 +219,15 @@ struct ImBuf *BKE_sequencer_give_ibuf_seqbase(const SeqRenderData *context, float cfra, int chan_shown, struct ListBase *seqbasep); +struct ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh, + const SeqRenderData *context, + struct Sequence *seq, + float cfra, + float facf0, + float facf1, + struct ImBuf *ibuf1, + struct ImBuf *ibuf2, + struct ImBuf *ibuf3); /* ********************************************************************** * sequencer.c @@ -380,6 +389,10 @@ struct Sequence *BKE_sequencer_prefetch_get_original_sequence(struct Sequence *s /* intern */ struct SeqEffectHandle BKE_sequence_get_blend(struct Sequence *seq); void BKE_sequence_effect_speed_rebuild_map(struct Scene *scene, struct Sequence *seq, bool force); +float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, + struct Sequence *seq, + float cfra, + int input); /* extern */ struct SeqEffectHandle BKE_sequence_get_effect(struct Sequence *seq); @@ -513,6 +526,7 @@ void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); void BKE_sequence_init_colorspace(struct Sequence *seq); float BKE_sequence_get_fps(struct Scene *scene, struct Sequence *seq); +float BKE_sequencer_give_stripelem_index(struct Sequence *seq, float cfra); /* RNA enums, just to be more readable */ enum { diff --git a/source/blender/blenkernel/BKE_shader_fx.h b/source/blender/blenkernel/BKE_shader_fx.h index c8386a42c9a..bdc782a606e 100644 --- a/source/blender/blenkernel/BKE_shader_fx.h +++ b/source/blender/blenkernel/BKE_shader_fx.h @@ -162,20 +162,20 @@ typedef struct ShaderFxTypeInfo { /* Initialize global data (type info and some common global storages). */ void BKE_shaderfx_init(void); -const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type); +const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type); struct ShaderFxData *BKE_shaderfx_new(int type); void BKE_shaderfx_free_ex(struct ShaderFxData *fx, const int flag); void BKE_shaderfx_free(struct ShaderFxData *fx); bool BKE_shaderfx_unique_name(struct ListBase *shaderfx, struct ShaderFxData *fx); -bool BKE_shaderfx_dependsOnTime(struct ShaderFxData *fx); -struct ShaderFxData *BKE_shaderfx_findByType(struct Object *ob, ShaderFxType type); -struct ShaderFxData *BKE_shaderfx_findByName(struct Object *ob, const char *name); -void BKE_shaderfx_copyData_generic(const struct ShaderFxData *fx_src, struct ShaderFxData *fx_dst); -void BKE_shaderfx_copyData(struct ShaderFxData *fx, struct ShaderFxData *target); -void BKE_shaderfx_copyData_ex(struct ShaderFxData *fx, +bool BKE_shaderfx_depends_ontime(struct ShaderFxData *fx); +struct ShaderFxData *BKE_shaderfx_findby_type(struct Object *ob, ShaderFxType type); +struct ShaderFxData *BKE_shaderfx_findby_name(struct Object *ob, const char *name); +void BKE_shaderfx_copydata_generic(const struct ShaderFxData *fx_src, struct ShaderFxData *fx_dst); +void BKE_shaderfx_copydata(struct ShaderFxData *fx, struct ShaderFxData *target); +void BKE_shaderfx_copydata_ex(struct ShaderFxData *fx, struct ShaderFxData *target, const int flag); -void BKE_shaderfx_foreachIDLink(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData); +void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, void *userData); bool BKE_shaderfx_has_gpencil(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_simulation.h b/source/blender/blenkernel/BKE_simulation.h new file mode 100644 index 00000000000..d1cf782e9e5 --- /dev/null +++ b/source/blender/blenkernel/BKE_simulation.h @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef __BKE_SIMULATION_H__ +#define __BKE_SIMULATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct Main; +struct Simulation; +struct Depsgraph; + +void *BKE_simulation_add(struct Main *bmain, const char *name); + +void BKE_simulation_data_update(struct Depsgraph *depsgraph, struct Scene *scene); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_SIMULATION_H__ */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 685582bcecf..b93591b7b60 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -164,7 +164,7 @@ void BKE_sound_stop_scene(struct Scene *scene); void BKE_sound_seek_scene(struct Main *bmain, struct Scene *scene); -float BKE_sound_sync_scene(struct Scene *scene); +double BKE_sound_sync_scene(struct Scene *scene); int BKE_sound_scene_playing(struct Scene *scene); @@ -180,10 +180,10 @@ float BKE_sound_get_length(struct Main *bmain, struct bSound *sound); char **BKE_sound_get_device_names(void); -typedef void (*SoundJackSyncCallback)(struct Main *bmain, int mode, float time); +typedef void (*SoundJackSyncCallback)(struct Main *bmain, int mode, double time); void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback); -void BKE_sound_jack_scene_update(struct Scene *scene, int mode, float time); +void BKE_sound_jack_scene_update(struct Scene *scene, int mode, double time); /* Dependency graph evaluation. */ diff --git a/source/blender/blenkernel/BKE_subdiv_ccg.h b/source/blender/blenkernel/BKE_subdiv_ccg.h index 7c7638e65d2..8d2565c31f7 100644 --- a/source/blender/blenkernel/BKE_subdiv_ccg.h +++ b/source/blender/blenkernel/BKE_subdiv_ccg.h @@ -40,7 +40,7 @@ struct DMFlagMat; struct Mesh; struct Subdiv; -/* ============================================================================= +/* -------------------------------------------------------------------- * Masks. */ @@ -61,7 +61,7 @@ typedef struct SubdivCCGMaskEvaluator { bool BKE_subdiv_ccg_mask_init_from_paint(SubdivCCGMaskEvaluator *mask_evaluator, const struct Mesh *mesh); -/* ============================================================================= +/* -------------------------------------------------------------------- * Materials. */ @@ -80,7 +80,7 @@ typedef struct SubdivCCGMaterialFlagsEvaluator { void BKE_subdiv_ccg_material_flags_init_from_mesh( SubdivCCGMaterialFlagsEvaluator *material_flags_evaluator, const struct Mesh *mesh); -/* ============================================================================= +/* -------------------------------------------------------------------- * SubdivCCG. */ diff --git a/source/blender/blenkernel/BKE_text_suggestions.h b/source/blender/blenkernel/BKE_text_suggestions.h index dc908ee5232..d618fcd6d11 100644 --- a/source/blender/blenkernel/BKE_text_suggestions.h +++ b/source/blender/blenkernel/BKE_text_suggestions.h @@ -23,12 +23,12 @@ * \ingroup bke */ +#include "DNA_text_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_text_types.h" - /* **************************************************************************** * Suggestions should be added in sorted order although a linear sorting method is * implemented. The list is then divided up based on the prefix provided by diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 20236745438..bb88fbf863b 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -261,8 +261,16 @@ void BKE_tracking_distortion_undistort_v2(struct MovieDistortion *distortion, float r_co[2]); void BKE_tracking_distortion_free(struct MovieDistortion *distortion); -void BKE_tracking_distort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); -void BKE_tracking_undistort_v2(struct MovieTracking *tracking, const float co[2], float r_co[2]); +void BKE_tracking_distort_v2(struct MovieTracking *tracking, + int image_width, + int image_height, + const float co[2], + float r_co[2]); +void BKE_tracking_undistort_v2(struct MovieTracking *tracking, + int image_width, + int image_height, + const float co[2], + float r_co[2]); struct ImBuf *BKE_tracking_undistort_frame(struct MovieTracking *tracking, struct ImBuf *ibuf, @@ -276,6 +284,8 @@ struct ImBuf *BKE_tracking_distort_frame(struct MovieTracking *tracking, float overscan); void BKE_tracking_max_distortion_delta_across_bound(struct MovieTracking *tracking, + int image_width, + int image_height, struct rcti *rect, bool undistort, float delta[2]); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 6e612df33d5..9716e5f5d3f 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -116,11 +116,13 @@ set(SRC intern/editmesh_tangent.c intern/effect.c intern/fcurve.c + intern/fcurve_driver.c intern/fluid.c intern/fmodifier.c intern/font.c intern/freestyle.c intern/gpencil.c + intern/gpencil_curve.c intern/gpencil_geom.c intern/gpencil_modifier.c intern/hair.c @@ -175,9 +177,11 @@ set(SRC intern/multires_reshape_apply_base.c intern/multires_reshape_ccg.c intern/multires_reshape_smooth.c + intern/multires_reshape_subdivide.c intern/multires_reshape_util.c intern/multires_reshape_vertcos.c intern/multires_subdiv.c + intern/multires_unsubdivide.c intern/nla.c intern/node.c intern/object.c @@ -197,7 +201,6 @@ set(SRC intern/particle_system.c intern/pbvh.c intern/pbvh_bmesh.c - intern/pbvh_parallel.cc intern/pointcache.c intern/pointcloud.c intern/report.c @@ -211,6 +214,7 @@ set(SRC intern/sequencer.c intern/shader_fx.c intern/shrinkwrap.c + intern/simulation.cc intern/softbody.c intern/sound.c intern/speaker.c @@ -299,11 +303,13 @@ set(SRC BKE_editmesh_tangent.h BKE_effect.h BKE_fcurve.h + BKE_fcurve_driver.h BKE_fluid.h BKE_font.h BKE_freestyle.h BKE_global.h BKE_gpencil.h + BKE_gpencil_curve.h BKE_gpencil_geom.h BKE_gpencil_modifier.h BKE_hair.h @@ -362,6 +368,7 @@ set(SRC BKE_sequencer.h BKE_shader_fx.h BKE_shrinkwrap.h + BKE_simulation.h BKE_softbody.h BKE_sound.h BKE_speaker.h @@ -396,6 +403,7 @@ set(SRC intern/lib_intern.h intern/multires_inline.h intern/multires_reshape.h + intern/multires_unsubdivide.h intern/pbvh_intern.h intern/subdiv_converter.h intern/subdiv_inline.h @@ -666,17 +674,6 @@ if(WITH_QUADRIFLOW) add_definitions(-DWITH_QUADRIFLOW) endif() -if(WITH_TBB) - add_definitions(-DWITH_TBB) - - list(APPEND INC_SYS - ${TBB_INCLUDE_DIRS} - ) - list(APPEND LIB - ${TBB_LIBRARIES} - ) -endif() - if(WITH_XR_OPENXR) add_definitions(-DWITH_XR_OPENXR) endif() diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index baef2b2290e..b3893d8600f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -698,7 +698,8 @@ static float (*get_orco_coords(Object *ob, BMEditMesh *em, int layer, int *free) /* apply shape key for cloth, this should really be solved * by a more flexible customdata system, but not simple */ if (!em) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type( + ob, eModifierType_Cloth); KeyBlock *kb = BKE_keyblock_from_key(BKE_key_from_object(ob), clmd->sim_parms->shapekey_rest); @@ -901,21 +902,21 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Sculpt can skip certain modifiers. */ MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); - const bool has_multires = (mmd && BKE_multires_sculpt_level_get(mmd) != 0); + const bool has_multires = (mmd && mmd->sculptlvl != 0); bool multires_applied = false; const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !use_render; const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !use_render; /* Modifier evaluation contexts for different types of modifiers. */ - ModifierApplyFlag app_render = use_render ? MOD_APPLY_RENDER : 0; - ModifierApplyFlag app_cache = use_cache ? MOD_APPLY_USECACHE : 0; - const ModifierEvalContext mectx = {depsgraph, ob, app_render | app_cache}; - const ModifierEvalContext mectx_orco = {depsgraph, ob, app_render | MOD_APPLY_ORCO}; + ModifierApplyFlag apply_render = use_render ? MOD_APPLY_RENDER : 0; + ModifierApplyFlag apply_cache = use_cache ? MOD_APPLY_USECACHE : 0; + const ModifierEvalContext mectx = {depsgraph, ob, apply_render | apply_cache}; + const ModifierEvalContext mectx_orco = {depsgraph, ob, apply_render | MOD_APPLY_ORCO}; /* Get effective list of modifiers to execute. Some effects like shape keys * are added as virtual modifiers before the user created modifiers. */ VirtualModifierData virtualModifierData; - ModifierData *firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *firstmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *md = firstmd; /* Preview colors by modifiers such as dynamic paint, to show the results @@ -929,7 +930,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* XXX Currently, DPaint modifier just ignores this. * Needs a stupid hack... * The whole "modifier preview" thing has to be (re?)designed, anyway! */ - previewmd = modifiers_getLastPreview(scene, md, required_mode); + previewmd = BKE_modifier_get_last_preview(scene, md, required_mode); } /* Compute accumulated datamasks needed by each modifier. It helps to do @@ -937,21 +938,21 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, * an armature modifier, but not through a following subsurf modifier where * subdividing them is expensive. */ CustomData_MeshMasks final_datamask = *dataMask; - CDMaskLink *datamasks = modifiers_calcDataMasks( + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( scene, ob, md, &final_datamask, required_mode, previewmd, &previewmask); CDMaskLink *md_datamask = datamasks; /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ CustomData_MeshMasks append_mask = CD_MASK_BAREMESH_ORIGINDEX; /* Clear errors before evaluation. */ - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); /* Apply all leading deform modifiers. */ if (useDeform) { for (; md; md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } @@ -971,7 +972,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } - modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); isPrevDeform = true; } @@ -1001,9 +1002,9 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, /* Apply all remaining constructive and deforming modifiers. */ bool have_non_onlydeform_modifiers_appled = false; for (; md; md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } @@ -1013,15 +1014,14 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && have_non_onlydeform_modifiers_appled) { - modifier_setError(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); continue; } if (sculpt_mode && (!has_multires || multires_applied || sculpt_dyntopo)) { bool unsupported = false; - if (md->type == eModifierType_Multires && - BKE_multires_sculpt_level_get((MultiresModifierData *)md) == 0) { + if (md->type == eModifierType_Multires && ((MultiresModifierData *)md)->sculptlvl == 0) { /* If multires is on level 0 skip it silently without warning message. */ if (!sculpt_dyntopo) { continue; @@ -1040,19 +1040,19 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, if (unsupported) { if (sculpt_dyntopo) { - modifier_setError(md, "Not supported in dyntopo"); + BKE_modifier_set_error(md, "Not supported in dyntopo"); } else { - modifier_setError(md, "Not supported in sculpt mode"); + BKE_modifier_set_error(md, "Not supported in sculpt mode"); } continue; } else { - modifier_setError(md, "Sculpt: Hide, Mask and optimized display disabled"); + BKE_modifier_set_error(md, "Sculpt: Hide, Mask and optimized display disabled"); } } - if (need_mapping && !modifier_supportsMapping(md)) { + if (need_mapping && !BKE_modifier_supports_mapping(md)) { continue; } @@ -1094,7 +1094,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } BKE_mesh_vert_coords_apply(mesh_final, deformed_verts); } - modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); } else { have_non_onlydeform_modifiers_appled = true; @@ -1176,7 +1176,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final); + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1212,7 +1212,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, CustomData_MeshMasks_update(&temp_cddata_masks, &nextmask); mesh_set_only_copy(mesh_orco, &temp_cddata_masks); - mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco); + mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1238,7 +1238,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, nextmask.pmask |= CD_MASK_ORIGINDEX; mesh_set_only_copy(mesh_orco_cloth, &nextmask); - mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco_cloth); + mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco_cloth); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1276,7 +1276,7 @@ static void mesh_calc_modifiers(struct Depsgraph *depsgraph, BLI_linklist_free((LinkNode *)datamasks, NULL); for (md = firstmd; md; md = md->next) { - modifier_freeTemporaryData(md); + BKE_modifier_free_temporary_data(md); } /* Yay, we are done. If we have a Mesh and deformed vertices, @@ -1376,15 +1376,15 @@ float (*editbmesh_vert_coords_alloc(BMEditMesh *em, int *r_vert_len))[3] bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, bool has_prev_mesh) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { return false; } if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && has_prev_mesh) { - modifier_setError(md, "Modifier requires original data, bad stack position"); + BKE_modifier_set_error(md, "Modifier requires original data, bad stack position"); return false; } @@ -1486,30 +1486,30 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, /* Get effective list of modifiers to execute. Some effects like shape keys * are added as virtual modifiers before the user created modifiers. */ VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* Compute accumulated datamasks needed by each modifier. It helps to do * this fine grained so that for example vertex groups are preserved up to * an armature modifier, but not through a following subsurf modifier where * subdividing them is expensive. */ CustomData_MeshMasks final_datamask = *dataMask; - CDMaskLink *datamasks = modifiers_calcDataMasks( + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( scene, ob, md, &final_datamask, required_mode, NULL, NULL); CDMaskLink *md_datamask = datamasks; CustomData_MeshMasks append_mask = CD_MASK_BAREMESH; /* Evaluate modifiers up to certain index to get the mesh cage. */ - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); if (r_cage && cageIndex == -1) { mesh_cage = BKE_mesh_from_editmesh_with_coords_thin_wrap( em_input, &final_datamask, NULL, mesh_input); } /* Clear errors before evaluation. */ - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); for (int i = 0; md; i++, md = md->next, md_datamask = md_datamask->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (!editbmesh_modifier_is_enabled(scene, md, mesh_final != NULL)) { continue; @@ -1550,11 +1550,11 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } if (mti->deformVertsEM) { - modwrap_deformVertsEM( + BKE_modifier_deform_vertsEM( md, &mectx, em_input, mesh_final, deformed_verts, num_deformed_verts); } else { - modwrap_deformVerts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts(md, &mectx, mesh_final, deformed_verts, num_deformed_verts); } } else { @@ -1595,7 +1595,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, mask.pmask |= CD_MASK_ORIGINDEX; mesh_set_only_copy(mesh_orco, &mask); - Mesh *mesh_next = modwrap_applyModifier(md, &mectx_orco, mesh_orco); + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx_orco, mesh_orco); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { @@ -1626,7 +1626,7 @@ static void editbmesh_calc_modifiers(struct Depsgraph *depsgraph, } } - Mesh *mesh_next = modwrap_applyModifier(md, &mectx, mesh_final); + Mesh *mesh_next = BKE_modifier_modify_mesh(md, &mectx, mesh_final); ASSERT_IS_VALID_MESH(mesh_next); if (mesh_next) { diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index ba77538bfb6..4f51e23496c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1665,6 +1665,6 @@ void what_does_obaction( adt.action = act; /* execute effects of Action on to workob (or it's PoseChannels) */ - BKE_animsys_evaluate_animdata(NULL, &workob->id, &adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob->id, &adt, cframe, ADT_RECALC_ANIM, false); } } diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 41bfc5b59e4..02b7763a9b4 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -29,6 +29,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_lib_id.h" #include "BKE_main.h" @@ -95,6 +96,7 @@ bool id_type_can_have_animdata(const short id_type) case ID_HA: case ID_PT: case ID_VO: + case ID_SIM: return true; /* no AnimData */ @@ -1321,6 +1323,9 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use /* volumes */ ANIMDATA_IDS_CB(bmain->volumes.first); + + /* simulations */ + ANIMDATA_IDS_CB(bmain->simulations.first); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -1430,6 +1435,9 @@ void BKE_animdata_fix_paths_rename_all(ID *ref_id, /* volumes */ RENAMEFIX_ANIM_IDS(bmain->volumes.first); + /* simulations */ + RENAMEFIX_ANIM_IDS(bmain->simulations.first); + /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(bmain->scenes.first, Scene); } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 18320ef0f8d..5e4b280d0d0 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -2500,7 +2500,7 @@ static void animsys_evaluate_overrides(PointerRNA *ptr, AnimData *adt) * have been set already by the depsgraph. Now, we use the recalc */ void BKE_animsys_evaluate_animdata( - Scene *scene, ID *id, AnimData *adt, float ctime, short recalc, const bool flush_to_original) + ID *id, AnimData *adt, float ctime, eAnimData_Recalc recalc, const bool flush_to_original) { PointerRNA id_ptr; @@ -2547,13 +2547,6 @@ void BKE_animsys_evaluate_animdata( * - It is best that we execute this every time, so that no errors are likely to occur. */ animsys_evaluate_overrides(&id_ptr, adt); - - /* execute and clear all cached property update functions */ - if (scene) { - Main *bmain = G.main; // xxx - to get passed in! - RNA_property_update_cache_flush(bmain, scene); - RNA_property_update_cache_free(); - } } /* Evaluation of all ID-blocks with Animation Data blocks - Animation Data Only @@ -2563,10 +2556,7 @@ void BKE_animsys_evaluate_animdata( * 'local' (i.e. belonging in the nearest ID-block that setting is related to, not a * standard 'root') block are overridden by a larger 'user' */ -void BKE_animsys_evaluate_all_animation(Main *main, - Depsgraph *depsgraph, - Scene *scene, - float ctime) +void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float ctime) { ID *id; @@ -2585,7 +2575,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, for (id = first; id; id = id->next) { \ if (ID_REAL_USERS(id) > 0) { \ AnimData *adt = BKE_animdata_from_id(id); \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2604,9 +2594,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, if (ntp->nodetree) { \ AnimData *adt2 = BKE_animdata_from_id((ID *)ntp->nodetree); \ BKE_animsys_evaluate_animdata( \ - scene, (ID *)ntp->nodetree, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ + &ntp->nodetree->id, adt2, ctime, ADT_RECALC_ANIM, flush_to_original); \ } \ - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, aflag, flush_to_original); \ + BKE_animsys_evaluate_animdata(id, adt, ctime, aflag, flush_to_original); \ } \ } \ (void)0 @@ -2690,6 +2680,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, /* volumes */ EVAL_ANIM_IDS(main->volumes.first, ADT_RECALC_ANIM); + /* simulations */ + EVAL_ANIM_IDS(main->simulations.first, ADT_RECALC_ANIM); + /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets * this tagged by Depsgraph on framechange. This optimization means that objects @@ -2718,10 +2711,9 @@ void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) AnimData *adt = BKE_animdata_from_id(id); /* XXX: this is only needed for flushing RNA updates, * which should get handled as part of the dependency graph instead. */ - Scene *scene = NULL; DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(scene, id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(id, adt, ctime, ADT_RECALC_ANIM, flush_to_original); } void BKE_animsys_update_driver_array(ID *id) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 4071cc024aa..8189385a69d 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -359,7 +359,7 @@ static bool get_path_user(char *targetpath, * \param folder_name: default name of folder within installation area * \param subfolder_name: optional name of subfolder within folder * \param ver: Blender version, used to construct a subdirectory name - * \return true if it was able to construct such a path. + * \return true if it was able to construct such a path. */ static bool get_path_system(char *targetpath, size_t targetpath_len, diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index af98992cc01..06a97fc3826 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -61,6 +61,7 @@ #include "BKE_idtype.h" #include "BKE_lattice.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -150,6 +151,24 @@ static void armature_free_data(struct ID *id) } } +static void armature_foreach_id_bone(Bone *bone, LibraryForeachIDData *data) +{ + IDP_foreach_property( + bone->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + + LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) { + armature_foreach_id_bone(curbone, data); + } +} + +static void armature_foreach_id(ID *id, LibraryForeachIDData *data) +{ + bArmature *arm = (bArmature *)id; + LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { + armature_foreach_id_bone(bone, data); + } +} + IDTypeInfo IDType_ID_AR = { .id_code = ID_AR, .id_filter = FILTER_ID_AR, @@ -164,6 +183,7 @@ IDTypeInfo IDType_ID_AR = { .copy_data = armature_copy_data, .free_data = armature_free_data, .make_local = NULL, + .foreach_id = armature_foreach_id, }; /* **************** Generic Functions, data level *************** */ diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index 5c000fbcb36..13dcc7b06f6 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -279,9 +279,6 @@ static void setup_app_data(bContext *C, // CTX_wm_manager_set(C, NULL); BKE_blender_globals_clear(); - /* clear old property update cache, in case some old references are left dangling */ - RNA_property_update_cache_free(); - bmain = G_MAIN = bfd->main; bfd->main = NULL; diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index a493d5f49c8..6197b9dbefd 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -861,7 +861,7 @@ static Object *boid_find_ground(BoidBrainData *bbd, SurfaceModifierData *surmd = NULL; float x[3], v[3]; - surmd = (SurfaceModifierData *)modifiers_findByType(bpa->ground, eModifierType_Surface); + surmd = (SurfaceModifierData *)BKE_modifiers_findby_type(bpa->ground, eModifierType_Surface); /* take surface velocity into account */ closest_point_on_surface(surmd, pa->state.co, x, NULL, v); diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 8d35abc1523..0e6b9409404 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -49,7 +49,7 @@ #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "RE_render_ext.h" /* externtex */ +#include "RE_render_ext.h" /* RE_texture_evaluate */ static void brush_init_data(ID *id) { @@ -89,6 +89,19 @@ static void brush_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c brush_src->gpencil_settings->curve_strength); brush_dst->gpencil_settings->curve_jitter = BKE_curvemapping_copy( brush_src->gpencil_settings->curve_jitter); + + brush_dst->gpencil_settings->curve_rand_pressure = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_pressure); + brush_dst->gpencil_settings->curve_rand_strength = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_strength); + brush_dst->gpencil_settings->curve_rand_uv = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_uv); + brush_dst->gpencil_settings->curve_rand_hue = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_hue); + brush_dst->gpencil_settings->curve_rand_saturation = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_saturation); + brush_dst->gpencil_settings->curve_rand_value = BKE_curvemapping_copy( + brush_src->gpencil_settings->curve_rand_value); } /* enable fake user by default */ @@ -107,6 +120,14 @@ static void brush_free_data(ID *id) BKE_curvemapping_free(brush->gpencil_settings->curve_sensitivity); BKE_curvemapping_free(brush->gpencil_settings->curve_strength); BKE_curvemapping_free(brush->gpencil_settings->curve_jitter); + + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_pressure); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_strength); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_uv); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_hue); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_saturation); + BKE_curvemapping_free(brush->gpencil_settings->curve_rand_value); + MEM_SAFE_FREE(brush->gpencil_settings); } @@ -280,6 +301,13 @@ void BKE_brush_init_gpencil_settings(Brush *brush) brush->gpencil_settings->curve_sensitivity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); brush->gpencil_settings->curve_strength = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); brush->gpencil_settings->curve_jitter = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + + brush->gpencil_settings->curve_rand_pressure = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_strength = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_uv = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_hue = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_saturation = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); } /* add a new gp-brush */ @@ -1572,8 +1600,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene, else if (mtex->brush_map_mode == MTEX_MAP_MODE_3D) { /* Get strength by feeding the vertex * location directly into a texture */ - hasrgb = externtex( - mtex, point, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + hasrgb = RE_texture_evaluate(mtex, point, thread, pool, false, false, &intensity, rgba); } else if (mtex->brush_map_mode == MTEX_MAP_MODE_STENCIL) { float rotation = -mtex->rot; @@ -1603,8 +1630,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene, co[1] = y; co[2] = 0.0f; - hasrgb = externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } else { float rotation = -mtex->rot; @@ -1660,8 +1686,7 @@ float BKE_brush_sample_tex_3d(const Scene *scene, co[1] = y; co[2] = 0.0f; - hasrgb = externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } intensity += br->texture_sample_bias; @@ -1718,8 +1743,7 @@ float BKE_brush_sample_masktex( co[1] = y; co[2] = 0.0f; - externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } else { float rotation = -mtex->rot; @@ -1775,8 +1799,7 @@ float BKE_brush_sample_masktex( co[1] = y; co[2] = 0.0f; - externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); } CLAMP(intensity, 0.0f, 1.0f); @@ -2080,7 +2103,7 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec unsigned int *texcache = NULL; MTex *mtex = (use_secondary) ? &br->mask_mtex : &br->mtex; float intensity; - float rgba[4]; + float rgba_dummy[4]; int ix, iy; int side = half_side * 2; @@ -2098,11 +2121,8 @@ unsigned int *BKE_brush_gen_texture_cache(Brush *br, int half_side, bool use_sec /* This is copied from displace modifier code */ /* TODO(sergey): brush are always caching with CM enabled for now. */ - externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); - - ((char *)texcache)[(iy * side + ix) * 4] = ((char *)texcache)[(iy * side + ix) * 4 + 1] = - ((char *)texcache)[(iy * side + ix) * 4 + 2] = (( - char *)texcache)[(iy * side + ix) * 4 + 3] = (char)(intensity * 255.0f); + RE_texture_evaluate(mtex, co, 0, NULL, false, false, &intensity, rgba_dummy); + copy_v4_uchar((uchar *)&texcache[iy * side + ix], (char)(intensity * 255.0f)); } } } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 8a0df6375be..879313783d9 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 04663115424..0b9780ac81c 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -333,13 +333,13 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, Mesh *result, int 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"); + BKE_modifier_set_error(&(clmd->modifier), "Can't initialize cloth"); return 0; } if (clmd->clothObject == NULL) { BKE_ptcache_invalidate(cache); - modifier_setError(&(clmd->modifier), "Null cloth object"); + BKE_modifier_set_error(&(clmd->modifier), "Null cloth object"); return 0; } @@ -841,7 +841,7 @@ static int cloth_from_object( clmd->clothObject->edgeset = NULL; } else { - modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); + BKE_modifier_set_error(&(clmd->modifier), "Out of memory on allocating clmd->clothObject"); return 0; } @@ -913,7 +913,7 @@ static int cloth_from_object( if (!cloth_build_springs(clmd, mesh)) { cloth_free_modifier(clmd); - modifier_setError(&(clmd->modifier), "Cannot build springs"); + BKE_modifier_set_error(&(clmd->modifier), "Cannot build springs"); return 0; } @@ -943,7 +943,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) "clothVertex"); if (clmd->clothObject->verts == NULL) { cloth_free_modifier(clmd); - modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->verts"); + BKE_modifier_set_error(&(clmd->modifier), + "Out of memory on allocating clmd->clothObject->verts"); printf("cloth_free_modifier clmd->clothObject->verts\n"); return; } @@ -959,7 +960,8 @@ static void cloth_from_mesh(ClothModifierData *clmd, Mesh *mesh) clmd->clothObject->tri = MEM_mallocN(sizeof(MVertTri) * looptri_num, "clothLoopTris"); if (clmd->clothObject->tri == NULL) { cloth_free_modifier(clmd); - modifier_setError(&(clmd->modifier), "Out of memory on allocating clmd->clothObject->looptri"); + BKE_modifier_set_error(&(clmd->modifier), + "Out of memory on allocating clmd->clothObject->looptri"); printf("cloth_free_modifier clmd->clothObject->looptri\n"); return; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 7cc40007e26..daf1602319f 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -1307,7 +1307,7 @@ static void add_collision_object(ListBase *relations, /* only get objects with collision modifier */ if (((modifier_type == eModifierType_Collision) && ob->pd && ob->pd->deflect) || (modifier_type != eModifierType_Collision)) { - cmd = (CollisionModifierData *)modifiers_findByType(ob, modifier_type); + cmd = (CollisionModifierData *)BKE_modifiers_findby_type(ob, modifier_type); } if (cmd) { @@ -1426,7 +1426,7 @@ ListBase *BKE_collider_cache_create(Depsgraph *depsgraph, Object *self, Collecti continue; } - CollisionModifierData *cmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *cmd = (CollisionModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Collision); if (cmd && cmd->bvhtree) { if (cache == NULL) { @@ -1527,7 +1527,7 @@ static int cloth_bvh_objcollisions_resolve(ClothModifierData *clmd, for (i = 0; i < numcollobj; i++) { Object *collob = collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *collmd = (CollisionModifierData *)BKE_modifiers_findby_type( collob, eModifierType_Collision); if (collmd->bvhtree) { @@ -1658,7 +1658,7 @@ int cloth_bvh_collision( for (i = 0; i < numcollobj; i++) { Object *collob = collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *collmd = (CollisionModifierData *)BKE_modifiers_findby_type( collob, eModifierType_Collision); if (!collmd->bvhtree) { @@ -1693,7 +1693,7 @@ int cloth_bvh_collision( for (i = 0; i < numcollobj; i++) { Object *collob = collobjs[i]; - CollisionModifierData *collmd = (CollisionModifierData *)modifiers_findByType( + CollisionModifierData *collmd = (CollisionModifierData *)BKE_modifiers_findby_type( collob, eModifierType_Collision); if (!collmd->bvhtree) { diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index f82b8b6675c..3da384a2745 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1383,8 +1383,6 @@ typedef struct ScopesUpdateData { struct ColormanageProcessor *cm_processor; const unsigned char *display_buffer; const int ycc_mode; - - unsigned int *bin_lum, *bin_r, *bin_g, *bin_b, *bin_a; } ScopesUpdateData; typedef struct ScopesUpdateDataChunk { @@ -1495,23 +1493,24 @@ static void scopes_update_cb(void *__restrict userdata, } } -static void scopes_update_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void scopes_update_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - const ScopesUpdateData *data = userdata; - const ScopesUpdateDataChunk *data_chunk = userdata_chunk; - - unsigned int *bin_lum = data->bin_lum; - unsigned int *bin_r = data->bin_r; - unsigned int *bin_g = data->bin_g; - unsigned int *bin_b = data->bin_b; - unsigned int *bin_a = data->bin_a; + ScopesUpdateDataChunk *join_chunk = chunk_join; + const ScopesUpdateDataChunk *data_chunk = chunk; + + unsigned int *bin_lum = join_chunk->bin_lum; + unsigned int *bin_r = join_chunk->bin_r; + unsigned int *bin_g = join_chunk->bin_g; + unsigned int *bin_b = join_chunk->bin_b; + unsigned int *bin_a = join_chunk->bin_a; const unsigned int *bin_lum_c = data_chunk->bin_lum; const unsigned int *bin_r_c = data_chunk->bin_r; const unsigned int *bin_g_c = data_chunk->bin_g; const unsigned int *bin_b_c = data_chunk->bin_b; const unsigned int *bin_a_c = data_chunk->bin_a; - float(*minmax)[2] = data->scopes->minmax; const float *min = data_chunk->min; const float *max = data_chunk->max; @@ -1524,11 +1523,11 @@ static void scopes_update_finalize(void *__restrict userdata, void *__restrict u } for (int c = 3; c--;) { - if (min[c] < minmax[c][0]) { - minmax[c][0] = min[c]; + if (min[c] < join_chunk->min[c]) { + join_chunk->min[c] = min[c]; } - if (max[c] > minmax[c][1]) { - minmax[c][1] = max[c]; + if (max[c] > join_chunk->max[c]) { + join_chunk->max[c] = max[c]; } } } @@ -1542,7 +1541,6 @@ void BKE_scopes_update(Scopes *scopes, unsigned int nl, na, nr, ng, nb; double divl, diva, divr, divg, divb; const unsigned char *display_buffer = NULL; - uint bin_lum[256] = {0}, bin_r[256] = {0}, bin_g[256] = {0}, bin_b[256] = {0}, bin_a[256] = {0}; int ycc_mode = -1; void *cache_handle = NULL; struct ColormanageProcessor *cm_processor = NULL; @@ -1638,11 +1636,6 @@ void BKE_scopes_update(Scopes *scopes, .cm_processor = cm_processor, .display_buffer = display_buffer, .ycc_mode = ycc_mode, - .bin_lum = bin_lum, - .bin_r = bin_r, - .bin_g = bin_g, - .bin_b = bin_b, - .bin_a = bin_a, }; ScopesUpdateDataChunk data_chunk = {{0}}; INIT_MINMAX(data_chunk.min, data_chunk.max); @@ -1652,26 +1645,26 @@ void BKE_scopes_update(Scopes *scopes, settings.use_threading = (ibuf->y > 256); settings.userdata_chunk = &data_chunk; settings.userdata_chunk_size = sizeof(data_chunk); - settings.func_finalize = scopes_update_finalize; + settings.func_reduce = scopes_update_reduce; BLI_task_parallel_range(0, ibuf->y, &data, scopes_update_cb, &settings); /* convert hist data to float (proportional to max count) */ nl = na = nr = nb = ng = 0; for (a = 0; a < 256; a++) { - if (bin_lum[a] > nl) { - nl = bin_lum[a]; + if (data_chunk.bin_lum[a] > nl) { + nl = data_chunk.bin_lum[a]; } - if (bin_r[a] > nr) { - nr = bin_r[a]; + if (data_chunk.bin_r[a] > nr) { + nr = data_chunk.bin_r[a]; } - if (bin_g[a] > ng) { - ng = bin_g[a]; + if (data_chunk.bin_g[a] > ng) { + ng = data_chunk.bin_g[a]; } - if (bin_b[a] > nb) { - nb = bin_b[a]; + if (data_chunk.bin_b[a] > nb) { + nb = data_chunk.bin_b[a]; } - if (bin_a[a] > na) { - na = bin_a[a]; + if (data_chunk.bin_a[a] > na) { + na = data_chunk.bin_a[a]; } } divl = nl ? 1.0 / (double)nl : 1.0; @@ -1681,11 +1674,11 @@ void BKE_scopes_update(Scopes *scopes, divb = nb ? 1.0 / (double)nb : 1.0; for (a = 0; a < 256; a++) { - scopes->hist.data_luma[a] = bin_lum[a] * divl; - scopes->hist.data_r[a] = bin_r[a] * divr; - scopes->hist.data_g[a] = bin_g[a] * divg; - scopes->hist.data_b[a] = bin_b[a] * divb; - scopes->hist.data_a[a] = bin_a[a] * diva; + scopes->hist.data_luma[a] = data_chunk.bin_lum[a] * divl; + scopes->hist.data_r[a] = data_chunk.bin_r[a] * divr; + scopes->hist.data_g[a] = data_chunk.bin_g[a] * divg; + scopes->hist.data_b[a] = data_chunk.bin_b[a] * divb; + scopes->hist.data_a[a] = data_chunk.bin_a[a] * diva; } if (cm_processor) { diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 099fdacf401..679fe703b13 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -62,7 +62,7 @@ #include "BKE_deform.h" #include "BKE_displist.h" #include "BKE_editmesh.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_lib_id.h" @@ -1009,8 +1009,8 @@ static void trackto_new_data(void *cdata) { bTrackToConstraint *data = (bTrackToConstraint *)cdata; - data->reserved1 = TRACK_Y; - data->reserved2 = UP_Z; + data->reserved1 = TRACK_nZ; + data->reserved2 = UP_Y; } static void trackto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -4590,230 +4590,390 @@ static void followtrack_id_looper(bConstraint *con, ConstraintIDFunc func, void func(con, (ID **)&data->depth_ob, false, userdata); } -static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) +static MovieClip *followtrack_tracking_clip_get(bConstraint *con, bConstraintOb *cob) { - Depsgraph *depsgraph = cob->depsgraph; - Scene *scene = cob->scene; bFollowTrackConstraint *data = con->data; - MovieClip *clip = data->clip; + + if (data->flag & FOLLOWTRACK_ACTIVECLIP) { + Scene *scene = cob->scene; + return scene->clip; + } + + return data->clip; +} + +static MovieTrackingObject *followtrack_tracking_object_get(bConstraint *con, bConstraintOb *cob) +{ + MovieClip *clip = followtrack_tracking_clip_get(con, cob); + MovieTracking *tracking = &clip->tracking; + bFollowTrackConstraint *data = con->data; + + if (data->object[0]) { + return BKE_tracking_object_get_named(tracking, data->object); + } + return BKE_tracking_object_get_camera(tracking); +} + +static Object *followtrack_camera_object_get(bConstraint *con, bConstraintOb *cob) +{ + bFollowTrackConstraint *data = con->data; + + if (data->camera == NULL) { + Scene *scene = cob->scene; + return scene->camera; + } + + return data->camera; +} + +typedef struct FollowTrackContext { + int flag; + int frame_method; + + Depsgraph *depsgraph; + Scene *scene; + + MovieClip *clip; + Object *camera_object; + Object *depth_object; + MovieTracking *tracking; - MovieTrackingTrack *track; MovieTrackingObject *tracking_object; - Object *camob = data->camera ? data->camera : scene->camera; + MovieTrackingTrack *track; - float ctime = DEG_get_ctime(depsgraph); - float framenr; + float depsgraph_time; + float clip_frame; +} FollowTrackContext; - if (data->flag & FOLLOWTRACK_ACTIVECLIP) { - clip = scene->clip; - } +static bool followtrack_context_init(FollowTrackContext *context, + bConstraint *con, + bConstraintOb *cob) +{ + bFollowTrackConstraint *data = con->data; - if (!clip || !data->track[0] || !camob) { - return; + context->flag = data->flag; + context->frame_method = data->frame_method; + + context->depsgraph = cob->depsgraph; + context->scene = cob->scene; + + context->clip = followtrack_tracking_clip_get(con, cob); + context->camera_object = followtrack_camera_object_get(con, cob); + if (context->clip == NULL || context->camera_object == NULL) { + return false; } + context->depth_object = data->depth_ob; - tracking = &clip->tracking; + context->tracking = &context->clip->tracking; + context->tracking_object = followtrack_tracking_object_get(con, cob); + if (context->tracking_object == NULL) { + return false; + } - if (data->object[0]) { - tracking_object = BKE_tracking_object_get_named(tracking, data->object); + context->track = BKE_tracking_track_get_named( + context->tracking, context->tracking_object, data->track); + if (context->track == NULL) { + return false; } - else { - tracking_object = BKE_tracking_object_get_camera(tracking); + + context->depsgraph_time = DEG_get_ctime(context->depsgraph); + context->clip_frame = BKE_movieclip_remap_scene_to_clip_frame(context->clip, + context->depsgraph_time); + + return true; +} + +static void followtrack_evaluate_using_3d_position_object(FollowTrackContext *context, + bConstraintOb *cob) +{ + Object *camera_object = context->camera_object; + MovieTracking *tracking = context->tracking; + MovieTrackingTrack *track = context->track; + MovieTrackingObject *tracking_object = context->tracking_object; + + /* Matrix of the object which is being solved prior to this contraint. */ + float obmat[4][4]; + copy_m4_m4(obmat, cob->matrix); + + /* Object matrix of the camera. */ + float camera_obmat[4][4]; + copy_m4_m4(camera_obmat, camera_object->obmat); + + /* Calculate inverted matrix of the solved camera at the current time. */ + float reconstructed_camera_mat[4][4]; + BKE_tracking_camera_get_reconstructed_interpolate( + tracking, tracking_object, context->clip_frame, reconstructed_camera_mat); + float reconstructed_camera_mat_inv[4][4]; + invert_m4_m4(reconstructed_camera_mat_inv, reconstructed_camera_mat); + + mul_m4_series(cob->matrix, obmat, camera_obmat, reconstructed_camera_mat_inv); + translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); +} + +static void followtrack_evaluate_using_3d_position_camera(FollowTrackContext *context, + bConstraintOb *cob) +{ + Object *camera_object = context->camera_object; + MovieTrackingTrack *track = context->track; + + /* Matrix of the object which is being solved prior to this contraint. */ + float obmat[4][4]; + copy_m4_m4(obmat, cob->matrix); + + float reconstructed_camera_mat[4][4]; + BKE_tracking_get_camera_object_matrix(camera_object, reconstructed_camera_mat); + + mul_m4_m4m4(cob->matrix, obmat, reconstructed_camera_mat); + translate_m4(cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); +} + +static void followtrack_evaluate_using_3d_position(FollowTrackContext *context, bConstraintOb *cob) +{ + MovieTrackingTrack *track = context->track; + if ((track->flag & TRACK_HAS_BUNDLE) == 0) { + return; } - if (!tracking_object) { + if ((context->tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { + followtrack_evaluate_using_3d_position_object(context, cob); return; } - track = BKE_tracking_track_get_named(tracking, tracking_object, data->track); + followtrack_evaluate_using_3d_position_camera(context, cob); +} - if (!track) { +/* Apply undistortion if it is enabled in constraint settings. */ +static void followtrack_undistort_if_needed(FollowTrackContext *context, + const int clip_width, + const int clip_height, + float marker_position[2]) +{ + if ((context->flag & FOLLOWTRACK_USE_UNDISTORTION) == 0) { return; } - framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, ctime); + /* Undistortion need to happen in pixel space. */ + marker_position[0] *= clip_width; + marker_position[1] *= clip_height; - if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { - if (track->flag & TRACK_HAS_BUNDLE) { - float obmat[4][4], mat[4][4]; + BKE_tracking_undistort_v2( + context->tracking, clip_width, clip_height, marker_position, marker_position); - copy_m4_m4(obmat, cob->matrix); + /* Normalize pixel coordinates back. */ + marker_position[0] /= clip_width; + marker_position[1] /= clip_height; +} - if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { - float imat[4][4]; +/* Modify the marker position matching the frame fitting method. */ +static void followtrack_fit_frame(FollowTrackContext *context, + const int clip_width, + const int clip_height, + float marker_position[2]) +{ + if (context->frame_method == FOLLOWTRACK_FRAME_STRETCH) { + return; + } - copy_m4_m4(mat, camob->obmat); + Scene *scene = context->scene; + MovieClip *clip = context->clip; - BKE_tracking_camera_get_reconstructed_interpolate( - tracking, tracking_object, framenr, imat); - invert_m4(imat); + /* apply clip display aspect */ + const float w_src = clip_width * clip->aspx; + const float h_src = clip_height * clip->aspy; - mul_m4_series(cob->matrix, obmat, mat, imat); - translate_m4( - cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); - } - else { - BKE_tracking_get_camera_object_matrix(camob, mat); + const float w_dst = scene->r.xsch * scene->r.xasp; + const float h_dst = scene->r.ysch * scene->r.yasp; - mul_m4_m4m4(cob->matrix, obmat, mat); - translate_m4( - cob->matrix, track->bundle_pos[0], track->bundle_pos[1], track->bundle_pos[2]); - } - } + const float asp_src = w_src / h_src; + const float asp_dst = w_dst / h_dst; + + if (fabsf(asp_src - asp_dst) < FLT_EPSILON) { + return; + } + + if ((asp_src > asp_dst) == (context->frame_method == FOLLOWTRACK_FRAME_CROP)) { + /* fit X */ + float div = asp_src / asp_dst; + float cent = (float)clip_width / 2.0f; + + marker_position[0] = (((marker_position[0] * clip_width - cent) * div) + cent) / clip_width; } else { - float vec[3], disp[3], axis[3], mat[4][4]; - float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); - float len, d; + /* fit Y */ + float div = asp_dst / asp_src; + float cent = (float)clip_height / 2.0f; - BKE_object_where_is_calc_mat4(camob, mat); + marker_position[1] = (((marker_position[1] * clip_height - cent) * div) + cent) / clip_height; + } +} - /* camera axis */ - vec[0] = 0.0f; - vec[1] = 0.0f; - vec[2] = 1.0f; - mul_v3_m4v3(axis, mat, vec); +/* Effectively this is a Z-depth of the object form the movie clip camera. + * The idea is to preserve this depth while moving the object in 2D. */ +static float followtrack_distance_from_viewplane_get(FollowTrackContext *context, + bConstraintOb *cob) +{ + Object *camera_object = context->camera_object; - /* distance to projection plane */ - copy_v3_v3(vec, cob->matrix[3]); - sub_v3_v3(vec, mat[3]); - project_v3_v3v3(disp, vec, axis); + float camera_matrix[4][4]; + BKE_object_where_is_calc_mat4(camera_object, camera_matrix); - len = len_v3(disp); + const float z_axis[3] = {0.0f, 0.0f, 1.0f}; - if (len > FLT_EPSILON) { - CameraParams params; - int width, height; - float pos[2], rmat[4][4]; + /* Direction of camera's local Z axis in the world space. */ + float camera_axis[3]; + mul_v3_mat3_m4v3(camera_axis, camera_matrix, z_axis); - BKE_movieclip_get_size(clip, NULL, &width, &height); - BKE_tracking_marker_get_subframe_position(track, framenr, pos); + /* Distance to projection plane. */ + float vec[3]; + copy_v3_v3(vec, cob->matrix[3]); + sub_v3_v3(vec, camera_matrix[3]); - if (data->flag & FOLLOWTRACK_USE_UNDISTORTION) { - /* Undistortion need to happen in pixel space. */ - pos[0] *= width; - pos[1] *= height; + float projection[3]; + project_v3_v3v3(projection, vec, camera_axis); - BKE_tracking_undistort_v2(tracking, pos, pos); + return len_v3(projection); +} - /* Normalize pixel coordinates back. */ - pos[0] /= width; - pos[1] /= height; - } +/* For the evaluated constraint object project it to the surface of the depth object. */ +static void followtrack_project_to_depth_object_if_needed(FollowTrackContext *context, + bConstraintOb *cob) +{ + if (context->depth_object == NULL) { + return; + } - /* aspect correction */ - if (data->frame_method != FOLLOWTRACK_FRAME_STRETCH) { - float w_src, h_src, w_dst, h_dst, asp_src, asp_dst; + Object *depth_object = context->depth_object; + Mesh *depth_mesh = BKE_object_get_evaluated_mesh(depth_object); + if (depth_mesh == NULL) { + return; + } - /* apply clip display aspect */ - w_src = width * clip->aspx; - h_src = height * clip->aspy; + float depth_object_mat_inv[4][4]; + invert_m4_m4(depth_object_mat_inv, depth_object->obmat); - w_dst = scene->r.xsch * scene->r.xasp; - h_dst = scene->r.ysch * scene->r.yasp; + float ray_start[3], ray_end[3]; + mul_v3_m4v3(ray_start, depth_object_mat_inv, context->camera_object->obmat[3]); + mul_v3_m4v3(ray_end, depth_object_mat_inv, cob->matrix[3]); - asp_src = w_src / h_src; - asp_dst = w_dst / h_dst; + float ray_direction[3]; + sub_v3_v3v3(ray_direction, ray_end, ray_start); + normalize_v3(ray_direction); - if (fabsf(asp_src - asp_dst) >= FLT_EPSILON) { - if ((asp_src > asp_dst) == (data->frame_method == FOLLOWTRACK_FRAME_CROP)) { - /* fit X */ - float div = asp_src / asp_dst; - float cent = (float)width / 2.0f; + BVHTreeFromMesh tree_data = NULL_BVHTreeFromMesh; + BKE_bvhtree_from_mesh_get(&tree_data, depth_mesh, BVHTREE_FROM_LOOPTRI, 4); - pos[0] = (((pos[0] * width - cent) * div) + cent) / width; - } - else { - /* fit Y */ - float div = asp_dst / asp_src; - float cent = (float)height / 2.0f; + BVHTreeRayHit hit; + hit.dist = BVH_RAYCAST_DIST_MAX; + hit.index = -1; - pos[1] = (((pos[1] * height - cent) * div) + cent) / height; - } - } - } + const int result = BLI_bvhtree_ray_cast(tree_data.tree, + ray_start, + ray_direction, + 0.0f, + &hit, + tree_data.raycast_callback, + &tree_data); - BKE_camera_params_init(¶ms); - BKE_camera_params_from_object(¶ms, camob); + if (result != -1) { + mul_v3_m4v3(cob->matrix[3], depth_object->obmat, hit.co); + } - if (params.is_ortho) { - vec[0] = params.ortho_scale * (pos[0] - 0.5f + params.shiftx); - vec[1] = params.ortho_scale * (pos[1] - 0.5f + params.shifty); - vec[2] = -len; + free_bvhtree_from_mesh(&tree_data); +} - if (aspect > 1.0f) { - vec[1] /= aspect; - } - else { - vec[0] *= aspect; - } +static void followtrack_evaluate_using_2d_position(FollowTrackContext *context, bConstraintOb *cob) +{ + Scene *scene = context->scene; + MovieClip *clip = context->clip; + MovieTrackingTrack *track = context->track; + Object *camera_object = context->camera_object; + const float clip_frame = context->clip_frame; + const float aspect = (scene->r.xsch * scene->r.xasp) / (scene->r.ysch * scene->r.yasp); - mul_v3_m4v3(disp, camob->obmat, vec); + const float object_depth = followtrack_distance_from_viewplane_get(context, cob); + if (object_depth < FLT_EPSILON) { + return; + } - copy_m4_m4(rmat, camob->obmat); - zero_v3(rmat[3]); - mul_m4_m4m4(cob->matrix, cob->matrix, rmat); + int clip_width, clip_height; + BKE_movieclip_get_size(clip, NULL, &clip_width, &clip_height); - copy_v3_v3(cob->matrix[3], disp); - } - else { - d = (len * params.sensor_x) / (2.0f * params.lens); + float marker_position[2]; + BKE_tracking_marker_get_subframe_position(track, clip_frame, marker_position); - vec[0] = d * (2.0f * (pos[0] + params.shiftx) - 1.0f); - vec[1] = d * (2.0f * (pos[1] + params.shifty) - 1.0f); - vec[2] = -len; + followtrack_undistort_if_needed(context, clip_width, clip_height, marker_position); + followtrack_fit_frame(context, clip_width, clip_height, marker_position); - if (aspect > 1.0f) { - vec[1] /= aspect; - } - else { - vec[0] *= aspect; - } + float rmat[4][4]; + CameraParams params; + BKE_camera_params_init(¶ms); + BKE_camera_params_from_object(¶ms, camera_object); - mul_v3_m4v3(disp, camob->obmat, vec); + if (params.is_ortho) { + float vec[3]; + vec[0] = params.ortho_scale * (marker_position[0] - 0.5f + params.shiftx); + vec[1] = params.ortho_scale * (marker_position[1] - 0.5f + params.shifty); + vec[2] = -object_depth; - /* apply camera rotation so Z-axis would be co-linear */ - copy_m4_m4(rmat, camob->obmat); - zero_v3(rmat[3]); - mul_m4_m4m4(cob->matrix, cob->matrix, rmat); + if (aspect > 1.0f) { + vec[1] /= aspect; + } + else { + vec[0] *= aspect; + } - copy_v3_v3(cob->matrix[3], disp); - } + float disp[3]; + mul_v3_m4v3(disp, camera_object->obmat, vec); - if (data->depth_ob) { - Object *depth_ob = data->depth_ob; - Mesh *target_eval = BKE_object_get_evaluated_mesh(depth_ob); - if (target_eval) { - BVHTreeFromMesh treeData = NULL_BVHTreeFromMesh; - BVHTreeRayHit hit; - float ray_start[3], ray_end[3], ray_nor[3], imat[4][4]; - int result; + copy_m4_m4(rmat, camera_object->obmat); + zero_v3(rmat[3]); + mul_m4_m4m4(cob->matrix, cob->matrix, rmat); - invert_m4_m4(imat, depth_ob->obmat); + copy_v3_v3(cob->matrix[3], disp); + } + else { + const float d = (object_depth * params.sensor_x) / (2.0f * params.lens); - mul_v3_m4v3(ray_start, imat, camob->obmat[3]); - mul_v3_m4v3(ray_end, imat, cob->matrix[3]); + float vec[3]; + vec[0] = d * (2.0f * (marker_position[0] + params.shiftx) - 1.0f); + vec[1] = d * (2.0f * (marker_position[1] + params.shifty) - 1.0f); + vec[2] = -object_depth; + + if (aspect > 1.0f) { + vec[1] /= aspect; + } + else { + vec[0] *= aspect; + } - sub_v3_v3v3(ray_nor, ray_end, ray_start); - normalize_v3(ray_nor); + float disp[3]; + mul_v3_m4v3(disp, camera_object->obmat, vec); - BKE_bvhtree_from_mesh_get(&treeData, target_eval, BVHTREE_FROM_LOOPTRI, 4); + /* apply camera rotation so Z-axis would be co-linear */ + copy_m4_m4(rmat, camera_object->obmat); + zero_v3(rmat[3]); + mul_m4_m4m4(cob->matrix, cob->matrix, rmat); - hit.dist = BVH_RAYCAST_DIST_MAX; - hit.index = -1; + copy_v3_v3(cob->matrix[3], disp); + } - result = BLI_bvhtree_ray_cast( - treeData.tree, ray_start, ray_nor, 0.0f, &hit, treeData.raycast_callback, &treeData); + followtrack_project_to_depth_object_if_needed(context, cob); +} - if (result != -1) { - mul_v3_m4v3(cob->matrix[3], depth_ob->obmat, hit.co); - } +static void followtrack_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *UNUSED(targets)) +{ + FollowTrackContext context; + if (!followtrack_context_init(&context, con, cob)) { + return; + } - free_bvhtree_from_mesh(&treeData); - } - } - } + bFollowTrackConstraint *data = con->data; + if (data->flag & FOLLOWTRACK_USE_3D_POSITION) { + followtrack_evaluate_using_3d_position(&context, cob); + return; } + + followtrack_evaluate_using_2d_position(&context, cob); } static bConstraintTypeInfo CTI_FOLLOWTRACK = { diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 7ec1da8eab4..f4acbdca772 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -84,7 +84,7 @@ static void set_crazy_vertex_quat(float r_quat[4], static bool modifiers_disable_subsurf_temporary(struct Scene *scene, Object *ob) { bool disabled = false; - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); ModifierData *md = ob->modifiers.first; for (int i = 0; md && i <= cageIndex; i++, md = md->next) { @@ -265,20 +265,20 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra Mesh *me_input = ob->data; Mesh *me = NULL; int i, a, numleft = 0, numVerts = 0; - int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); + int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; VirtualModifierData virtualModifierData; ModifierEvalContext mectx = {depsgraph, ob, 0}; - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* compute the deformation matrices and coordinates for the first * modifiers with on cage editing that are enabled and support computing * deform matrices */ for (i = 0; md && i <= cageIndex; i++, md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (!editbmesh_modifier_is_enabled(scene, md, me != NULL)) { continue; @@ -288,7 +288,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra if (!defmats) { const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; CustomData_MeshMasks cd_mask_extra = CD_MASK_BAREMESH; - CDMaskLink *datamasks = modifiers_calcDataMasks( + CDMaskLink *datamasks = BKE_modifier_calc_data_masks( scene, ob, md, &cd_mask_extra, required_mode, NULL, NULL); cd_mask_extra = datamasks->mask; BLI_linklist_free((LinkNode *)datamasks, NULL); @@ -310,7 +310,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra for (; md && i <= cageIndex; md = md->next, i++) { if (editbmesh_modifier_is_enabled(scene, md, me != NULL) && - modifier_isCorrectableDeformed(md)) { + BKE_modifier_is_correctable_deformed(md)) { numleft++; } } @@ -361,13 +361,13 @@ static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md) if (ELEM(md->type, eModifierType_Subsurf, eModifierType_Multires)) { return true; } - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_OnlyDeform); } static bool crazyspace_modifier_supports_deform(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_OnlyDeform); } @@ -386,7 +386,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, crazyspace_init_object_for_eval(depsgraph, object, &object_eval); MultiresModifierData *mmd = get_multires_modifier(scene, &object_eval, 0); const bool is_sculpt_mode = (object->mode & OB_MODE_SCULPT) != 0; - const bool has_multires = mmd != NULL && BKE_multires_sculpt_level_get(mmd) > 0; + const bool has_multires = mmd != NULL && mmd->sculptlvl > 0; const ModifierEvalContext mectx = {depsgraph, &object_eval, 0}; if (is_sculpt_mode && has_multires) { @@ -395,15 +395,15 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, return numleft; } - md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } if (crazyspace_modifier_supports_deform_matrices(md)) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (defmats == NULL) { /* NOTE: Evaluated object si re-set to its original undeformed * state. */ @@ -425,7 +425,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph, } for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } @@ -471,16 +471,16 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph, VirtualModifierData virtualModifierData; Object object_eval; crazyspace_init_object_for_eval(depsgraph, object, &object_eval); - ModifierData *md = modifiers_getVirtualModifierList(&object_eval, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData); const ModifierEvalContext mectx = {depsgraph, &object_eval, 0}; for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } if (crazyspace_modifier_supports_deform(md)) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); /* skip leading modifiers which have been already * handled in sculpt_get_first_deform_matrices */ diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index b4a8625c0bb..72197869f58 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -52,6 +52,7 @@ #include "BKE_idtype.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_object.h" @@ -117,6 +118,22 @@ static void curve_free_data(ID *id) MEM_SAFE_FREE(curve->tb); } +static void curve_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Curve *curve = (Curve *)id; + BKE_LIB_FOREACHID_PROCESS(data, curve->bevobj, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, curve->taperobj, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, curve->textoncurve, IDWALK_CB_NOP); + BKE_LIB_FOREACHID_PROCESS(data, curve->key, IDWALK_CB_USER); + for (int i = 0; i < curve->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, curve->mat[i], IDWALK_CB_USER); + } + BKE_LIB_FOREACHID_PROCESS(data, curve->vfont, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, curve->vfontb, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, curve->vfonti, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, curve->vfontbi, IDWALK_CB_USER); +} + IDTypeInfo IDType_ID_CU = { .id_code = ID_CU, .id_filter = FILTER_ID_CU, @@ -131,6 +148,7 @@ IDTypeInfo IDType_ID_CU = { .copy_data = curve_copy_data, .free_data = curve_free_data, .make_local = NULL, + .foreach_id = curve_foreach_id, }; static int cu_isectLL(const float v1[3], @@ -5506,6 +5524,20 @@ void BKE_curve_material_remap(Curve *cu, const unsigned int *remap, unsigned int #undef MAT_NR_REMAP } +void BKE_curve_smooth_flag_set(Curve *cu, const bool use_smooth) +{ + if (use_smooth) { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + nu->flag |= CU_SMOOTH; + } + } + else { + for (Nurb *nu = cu->nurb.first; nu; nu = nu->next) { + nu->flag &= ~CU_SMOOTH; + } + } +} + void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *tb, struct rctf *r_rect) diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index eb5a90a7c4a..8c47401cbc3 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 Blender Foundation. diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 5cb536f98b9..d73f92b6073 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -805,7 +805,7 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, const bool editmode) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *pretessellatePoint; int required_mode; @@ -822,9 +822,9 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, pretessellatePoint = NULL; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } if (mti->type == eModifierTypeType_Constructive) { @@ -853,31 +853,31 @@ static bool curve_calc_modifiers_pre( Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb, const bool for_render) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; int numElems = 0, numVerts = 0; const bool editmode = (!for_render && (cu->editnurb || cu->editfont)); - ModifierApplyFlag app_flag = 0; + ModifierApplyFlag apply_flag = 0; float(*deformedVerts)[3] = NULL; float *keyVerts = NULL; int required_mode; bool modified = false; - modifiers_clearErrors(ob); + BKE_modifiers_clear_errors(ob); if (editmode) { - app_flag |= MOD_APPLY_USECACHE; + apply_flag |= MOD_APPLY_USECACHE; } if (for_render) { - app_flag |= MOD_APPLY_RENDER; + apply_flag |= MOD_APPLY_RENDER; required_mode = eModifierMode_Render; } else { required_mode = eModifierMode_Realtime; } - const ModifierEvalContext mectx = {depsgraph, ob, app_flag}; + const ModifierEvalContext mectx = {depsgraph, ob, apply_flag}; pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode); @@ -901,9 +901,9 @@ static bool curve_calc_modifiers_pre( if (pretessellatePoint) { for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } if (mti->type != eModifierTypeType_OnlyDeform) { @@ -982,7 +982,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, const bool force_mesh_conversion) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ModifierData *pretessellatePoint; Curve *cu = ob->data; int required_mode = 0, totvert = 0; @@ -990,10 +990,10 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, Mesh *modified = NULL, *mesh_applied; float(*vertCos)[3] = NULL; int useCache = !for_render; - ModifierApplyFlag app_flag = 0; + ModifierApplyFlag apply_flag = 0; if (for_render) { - app_flag |= MOD_APPLY_RENDER; + apply_flag |= MOD_APPLY_RENDER; required_mode = eModifierMode_Render; } else { @@ -1001,9 +1001,9 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, } const ModifierEvalContext mectx_deform = { - depsgraph, ob, editmode ? app_flag | MOD_APPLY_USECACHE : app_flag}; + depsgraph, ob, editmode ? apply_flag | MOD_APPLY_USECACHE : apply_flag}; const ModifierEvalContext mectx_apply = { - depsgraph, ob, useCache ? app_flag | MOD_APPLY_USECACHE : app_flag}; + depsgraph, ob, useCache ? apply_flag | MOD_APPLY_USECACHE : apply_flag}; pretessellatePoint = curve_get_tessellate_point(scene, ob, for_render, editmode); @@ -1020,9 +1020,9 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, } for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { continue; } @@ -1100,7 +1100,7 @@ static void curve_calc_modifiers_post(Depsgraph *depsgraph, if (need_normal) { BKE_mesh_ensure_normals(modified); } - mesh_applied = mti->applyModifier(md, &mectx_apply, modified); + mesh_applied = mti->modifyMesh(md, &mectx_apply, modified); if (mesh_applied) { /* Modifier returned a new derived mesh */ diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index a704e199007..79d9a40f06b 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -540,7 +540,7 @@ static int surface_getBrushFlags(DynamicPaintSurface *surface, Depsgraph *depsgr for (int i = 0; i < numobjects; i++) { Object *brushObj = objects[i]; - ModifierData *md = modifiers_findByType(brushObj, eModifierType_DynamicPaint); + ModifierData *md = BKE_modifiers_findby_type(brushObj, eModifierType_DynamicPaint); if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) { DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md; @@ -653,15 +653,15 @@ static void grid_bound_insert_cb_ex(void *__restrict userdata, boundInsert(grid_bound, bData->realCoord[bData->s_pos[i]].v); } -static void grid_bound_insert_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void grid_bound_insert_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - PaintBakeData *bData = userdata; - VolumeGrid *grid = bData->grid; - - Bounds3D *grid_bound = userdata_chunk; + Bounds3D *join = chunk_join; + Bounds3D *grid_bound = chunk; - boundInsert(&grid->grid_bounds, grid_bound->min); - boundInsert(&grid->grid_bounds, grid_bound->max); + boundInsert(join, grid_bound->min); + boundInsert(join, grid_bound->max); } static void grid_cell_points_cb_ex(void *__restrict userdata, @@ -685,17 +685,20 @@ static void grid_cell_points_cb_ex(void *__restrict userdata, s_num[temp_t_index[i]]++; } -static void grid_cell_points_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void grid_cell_points_reduce(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk) { - PaintBakeData *bData = userdata; - VolumeGrid *grid = bData->grid; + const PaintBakeData *bData = userdata; + const VolumeGrid *grid = bData->grid; const int grid_cells = grid->dim[0] * grid->dim[1] * grid->dim[2]; - int *s_num = userdata_chunk; + int *join_s_num = chunk_join; + int *s_num = chunk; /* calculate grid indexes */ for (int i = 0; i < grid_cells; i++) { - grid->s_num[i] += s_num[i]; + join_s_num[i] += s_num[i]; } } @@ -753,7 +756,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = &grid->grid_bounds; settings.userdata_chunk_size = sizeof(grid->grid_bounds); - settings.func_finalize = grid_bound_insert_finalize; + settings.func_reduce = grid_bound_insert_reduce; BLI_task_parallel_range(0, sData->total_points, bData, grid_bound_insert_cb_ex, &settings); } /* get dimensions */ @@ -814,7 +817,7 @@ static void surfaceGenerateGrid(struct DynamicPaintSurface *surface) settings.use_threading = (sData->total_points > 1000); settings.userdata_chunk = grid->s_num; settings.userdata_chunk_size = sizeof(*grid->s_num) * grid_cells; - settings.func_finalize = grid_cell_points_finalize; + settings.func_reduce = grid_cell_points_reduce; BLI_task_parallel_range(0, sData->total_points, bData, grid_cell_points_cb_ex, &settings); } @@ -1096,7 +1099,7 @@ DynamicPaintSurface *dynamicPaint_createNewSurface(DynamicPaintCanvasSettings *c surface->wave_spring = 0.20f; surface->wave_smoothness = 1.0f; - modifier_path_init( + BKE_modifier_path_init( surface->image_output_path, sizeof(surface->image_output_path), "cache_dynamicpaint"); /* Using ID_BRUSH i18n context, as we have no physics/dpaint one for now... */ @@ -4882,7 +4885,7 @@ static void dynamicPaint_prepareAdjacencyData(DynamicPaintSurface *surface, cons 0, sData->total_points, sData, dynamic_paint_prepare_adjacency_cb, &settings); /* calculate average values (single thread). - * Note: tried to put this in threaded callback (using _finalize feature), + * Note: tried to put this in threaded callback (using _reduce feature), * but gave ~30% slower result! */ bData->average_dist = 0.0; for (index = 0; index < sData->total_points; index++) { @@ -6245,7 +6248,7 @@ static int dynamicPaint_doStep(Depsgraph *depsgraph, Object *brushObj = objects[i]; /* check if target has an active dp modifier */ - ModifierData *md = modifiers_findByType(brushObj, eModifierType_DynamicPaint); + ModifierData *md = BKE_modifiers_findby_type(brushObj, eModifierType_DynamicPaint); if (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)) { DynamicPaintModifierData *pmd2 = (DynamicPaintModifierData *)md; /* make sure we're dealing with a brush */ diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c index c3ae2a54e13..6fcaf84d4ca 100644 --- a/source/blender/blenkernel/intern/editmesh_tangent.c +++ b/source/blender/blenkernel/intern/editmesh_tangent.c @@ -251,9 +251,7 @@ finally: pRes[3] = fSign; } -static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void emDM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata) { struct SGLSLEditMeshToTangent *mesh2tangent = taskdata; /* new computation method */ @@ -362,9 +360,8 @@ void BKE_editmesh_loop_tangent_calc(BMEditMesh *em, #endif /* Calculation */ if (em->tottri != 0) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(NULL, TASK_PRIORITY_LOW); tangent_mask_curr = 0; /* Calculate tangent layers */ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e1e818a5a34..bfb03dea39c 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -177,7 +177,7 @@ static void precalculate_effector(struct Depsgraph *depsgraph, EffectorCache *ef } } else if (eff->pd->shape == PFIELD_SHAPE_SURFACE) { - eff->surmd = (SurfaceModifierData *)modifiers_findByType(eff->ob, eModifierType_Surface); + eff->surmd = (SurfaceModifierData *)BKE_modifiers_findby_type(eff->ob, eModifierType_Surface); if (eff->ob->type == OB_CURVE) { eff->flag |= PE_USE_NORMAL_DATA; } diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index 439992a4113..543d5c8b7c7 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -30,49 +30,28 @@ #include "MEM_guardedalloc.h" #include "DNA_anim_types.h" -#include "DNA_constraint_types.h" #include "DNA_object_types.h" -#include "BLI_alloca.h" #include "BLI_blenlib.h" #include "BLI_easing.h" -#include "BLI_expr_pylike_eval.h" #include "BLI_math.h" -#include "BLI_string_utils.h" -#include "BLI_threads.h" -#include "BLI_utildefines.h" -#include "BLT_translation.h" - -#include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_animsys.h" -#include "BKE_armature.h" -#include "BKE_constraint.h" #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_nla.h" -#include "BKE_object.h" #include "RNA_access.h" -#include "atomic_ops.h" - #include "CLG_log.h" -#ifdef WITH_PYTHON -# include "BPY_extern.h" -#endif - #define SMALL -1.0e-10 #define SELECT 1 -#ifdef WITH_PYTHON -static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; -#endif - static CLG_LogRef LOG = {"bke.fcurve"}; /* ************************** Data-Level Functions ************************* */ @@ -1256,1236 +1235,6 @@ short test_time_fcurve(FCurve *fcu) return 0; } -/* ***************************** Drivers ********************************* */ - -/* Driver Variables --------------------------- */ - -/* TypeInfo for Driver Variables (dvti) */ -typedef struct DriverVarTypeInfo { - /* evaluation callback */ - float (*get_value)(ChannelDriver *driver, DriverVar *dvar); - - /* allocation of target slots */ - int num_targets; /* number of target slots required */ - const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ - short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ -} DriverVarTypeInfo; - -/* Macro to begin definitions */ -#define BEGIN_DVAR_TYPEDEF(type) { - -/* Macro to end definitions */ -#define END_DVAR_TYPEDEF } - -/* ......... */ - -static ID *dtar_id_ensure_proxy_from(ID *id) -{ - if (id && GS(id->name) == ID_OB && ((Object *)id)->proxy_from) { - return (ID *)(((Object *)id)->proxy_from); - } - return id; -} - -/** - * Helper function to obtain a value using RNA from the specified source - * (for evaluating drivers). - */ -static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) -{ - PointerRNA id_ptr, ptr; - PropertyRNA *prop; - ID *id; - int index = -1; - float value = 0.0f; - - /* sanity check */ - if (ELEM(NULL, driver, dtar)) { - return 0.0f; - } - - id = dtar_id_ensure_proxy_from(dtar->id); - - /* error check for missing pointer... */ - if (id == NULL) { - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - - /* get RNA-pointer for the ID-block given in target */ - RNA_id_pointer_create(id, &id_ptr); - - /* get property to read from, and get value as appropriate */ - if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - /* path couldn't be resolved */ - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, - "Driver Evaluation Error: cannot resolve target for %s -> %s", - id->name, - dtar->rna_path); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - - if (RNA_property_array_check(prop)) { - /* array */ - if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) { - /* out of bounds */ - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, - "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)", - id->name, - dtar->rna_path, - index); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get_index(&ptr, prop, index); - break; - case PROP_INT: - value = (float)RNA_property_int_get_index(&ptr, prop, index); - break; - case PROP_FLOAT: - value = RNA_property_float_get_index(&ptr, prop, index); - break; - default: - break; - } - } - else { - /* not an array */ - switch (RNA_property_type(prop)) { - case PROP_BOOLEAN: - value = (float)RNA_property_boolean_get(&ptr, prop); - break; - case PROP_INT: - value = (float)RNA_property_int_get(&ptr, prop); - break; - case PROP_FLOAT: - value = RNA_property_float_get(&ptr, prop); - break; - case PROP_ENUM: - value = (float)RNA_property_enum_get(&ptr, prop); - break; - default: - break; - } - } - - /* if we're still here, we should be ok... */ - dtar->flag &= ~DTAR_FLAG_INVALID; - return value; -} - -/** - * Same as 'dtar_get_prop_val'. but get the RNA property. - */ -bool driver_get_variable_property(ChannelDriver *driver, - DriverTarget *dtar, - PointerRNA *r_ptr, - PropertyRNA **r_prop, - int *r_index) -{ - PointerRNA id_ptr; - PointerRNA ptr; - PropertyRNA *prop; - ID *id; - int index = -1; - - /* sanity check */ - if (ELEM(NULL, driver, dtar)) { - return false; - } - - id = dtar_id_ensure_proxy_from(dtar->id); - - /* error check for missing pointer... */ - if (id == NULL) { - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); - } - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return false; - } - - /* get RNA-pointer for the ID-block given in target */ - RNA_id_pointer_create(id, &id_ptr); - - /* get property to read from, and get value as appropriate */ - if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') { - ptr = PointerRNA_NULL; - prop = NULL; /* ok */ - } - else if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { - /* ok */ - } - else { - /* path couldn't be resolved */ - if (G.debug & G_DEBUG) { - CLOG_ERROR(&LOG, - "Driver Evaluation Error: cannot resolve target for %s -> %s", - id->name, - dtar->rna_path); - } - - ptr = PointerRNA_NULL; - *r_prop = NULL; - *r_index = -1; - - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return false; - } - - *r_ptr = ptr; - *r_prop = prop; - *r_index = index; - - /* if we're still here, we should be ok... */ - dtar->flag &= ~DTAR_FLAG_INVALID; - return true; -} - -static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar) -{ - short valid_targets = 0; - - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - - /* check if this target has valid data */ - if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { - /* invalid target, so will not have enough targets */ - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - } - else { - /* target seems to be OK now... */ - dtar->flag &= ~DTAR_FLAG_INVALID; - valid_targets++; - } - } - DRIVER_TARGETS_LOOPER_END; - - return valid_targets; -} - -/* ......... */ - -/* evaluate 'single prop' driver variable */ -static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar) -{ - /* just evaluate the first target slot */ - return dtar_get_prop_val(driver, &dvar->targets[0]); -} - -/* evaluate 'rotation difference' driver variable */ -static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) -{ - short valid_targets = driver_check_valid_targets(driver, dvar); - - /* make sure we have enough valid targets to use - all or nothing for now... */ - if (driver_check_valid_targets(driver, dvar) != 2) { - if (G.debug & G_DEBUG) { - CLOG_WARN(&LOG, - "RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", - valid_targets, - dvar->targets[0].id, - dvar->targets[1].id); - } - return 0.0f; - } - - float(*mat[2])[4]; - - /* NOTE: for now, these are all just worldspace */ - for (int i = 0; i < 2; i++) { - /* get pointer to loc values to store in */ - DriverTarget *dtar = &dvar->targets[i]; - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - bPoseChannel *pchan; - - /* after the checks above, the targets should be valid here... */ - BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); - - /* try to get posechannel */ - pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - - /* check if object or bone */ - if (pchan) { - /* bone */ - mat[i] = pchan->pose_mat; - } - else { - /* object */ - mat[i] = ob->obmat; - } - } - - float q1[4], q2[4], quat[4], angle; - - /* use the final posed locations */ - mat4_to_quat(q1, mat[0]); - mat4_to_quat(q2, mat[1]); - - invert_qt_normalized(q1); - mul_qt_qtqt(quat, q1, q2); - angle = 2.0f * (saacos(quat[0])); - angle = fabsf(angle); - - return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle); -} - -/* evaluate 'location difference' driver variable */ -/* TODO: this needs to take into account space conversions... */ -static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) -{ - float loc1[3] = {0.0f, 0.0f, 0.0f}; - float loc2[3] = {0.0f, 0.0f, 0.0f}; - short valid_targets = driver_check_valid_targets(driver, dvar); - - /* make sure we have enough valid targets to use - all or nothing for now... */ - if (valid_targets < dvar->num_targets) { - if (G.debug & G_DEBUG) { - CLOG_WARN(&LOG, - "LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", - valid_targets, - dvar->targets[0].id, - dvar->targets[1].id); - } - return 0.0f; - } - - /* SECOND PASS: get two location values */ - /* NOTE: for now, these are all just worldspace */ - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - /* get pointer to loc values to store in */ - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - bPoseChannel *pchan; - float tmp_loc[3]; - - /* after the checks above, the targets should be valid here... */ - BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); - - /* try to get posechannel */ - pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - - /* check if object or bone */ - if (pchan) { - /* bone */ - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - float mat[4][4]; - - /* extract transform just like how the constraints do it! */ - copy_m4_m4(mat, pchan->pose_mat); - BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); - - /* ... and from that, we get our transform */ - copy_v3_v3(tmp_loc, mat[3]); - } - else { - /* transform space (use transform values directly) */ - copy_v3_v3(tmp_loc, pchan->loc); - } - } - else { - /* convert to worldspace */ - copy_v3_v3(tmp_loc, pchan->pose_head); - mul_m4_v3(ob->obmat, tmp_loc); - } - } - else { - /* object */ - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* XXX: this should practically be the same as transform space... */ - float mat[4][4]; - - /* extract transform just like how the constraints do it! */ - copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); - - /* ... and from that, we get our transform */ - copy_v3_v3(tmp_loc, mat[3]); - } - else { - /* transform space (use transform values directly) */ - copy_v3_v3(tmp_loc, ob->loc); - } - } - else { - /* worldspace */ - copy_v3_v3(tmp_loc, ob->obmat[3]); - } - } - - /* copy the location to the right place */ - if (tarIndex) { - copy_v3_v3(loc2, tmp_loc); - } - else { - copy_v3_v3(loc1, tmp_loc); - } - } - DRIVER_TARGETS_LOOPER_END; - - /* if we're still here, there should now be two targets to use, - * so just take the length of the vector between these points - */ - return len_v3v3(loc1, loc2); -} - -/* evaluate 'transform channel' driver variable */ -static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) -{ - DriverTarget *dtar = &dvar->targets[0]; - Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); - bPoseChannel *pchan; - float mat[4][4]; - float oldEul[3] = {0.0f, 0.0f, 0.0f}; - bool use_eulers = false; - short rot_order = ROT_MODE_EUL; - - /* check if this target has valid data */ - if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { - /* invalid target, so will not have enough targets */ - driver->flag |= DRIVER_FLAG_INVALID; - dtar->flag |= DTAR_FLAG_INVALID; - return 0.0f; - } - else { - /* target should be valid now */ - dtar->flag &= ~DTAR_FLAG_INVALID; - } - - /* try to get posechannel */ - pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); - - /* check if object or bone, and get transform matrix accordingly - * - "useEulers" code is used to prevent the problems associated with non-uniqueness - * of euler decomposition from matrices [#20870] - * - localspace is for [#21384], where parent results are not wanted - * but local-consts is for all the common "corrective-shapes-for-limbs" situations - */ - if (pchan) { - /* bone */ - if (pchan->rotmode > 0) { - copy_v3_v3(oldEul, pchan->eul); - rot_order = pchan->rotmode; - use_eulers = true; - } - - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* just like how the constraints do it! */ - copy_m4_m4(mat, pchan->pose_mat); - BKE_constraint_mat_convertspace( - ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); - } - else { - /* specially calculate local matrix, since chan_mat is not valid - * since it stores delta transform of pose_mat so that deforms work - * so it cannot be used here for "transform" space - */ - BKE_pchan_to_mat4(pchan, mat); - } - } - else { - /* worldspace matrix */ - mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); - } - } - else { - /* object */ - if (ob->rotmode > 0) { - copy_v3_v3(oldEul, ob->rot); - rot_order = ob->rotmode; - use_eulers = true; - } - - if (dtar->flag & DTAR_FLAG_LOCALSPACE) { - if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { - /* just like how the constraints do it! */ - copy_m4_m4(mat, ob->obmat); - BKE_constraint_mat_convertspace( - ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); - } - else { - /* transforms to matrix */ - BKE_object_to_mat4(ob, mat); - } - } - else { - /* worldspace matrix - just the good-old one */ - copy_m4_m4(mat, ob->obmat); - } - } - - /* check which transform */ - if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) { - /* not valid channel */ - return 0.0f; - } - else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) { - /* Cubic root of the change in volume, equal to the geometric mean - * of scale over all three axes unless the matrix includes shear. */ - return cbrtf(mat4_to_volume_scale(mat)); - } - else if (ELEM(dtar->transChan, - DTAR_TRANSCHAN_SCALEX, - DTAR_TRANSCHAN_SCALEY, - DTAR_TRANSCHAN_SCALEZ)) { - /* Extract scale, and choose the right axis, - * inline 'mat4_to_size'. */ - return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]); - } - else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { - /* extract rotation as eulers (if needed) - * - definitely if rotation order isn't eulers already - * - if eulers, then we have 2 options: - * a) decompose transform matrix as required, then try to make eulers from - * there compatible with original values - * b) [NOT USED] directly use the original values (no decomposition) - * - only an option for "transform space", if quality is really bad with a) - */ - float quat[4]; - int channel; - - if (dtar->transChan == DTAR_TRANSCHAN_ROTW) { - channel = 0; - } - else { - channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX; - BLI_assert(channel < 4); - } - - BKE_driver_target_matrix_to_rot_channels( - mat, rot_order, dtar->rotation_mode, channel, false, quat); - - if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) { - compatible_eul(quat + 1, oldEul); - } - - return quat[channel]; - } - else { - /* extract location and choose right axis */ - return mat[3][dtar->transChan]; - } -} - -/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */ -static void quaternion_to_angles(float quat[4], int channel) -{ - if (channel < 0) { - quat[0] = 2.0f * saacosf(quat[0]); - - for (int i = 1; i < 4; i++) { - quat[i] = 2.0f * saasinf(quat[i]); - } - } - else if (channel == 0) { - quat[0] = 2.0f * saacosf(quat[0]); - } - else { - quat[channel] = 2.0f * saasinf(quat[channel]); - } -} - -/* Compute channel values for a rotational Transform Channel driver variable. */ -void BKE_driver_target_matrix_to_rot_channels( - float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]) -{ - float *const quat = r_buf; - float *const eul = r_buf + 1; - - zero_v4(r_buf); - - if (rotation_mode == DTAR_ROTMODE_AUTO) { - mat4_to_eulO(eul, auto_order, mat); - } - else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) { - mat4_to_eulO(eul, rotation_mode, mat); - } - else if (rotation_mode == DTAR_ROTMODE_QUATERNION) { - mat4_to_quat(quat, mat); - - /* For Transformation constraint convenience, convert to pseudo-angles. */ - if (angles) { - quaternion_to_angles(quat, channel); - } - } - else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X && - rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z) { - int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X; - float raw_quat[4], twist; - - mat4_to_quat(raw_quat, mat); - - if (channel == axis + 1) { - /* If only the twist angle is needed, skip computing swing. */ - twist = quat_split_swing_and_twist(raw_quat, axis, NULL, NULL); - } - else { - twist = quat_split_swing_and_twist(raw_quat, axis, quat, NULL); - - quaternion_to_angles(quat, channel); - } - - quat[axis + 1] = twist; - } - else { - BLI_assert(false); - } -} - -/* ......... */ - -/* Table of Driver Variable Type Info Data */ -static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* eval callback */ - 1, /* number of targets used */ - {"Property"}, /* UI names for targets */ - {0} /* flags */ - END_DVAR_TYPEDEF, - - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) dvar_eval_rotDiff, /* eval callback */ - 2, /* number of targets used */ - {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, - DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ - END_DVAR_TYPEDEF, - - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) dvar_eval_locDiff, /* eval callback */ - 2, /* number of targets used */ - {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, - DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ - END_DVAR_TYPEDEF, - - BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) dvar_eval_transChan, /* eval callback */ - 1, /* number of targets used */ - {"Object/Bone"}, /* UI names for targets */ - {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ - END_DVAR_TYPEDEF, -}; - -/* Get driver variable typeinfo */ -static const DriverVarTypeInfo *get_dvar_typeinfo(int type) -{ - /* check if valid type */ - if ((type >= 0) && (type < MAX_DVAR_TYPES)) { - return &dvar_types[type]; - } - else { - return NULL; - } -} - -/* Driver API --------------------------------- */ - -/* Perform actual freeing driver variable and remove it from the given list */ -void driver_free_variable(ListBase *variables, DriverVar *dvar) -{ - /* sanity checks */ - if (dvar == NULL) { - return; - } - - /* free target vars - * - need to go over all of them, not just up to the ones that are used - * currently, since there may be some lingering RNA paths from - * previous users needing freeing - */ - DRIVER_TARGETS_LOOPER_BEGIN (dvar) { - /* free RNA path if applicable */ - if (dtar->rna_path) { - MEM_freeN(dtar->rna_path); - } - } - DRIVER_TARGETS_LOOPER_END; - - /* remove the variable from the driver */ - BLI_freelinkN(variables, dvar); -} - -/* Free the driver variable and do extra updates */ -void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar) -{ - /* remove and free the driver variable */ - driver_free_variable(&driver->variables, dvar); - - /* since driver variables are cached, the expression needs re-compiling too */ - BKE_driver_invalidate_expression(driver, false, true); -} - -/* Copy driver variables from src_vars list to dst_vars list */ -void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars) -{ - BLI_assert(BLI_listbase_is_empty(dst_vars)); - BLI_duplicatelist(dst_vars, src_vars); - - LISTBASE_FOREACH (DriverVar *, dvar, dst_vars) { - /* need to go over all targets so that we don't leave any dangling paths */ - DRIVER_TARGETS_LOOPER_BEGIN (dvar) { - /* make a copy of target's rna path if available */ - if (dtar->rna_path) { - dtar->rna_path = MEM_dupallocN(dtar->rna_path); - } - } - DRIVER_TARGETS_LOOPER_END; - } -} - -/* Change the type of driver variable */ -void driver_change_variable_type(DriverVar *dvar, int type) -{ - const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); - - /* sanity check */ - if (ELEM(NULL, dvar, dvti)) { - return; - } - - /* set the new settings */ - dvar->type = type; - dvar->num_targets = dvti->num_targets; - - /* make changes to the targets based on the defines for these types - * NOTE: only need to make sure the ones we're using here are valid... - */ - DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { - short flags = dvti->target_flags[tarIndex]; - - /* store the flags */ - dtar->flag = flags; - - /* object ID types only, or idtype not yet initialized */ - if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) { - dtar->idtype = ID_OB; - } - } - DRIVER_TARGETS_LOOPER_END; -} - -/* Validate driver name (after being renamed) */ -void driver_variable_name_validate(DriverVar *dvar) -{ - /* Special character blacklist */ - const char special_char_blacklist[] = { - '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '+', '=', '-', '/', '\\', - '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', ' ', '.', '\t', '\n', '\r', - }; - - /* sanity checks */ - if (dvar == NULL) { - return; - } - - /* clear all invalid-name flags */ - dvar->flag &= ~DVAR_ALL_INVALID_FLAGS; - - /* 0) Zero-length identifiers are not allowed */ - if (dvar->name[0] == '\0') { - dvar->flag |= DVAR_FLAG_INVALID_EMPTY; - } - - /* 1) Must start with a letter */ - /* XXX: We assume that valid unicode letters in other languages are ok too, - * hence the blacklisting. */ - if (IN_RANGE_INCL(dvar->name[0], '0', '9')) { - dvar->flag |= DVAR_FLAG_INVALID_START_NUM; - } - else if (dvar->name[0] == '_') { - /* NOTE: We don't allow names to start with underscores - * (i.e. it helps when ruling out security risks) */ - dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; - } - - /* 2) Must not contain invalid stuff in the middle of the string */ - if (strchr(dvar->name, ' ')) { - dvar->flag |= DVAR_FLAG_INVALID_HAS_SPACE; - } - if (strchr(dvar->name, '.')) { - dvar->flag |= DVAR_FLAG_INVALID_HAS_DOT; - } - - /* 3) Check for special characters - Either at start, or in the middle */ - for (int i = 0; i < sizeof(special_char_blacklist); i++) { - char *match = strchr(dvar->name, special_char_blacklist[i]); - - if (match == dvar->name) { - dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; - } - else if (match != NULL) { - dvar->flag |= DVAR_FLAG_INVALID_HAS_SPECIAL; - } - } - - /* 4) Check if the name is a reserved keyword - * NOTE: These won't confuse Python, but it will be impossible to use the variable - * in an expression without Python misinterpreting what these are for - */ -#ifdef WITH_PYTHON - if (BPY_string_is_keyword(dvar->name)) { - dvar->flag |= DVAR_FLAG_INVALID_PY_KEYWORD; - } -#endif - - /* If any these conditions match, the name is invalid */ - if (dvar->flag & DVAR_ALL_INVALID_FLAGS) { - dvar->flag |= DVAR_FLAG_INVALID_NAME; - } -} - -/* Add a new driver variable */ -DriverVar *driver_add_new_variable(ChannelDriver *driver) -{ - DriverVar *dvar; - - /* sanity checks */ - if (driver == NULL) { - return NULL; - } - - /* make a new variable */ - dvar = MEM_callocN(sizeof(DriverVar), "DriverVar"); - BLI_addtail(&driver->variables, dvar); - - /* give the variable a 'unique' name */ - strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var")); - BLI_uniquename(&driver->variables, - dvar, - CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"), - '_', - offsetof(DriverVar, name), - sizeof(dvar->name)); - - /* set the default type to 'single prop' */ - driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); - - /* since driver variables are cached, the expression needs re-compiling too */ - BKE_driver_invalidate_expression(driver, false, true); - - /* return the target */ - return dvar; -} - -/* This frees the driver itself */ -void fcurve_free_driver(FCurve *fcu) -{ - ChannelDriver *driver; - DriverVar *dvar, *dvarn; - - /* sanity checks */ - if (ELEM(NULL, fcu, fcu->driver)) { - return; - } - driver = fcu->driver; - - /* free driver targets */ - for (dvar = driver->variables.first; dvar; dvar = dvarn) { - dvarn = dvar->next; - driver_free_variable_ex(driver, dvar); - } - -#ifdef WITH_PYTHON - /* free compiled driver expression */ - if (driver->expr_comp) { - BPY_DECREF(driver->expr_comp); - } -#endif - - BLI_expr_pylike_free(driver->expr_simple); - - /* Free driver itself, then set F-Curve's point to this to NULL - * (as the curve may still be used). */ - MEM_freeN(driver); - fcu->driver = NULL; -} - -/* This makes a copy of the given driver */ -ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver) -{ - ChannelDriver *ndriver; - - /* sanity checks */ - if (driver == NULL) { - return NULL; - } - - /* copy all data */ - ndriver = MEM_dupallocN(driver); - ndriver->expr_comp = NULL; - ndriver->expr_simple = NULL; - - /* copy variables */ - - /* to get rid of refs to non-copied data (that's still used on original) */ - BLI_listbase_clear(&ndriver->variables); - driver_variables_copy(&ndriver->variables, &driver->variables); - - /* return the new driver */ - return ndriver; -} - -/* Driver Expression Evaluation --------------- */ - -/* Index constants for the expression parameter array. */ -enum { - /* Index of the 'frame' variable. */ - VAR_INDEX_FRAME = 0, - /* Index of the first user-defined driver variable. */ - VAR_INDEX_CUSTOM -}; - -static ExprPyLike_Parsed *driver_compile_simple_expr_impl(ChannelDriver *driver) -{ - /* Prepare parameter names. */ - int names_len = BLI_listbase_count(&driver->variables); - const char **names = BLI_array_alloca(names, names_len + VAR_INDEX_CUSTOM); - int i = VAR_INDEX_CUSTOM; - - names[VAR_INDEX_FRAME] = "frame"; - - LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { - names[i++] = dvar->name; - } - - return BLI_expr_pylike_parse(driver->expression, names, names_len + VAR_INDEX_CUSTOM); -} - -static bool driver_check_simple_expr_depends_on_time(ExprPyLike_Parsed *expr) -{ - /* Check if the 'frame' parameter is actually used. */ - return BLI_expr_pylike_is_using_param(expr, VAR_INDEX_FRAME); -} - -static bool driver_evaluate_simple_expr(ChannelDriver *driver, - ExprPyLike_Parsed *expr, - float *result, - float time) -{ - /* Prepare parameter values. */ - int vars_len = BLI_listbase_count(&driver->variables); - double *vars = BLI_array_alloca(vars, vars_len + VAR_INDEX_CUSTOM); - int i = VAR_INDEX_CUSTOM; - - vars[VAR_INDEX_FRAME] = time; - - LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { - vars[i++] = driver_get_variable_value(driver, dvar); - } - - /* Evaluate expression. */ - double result_val; - eExprPyLike_EvalStatus status = BLI_expr_pylike_eval( - expr, vars, vars_len + VAR_INDEX_CUSTOM, &result_val); - const char *message; - - switch (status) { - case EXPR_PYLIKE_SUCCESS: - if (isfinite(result_val)) { - *result = (float)result_val; - } - return true; - - case EXPR_PYLIKE_DIV_BY_ZERO: - case EXPR_PYLIKE_MATH_ERROR: - message = (status == EXPR_PYLIKE_DIV_BY_ZERO) ? "Division by Zero" : "Math Domain Error"; - CLOG_ERROR(&LOG, "%s in Driver: '%s'", message, driver->expression); - - driver->flag |= DRIVER_FLAG_INVALID; - return true; - - default: - /* arriving here means a bug, not user error */ - CLOG_ERROR(&LOG, "simple driver expression evaluation failed: '%s'", driver->expression); - return false; - } -} - -/* Compile and cache the driver expression if necessary, with thread safety. */ -static bool driver_compile_simple_expr(ChannelDriver *driver) -{ - if (driver->expr_simple != NULL) { - return true; - } - - if (driver->type != DRIVER_TYPE_PYTHON) { - return false; - } - - /* It's safe to parse in multiple threads; at worst it'll - * waste some effort, but in return avoids mutex contention. */ - ExprPyLike_Parsed *expr = driver_compile_simple_expr_impl(driver); - - /* Store the result if the field is still NULL, or discard - * it if another thread got here first. */ - if (atomic_cas_ptr((void **)&driver->expr_simple, NULL, expr) != NULL) { - BLI_expr_pylike_free(expr); - } - - return true; -} - -/* Try using the simple expression evaluator to compute the result of the driver. - * On success, stores the result and returns true; on failure result is set to 0. */ -static bool driver_try_evaluate_simple_expr(ChannelDriver *driver, - ChannelDriver *driver_orig, - float *result, - float time) -{ - *result = 0.0f; - - return driver_compile_simple_expr(driver_orig) && - BLI_expr_pylike_is_valid(driver_orig->expr_simple) && - driver_evaluate_simple_expr(driver, driver_orig->expr_simple, result, time); -} - -/* Check if the expression in the driver conforms to the simple subset. */ -bool BKE_driver_has_simple_expression(ChannelDriver *driver) -{ - return driver_compile_simple_expr(driver) && BLI_expr_pylike_is_valid(driver->expr_simple); -} - -/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive - * time dependencies nor special exceptions in the depsgraph evaluation. */ -static bool python_driver_exression_depends_on_time(const char *expression) -{ - if (expression[0] == '\0') { - /* Empty expression depends on nothing. */ - return false; - } - if (strchr(expression, '(') != NULL) { - /* Function calls are considered dependent on a time. */ - return true; - } - if (strstr(expression, "frame") != NULL) { - /* Variable `frame` depends on time. */ - /* TODO(sergey): This is a bit weak, but not sure about better way of handling this. */ - return true; - } - /* Possible indirect time relation s should be handled via variable targets. */ - return false; -} - -/* Check if the expression in the driver may depend on the current frame. */ -bool BKE_driver_expression_depends_on_time(ChannelDriver *driver) -{ - if (driver->type != DRIVER_TYPE_PYTHON) { - return false; - } - - if (BKE_driver_has_simple_expression(driver)) { - /* Simple expressions can be checked exactly. */ - return driver_check_simple_expr_depends_on_time(driver->expr_simple); - } - else { - /* Otherwise, heuristically scan the expression string for certain patterns. */ - return python_driver_exression_depends_on_time(driver->expression); - } -} - -/* Reset cached compiled expression data */ -void BKE_driver_invalidate_expression(ChannelDriver *driver, - bool expr_changed, - bool varname_changed) -{ - if (expr_changed || varname_changed) { - BLI_expr_pylike_free(driver->expr_simple); - driver->expr_simple = NULL; - } - -#ifdef WITH_PYTHON - if (expr_changed) { - driver->flag |= DRIVER_FLAG_RECOMPILE; - } - - if (varname_changed) { - driver->flag |= DRIVER_FLAG_RENAMEVAR; - } -#endif -} - -/* Driver Evaluation -------------------------- */ - -/* Evaluate a Driver Variable to get a value that contributes to the final */ -float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) -{ - const DriverVarTypeInfo *dvti; - - /* sanity check */ - if (ELEM(NULL, driver, dvar)) { - return 0.0f; - } - - /* call the relevant callbacks to get the variable value - * using the variable type info, storing the obtained value - * in dvar->curval so that drivers can be debugged - */ - dvti = get_dvar_typeinfo(dvar->type); - - if (dvti && dvti->get_value) { - dvar->curval = dvti->get_value(driver, dvar); - } - else { - dvar->curval = 0.0f; - } - - return dvar->curval; -} - -static void evaluate_driver_sum(ChannelDriver *driver) -{ - DriverVar *dvar; - - /* check how many variables there are first (i.e. just one?) */ - if (BLI_listbase_is_single(&driver->variables)) { - /* just one target, so just use that */ - dvar = driver->variables.first; - driver->curval = driver_get_variable_value(driver, dvar); - return; - } - - /* more than one target, so average the values of the targets */ - float value = 0.0f; - int tot = 0; - - /* loop through targets, adding (hopefully we don't get any overflow!) */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - value += driver_get_variable_value(driver, dvar); - tot++; - } - - /* perform operations on the total if appropriate */ - if (driver->type == DRIVER_TYPE_AVERAGE) { - driver->curval = tot ? (value / (float)tot) : 0.0f; - } - else { - driver->curval = value; - } -} - -static void evaluate_driver_min_max(ChannelDriver *driver) -{ - DriverVar *dvar; - float value = 0.0f; - - /* loop through the variables, getting the values and comparing them to existing ones */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* get value */ - float tmp_val = driver_get_variable_value(driver, dvar); - - /* store this value if appropriate */ - if (dvar->prev) { - /* check if greater/smaller than the baseline */ - if (driver->type == DRIVER_TYPE_MAX) { - /* max? */ - if (tmp_val > value) { - value = tmp_val; - } - } - else { - /* min? */ - if (tmp_val < value) { - value = tmp_val; - } - } - } - else { - /* first item - make this the baseline for comparisons */ - value = tmp_val; - } - } - - /* store value in driver */ - driver->curval = value; -} - -static void evaluate_driver_python(PathResolvedRNA *anim_rna, - ChannelDriver *driver, - ChannelDriver *driver_orig, - const float evaltime) -{ - /* check for empty or invalid expression */ - if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) { - driver->curval = 0.0f; - } - else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) { -#ifdef WITH_PYTHON - /* this evaluates the expression using Python, and returns its result: - * - on errors it reports, then returns 0.0f - */ - BLI_mutex_lock(&python_driver_lock); - - driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); - - BLI_mutex_unlock(&python_driver_lock); -#else /* WITH_PYTHON*/ - UNUSED_VARS(anim_rna, evaltime); -#endif /* WITH_PYTHON*/ - } -} - -/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" - * - "evaltime" is the frame at which F-Curve is being evaluated - * - has to return a float value - * - driver_orig is where we cache Python expressions, in case of COW - */ -float evaluate_driver(PathResolvedRNA *anim_rna, - ChannelDriver *driver, - ChannelDriver *driver_orig, - const float evaltime) -{ - /* check if driver can be evaluated */ - if (driver_orig->flag & DRIVER_FLAG_INVALID) { - return 0.0f; - } - - switch (driver->type) { - case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ - case DRIVER_TYPE_SUM: /* sum values of driver targets */ - evaluate_driver_sum(driver); - break; - case DRIVER_TYPE_MIN: /* smallest value */ - case DRIVER_TYPE_MAX: /* largest value */ - evaluate_driver_min_max(driver); - break; - case DRIVER_TYPE_PYTHON: /* expression */ - evaluate_driver_python(anim_rna, driver, driver_orig, evaltime); - break; - default: - /* special 'hack' - just use stored value - * This is currently used as the mechanism which allows animated settings to be able - * to be changed via the UI. - */ - break; - } - - /* return value for driver */ - return driver->curval; -} - /* ***************************** Curve Calculations ********************************* */ /* The total length of the handles is not allowed to be more @@ -2666,437 +1415,327 @@ static void berekeny(float f1, float f2, float f3, float f4, float *o, int b) /* -------------------------- */ -/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ -static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) +static float fcurve_eval_keyframes_extrapolate( + FCurve *fcu, BezTriple *bezts, float evaltime, int endpoint_offset, int direction_to_neighbor) +{ + BezTriple *endpoint_bezt = bezts + endpoint_offset; /* The first/last keyframe. */ + BezTriple *neighbor_bezt = endpoint_bezt + + direction_to_neighbor; /* The second (to last) keyframe. */ + + if (endpoint_bezt->ipo == BEZT_IPO_CONST || fcu->extend == FCURVE_EXTRAPOLATE_CONSTANT || + (fcu->flag & FCURVE_DISCRETE_VALUES) != 0) { + /* Constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, so just extend the + * endpoint's value. */ + return endpoint_bezt->vec[1][1]; + } + + if (endpoint_bezt->ipo == BEZT_IPO_LIN) { + /* Use the next center point instead of our own handle for linear interpolated extrapolate. */ + if (fcu->totvert == 1) { + return endpoint_bezt->vec[1][1]; + } + + float dx = endpoint_bezt->vec[1][0] - evaltime; + float fac = neighbor_bezt->vec[1][0] - endpoint_bezt->vec[1][0]; + + /* Prevent division by zero. */ + if (fac == 0.0f) { + return endpoint_bezt->vec[1][1]; + } + + fac = (neighbor_bezt->vec[1][1] - endpoint_bezt->vec[1][1]) / fac; + return endpoint_bezt->vec[1][1] - (fac * dx); + } + + /* Use the gradient of the second handle (later) of neighbour to calculate the gradient and thus + * the value of the curve at evaltime */ + int handle = direction_to_neighbor > 0 ? 0 : 2; + float dx = endpoint_bezt->vec[1][0] - evaltime; + float fac = endpoint_bezt->vec[1][0] - endpoint_bezt->vec[handle][0]; + + /* Prevent division by zero. */ + if (fac == 0.0f) { + return endpoint_bezt->vec[1][1]; + } + + fac = (endpoint_bezt->vec[1][1] - endpoint_bezt->vec[handle][1]) / fac; + return endpoint_bezt->vec[1][1] - (fac * dx); +} + +static float fcurve_eval_keyframes_interpolate(FCurve *fcu, BezTriple *bezts, float evaltime) { const float eps = 1.e-8f; - BezTriple *bezt, *prevbezt, *lastbezt; - float v1[2], v2[2], v3[2], v4[2], opl[32], dx, fac; + BezTriple *bezt, *prevbezt; unsigned int a; - int b; - float cvalue = 0.0f; - /* get pointers */ - a = fcu->totvert - 1; - prevbezt = bezts; - bezt = prevbezt + 1; - lastbezt = prevbezt + a; + /* evaltime occurs somewhere in the middle of the curve */ + bool exact = false; + + /* Use binary search to find appropriate keyframes... + * + * The threshold here has the following constraints: + * - 0.001 is too coarse: + * We get artifacts with 2cm driver movements at 1BU = 1m (see T40332) + * + * - 0.00001 is too fine: + * Weird errors, like selecting the wrong keyframe range (see T39207), occur. + * This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd. + */ + a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact); + bezt = bezts + a; - /* evaluation time at or past endpoints? */ - if (prevbezt->vec[1][0] >= evaltime) { - /* before or on first keyframe */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (prevbezt->ipo != BEZT_IPO_CONST) && - !(fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* linear or bezier interpolation */ - if (prevbezt->ipo == BEZT_IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate - */ - if (fcu->totvert == 1) { - cvalue = prevbezt->vec[1][1]; - } - else { - bezt = prevbezt + 1; - dx = prevbezt->vec[1][0] - evaltime; - fac = bezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (bezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue = prevbezt->vec[1][1] - (fac * dx); - } - else { - cvalue = prevbezt->vec[1][1]; - } - } - } - else { - /* Use the first handle (earlier) of first BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ - dx = prevbezt->vec[1][0] - evaltime; - fac = prevbezt->vec[1][0] - prevbezt->vec[0][0]; + if (exact) { + /* index returned must be interpreted differently when it sits on top of an existing keyframe + * - that keyframe is the start of the segment we need (see action_bug_2.blend in T39207) + */ + return bezt->vec[1][1]; + } - /* prevent division by zero */ - if (fac) { - fac = (prevbezt->vec[1][1] - prevbezt->vec[0][1]) / fac; - cvalue = prevbezt->vec[1][1] - (fac * dx); - } - else { - cvalue = prevbezt->vec[1][1]; - } - } - } - else { - /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, - * so just extend first keyframe's value - */ - cvalue = prevbezt->vec[1][1]; + /* index returned refers to the keyframe that the eval-time occurs *before* + * - hence, that keyframe marks the start of the segment we're dealing with + */ + prevbezt = (a > 0) ? (bezt - 1) : bezt; + + /* Use if the key is directly on the frame, in rare cases this is needed else we get 0.0 instead. + * XXX: consult T39207 for examples of files where failure of these checks can cause issues */ + if (fabsf(bezt->vec[1][0] - evaltime) < eps) { + return bezt->vec[1][1]; + } + + if (evaltime < prevbezt->vec[1][0] || bezt->vec[1][0] < evaltime) { + if (G.debug & G_DEBUG) { + printf(" ERROR: failed eval - p=%f b=%f, t=%f (%f)\n", + prevbezt->vec[1][0], + bezt->vec[1][0], + evaltime, + fabsf(bezt->vec[1][0] - evaltime)); } + return 0.0f; } - else if (lastbezt->vec[1][0] <= evaltime) { - /* after or on last keyframe */ - if ((fcu->extend == FCURVE_EXTRAPOLATE_LINEAR) && (lastbezt->ipo != BEZT_IPO_CONST) && - !(fcu->flag & FCURVE_DISCRETE_VALUES)) { - /* linear or bezier interpolation */ - if (lastbezt->ipo == BEZT_IPO_LIN) { - /* Use the next center point instead of our own handle for - * linear interpolated extrapolate + + /* Evaltime occurs within the interval defined by these two keyframes. */ + const float begin = prevbezt->vec[1][1]; + const float change = bezt->vec[1][1] - prevbezt->vec[1][1]; + const float duration = bezt->vec[1][0] - prevbezt->vec[1][0]; + const float time = evaltime - prevbezt->vec[1][0]; + const float amplitude = prevbezt->amplitude; + const float period = prevbezt->period; + + /* value depends on interpolation mode */ + if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES) || + (duration == 0)) { + /* constant (evaltime not relevant, so no interpolation needed) */ + return prevbezt->vec[1][1]; + } + + switch (prevbezt->ipo) { + /* interpolation ...................................... */ + case BEZT_IPO_BEZ: { + float v1[2], v2[2], v3[2], v4[2], opl[32]; + + /* bezier interpolation */ + /* (v1, v2) are the first keyframe and its 2nd handle */ + v1[0] = prevbezt->vec[1][0]; + v1[1] = prevbezt->vec[1][1]; + v2[0] = prevbezt->vec[2][0]; + v2[1] = prevbezt->vec[2][1]; + /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ + v3[0] = bezt->vec[0][0]; + v3[1] = bezt->vec[0][1]; + v4[0] = bezt->vec[1][0]; + v4[1] = bezt->vec[1][1]; + + if (fabsf(v1[1] - v4[1]) < FLT_EPSILON && fabsf(v2[1] - v3[1]) < FLT_EPSILON && + fabsf(v3[1] - v4[1]) < FLT_EPSILON) { + /* Optimization: If all the handles are flat/at the same values, + * the value is simply the shared value (see T40372 -> F91346) */ - if (fcu->totvert == 1) { - cvalue = lastbezt->vec[1][1]; - } - else { - prevbezt = lastbezt - 1; - dx = evaltime - lastbezt->vec[1][0]; - fac = lastbezt->vec[1][0] - prevbezt->vec[1][0]; - - /* prevent division by zero */ - if (fac) { - fac = (lastbezt->vec[1][1] - prevbezt->vec[1][1]) / fac; - cvalue = lastbezt->vec[1][1] + (fac * dx); - } - else { - cvalue = lastbezt->vec[1][1]; - } + return v1[1]; + } + /* adjust handles so that they don't overlap (forming a loop) */ + correct_bezpart(v1, v2, v3, v4); + + /* try to get a value for this position - if failure, try another set of points */ + if (!findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl)) { + if (G.debug & G_DEBUG) { + printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", + evaltime, + v1[0], + v2[0], + v3[0], + v4[0]); } + return 0.0; } - else { - /* Use the gradient of the second handle (later) of last BezTriple to calculate the - * gradient and thus the value of the curve at evaltime - */ - dx = evaltime - lastbezt->vec[1][0]; - fac = lastbezt->vec[2][0] - lastbezt->vec[1][0]; - /* prevent division by zero */ - if (fac) { - fac = (lastbezt->vec[2][1] - lastbezt->vec[1][1]) / fac; - cvalue = lastbezt->vec[1][1] + (fac * dx); - } - else { - cvalue = lastbezt->vec[1][1]; - } + berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); + return opl[0]; + } + case BEZT_IPO_LIN: + /* linear - simply linearly interpolate between values of the two keyframes */ + return BLI_easing_linear_ease(time, begin, change, duration); + + /* easing ............................................ */ + case BEZT_IPO_BACK: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_back_ease_in(time, begin, change, duration, prevbezt->back); + case BEZT_IPO_EASE_OUT: + return BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_back_ease_in_out(time, begin, change, duration, prevbezt->back); + + default: /* default/auto: same as ease out */ + return BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); } - } - else { - /* constant (BEZT_IPO_HORIZ) extrapolation or constant interpolation, - * so just extend last keyframe's value - */ - cvalue = lastbezt->vec[1][1]; - } - } - else { - /* evaltime occurs somewhere in the middle of the curve */ - bool exact = false; - - /* Use binary search to find appropriate keyframes... - * - * The threshold here has the following constraints: - * - 0.001 is too coarse: - * We get artifacts with 2cm driver movements at 1BU = 1m (see T40332) - * - * - 0.00001 is too fine: - * Weird errors, like selecting the wrong keyframe range (see T39207), occur. - * This lower bound was established in b888a32eee8147b028464336ad2404d8155c64dd. - */ - a = binarysearch_bezt_index_ex(bezts, evaltime, fcu->totvert, 0.0001, &exact); + break; - if (exact) { - /* index returned must be interpreted differently when it sits on top of an existing keyframe - * - that keyframe is the start of the segment we need (see action_bug_2.blend in T39207) - */ - prevbezt = bezts + a; - bezt = (a < fcu->totvert - 1) ? (prevbezt + 1) : prevbezt; - } - else { - /* index returned refers to the keyframe that the eval-time occurs *before* - * - hence, that keyframe marks the start of the segment we're dealing with - */ - bezt = bezts + a; - prevbezt = (a > 0) ? (bezt - 1) : bezt; - } + case BEZT_IPO_BOUNCE: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_bounce_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_bounce_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_bounce_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease out */ + return BLI_easing_bounce_ease_out(time, begin, change, duration); + } + break; - /* use if the key is directly on the frame, - * rare cases this is needed else we get 0.0 instead. */ - /* XXX: consult T39207 for examples of files where failure of these checks can cause issues */ - if (exact) { - cvalue = prevbezt->vec[1][1]; - } - else if (fabsf(bezt->vec[1][0] - evaltime) < eps) { - cvalue = bezt->vec[1][1]; - } - /* evaltime occurs within the interval defined by these two keyframes */ - else if ((prevbezt->vec[1][0] <= evaltime) && (bezt->vec[1][0] >= evaltime)) { - const float begin = prevbezt->vec[1][1]; - const float change = bezt->vec[1][1] - prevbezt->vec[1][1]; - const float duration = bezt->vec[1][0] - prevbezt->vec[1][0]; - const float time = evaltime - prevbezt->vec[1][0]; - const float amplitude = prevbezt->amplitude; - const float period = prevbezt->period; - - /* value depends on interpolation mode */ - if ((prevbezt->ipo == BEZT_IPO_CONST) || (fcu->flag & FCURVE_DISCRETE_VALUES) || - (duration == 0)) { - /* constant (evaltime not relevant, so no interpolation needed) */ - cvalue = prevbezt->vec[1][1]; + case BEZT_IPO_CIRC: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_circ_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_circ_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_circ_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_circ_ease_in(time, begin, change, duration); } - else { - switch (prevbezt->ipo) { - /* interpolation ...................................... */ - case BEZT_IPO_BEZ: - /* bezier interpolation */ - /* (v1, v2) are the first keyframe and its 2nd handle */ - v1[0] = prevbezt->vec[1][0]; - v1[1] = prevbezt->vec[1][1]; - v2[0] = prevbezt->vec[2][0]; - v2[1] = prevbezt->vec[2][1]; - /* (v3, v4) are the last keyframe's 1st handle + the last keyframe */ - v3[0] = bezt->vec[0][0]; - v3[1] = bezt->vec[0][1]; - v4[0] = bezt->vec[1][0]; - v4[1] = bezt->vec[1][1]; - - if (fabsf(v1[1] - v4[1]) < FLT_EPSILON && fabsf(v2[1] - v3[1]) < FLT_EPSILON && - fabsf(v3[1] - v4[1]) < FLT_EPSILON) { - /* Optimization: If all the handles are flat/at the same values, - * the value is simply the shared value (see T40372 -> F91346) - */ - cvalue = v1[1]; - } - else { - /* adjust handles so that they don't overlap (forming a loop) */ - correct_bezpart(v1, v2, v3, v4); - - /* try to get a value for this position - if failure, try another set of points */ - b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); - if (b) { - berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); - cvalue = opl[0]; - /* break; */ - } - else { - if (G.debug & G_DEBUG) { - printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", - evaltime, - v1[0], - v2[0], - v3[0], - v4[0]); - } - } - } - break; - - case BEZT_IPO_LIN: - /* linear - simply linearly interpolate between values of the two keyframes */ - cvalue = BLI_easing_linear_ease(time, begin, change, duration); - break; - - /* easing ............................................ */ - case BEZT_IPO_BACK: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_back_ease_in(time, begin, change, duration, prevbezt->back); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_back_ease_in_out( - time, begin, change, duration, prevbezt->back); - break; - - default: /* default/auto: same as ease out */ - cvalue = BLI_easing_back_ease_out(time, begin, change, duration, prevbezt->back); - break; - } - break; - - case BEZT_IPO_BOUNCE: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_bounce_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_bounce_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_bounce_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease out */ - cvalue = BLI_easing_bounce_ease_out(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_CIRC: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_circ_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_circ_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_circ_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_circ_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_CUBIC: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_cubic_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_cubic_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_cubic_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_cubic_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_ELASTIC: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_elastic_ease_in( - time, begin, change, duration, amplitude, period); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_elastic_ease_out( - time, begin, change, duration, amplitude, period); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_elastic_ease_in_out( - time, begin, change, duration, amplitude, period); - break; - - default: /* default/auto: same as ease out */ - cvalue = BLI_easing_elastic_ease_out( - time, begin, change, duration, amplitude, period); - break; - } - break; - - case BEZT_IPO_EXPO: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_expo_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_expo_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_expo_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_expo_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_QUAD: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_quad_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_quad_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_quad_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_quad_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_QUART: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_quart_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_quart_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_quart_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_quart_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_QUINT: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_quint_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_quint_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_quint_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_quint_ease_in(time, begin, change, duration); - break; - } - break; - - case BEZT_IPO_SINE: - switch (prevbezt->easing) { - case BEZT_IPO_EASE_IN: - cvalue = BLI_easing_sine_ease_in(time, begin, change, duration); - break; - case BEZT_IPO_EASE_OUT: - cvalue = BLI_easing_sine_ease_out(time, begin, change, duration); - break; - case BEZT_IPO_EASE_IN_OUT: - cvalue = BLI_easing_sine_ease_in_out(time, begin, change, duration); - break; - - default: /* default/auto: same as ease in */ - cvalue = BLI_easing_sine_ease_in(time, begin, change, duration); - break; - } - break; + break; - default: - cvalue = prevbezt->vec[1][1]; - break; - } + case BEZT_IPO_CUBIC: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_cubic_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_cubic_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_cubic_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_cubic_ease_in(time, begin, change, duration); } - } - else { - if (G.debug & G_DEBUG) { - printf(" ERROR: failed eval - p=%f b=%f, t=%f (%f)\n", - prevbezt->vec[1][0], - bezt->vec[1][0], - evaltime, - fabsf(bezt->vec[1][0] - evaltime)); + break; + + case BEZT_IPO_ELASTIC: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_elastic_ease_in(time, begin, change, duration, amplitude, period); + case BEZT_IPO_EASE_OUT: + return BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_elastic_ease_in_out(time, begin, change, duration, amplitude, period); + + default: /* default/auto: same as ease out */ + return BLI_easing_elastic_ease_out(time, begin, change, duration, amplitude, period); } - } + break; + + case BEZT_IPO_EXPO: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_expo_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_expo_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_expo_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_expo_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_QUAD: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_quad_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_quad_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_quad_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_quad_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_QUART: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_quart_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_quart_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_quart_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_quart_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_QUINT: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_quint_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_quint_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_quint_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_quint_ease_in(time, begin, change, duration); + } + break; + + case BEZT_IPO_SINE: + switch (prevbezt->easing) { + case BEZT_IPO_EASE_IN: + return BLI_easing_sine_ease_in(time, begin, change, duration); + case BEZT_IPO_EASE_OUT: + return BLI_easing_sine_ease_out(time, begin, change, duration); + case BEZT_IPO_EASE_IN_OUT: + return BLI_easing_sine_ease_in_out(time, begin, change, duration); + + default: /* default/auto: same as ease in */ + return BLI_easing_sine_ease_in(time, begin, change, duration); + } + break; + + default: + return prevbezt->vec[1][1]; } - /* return value */ - return cvalue; + return 0.0f; +} + +/* Calculate F-Curve value for 'evaltime' using BezTriple keyframes */ +static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime) +{ + if (evaltime <= bezts->vec[1][0]) { + return fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, 0, +1); + } + + BezTriple *lastbezt = bezts + fcu->totvert - 1; + if (lastbezt->vec[1][0] <= evaltime) { + return fcurve_eval_keyframes_extrapolate(fcu, bezts, evaltime, fcu->totvert - 1, -1); + } + + return fcurve_eval_keyframes_interpolate(fcu, bezts, evaltime); } /* Calculate F-Curve value for 'evaltime' using FPoint samples */ diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c new file mode 100644 index 00000000000..78a6cf28824 --- /dev/null +++ b/source/blender/blenkernel/intern/fcurve_driver.c @@ -0,0 +1,1294 @@ +/* + * 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) 2009 Blender Foundation, Joshua Leung + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +// #include <float.h> +// #include <math.h> +// #include <stddef.h> +// #include <stdio.h> +// #include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_anim_types.h" +#include "DNA_constraint_types.h" +#include "DNA_object_types.h" + +#include "BLI_alloca.h" +#include "BLI_expr_pylike_eval.h" +#include "BLI_math.h" +#include "BLI_string_utils.h" +#include "BLI_threads.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_action.h" +#include "BKE_armature.h" +#include "BKE_constraint.h" +#include "BKE_fcurve_driver.h" +#include "BKE_global.h" +#include "BKE_object.h" + +#include "RNA_access.h" + +#include "atomic_ops.h" + +#include "CLG_log.h" + +#ifdef WITH_PYTHON +# include "BPY_extern.h" +#endif + +#ifdef WITH_PYTHON +static ThreadMutex python_driver_lock = BLI_MUTEX_INITIALIZER; +#endif + +static CLG_LogRef LOG = {"bke.fcurve"}; + +/* Driver Variables --------------------------- */ + +/* TypeInfo for Driver Variables (dvti) */ +typedef struct DriverVarTypeInfo { + /* evaluation callback */ + float (*get_value)(ChannelDriver *driver, DriverVar *dvar); + + /* allocation of target slots */ + int num_targets; /* number of target slots required */ + const char *target_names[MAX_DRIVER_TARGETS]; /* UI names that should be given to the slots */ + short target_flags[MAX_DRIVER_TARGETS]; /* flags defining the requirements for each slot */ +} DriverVarTypeInfo; + +/* Macro to begin definitions */ +#define BEGIN_DVAR_TYPEDEF(type) { + +/* Macro to end definitions */ +#define END_DVAR_TYPEDEF } + +/* ......... */ + +static ID *dtar_id_ensure_proxy_from(ID *id) +{ + if (id && GS(id->name) == ID_OB && ((Object *)id)->proxy_from) { + return (ID *)(((Object *)id)->proxy_from); + } + return id; +} + +/** + * Helper function to obtain a value using RNA from the specified source + * (for evaluating drivers). + */ +static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar) +{ + PointerRNA id_ptr, ptr; + PropertyRNA *prop; + ID *id; + int index = -1; + float value = 0.0f; + + /* sanity check */ + if (ELEM(NULL, driver, dtar)) { + return 0.0f; + } + + id = dtar_id_ensure_proxy_from(dtar->id); + + /* error check for missing pointer... */ + if (id == NULL) { + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(id, &id_ptr); + + /* get property to read from, and get value as appropriate */ + if (!RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { + /* path couldn't be resolved */ + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, + "Driver Evaluation Error: cannot resolve target for %s -> %s", + id->name, + dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + + if (RNA_property_array_check(prop)) { + /* array */ + if (index < 0 || index >= RNA_property_array_length(&ptr, prop)) { + /* out of bounds */ + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, + "Driver Evaluation Error: array index is out of bounds for %s -> %s (%d)", + id->name, + dtar->rna_path, + index); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value = (float)RNA_property_boolean_get_index(&ptr, prop, index); + break; + case PROP_INT: + value = (float)RNA_property_int_get_index(&ptr, prop, index); + break; + case PROP_FLOAT: + value = RNA_property_float_get_index(&ptr, prop, index); + break; + default: + break; + } + } + else { + /* not an array */ + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + value = (float)RNA_property_boolean_get(&ptr, prop); + break; + case PROP_INT: + value = (float)RNA_property_int_get(&ptr, prop); + break; + case PROP_FLOAT: + value = RNA_property_float_get(&ptr, prop); + break; + case PROP_ENUM: + value = (float)RNA_property_enum_get(&ptr, prop); + break; + default: + break; + } + } + + /* if we're still here, we should be ok... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + return value; +} + +/** + * Same as 'dtar_get_prop_val'. but get the RNA property. + */ +bool driver_get_variable_property(ChannelDriver *driver, + DriverTarget *dtar, + PointerRNA *r_ptr, + PropertyRNA **r_prop, + int *r_index) +{ + PointerRNA id_ptr; + PointerRNA ptr; + PropertyRNA *prop; + ID *id; + int index = -1; + + /* sanity check */ + if (ELEM(NULL, driver, dtar)) { + return false; + } + + id = dtar_id_ensure_proxy_from(dtar->id); + + /* error check for missing pointer... */ + if (id == NULL) { + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, "driver has an invalid target to use (path = %s)", dtar->rna_path); + } + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return false; + } + + /* get RNA-pointer for the ID-block given in target */ + RNA_id_pointer_create(id, &id_ptr); + + /* get property to read from, and get value as appropriate */ + if (dtar->rna_path == NULL || dtar->rna_path[0] == '\0') { + ptr = PointerRNA_NULL; + prop = NULL; /* ok */ + } + else if (RNA_path_resolve_property_full(&id_ptr, dtar->rna_path, &ptr, &prop, &index)) { + /* ok */ + } + else { + /* path couldn't be resolved */ + if (G.debug & G_DEBUG) { + CLOG_ERROR(&LOG, + "Driver Evaluation Error: cannot resolve target for %s -> %s", + id->name, + dtar->rna_path); + } + + ptr = PointerRNA_NULL; + *r_prop = NULL; + *r_index = -1; + + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return false; + } + + *r_ptr = ptr; + *r_prop = prop; + *r_index = index; + + /* if we're still here, we should be ok... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + return true; +} + +static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar) +{ + short valid_targets = 0; + + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + + /* check if this target has valid data */ + if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { + /* invalid target, so will not have enough targets */ + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + } + else { + /* target seems to be OK now... */ + dtar->flag &= ~DTAR_FLAG_INVALID; + valid_targets++; + } + } + DRIVER_TARGETS_LOOPER_END; + + return valid_targets; +} + +/* ......... */ + +/* evaluate 'single prop' driver variable */ +static float dvar_eval_singleProp(ChannelDriver *driver, DriverVar *dvar) +{ + /* just evaluate the first target slot */ + return dtar_get_prop_val(driver, &dvar->targets[0]); +} + +/* evaluate 'rotation difference' driver variable */ +static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar) +{ + short valid_targets = driver_check_valid_targets(driver, dvar); + + /* make sure we have enough valid targets to use - all or nothing for now... */ + if (driver_check_valid_targets(driver, dvar) != 2) { + if (G.debug & G_DEBUG) { + CLOG_WARN(&LOG, + "RotDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", + valid_targets, + dvar->targets[0].id, + dvar->targets[1].id); + } + return 0.0f; + } + + float(*mat[2])[4]; + + /* NOTE: for now, these are all just worldspace */ + for (int i = 0; i < 2; i++) { + /* get pointer to loc values to store in */ + DriverTarget *dtar = &dvar->targets[i]; + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + bPoseChannel *pchan; + + /* after the checks above, the targets should be valid here... */ + BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); + + /* try to get posechannel */ + pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + + /* check if object or bone */ + if (pchan) { + /* bone */ + mat[i] = pchan->pose_mat; + } + else { + /* object */ + mat[i] = ob->obmat; + } + } + + float q1[4], q2[4], quat[4], angle; + + /* use the final posed locations */ + mat4_to_quat(q1, mat[0]); + mat4_to_quat(q2, mat[1]); + + invert_qt_normalized(q1); + mul_qt_qtqt(quat, q1, q2); + angle = 2.0f * (saacos(quat[0])); + angle = fabsf(angle); + + return (angle > (float)M_PI) ? (float)((2.0f * (float)M_PI) - angle) : (float)(angle); +} + +/* evaluate 'location difference' driver variable */ +/* TODO: this needs to take into account space conversions... */ +static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar) +{ + float loc1[3] = {0.0f, 0.0f, 0.0f}; + float loc2[3] = {0.0f, 0.0f, 0.0f}; + short valid_targets = driver_check_valid_targets(driver, dvar); + + /* make sure we have enough valid targets to use - all or nothing for now... */ + if (valid_targets < dvar->num_targets) { + if (G.debug & G_DEBUG) { + CLOG_WARN(&LOG, + "LocDiff DVar: not enough valid targets (n = %d) (a = %p, b = %p)", + valid_targets, + dvar->targets[0].id, + dvar->targets[1].id); + } + return 0.0f; + } + + /* SECOND PASS: get two location values */ + /* NOTE: for now, these are all just worldspace */ + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + /* get pointer to loc values to store in */ + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + bPoseChannel *pchan; + float tmp_loc[3]; + + /* after the checks above, the targets should be valid here... */ + BLI_assert((ob != NULL) && (GS(ob->id.name) == ID_OB)); + + /* try to get posechannel */ + pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + + /* check if object or bone */ + if (pchan) { + /* bone */ + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + float mat[4][4]; + + /* extract transform just like how the constraints do it! */ + copy_m4_m4(mat, pchan->pose_mat); + BKE_constraint_mat_convertspace( + ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); + + /* ... and from that, we get our transform */ + copy_v3_v3(tmp_loc, mat[3]); + } + else { + /* transform space (use transform values directly) */ + copy_v3_v3(tmp_loc, pchan->loc); + } + } + else { + /* convert to worldspace */ + copy_v3_v3(tmp_loc, pchan->pose_head); + mul_m4_v3(ob->obmat, tmp_loc); + } + } + else { + /* object */ + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* XXX: this should practically be the same as transform space... */ + float mat[4][4]; + + /* extract transform just like how the constraints do it! */ + copy_m4_m4(mat, ob->obmat); + BKE_constraint_mat_convertspace( + ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); + + /* ... and from that, we get our transform */ + copy_v3_v3(tmp_loc, mat[3]); + } + else { + /* transform space (use transform values directly) */ + copy_v3_v3(tmp_loc, ob->loc); + } + } + else { + /* worldspace */ + copy_v3_v3(tmp_loc, ob->obmat[3]); + } + } + + /* copy the location to the right place */ + if (tarIndex) { + copy_v3_v3(loc2, tmp_loc); + } + else { + copy_v3_v3(loc1, tmp_loc); + } + } + DRIVER_TARGETS_LOOPER_END; + + /* if we're still here, there should now be two targets to use, + * so just take the length of the vector between these points + */ + return len_v3v3(loc1, loc2); +} + +/* evaluate 'transform channel' driver variable */ +static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar) +{ + DriverTarget *dtar = &dvar->targets[0]; + Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id); + bPoseChannel *pchan; + float mat[4][4]; + float oldEul[3] = {0.0f, 0.0f, 0.0f}; + bool use_eulers = false; + short rot_order = ROT_MODE_EUL; + + /* check if this target has valid data */ + if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) { + /* invalid target, so will not have enough targets */ + driver->flag |= DRIVER_FLAG_INVALID; + dtar->flag |= DTAR_FLAG_INVALID; + return 0.0f; + } + else { + /* target should be valid now */ + dtar->flag &= ~DTAR_FLAG_INVALID; + } + + /* try to get posechannel */ + pchan = BKE_pose_channel_find_name(ob->pose, dtar->pchan_name); + + /* check if object or bone, and get transform matrix accordingly + * - "useEulers" code is used to prevent the problems associated with non-uniqueness + * of euler decomposition from matrices [#20870] + * - localspace is for [#21384], where parent results are not wanted + * but local-consts is for all the common "corrective-shapes-for-limbs" situations + */ + if (pchan) { + /* bone */ + if (pchan->rotmode > 0) { + copy_v3_v3(oldEul, pchan->eul); + rot_order = pchan->rotmode; + use_eulers = true; + } + + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* just like how the constraints do it! */ + copy_m4_m4(mat, pchan->pose_mat); + BKE_constraint_mat_convertspace( + ob, pchan, mat, CONSTRAINT_SPACE_POSE, CONSTRAINT_SPACE_LOCAL, false); + } + else { + /* specially calculate local matrix, since chan_mat is not valid + * since it stores delta transform of pose_mat so that deforms work + * so it cannot be used here for "transform" space + */ + BKE_pchan_to_mat4(pchan, mat); + } + } + else { + /* worldspace matrix */ + mul_m4_m4m4(mat, ob->obmat, pchan->pose_mat); + } + } + else { + /* object */ + if (ob->rotmode > 0) { + copy_v3_v3(oldEul, ob->rot); + rot_order = ob->rotmode; + use_eulers = true; + } + + if (dtar->flag & DTAR_FLAG_LOCALSPACE) { + if (dtar->flag & DTAR_FLAG_LOCAL_CONSTS) { + /* just like how the constraints do it! */ + copy_m4_m4(mat, ob->obmat); + BKE_constraint_mat_convertspace( + ob, NULL, mat, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL, false); + } + else { + /* transforms to matrix */ + BKE_object_to_mat4(ob, mat); + } + } + else { + /* worldspace matrix - just the good-old one */ + copy_m4_m4(mat, ob->obmat); + } + } + + /* check which transform */ + if (dtar->transChan >= MAX_DTAR_TRANSCHAN_TYPES) { + /* not valid channel */ + return 0.0f; + } + else if (dtar->transChan == DTAR_TRANSCHAN_SCALE_AVG) { + /* Cubic root of the change in volume, equal to the geometric mean + * of scale over all three axes unless the matrix includes shear. */ + return cbrtf(mat4_to_volume_scale(mat)); + } + else if (ELEM(dtar->transChan, + DTAR_TRANSCHAN_SCALEX, + DTAR_TRANSCHAN_SCALEY, + DTAR_TRANSCHAN_SCALEZ)) { + /* Extract scale, and choose the right axis, + * inline 'mat4_to_size'. */ + return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]); + } + else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) { + /* extract rotation as eulers (if needed) + * - definitely if rotation order isn't eulers already + * - if eulers, then we have 2 options: + * a) decompose transform matrix as required, then try to make eulers from + * there compatible with original values + * b) [NOT USED] directly use the original values (no decomposition) + * - only an option for "transform space", if quality is really bad with a) + */ + float quat[4]; + int channel; + + if (dtar->transChan == DTAR_TRANSCHAN_ROTW) { + channel = 0; + } + else { + channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX; + BLI_assert(channel < 4); + } + + BKE_driver_target_matrix_to_rot_channels( + mat, rot_order, dtar->rotation_mode, channel, false, quat); + + if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) { + compatible_eul(quat + 1, oldEul); + } + + return quat[channel]; + } + else { + /* extract location and choose right axis */ + return mat[3][dtar->transChan]; + } +} + +/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */ +static void quaternion_to_angles(float quat[4], int channel) +{ + if (channel < 0) { + quat[0] = 2.0f * saacosf(quat[0]); + + for (int i = 1; i < 4; i++) { + quat[i] = 2.0f * saasinf(quat[i]); + } + } + else if (channel == 0) { + quat[0] = 2.0f * saacosf(quat[0]); + } + else { + quat[channel] = 2.0f * saasinf(quat[channel]); + } +} + +/* Compute channel values for a rotational Transform Channel driver variable. */ +void BKE_driver_target_matrix_to_rot_channels( + float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]) +{ + float *const quat = r_buf; + float *const eul = r_buf + 1; + + zero_v4(r_buf); + + if (rotation_mode == DTAR_ROTMODE_AUTO) { + mat4_to_eulO(eul, auto_order, mat); + } + else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) { + mat4_to_eulO(eul, rotation_mode, mat); + } + else if (rotation_mode == DTAR_ROTMODE_QUATERNION) { + mat4_to_quat(quat, mat); + + /* For Transformation constraint convenience, convert to pseudo-angles. */ + if (angles) { + quaternion_to_angles(quat, channel); + } + } + else if (rotation_mode >= DTAR_ROTMODE_SWING_TWIST_X && + rotation_mode <= DTAR_ROTMODE_SWING_TWIST_Z) { + int axis = rotation_mode - DTAR_ROTMODE_SWING_TWIST_X; + float raw_quat[4], twist; + + mat4_to_quat(raw_quat, mat); + + if (channel == axis + 1) { + /* If only the twist angle is needed, skip computing swing. */ + twist = quat_split_swing_and_twist(raw_quat, axis, NULL, NULL); + } + else { + twist = quat_split_swing_and_twist(raw_quat, axis, quat, NULL); + + quaternion_to_angles(quat, channel); + } + + quat[axis + 1] = twist; + } + else { + BLI_assert(false); + } +} + +/* ......... */ + +/* Table of Driver Variable Type Info Data */ +static DriverVarTypeInfo dvar_types[MAX_DVAR_TYPES] = { + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_SINGLE_PROP) dvar_eval_singleProp, /* eval callback */ + 1, /* number of targets used */ + {"Property"}, /* UI names for targets */ + {0} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_ROT_DIFF) dvar_eval_rotDiff, /* eval callback */ + 2, /* number of targets used */ + {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, + DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_LOC_DIFF) dvar_eval_locDiff, /* eval callback */ + 2, /* number of targets used */ + {"Object/Bone 1", "Object/Bone 2"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY, + DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, + + BEGIN_DVAR_TYPEDEF(DVAR_TYPE_TRANSFORM_CHAN) dvar_eval_transChan, /* eval callback */ + 1, /* number of targets used */ + {"Object/Bone"}, /* UI names for targets */ + {DTAR_FLAG_STRUCT_REF | DTAR_FLAG_ID_OB_ONLY} /* flags */ + END_DVAR_TYPEDEF, +}; + +/* Get driver variable typeinfo */ +static const DriverVarTypeInfo *get_dvar_typeinfo(int type) +{ + /* check if valid type */ + if ((type >= 0) && (type < MAX_DVAR_TYPES)) { + return &dvar_types[type]; + } + else { + return NULL; + } +} + +/* Driver API --------------------------------- */ + +/* Perform actual freeing driver variable and remove it from the given list */ +void driver_free_variable(ListBase *variables, DriverVar *dvar) +{ + /* sanity checks */ + if (dvar == NULL) { + return; + } + + /* free target vars + * - need to go over all of them, not just up to the ones that are used + * currently, since there may be some lingering RNA paths from + * previous users needing freeing + */ + DRIVER_TARGETS_LOOPER_BEGIN (dvar) { + /* free RNA path if applicable */ + if (dtar->rna_path) { + MEM_freeN(dtar->rna_path); + } + } + DRIVER_TARGETS_LOOPER_END; + + /* remove the variable from the driver */ + BLI_freelinkN(variables, dvar); +} + +/* Free the driver variable and do extra updates */ +void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar) +{ + /* remove and free the driver variable */ + driver_free_variable(&driver->variables, dvar); + + /* since driver variables are cached, the expression needs re-compiling too */ + BKE_driver_invalidate_expression(driver, false, true); +} + +/* Copy driver variables from src_vars list to dst_vars list */ +void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars) +{ + BLI_assert(BLI_listbase_is_empty(dst_vars)); + BLI_duplicatelist(dst_vars, src_vars); + + LISTBASE_FOREACH (DriverVar *, dvar, dst_vars) { + /* need to go over all targets so that we don't leave any dangling paths */ + DRIVER_TARGETS_LOOPER_BEGIN (dvar) { + /* make a copy of target's rna path if available */ + if (dtar->rna_path) { + dtar->rna_path = MEM_dupallocN(dtar->rna_path); + } + } + DRIVER_TARGETS_LOOPER_END; + } +} + +/* Change the type of driver variable */ +void driver_change_variable_type(DriverVar *dvar, int type) +{ + const DriverVarTypeInfo *dvti = get_dvar_typeinfo(type); + + /* sanity check */ + if (ELEM(NULL, dvar, dvti)) { + return; + } + + /* set the new settings */ + dvar->type = type; + dvar->num_targets = dvti->num_targets; + + /* make changes to the targets based on the defines for these types + * NOTE: only need to make sure the ones we're using here are valid... + */ + DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) { + short flags = dvti->target_flags[tarIndex]; + + /* store the flags */ + dtar->flag = flags; + + /* object ID types only, or idtype not yet initialized */ + if ((flags & DTAR_FLAG_ID_OB_ONLY) || (dtar->idtype == 0)) { + dtar->idtype = ID_OB; + } + } + DRIVER_TARGETS_LOOPER_END; +} + +/* Validate driver name (after being renamed) */ +void driver_variable_name_validate(DriverVar *dvar) +{ + /* Special character blacklist */ + const char special_char_blacklist[] = { + '~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '+', '=', '-', '/', '\\', + '?', ':', ';', '<', '>', '{', '}', '[', ']', '|', ' ', '.', '\t', '\n', '\r', + }; + + /* sanity checks */ + if (dvar == NULL) { + return; + } + + /* clear all invalid-name flags */ + dvar->flag &= ~DVAR_ALL_INVALID_FLAGS; + + /* 0) Zero-length identifiers are not allowed */ + if (dvar->name[0] == '\0') { + dvar->flag |= DVAR_FLAG_INVALID_EMPTY; + } + + /* 1) Must start with a letter */ + /* XXX: We assume that valid unicode letters in other languages are ok too, + * hence the blacklisting. */ + if (IN_RANGE_INCL(dvar->name[0], '0', '9')) { + dvar->flag |= DVAR_FLAG_INVALID_START_NUM; + } + else if (dvar->name[0] == '_') { + /* NOTE: We don't allow names to start with underscores + * (i.e. it helps when ruling out security risks) */ + dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; + } + + /* 2) Must not contain invalid stuff in the middle of the string */ + if (strchr(dvar->name, ' ')) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_SPACE; + } + if (strchr(dvar->name, '.')) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_DOT; + } + + /* 3) Check for special characters - Either at start, or in the middle */ + for (int i = 0; i < sizeof(special_char_blacklist); i++) { + char *match = strchr(dvar->name, special_char_blacklist[i]); + + if (match == dvar->name) { + dvar->flag |= DVAR_FLAG_INVALID_START_CHAR; + } + else if (match != NULL) { + dvar->flag |= DVAR_FLAG_INVALID_HAS_SPECIAL; + } + } + + /* 4) Check if the name is a reserved keyword + * NOTE: These won't confuse Python, but it will be impossible to use the variable + * in an expression without Python misinterpreting what these are for + */ +#ifdef WITH_PYTHON + if (BPY_string_is_keyword(dvar->name)) { + dvar->flag |= DVAR_FLAG_INVALID_PY_KEYWORD; + } +#endif + + /* If any these conditions match, the name is invalid */ + if (dvar->flag & DVAR_ALL_INVALID_FLAGS) { + dvar->flag |= DVAR_FLAG_INVALID_NAME; + } +} + +/* Add a new driver variable */ +DriverVar *driver_add_new_variable(ChannelDriver *driver) +{ + DriverVar *dvar; + + /* sanity checks */ + if (driver == NULL) { + return NULL; + } + + /* make a new variable */ + dvar = MEM_callocN(sizeof(DriverVar), "DriverVar"); + BLI_addtail(&driver->variables, dvar); + + /* give the variable a 'unique' name */ + strcpy(dvar->name, CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var")); + BLI_uniquename(&driver->variables, + dvar, + CTX_DATA_(BLT_I18NCONTEXT_ID_ACTION, "var"), + '_', + offsetof(DriverVar, name), + sizeof(dvar->name)); + + /* set the default type to 'single prop' */ + driver_change_variable_type(dvar, DVAR_TYPE_SINGLE_PROP); + + /* since driver variables are cached, the expression needs re-compiling too */ + BKE_driver_invalidate_expression(driver, false, true); + + /* return the target */ + return dvar; +} + +/* This frees the driver itself */ +void fcurve_free_driver(FCurve *fcu) +{ + ChannelDriver *driver; + DriverVar *dvar, *dvarn; + + /* sanity checks */ + if (ELEM(NULL, fcu, fcu->driver)) { + return; + } + driver = fcu->driver; + + /* free driver targets */ + for (dvar = driver->variables.first; dvar; dvar = dvarn) { + dvarn = dvar->next; + driver_free_variable_ex(driver, dvar); + } + +#ifdef WITH_PYTHON + /* free compiled driver expression */ + if (driver->expr_comp) { + BPY_DECREF(driver->expr_comp); + } +#endif + + BLI_expr_pylike_free(driver->expr_simple); + + /* Free driver itself, then set F-Curve's point to this to NULL + * (as the curve may still be used). */ + MEM_freeN(driver); + fcu->driver = NULL; +} + +/* This makes a copy of the given driver */ +ChannelDriver *fcurve_copy_driver(const ChannelDriver *driver) +{ + ChannelDriver *ndriver; + + /* sanity checks */ + if (driver == NULL) { + return NULL; + } + + /* copy all data */ + ndriver = MEM_dupallocN(driver); + ndriver->expr_comp = NULL; + ndriver->expr_simple = NULL; + + /* copy variables */ + + /* to get rid of refs to non-copied data (that's still used on original) */ + BLI_listbase_clear(&ndriver->variables); + driver_variables_copy(&ndriver->variables, &driver->variables); + + /* return the new driver */ + return ndriver; +} + +/* Driver Expression Evaluation --------------- */ + +/* Index constants for the expression parameter array. */ +enum { + /* Index of the 'frame' variable. */ + VAR_INDEX_FRAME = 0, + /* Index of the first user-defined driver variable. */ + VAR_INDEX_CUSTOM +}; + +static ExprPyLike_Parsed *driver_compile_simple_expr_impl(ChannelDriver *driver) +{ + /* Prepare parameter names. */ + int names_len = BLI_listbase_count(&driver->variables); + const char **names = BLI_array_alloca(names, names_len + VAR_INDEX_CUSTOM); + int i = VAR_INDEX_CUSTOM; + + names[VAR_INDEX_FRAME] = "frame"; + + LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { + names[i++] = dvar->name; + } + + return BLI_expr_pylike_parse(driver->expression, names, names_len + VAR_INDEX_CUSTOM); +} + +static bool driver_check_simple_expr_depends_on_time(ExprPyLike_Parsed *expr) +{ + /* Check if the 'frame' parameter is actually used. */ + return BLI_expr_pylike_is_using_param(expr, VAR_INDEX_FRAME); +} + +static bool driver_evaluate_simple_expr(ChannelDriver *driver, + ExprPyLike_Parsed *expr, + float *result, + float time) +{ + /* Prepare parameter values. */ + int vars_len = BLI_listbase_count(&driver->variables); + double *vars = BLI_array_alloca(vars, vars_len + VAR_INDEX_CUSTOM); + int i = VAR_INDEX_CUSTOM; + + vars[VAR_INDEX_FRAME] = time; + + LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) { + vars[i++] = driver_get_variable_value(driver, dvar); + } + + /* Evaluate expression. */ + double result_val; + eExprPyLike_EvalStatus status = BLI_expr_pylike_eval( + expr, vars, vars_len + VAR_INDEX_CUSTOM, &result_val); + const char *message; + + switch (status) { + case EXPR_PYLIKE_SUCCESS: + if (isfinite(result_val)) { + *result = (float)result_val; + } + return true; + + case EXPR_PYLIKE_DIV_BY_ZERO: + case EXPR_PYLIKE_MATH_ERROR: + message = (status == EXPR_PYLIKE_DIV_BY_ZERO) ? "Division by Zero" : "Math Domain Error"; + CLOG_ERROR(&LOG, "%s in Driver: '%s'", message, driver->expression); + + driver->flag |= DRIVER_FLAG_INVALID; + return true; + + default: + /* arriving here means a bug, not user error */ + CLOG_ERROR(&LOG, "simple driver expression evaluation failed: '%s'", driver->expression); + return false; + } +} + +/* Compile and cache the driver expression if necessary, with thread safety. */ +static bool driver_compile_simple_expr(ChannelDriver *driver) +{ + if (driver->expr_simple != NULL) { + return true; + } + + if (driver->type != DRIVER_TYPE_PYTHON) { + return false; + } + + /* It's safe to parse in multiple threads; at worst it'll + * waste some effort, but in return avoids mutex contention. */ + ExprPyLike_Parsed *expr = driver_compile_simple_expr_impl(driver); + + /* Store the result if the field is still NULL, or discard + * it if another thread got here first. */ + if (atomic_cas_ptr((void **)&driver->expr_simple, NULL, expr) != NULL) { + BLI_expr_pylike_free(expr); + } + + return true; +} + +/* Try using the simple expression evaluator to compute the result of the driver. + * On success, stores the result and returns true; on failure result is set to 0. */ +static bool driver_try_evaluate_simple_expr(ChannelDriver *driver, + ChannelDriver *driver_orig, + float *result, + float time) +{ + *result = 0.0f; + + return driver_compile_simple_expr(driver_orig) && + BLI_expr_pylike_is_valid(driver_orig->expr_simple) && + driver_evaluate_simple_expr(driver, driver_orig->expr_simple, result, time); +} + +/* Check if the expression in the driver conforms to the simple subset. */ +bool BKE_driver_has_simple_expression(ChannelDriver *driver) +{ + return driver_compile_simple_expr(driver) && BLI_expr_pylike_is_valid(driver->expr_simple); +} + +/* TODO(sergey): This is somewhat weak, but we don't want neither false-positive + * time dependencies nor special exceptions in the depsgraph evaluation. */ +static bool python_driver_exression_depends_on_time(const char *expression) +{ + if (expression[0] == '\0') { + /* Empty expression depends on nothing. */ + return false; + } + if (strchr(expression, '(') != NULL) { + /* Function calls are considered dependent on a time. */ + return true; + } + if (strstr(expression, "frame") != NULL) { + /* Variable `frame` depends on time. */ + /* TODO(sergey): This is a bit weak, but not sure about better way of handling this. */ + return true; + } + /* Possible indirect time relation s should be handled via variable targets. */ + return false; +} + +/* Check if the expression in the driver may depend on the current frame. */ +bool BKE_driver_expression_depends_on_time(ChannelDriver *driver) +{ + if (driver->type != DRIVER_TYPE_PYTHON) { + return false; + } + + if (BKE_driver_has_simple_expression(driver)) { + /* Simple expressions can be checked exactly. */ + return driver_check_simple_expr_depends_on_time(driver->expr_simple); + } + else { + /* Otherwise, heuristically scan the expression string for certain patterns. */ + return python_driver_exression_depends_on_time(driver->expression); + } +} + +/* Reset cached compiled expression data */ +void BKE_driver_invalidate_expression(ChannelDriver *driver, + bool expr_changed, + bool varname_changed) +{ + if (expr_changed || varname_changed) { + BLI_expr_pylike_free(driver->expr_simple); + driver->expr_simple = NULL; + } + +#ifdef WITH_PYTHON + if (expr_changed) { + driver->flag |= DRIVER_FLAG_RECOMPILE; + } + + if (varname_changed) { + driver->flag |= DRIVER_FLAG_RENAMEVAR; + } +#endif +} + +/* Driver Evaluation -------------------------- */ + +/* Evaluate a Driver Variable to get a value that contributes to the final */ +float driver_get_variable_value(ChannelDriver *driver, DriverVar *dvar) +{ + const DriverVarTypeInfo *dvti; + + /* sanity check */ + if (ELEM(NULL, driver, dvar)) { + return 0.0f; + } + + /* call the relevant callbacks to get the variable value + * using the variable type info, storing the obtained value + * in dvar->curval so that drivers can be debugged + */ + dvti = get_dvar_typeinfo(dvar->type); + + if (dvti && dvti->get_value) { + dvar->curval = dvti->get_value(driver, dvar); + } + else { + dvar->curval = 0.0f; + } + + return dvar->curval; +} + +static void evaluate_driver_sum(ChannelDriver *driver) +{ + DriverVar *dvar; + + /* check how many variables there are first (i.e. just one?) */ + if (BLI_listbase_is_single(&driver->variables)) { + /* just one target, so just use that */ + dvar = driver->variables.first; + driver->curval = driver_get_variable_value(driver, dvar); + return; + } + + /* more than one target, so average the values of the targets */ + float value = 0.0f; + int tot = 0; + + /* loop through targets, adding (hopefully we don't get any overflow!) */ + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + value += driver_get_variable_value(driver, dvar); + tot++; + } + + /* perform operations on the total if appropriate */ + if (driver->type == DRIVER_TYPE_AVERAGE) { + driver->curval = tot ? (value / (float)tot) : 0.0f; + } + else { + driver->curval = value; + } +} + +static void evaluate_driver_min_max(ChannelDriver *driver) +{ + DriverVar *dvar; + float value = 0.0f; + + /* loop through the variables, getting the values and comparing them to existing ones */ + for (dvar = driver->variables.first; dvar; dvar = dvar->next) { + /* get value */ + float tmp_val = driver_get_variable_value(driver, dvar); + + /* store this value if appropriate */ + if (dvar->prev) { + /* check if greater/smaller than the baseline */ + if (driver->type == DRIVER_TYPE_MAX) { + /* max? */ + if (tmp_val > value) { + value = tmp_val; + } + } + else { + /* min? */ + if (tmp_val < value) { + value = tmp_val; + } + } + } + else { + /* first item - make this the baseline for comparisons */ + value = tmp_val; + } + } + + /* store value in driver */ + driver->curval = value; +} + +static void evaluate_driver_python(PathResolvedRNA *anim_rna, + ChannelDriver *driver, + ChannelDriver *driver_orig, + const float evaltime) +{ + /* check for empty or invalid expression */ + if ((driver_orig->expression[0] == '\0') || (driver_orig->flag & DRIVER_FLAG_INVALID)) { + driver->curval = 0.0f; + } + else if (!driver_try_evaluate_simple_expr(driver, driver_orig, &driver->curval, evaltime)) { +#ifdef WITH_PYTHON + /* this evaluates the expression using Python, and returns its result: + * - on errors it reports, then returns 0.0f + */ + BLI_mutex_lock(&python_driver_lock); + + driver->curval = BPY_driver_exec(anim_rna, driver, driver_orig, evaltime); + + BLI_mutex_unlock(&python_driver_lock); +#else /* WITH_PYTHON*/ + UNUSED_VARS(anim_rna, evaltime); +#endif /* WITH_PYTHON*/ + } +} + +/* Evaluate an Channel-Driver to get a 'time' value to use instead of "evaltime" + * - "evaltime" is the frame at which F-Curve is being evaluated + * - has to return a float value + * - driver_orig is where we cache Python expressions, in case of COW + */ +float evaluate_driver(PathResolvedRNA *anim_rna, + ChannelDriver *driver, + ChannelDriver *driver_orig, + const float evaltime) +{ + /* check if driver can be evaluated */ + if (driver_orig->flag & DRIVER_FLAG_INVALID) { + return 0.0f; + } + + switch (driver->type) { + case DRIVER_TYPE_AVERAGE: /* average values of driver targets */ + case DRIVER_TYPE_SUM: /* sum values of driver targets */ + evaluate_driver_sum(driver); + break; + case DRIVER_TYPE_MIN: /* smallest value */ + case DRIVER_TYPE_MAX: /* largest value */ + evaluate_driver_min_max(driver); + break; + case DRIVER_TYPE_PYTHON: /* expression */ + evaluate_driver_python(anim_rna, driver, driver_orig, evaltime); + break; + default: + /* special 'hack' - just use stored value + * This is currently used as the mechanism which allows animated settings to be able + * to be changed via the UI. + */ + break; + } + + /* return value for driver */ + return driver->curval; +} diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index 7adac2d4a4d..6e4c343eac3 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -81,6 +81,8 @@ # include "RE_shader_ext.h" +# include "CLG_log.h" + # include "manta_fluid_API.h" #endif /* WITH_FLUID */ @@ -96,6 +98,8 @@ static void BKE_fluid_modifier_reset_ex(struct FluidModifierData *mmd, bool need #ifdef WITH_FLUID // #define DEBUG_PRINT +static CLG_LogRef LOG = {"bke.fluid"}; + /* -------------------------------------------------------------------- */ /** \name Fluid API * \{ */ @@ -346,7 +350,7 @@ void BKE_fluid_cache_free(FluidDomainSettings *mds, Object *ob, int cache_map) { char temp_dir[FILE_MAX]; int flags = mds->cache_flag; - const char *relbase = modifier_path_relbase_from_global(ob); + const char *relbase = BKE_modifier_path_relbase_from_global(ob); if (cache_map & FLUID_DOMAIN_OUTDATED_DATA) { flags &= ~(FLUID_DOMAIN_BAKING_DATA | FLUID_DOMAIN_BAKED_DATA | FLUID_DOMAIN_OUTDATED_DATA); @@ -487,32 +491,6 @@ static void manta_set_domain_from_mesh(FluidDomainSettings *mds, mds->cell_size[2] /= (float)mds->base_res[2]; } -static void manta_set_domain_gravity(Scene *scene, FluidDomainSettings *mds) -{ - const float normalization_factor = 1.0f / 9.81f; - - /* Use global gravity if enabled. */ - if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { - float gravity[3]; - copy_v3_v3(gravity, scene->physics_settings.gravity); - /* Map default value to 1.0. */ - mul_v3_fl(gravity, normalization_factor); - - /* Convert gravity to domain space. */ - float gravity_mag = len_v3(gravity); - mul_mat3_m4_v3(mds->imat, gravity); - normalize_v3(gravity); - mul_v3_fl(gravity, gravity_mag); - - copy_v3_v3(mds->gravity, gravity); - } - else { - mul_v3_fl(mds->gravity, normalization_factor); - } - - mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); -} - static bool BKE_fluid_modifier_init( FluidModifierData *mmd, Depsgraph *depsgraph, Object *ob, Scene *scene, Mesh *me) { @@ -523,8 +501,11 @@ static bool BKE_fluid_modifier_init( int res[3]; /* Set domain dimensions from mesh. */ manta_set_domain_from_mesh(mds, ob, me, true); - /* Set domain gravity. */ - manta_set_domain_gravity(scene, mds); + /* Set domain gravity, use global gravity if enabled. */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(mds->gravity, scene->physics_settings.gravity); + } + mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); /* Reset domain values. */ zero_v3_int(mds->shift); zero_v3(mds->shift_f); @@ -552,7 +533,6 @@ static bool BKE_fluid_modifier_init( /* Initially dt is equal to frame length (dt can change with adaptive-time stepping though). */ mds->dt = mds->frame_length; mds->time_per_frame = 0; - mds->time_total = abs(scene_framenr - mds->cache_frame_start) * mds->frame_length; mmd->time = scene_framenr; @@ -948,11 +928,7 @@ static void sample_effector(FluidEffectorSettings *mes, velocity_map[index * 3 + 2] += hit_vel[2]; # ifdef DEBUG_PRINT /* Debugging: Print object velocities. */ - printf("adding effector object vel: [%f, %f, %f], dx is: %f\n", - hit_vel[0], - hit_vel[1], - hit_vel[2], - mds->dx); + printf("adding effector object vel: [%f, %f, %f]\n", hit_vel[0], hit_vel[1], hit_vel[2]); # endif } } @@ -1165,8 +1141,8 @@ static void update_obstacleflags(FluidDomainSettings *mds, /* Monitor active fields based on flow settings */ for (coll_index = 0; coll_index < coll_ob_array_len; coll_index++) { Object *coll_ob = coll_ob_array[coll_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(coll_ob, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(coll_ob, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -1238,8 +1214,8 @@ static void compute_obstaclesemission(Scene *scene, /* Prepare effector maps. */ for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) { Object *effecobj = effecobjs[effec_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(effecobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(effecobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -1411,8 +1387,8 @@ static void update_obstacles(Depsgraph *depsgraph, /* Prepare grids from effector objects. */ for (int effec_index = 0; effec_index < numeffecobjs; effec_index++) { Object *effecobj = effecobjs[effec_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(effecobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(effecobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -1996,9 +1972,9 @@ static void sample_mesh(FluidFlowSettings *mfs, normalize_v3(hit_normal); /* Apply normal directional velocity. */ - velocity_map[index * 3] += hit_normal[0] * mfs->vel_normal * 0.25f; - velocity_map[index * 3 + 1] += hit_normal[1] * mfs->vel_normal * 0.25f; - velocity_map[index * 3 + 2] += hit_normal[2] * mfs->vel_normal * 0.25f; + velocity_map[index * 3] += hit_normal[0] * mfs->vel_normal; + velocity_map[index * 3 + 1] += hit_normal[1] * mfs->vel_normal; + velocity_map[index * 3 + 2] += hit_normal[2] * mfs->vel_normal; } /* Apply object velocity. */ if (has_velocity && mfs->vel_multi) { @@ -2651,8 +2627,8 @@ static void update_flowsflags(FluidDomainSettings *mds, Object **flowobjs, int n /* Monitor active fields based on flow settings */ for (flow_index = 0; flow_index < numflowobj; flow_index++) { Object *flow_ob = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flow_ob, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flow_ob, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -2782,8 +2758,8 @@ static void compute_flowsemission(Scene *scene, /* Prepare flow emission maps. */ for (int flow_index = 0; flow_index < numflowobjs; flow_index++) { Object *flowobj = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flowobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -3002,8 +2978,8 @@ static void update_flowsfluids(struct Depsgraph *depsgraph, /* Apply emission data for every flow object. */ for (int flow_index = 0; flow_index < numflowobjs; flow_index++) { Object *flowobj = flowobjs[flow_index]; - FluidModifierData *mmd2 = (FluidModifierData *)modifiers_findByType(flowobj, - eModifierType_Fluid); + FluidModifierData *mmd2 = (FluidModifierData *)BKE_modifiers_findby_type(flowobj, + eModifierType_Fluid); /* Sanity check. */ if (!mmd2) { @@ -3570,7 +3546,7 @@ static int manta_step( Depsgraph *depsgraph, Scene *scene, Object *ob, Mesh *me, FluidModifierData *mmd, int frame) { FluidDomainSettings *mds = mmd->domain; - float dt, frame_length, time_total; + float dt, frame_length, time_total, time_total_old; float time_per_frame; bool init_resolution = true; @@ -3594,6 +3570,8 @@ static int manta_step( dt = mds->dt; time_per_frame = 0; time_total = mds->time_total; + /* Keep track of original total time to correct small errors at end of step. */ + time_total_old = mds->time_total; BLI_mutex_lock(&object_update_lock); @@ -3639,6 +3617,8 @@ static int manta_step( mds->time_per_frame = time_per_frame; mds->time_total = time_total; } + /* Total time must not exceed framecount times framelength. Correct tiny errors here. */ + CLAMP(mds->time_total, mds->time_total, time_total_old + mds->frame_length); if (mds->type == FLUID_DOMAIN_TYPE_GAS && result) { manta_smoke_calc_transparency(mds, DEG_get_evaluated_view_layer(depsgraph)); @@ -3745,7 +3725,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, } /* Ensure cache directory is not relative. */ - const char *relbase = modifier_path_relbase_from_global(ob); + const char *relbase = BKE_modifier_path_relbase_from_global(ob); BLI_path_abs(mds->cache_directory, relbase); /* Ensure that all flags are up to date before doing any baking and/or cache reading. */ @@ -3775,6 +3755,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Fluid domain init must not fail in order to continue modifier evaluation. */ if (!mds->fluid && !BKE_fluid_modifier_init(mmd, depsgraph, ob, scene, me)) { + CLOG_ERROR(&LOG, "Fluid initialization failed. Should not happen!"); return; } BLI_assert(mds->fluid); @@ -3782,7 +3763,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Guiding parent res pointer needs initialization. */ guide_parent = mds->guide_parent; if (guide_parent) { - mmd_parent = (FluidModifierData *)modifiers_findByType(guide_parent, eModifierType_Fluid); + mmd_parent = (FluidModifierData *)BKE_modifiers_findby_type(guide_parent, eModifierType_Fluid); if (mmd_parent && mmd_parent->domain) { copy_v3_v3_int(mds->guide_res, mmd_parent->domain->res); } @@ -3793,8 +3774,12 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, mds->frame_length = DT_DEFAULT * (25.0f / fps) * mds->time_scale; mds->dt = mds->frame_length; mds->time_per_frame = 0; - /* Get distance between cache start and current frame for total time. */ - mds->time_total = abs(scene_framenr - mds->cache_frame_start) * mds->frame_length; + + /* Ensure that gravity is copied over every frame (could be keyframed). */ + if (scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY) { + copy_v3_v3(mds->gravity, scene->physics_settings.gravity); + mul_v3_fl(mds->gravity, mds->effector_weights->global_gravity); + } int next_frame = scene_framenr + 1; int prev_frame = scene_framenr - 1; @@ -3821,12 +3806,13 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, with_guide = mds->flags & FLUID_DOMAIN_USE_GUIDE; with_particles = drops || bubble || floater; - bool has_data, has_noise, has_mesh, has_particles, has_guide; + bool has_data, has_noise, has_mesh, has_particles, has_guide, has_config; has_data = manta_has_data(mds->fluid, mmd, scene_framenr); has_noise = manta_has_noise(mds->fluid, mmd, scene_framenr); has_mesh = manta_has_mesh(mds->fluid, mmd, scene_framenr); has_particles = manta_has_particles(mds->fluid, mmd, scene_framenr); has_guide = manta_has_guiding(mds->fluid, mmd, scene_framenr, guide_parent); + has_config = false; bool baking_data, baking_noise, baking_mesh, baking_particles, baking_guide; baking_data = mds->cache_flag & FLUID_DOMAIN_BAKING_DATA; @@ -3937,12 +3923,16 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Read mesh cache. */ if (with_liquid && with_mesh) { + has_config = manta_read_config(mds->fluid, mmd, mesh_frame); + /* Update mesh data from file is faster than via Python (manta_read_mesh()). */ has_mesh = manta_update_mesh_structures(mds->fluid, mmd, mesh_frame); } /* Read particles cache. */ if (with_liquid && with_particles) { + has_config = manta_read_config(mds->fluid, mmd, particles_frame); + if (!baking_data && !baking_particles && next_particles) { /* Update particle data from file is faster than via Python (manta_read_particles()). */ has_particles = manta_update_particle_structures(mds->fluid, mmd, particles_frame); @@ -3960,10 +3950,10 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, /* Read noise and data cache */ if (with_smoke && with_noise) { + has_config = manta_read_config(mds->fluid, mmd, noise_frame); /* Only reallocate when just reading cache or when resuming during bake. */ - if ((!baking_noise || (baking_noise && resume_noise)) && - manta_read_config(mds->fluid, mmd, noise_frame) && + if ((!baking_noise || (baking_noise && resume_noise)) && has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } @@ -3981,8 +3971,7 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, copy_v3_v3_int(o_min, mds->res_min); copy_v3_v3_int(o_max, mds->res_max); copy_v3_v3_int(o_shift, mds->shift); - if (manta_read_config(mds->fluid, mmd, data_frame) && - manta_needs_realloc(mds->fluid, mmd)) { + if (has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_copy_fluid( mds, o_res, mds->res, o_min, mds->res_min, o_max, o_shift, mds->shift); } @@ -3998,10 +3987,11 @@ static void BKE_fluid_modifier_processDomain(FluidModifierData *mmd, } /* Read data cache only */ else { + has_config = manta_read_config(mds->fluid, mmd, data_frame); + if (with_smoke) { /* Read config and realloc fluid object if needed. */ - if (manta_read_config(mds->fluid, mmd, data_frame) && - manta_needs_realloc(mds->fluid, mmd)) { + if (has_config && manta_needs_realloc(mds->fluid, mmd)) { BKE_fluid_reallocate_fluid(mds, mds->res, 1); } /* Read data cache */ @@ -4394,7 +4384,7 @@ static void manta_smoke_calc_transparency(FluidDomainSettings *mds, ViewLayer *v * returns fluid density or -1.0f if outside domain. */ float BKE_fluid_get_velocity_at(struct Object *ob, float position[3], float velocity[3]) { - FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); zero_v3(velocity); if (mmd && (mmd->type & MOD_FLUID_TYPE_DOMAIN) && mmd->domain && mmd->domain->fluid) { @@ -4501,11 +4491,11 @@ void BKE_fluid_particle_system_create(struct Main *bmain, BLI_addtail(&ob->particlesystem, psys); /* add modifier */ - pmmd = (ParticleSystemModifierData *)modifier_new(eModifierType_ParticleSystem); + pmmd = (ParticleSystemModifierData *)BKE_modifier_new(eModifierType_ParticleSystem); BLI_strncpy(pmmd->modifier.name, psys_name, sizeof(pmmd->modifier.name)); pmmd->psys = psys; BLI_addtail(&ob->modifiers, pmmd); - modifier_unique_name(&ob->modifiers, (ModifierData *)pmmd); + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)pmmd); } void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_type) @@ -4519,7 +4509,7 @@ void BKE_fluid_particle_system_destroy(struct Object *ob, const int particle_typ /* clear modifier */ pmmd = psys_get_modifier(ob, psys); BLI_remlink(&ob->modifiers, pmmd); - modifier_free((ModifierData *)pmmd); + BKE_modifier_free((ModifierData *)pmmd); /* clear particle system */ BLI_remlink(&ob->particlesystem, psys); @@ -4952,7 +4942,7 @@ void BKE_fluid_modifier_create_type_data(struct FluidModifierData *mmd) #endif char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); - modifier_path_init( + BKE_modifier_path_init( mmd->domain->cache_directory, sizeof(mmd->domain->cache_directory), cache_name); /* time options */ diff --git a/source/blender/blenkernel/intern/gpencil_curve.c b/source/blender/blenkernel/intern/gpencil_curve.c new file mode 100644 index 00000000000..8299943cc49 --- /dev/null +++ b/source/blender/blenkernel/intern/gpencil_curve.c @@ -0,0 +1,450 @@ +/* + * 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) 2008, Blender Foundation + * This is a new part of Blender + */ + +/** \file + * \ingroup bke + */ + +#include <math.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "CLG_log.h" + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_math_vector.h" + +#include "BLT_translation.h" + +#include "DNA_gpencil_types.h" + +#include "BKE_collection.h" +#include "BKE_curve.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_curve.h" +#include "BKE_gpencil_geom.h" +#include "BKE_main.h" +#include "BKE_material.h" +#include "BKE_object.h" + +#include "DEG_depsgraph_query.h" + +/* Helper: Check materials with same color. */ +static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat) +{ + Material *ma = NULL; + float color_cu[4]; + linearrgb_to_srgb_v3_v3(color_cu, color); + float hsv1[4]; + rgb_to_hsv_v(color_cu, hsv1); + hsv1[3] = color[3]; + + for (int i = 1; i <= ob_gp->totcol; i++) { + ma = BKE_object_material_get(ob_gp, i); + MaterialGPencilStyle *gp_style = ma->gp_style; + /* Check color with small tolerance (better in HSV). */ + float hsv2[4]; + rgb_to_hsv_v(gp_style->fill_rgba, hsv2); + hsv2[3] = gp_style->fill_rgba[3]; + if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) && + (compare_v4v4(hsv1, hsv2, 0.01f))) { + *r_mat = ma; + return i - 1; + } + } + + *r_mat = NULL; + return -1; +} + +/* Helper: Add gpencil material using curve material as base. */ +static Material *gpencil_add_from_curve_material(Main *bmain, + Object *ob_gp, + const float cu_color[4], + const bool gpencil_lines, + const bool fill, + int *r_idx) +{ + Material *mat_gp = BKE_gpencil_object_material_new( + bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx); + MaterialGPencilStyle *gp_style = mat_gp->gp_style; + + /* Stroke color. */ + if (gpencil_lines) { + ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); + gp_style->flag |= GP_MATERIAL_STROKE_SHOW; + } + else { + linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color); + gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; + } + + /* Fill color. */ + linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color); + /* Fill is false if the original curve hasn't material assigned, so enable it. */ + if (fill) { + gp_style->flag |= GP_MATERIAL_FILL_SHOW; + } + + /* Check at least one is enabled. */ + if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) && + ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) { + gp_style->flag |= GP_MATERIAL_STROKE_SHOW; + } + + return mat_gp; +} + +/* Helper: Create new stroke section. */ +static void gpencil_add_new_points(bGPDstroke *gps, + float *coord_array, + float pressure, + int init, + int totpoints, + const float init_co[3], + bool last) +{ + for (int i = 0; i < totpoints; i++) { + bGPDspoint *pt = &gps->points[i + init]; + copy_v3_v3(&pt->x, &coord_array[3 * i]); + /* Be sure the last point is not on top of the first point of the curve or + * the close of the stroke will produce glitches. */ + if ((last) && (i > 0) && (i == totpoints - 1)) { + float dist = len_v3v3(init_co, &pt->x); + if (dist < 0.1f) { + /* Interpolate between previous point and current to back slightly. */ + bGPDspoint *pt_prev = &gps->points[i + init - 1]; + interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); + } + } + + pt->pressure = pressure; + pt->strength = 1.0f; + } +} + +/* Helper: Get the first collection that includes the object. */ +static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) +{ + Collection *mycol = NULL; + FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { + LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { + if ((mycol == NULL) && (cob->ob == ob)) { + mycol = collection; + } + } + } + FOREACH_SCENE_COLLECTION_END; + + return mycol; +} + +/* Helper: Convert one spline to grease pencil stroke. */ +static void gpencil_convert_spline(Main *bmain, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool only_stroke, + bGPDframe *gpf, + Nurb *nu) +{ + Curve *cu = (Curve *)ob_cu->data; + bool cyclic = true; + + /* Create Stroke. */ + bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); + gps->thickness = 10.0f; + gps->fill_opacity_fac = 1.0f; + gps->hardeness = 1.0f; + gps->uv_scale = 1.0f; + + ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f); + ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); + gps->inittime = 0.0f; + + gps->flag &= ~GP_STROKE_SELECT; + gps->flag |= GP_STROKE_3DSPACE; + + gps->mat_nr = 0; + /* Count total points + * The total of points must consider that last point of each segment is equal to the first + * point of next segment. + */ + int totpoints = 0; + int segments = 0; + int resolu = nu->resolu + 1; + segments = nu->pntsu; + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { + segments--; + cyclic = false; + } + totpoints = (resolu * segments) - (segments - 1); + + /* Materials + * Notice: The color of the material is the color of viewport and not the final shader color. + */ + Material *mat_gp = NULL; + bool fill = true; + /* Check if grease pencil has a material with same color.*/ + float color[4]; + if ((cu->mat) && (*cu->mat)) { + Material *mat_cu = *cu->mat; + copy_v4_v4(color, &mat_cu->r); + } + else { + /* Gray (unassigned from SVG add-on) */ + zero_v4(color); + add_v3_fl(color, 0.6f); + color[3] = 1.0f; + fill = false; + } + + /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and + * there is only one color, the stroke must not be closed, fill to false and use for + * stroke the fill color. + */ + bool do_stroke = false; + if (ob_cu->totcol == 1) { + Material *ma_stroke = BKE_object_material_get(ob_cu, 1); + if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) { + do_stroke = true; + } + } + + int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp); + if ((ob_cu->totcol > 0) && (r_idx < 0)) { + Material *mat_curve = BKE_object_material_get(ob_cu, 1); + mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx); + + if ((mat_curve) && (mat_curve->gp_style != NULL)) { + MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style; + MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style; + + copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba); + gp_style_gp->fill_style = gp_style_cur->fill_style; + gp_style_gp->mix_factor = gp_style_cur->mix_factor; + } + + /* If object has more than 1 material, use second material for stroke color. */ + if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) { + mat_curve = BKE_object_material_get(ob_cu, 2); + if (mat_curve) { + linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); + mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; + } + } + else if ((only_stroke) || (do_stroke)) { + /* Also use the first color if the fill is none for stroke color. */ + if (ob_cu->totcol > 0) { + mat_curve = BKE_object_material_get(ob_cu, 1); + if (mat_curve) { + copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); + mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; + /* Set fill and stroke depending of curve type (3D or 2D). */ + if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) { + mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW; + mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW; + } + else { + mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; + mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW; + } + } + } + } + } + CLAMP_MIN(r_idx, 0); + + /* Assign material index to stroke. */ + gps->mat_nr = r_idx; + + /* Add stroke to frame.*/ + BLI_addtail(&gpf->strokes, gps); + + float *coord_array = NULL; + float init_co[3]; + + switch (nu->type) { + case CU_POLY: { + /* Allocate memory for storage points. */ + gps->totpoints = nu->pntsu; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + /* Increase thickness for this type. */ + gps->thickness = 10.0f; + + /* Get all curve points */ + for (int s = 0; s < gps->totpoints; s++) { + BPoint *bp = &nu->bp[s]; + bGPDspoint *pt = &gps->points[s]; + copy_v3_v3(&pt->x, bp->vec); + pt->pressure = bp->radius; + pt->strength = 1.0f; + } + break; + } + case CU_BEZIER: { + /* Allocate memory for storage points. */ + gps->totpoints = totpoints; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + + int init = 0; + resolu = nu->resolu + 1; + segments = nu->pntsu; + if ((nu->flagu & CU_NURB_CYCLIC) == 0) { + segments--; + } + /* Get all interpolated curve points of Beziert */ + for (int s = 0; s < segments; s++) { + int inext = (s + 1) % nu->pntsu; + BezTriple *prevbezt = &nu->bezt[s]; + BezTriple *bezt = &nu->bezt[inext]; + bool last = (bool)(s == segments - 1); + + coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__); + + for (int j = 0; j < 3; j++) { + BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], + prevbezt->vec[2][j], + bezt->vec[0][j], + bezt->vec[1][j], + coord_array + j, + resolu - 1, + 3 * sizeof(float)); + } + /* Save first point coordinates. */ + if (s == 0) { + copy_v3_v3(init_co, &coord_array[0]); + } + /* Add points to the stroke */ + gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last); + /* Free memory. */ + MEM_SAFE_FREE(coord_array); + + /* As the last point of segment is the first point of next segment, back one array + * element to avoid duplicated points on the same location. + */ + init += resolu - 1; + } + break; + } + case CU_NURBS: { + if (nu->pntsv == 1) { + + int nurb_points; + if (nu->flagu & CU_NURB_CYCLIC) { + resolu++; + nurb_points = nu->pntsu * resolu; + } + else { + nurb_points = (nu->pntsu - 1) * resolu; + } + /* Get all curve points. */ + coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__); + BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3])); + + /* Allocate memory for storage points. */ + gps->totpoints = nurb_points - 1; + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); + + /* Add points. */ + gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false); + + MEM_SAFE_FREE(coord_array); + } + break; + } + default: { + break; + } + } + /* Cyclic curve, close stroke. */ + if ((cyclic) && (!do_stroke)) { + BKE_gpencil_stroke_close(gps); + } + + /* Recalc fill geometry. */ + BKE_gpencil_stroke_geometry_update(gps); +} + +/* Convert a curve object to grease pencil stroke. + * + * \param bmain: Main thread pointer + * \param scene: Original scene. + * \param ob_gp: Grease pencil object to add strokes. + * \param ob_cu: Curve to convert. + * \param gpencil_lines: Use lines for strokes. + * \param use_collections: Create layers using collection names. + * \param only_stroke: The material must be only stroke without fill. + */ +void BKE_gpencil_convert_curve(Main *bmain, + Scene *scene, + Object *ob_gp, + Object *ob_cu, + const bool gpencil_lines, + const bool use_collections, + const bool only_stroke) +{ + if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { + return; + } + + Curve *cu = (Curve *)ob_cu->data; + bGPdata *gpd = (bGPdata *)ob_gp->data; + bGPDlayer *gpl = NULL; + + /* If the curve is empty, cancel. */ + if (cu->nurb.first == NULL) { + return; + } + + /* Check if there is an active layer. */ + if (use_collections) { + Collection *collection = gpencil_get_parent_collection(scene, ob_cu); + if (collection != NULL) { + gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true); + } + } + } + + if (gpl == NULL) { + gpl = BKE_gpencil_layer_active_get(gpd); + if (gpl == NULL) { + gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); + } + } + + /* Check if there is an active frame and add if needed. */ + bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); + + /* Read all splines of the curve and create a stroke for each. */ + LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { + gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu); + } + + /* Tag for recalculation */ + DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/gpencil_geom.c b/source/blender/blenkernel/intern/gpencil_geom.c index 413e28c431b..d200e4e3a15 100644 --- a/source/blender/blenkernel/intern/gpencil_geom.c +++ b/source/blender/blenkernel/intern/gpencil_geom.c @@ -35,18 +35,12 @@ #include "BLI_math_vector.h" #include "BLI_polyfill_2d.h" -#include "BLT_translation.h" - #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" -#include "BKE_collection.h" -#include "BKE_curve.h" #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" -#include "BKE_main.h" -#include "BKE_material.h" #include "BKE_object.h" #include "DEG_depsgraph_query.h" @@ -1586,404 +1580,6 @@ void BKE_gpencil_stroke_merge_distance(bGPDframe *gpf, BKE_gpencil_stroke_geometry_update(gps); } -/* Helper: Check materials with same color. */ -static int gpencil_check_same_material_color(Object *ob_gp, float color[4], Material **r_mat) -{ - Material *ma = NULL; - float color_cu[4]; - linearrgb_to_srgb_v3_v3(color_cu, color); - float hsv1[4]; - rgb_to_hsv_v(color_cu, hsv1); - hsv1[3] = color[3]; - - for (int i = 1; i <= ob_gp->totcol; i++) { - ma = BKE_object_material_get(ob_gp, i); - MaterialGPencilStyle *gp_style = ma->gp_style; - /* Check color with small tolerance (better in HSV). */ - float hsv2[4]; - rgb_to_hsv_v(gp_style->fill_rgba, hsv2); - hsv2[3] = gp_style->fill_rgba[3]; - if ((gp_style->fill_style == GP_MATERIAL_FILL_STYLE_SOLID) && - (compare_v4v4(hsv1, hsv2, 0.01f))) { - *r_mat = ma; - return i - 1; - } - } - - *r_mat = NULL; - return -1; -} - -/* Helper: Add gpencil material using curve material as base. */ -static Material *gpencil_add_from_curve_material(Main *bmain, - Object *ob_gp, - const float cu_color[4], - const bool gpencil_lines, - const bool fill, - int *r_idx) -{ - Material *mat_gp = BKE_gpencil_object_material_new( - bmain, ob_gp, (fill) ? "Material" : "Unassigned", r_idx); - MaterialGPencilStyle *gp_style = mat_gp->gp_style; - - /* Stroke color. */ - if (gpencil_lines) { - ARRAY_SET_ITEMS(gp_style->stroke_rgba, 0.0f, 0.0f, 0.0f, 1.0f); - gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - } - else { - linearrgb_to_srgb_v4(gp_style->stroke_rgba, cu_color); - gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - } - - /* Fill color. */ - linearrgb_to_srgb_v4(gp_style->fill_rgba, cu_color); - /* Fill is false if the original curve hasn't material assigned, so enable it. */ - if (fill) { - gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - - /* Check at least one is enabled. */ - if (((gp_style->flag & GP_MATERIAL_STROKE_SHOW) == 0) && - ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0)) { - gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - } - - return mat_gp; -} - -/* Helper: Create new stroke section. */ -static void gpencil_add_new_points(bGPDstroke *gps, - float *coord_array, - float pressure, - int init, - int totpoints, - const float init_co[3], - bool last) -{ - for (int i = 0; i < totpoints; i++) { - bGPDspoint *pt = &gps->points[i + init]; - copy_v3_v3(&pt->x, &coord_array[3 * i]); - /* Be sure the last point is not on top of the first point of the curve or - * the close of the stroke will produce glitches. */ - if ((last) && (i > 0) && (i == totpoints - 1)) { - float dist = len_v3v3(init_co, &pt->x); - if (dist < 0.1f) { - /* Interpolate between previous point and current to back slightly. */ - bGPDspoint *pt_prev = &gps->points[i + init - 1]; - interp_v3_v3v3(&pt->x, &pt_prev->x, &pt->x, 0.95f); - } - } - - pt->pressure = pressure; - pt->strength = 1.0f; - } -} - -/* Helper: Get the first collection that includes the object. */ -static Collection *gpencil_get_parent_collection(Scene *scene, Object *ob) -{ - Collection *mycol = NULL; - FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) { - LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) { - if ((mycol == NULL) && (cob->ob == ob)) { - mycol = collection; - } - } - } - FOREACH_SCENE_COLLECTION_END; - - return mycol; -} - -/* Helper: Convert one spline to grease pencil stroke. */ -static void gpencil_convert_spline(Main *bmain, - Object *ob_gp, - Object *ob_cu, - const bool gpencil_lines, - const bool only_stroke, - bGPDframe *gpf, - Nurb *nu) -{ - Curve *cu = (Curve *)ob_cu->data; - bool cyclic = true; - - /* Create Stroke. */ - bGPDstroke *gps = MEM_callocN(sizeof(bGPDstroke), "bGPDstroke"); - gps->thickness = 10.0f; - gps->fill_opacity_fac = 1.0f; - gps->hardeness = 1.0f; - gps->uv_scale = 1.0f; - - ARRAY_SET_ITEMS(gps->aspect_ratio, 1.0f, 1.0f); - ARRAY_SET_ITEMS(gps->caps, GP_STROKE_CAP_ROUND, GP_STROKE_CAP_ROUND); - gps->inittime = 0.0f; - - gps->flag &= ~GP_STROKE_SELECT; - gps->flag |= GP_STROKE_3DSPACE; - - gps->mat_nr = 0; - /* Count total points - * The total of points must consider that last point of each segment is equal to the first - * point of next segment. - */ - int totpoints = 0; - int segments = 0; - int resolu = nu->resolu + 1; - segments = nu->pntsu; - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - segments--; - cyclic = false; - } - totpoints = (resolu * segments) - (segments - 1); - - /* Materials - * Notice: The color of the material is the color of viewport and not the final shader color. - */ - Material *mat_gp = NULL; - bool fill = true; - /* Check if grease pencil has a material with same color.*/ - float color[4]; - if ((cu->mat) && (*cu->mat)) { - Material *mat_cu = *cu->mat; - copy_v4_v4(color, &mat_cu->r); - } - else { - /* Gray (unassigned from SVG add-on) */ - zero_v4(color); - add_v3_fl(color, 0.6f); - color[3] = 1.0f; - fill = false; - } - - /* Special case: If the color was created by the SVG add-on and the name contains '_stroke' and - * there is only one color, the stroke must not be closed, fill to false and use for - * stroke the fill color. - */ - bool do_stroke = false; - if (ob_cu->totcol == 1) { - Material *ma_stroke = BKE_object_material_get(ob_cu, 1); - if ((ma_stroke) && (strstr(ma_stroke->id.name, "_stroke") != NULL)) { - do_stroke = true; - } - } - - int r_idx = gpencil_check_same_material_color(ob_gp, color, &mat_gp); - if ((ob_cu->totcol > 0) && (r_idx < 0)) { - Material *mat_curve = BKE_object_material_get(ob_cu, 1); - mat_gp = gpencil_add_from_curve_material(bmain, ob_gp, color, gpencil_lines, fill, &r_idx); - - if ((mat_curve) && (mat_curve->gp_style != NULL)) { - MaterialGPencilStyle *gp_style_cur = mat_curve->gp_style; - MaterialGPencilStyle *gp_style_gp = mat_gp->gp_style; - - copy_v4_v4(gp_style_gp->mix_rgba, gp_style_cur->mix_rgba); - gp_style_gp->fill_style = gp_style_cur->fill_style; - gp_style_gp->mix_factor = gp_style_cur->mix_factor; - } - - /* If object has more than 1 material, use second material for stroke color. */ - if ((!only_stroke) && (ob_cu->totcol > 1) && (BKE_object_material_get(ob_cu, 2))) { - mat_curve = BKE_object_material_get(ob_cu, 2); - if (mat_curve) { - linearrgb_to_srgb_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); - mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; - } - } - else if ((only_stroke) || (do_stroke)) { - /* Also use the first color if the fill is none for stroke color. */ - if (ob_cu->totcol > 0) { - mat_curve = BKE_object_material_get(ob_cu, 1); - if (mat_curve) { - copy_v3_v3(mat_gp->gp_style->stroke_rgba, &mat_curve->r); - mat_gp->gp_style->stroke_rgba[3] = mat_curve->a; - /* Set fill and stroke depending of curve type (3D or 2D). */ - if ((cu->flag & CU_3D) || ((cu->flag & (CU_FRONT | CU_BACK)) == 0)) { - mat_gp->gp_style->flag |= GP_MATERIAL_STROKE_SHOW; - mat_gp->gp_style->flag &= ~GP_MATERIAL_FILL_SHOW; - } - else { - mat_gp->gp_style->flag &= ~GP_MATERIAL_STROKE_SHOW; - mat_gp->gp_style->flag |= GP_MATERIAL_FILL_SHOW; - } - } - } - } - } - CLAMP_MIN(r_idx, 0); - - /* Assign material index to stroke. */ - gps->mat_nr = r_idx; - - /* Add stroke to frame.*/ - BLI_addtail(&gpf->strokes, gps); - - float *coord_array = NULL; - float init_co[3]; - - switch (nu->type) { - case CU_POLY: { - /* Allocate memory for storage points. */ - gps->totpoints = nu->pntsu; - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - /* Increase thickness for this type. */ - gps->thickness = 10.0f; - - /* Get all curve points */ - for (int s = 0; s < gps->totpoints; s++) { - BPoint *bp = &nu->bp[s]; - bGPDspoint *pt = &gps->points[s]; - copy_v3_v3(&pt->x, bp->vec); - pt->pressure = bp->radius; - pt->strength = 1.0f; - } - break; - } - case CU_BEZIER: { - /* Allocate memory for storage points. */ - gps->totpoints = totpoints; - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - - int init = 0; - resolu = nu->resolu + 1; - segments = nu->pntsu; - if ((nu->flagu & CU_NURB_CYCLIC) == 0) { - segments--; - } - /* Get all interpolated curve points of Beziert */ - for (int s = 0; s < segments; s++) { - int inext = (s + 1) % nu->pntsu; - BezTriple *prevbezt = &nu->bezt[s]; - BezTriple *bezt = &nu->bezt[inext]; - bool last = (bool)(s == segments - 1); - - coord_array = MEM_callocN((size_t)3 * resolu * sizeof(float), __func__); - - for (int j = 0; j < 3; j++) { - BKE_curve_forward_diff_bezier(prevbezt->vec[1][j], - prevbezt->vec[2][j], - bezt->vec[0][j], - bezt->vec[1][j], - coord_array + j, - resolu - 1, - 3 * sizeof(float)); - } - /* Save first point coordinates. */ - if (s == 0) { - copy_v3_v3(init_co, &coord_array[0]); - } - /* Add points to the stroke */ - gpencil_add_new_points(gps, coord_array, bezt->radius, init, resolu, init_co, last); - /* Free memory. */ - MEM_SAFE_FREE(coord_array); - - /* As the last point of segment is the first point of next segment, back one array - * element to avoid duplicated points on the same location. - */ - init += resolu - 1; - } - break; - } - case CU_NURBS: { - if (nu->pntsv == 1) { - - int nurb_points; - if (nu->flagu & CU_NURB_CYCLIC) { - resolu++; - nurb_points = nu->pntsu * resolu; - } - else { - nurb_points = (nu->pntsu - 1) * resolu; - } - /* Get all curve points. */ - coord_array = MEM_callocN(sizeof(float[3]) * nurb_points, __func__); - BKE_nurb_makeCurve(nu, coord_array, NULL, NULL, NULL, resolu, sizeof(float[3])); - - /* Allocate memory for storage points. */ - gps->totpoints = nurb_points - 1; - gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); - - /* Add points. */ - gpencil_add_new_points(gps, coord_array, 1.0f, 0, gps->totpoints, init_co, false); - - MEM_SAFE_FREE(coord_array); - } - break; - } - default: { - break; - } - } - /* Cyclic curve, close stroke. */ - if ((cyclic) && (!do_stroke)) { - BKE_gpencil_stroke_close(gps); - } - - /* Recalc fill geometry. */ - BKE_gpencil_stroke_geometry_update(gps); -} - -/* Convert a curve object to grease pencil stroke. - * - * \param bmain: Main thread pointer - * \param scene: Original scene. - * \param ob_gp: Grease pencil object to add strokes. - * \param ob_cu: Curve to convert. - * \param gpencil_lines: Use lines for strokes. - * \param use_collections: Create layers using collection names. - * \param only_stroke: The material must be only stroke without fill. - */ -void BKE_gpencil_convert_curve(Main *bmain, - Scene *scene, - Object *ob_gp, - Object *ob_cu, - const bool gpencil_lines, - const bool use_collections, - const bool only_stroke) -{ - if (ELEM(NULL, ob_gp, ob_cu) || (ob_gp->type != OB_GPENCIL) || (ob_gp->data == NULL)) { - return; - } - - Curve *cu = (Curve *)ob_cu->data; - bGPdata *gpd = (bGPdata *)ob_gp->data; - bGPDlayer *gpl = NULL; - - /* If the curve is empty, cancel. */ - if (cu->nurb.first == NULL) { - return; - } - - /* Check if there is an active layer. */ - if (use_collections) { - Collection *collection = gpencil_get_parent_collection(scene, ob_cu); - if (collection != NULL) { - gpl = BKE_gpencil_layer_named_get(gpd, collection->id.name + 2); - if (gpl == NULL) { - gpl = BKE_gpencil_layer_addnew(gpd, collection->id.name + 2, true); - } - } - } - - if (gpl == NULL) { - gpl = BKE_gpencil_layer_active_get(gpd); - if (gpl == NULL) { - gpl = BKE_gpencil_layer_addnew(gpd, DATA_("GP_Layer"), true); - } - } - - /* Check if there is an active frame and add if needed. */ - bGPDframe *gpf = BKE_gpencil_layer_frame_get(gpl, CFRA, GP_GETFRAME_ADD_COPY); - - /* Read all splines of the curve and create a stroke for each. */ - LISTBASE_FOREACH (Nurb *, nu, &cu->nurb) { - gpencil_convert_spline(bmain, ob_gp, ob_cu, gpencil_lines, only_stroke, gpf, nu); - } - - /* Tag for recalculation */ - DEG_id_tag_update(&gpd->id, ID_RECALC_GEOMETRY | ID_RECALC_COPY_ON_WRITE); -} - /* Apply Transforms */ void BKE_gpencil_transform(bGPdata *gpd, float mat[4][4]) { diff --git a/source/blender/blenkernel/intern/gpencil_modifier.c b/source/blender/blenkernel/intern/gpencil_modifier.c index b732d9cdd4c..b889b91e366 100644 --- a/source/blender/blenkernel/intern/gpencil_modifier.c +++ b/source/blender/blenkernel/intern/gpencil_modifier.c @@ -318,7 +318,7 @@ bool BKE_gpencil_has_geometry_modifiers(Object *ob) { GpencilModifierData *md; for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti && mti->generateStrokes) { return true; @@ -332,7 +332,7 @@ bool BKE_gpencil_has_time_modifiers(Object *ob) { GpencilModifierData *md; for (md = ob->greasepencil_modifiers.first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti && mti->remapTime) { return true; @@ -369,7 +369,7 @@ static int gpencil_time_modifier( for (md = ob->greasepencil_modifiers.first; md; md = md->next) { if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { continue; @@ -421,7 +421,7 @@ void BKE_gpencil_modifier_init(void) GpencilModifierData *BKE_gpencil_modifier_new(int type) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type); GpencilModifierData *md = MEM_callocN(mti->struct_size, mti->struct_name); /* note, this name must be made unique later */ @@ -456,7 +456,7 @@ static void modifier_free_data_id_us_cb(void *UNUSED(userData), void BKE_gpencil_modifier_free_ex(GpencilModifierData *md, const int flag) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { if (mti->foreachIDLink) { @@ -487,7 +487,7 @@ void BKE_gpencil_modifier_free(GpencilModifierData *md) bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData *gmd) { if (modifiers && gmd) { - const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifierType_getInfo(gmd->type); + const GpencilModifierTypeInfo *gmti = BKE_gpencil_modifier_get_info(gmd->type); return BLI_uniquename(modifiers, gmd, DATA_(gmti->name), @@ -498,14 +498,14 @@ bool BKE_gpencil_modifier_unique_name(ListBase *modifiers, GpencilModifierData * return false; } -bool BKE_gpencil_modifier_dependsOnTime(GpencilModifierData *md) +bool BKE_gpencil_modifier_depends_ontime(GpencilModifierData *md) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); return mti->dependsOnTime && mti->dependsOnTime(md); } -const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierType type) +const GpencilModifierTypeInfo *BKE_gpencil_modifier_get_info(GpencilModifierType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_GREASEPENCIL_MODIFIER_TYPES && modifier_gpencil_types[type]->name[0] != '\0') { @@ -516,10 +516,10 @@ const GpencilModifierTypeInfo *BKE_gpencil_modifierType_getInfo(GpencilModifierT } } -void BKE_gpencil_modifier_copyData_generic(const GpencilModifierData *md_src, +void BKE_gpencil_modifier_copydata_generic(const GpencilModifierData *md_src, GpencilModifierData *md_dst) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md_src->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md_src->type); /* md_dst may have already be fully initialized with some extra allocated data, * we need to free it now to avoid memleak. */ @@ -545,11 +545,11 @@ static void gpencil_modifier_copy_data_id_us_cb(void *UNUSED(userData), } } -void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, +void BKE_gpencil_modifier_copydata_ex(GpencilModifierData *md, GpencilModifierData *target, const int flag) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); target->mode = md->mode; target->flag = md->flag; @@ -569,12 +569,12 @@ void BKE_gpencil_modifier_copyData_ex(GpencilModifierData *md, } } -void BKE_gpencil_modifier_copyData(GpencilModifierData *md, GpencilModifierData *target) +void BKE_gpencil_modifier_copydata(GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_ex(md, target, 0); + BKE_gpencil_modifier_copydata_ex(md, target, 0); } -GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifierType type) +GpencilModifierData *BKE_gpencil_modifiers_findby_type(Object *ob, GpencilModifierType type) { GpencilModifierData *md = ob->greasepencil_modifiers.first; @@ -587,12 +587,12 @@ GpencilModifierData *BKE_gpencil_modifiers_findByType(Object *ob, GpencilModifie return md; } -void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk, void *userData) +void BKE_gpencil_modifiers_foreach_ID_link(Object *ob, GreasePencilIDWalkFunc walk, void *userData) { GpencilModifierData *md = ob->greasepencil_modifiers.first; for (; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->foreachIDLink) { mti->foreachIDLink(md, ob, walk, userData); @@ -605,12 +605,14 @@ void BKE_gpencil_modifiers_foreachIDLink(Object *ob, GreasePencilIDWalkFunc walk } } -void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc walk, void *userData) +void BKE_gpencil_modifiers_foreach_tex_link(Object *ob, + GreasePencilTexWalkFunc walk, + void *userData) { GpencilModifierData *md = ob->greasepencil_modifiers.first; for (; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->foreachTexLink) { mti->foreachTexLink(md, ob, walk, userData); @@ -618,7 +620,7 @@ void BKE_gpencil_modifiers_foreachTexLink(Object *ob, GreasePencilTexWalkFunc wa } } -GpencilModifierData *BKE_gpencil_modifiers_findByName(Object *ob, const char *name) +GpencilModifierData *BKE_gpencil_modifiers_findby_name(Object *ob, const char *name) { return BLI_findstring(&(ob->greasepencil_modifiers), name, offsetof(GpencilModifierData, name)); } @@ -881,7 +883,7 @@ void BKE_gpencil_modifiers_calc(Depsgraph *depsgraph, Scene *scene, Object *ob) LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { if (GPENCIL_MODIFIER_ACTIVE(md, is_render)) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if ((GPENCIL_MODIFIER_EDIT(md, is_edit)) && (!is_render)) { continue; diff --git a/source/blender/blenkernel/intern/hair.c b/source/blender/blenkernel/intern/hair.c index 5cdb7761540..808c0347a37 100644 --- a/source/blender/blenkernel/intern/hair.c +++ b/source/blender/blenkernel/intern/hair.c @@ -247,12 +247,65 @@ Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference) return result; } -static Hair *hair_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph), - struct Scene *UNUSED(scene), - Object *UNUSED(object), +static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, Hair *hair_input) { - return hair_input; + Hair *hair = hair_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if ((mti->type == eModifierTypeType_OnlyDeform) && + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { + /* Ensure we are not modifying the input. */ + if (hair == hair_input) { + hair = BKE_hair_copy_for_eval(hair, true); + } + + /* Ensure we are not overwriting referenced data. */ + CustomData_duplicate_referenced_layer(&hair->pdata, CD_LOCATION, hair->totpoint); + BKE_hair_update_customdata_pointers(hair); + + /* Created deformed coordinates array on demand. */ + mti->deformVerts(md, &mectx, NULL, hair->co, hair->totpoint); + } + else if (mti->modifyHair) { + /* Ensure we are not modifying the input. */ + if (hair == hair_input) { + hair = BKE_hair_copy_for_eval(hair, true); + } + + Hair *hair_next = mti->modifyHair(md, &mectx, hair); + + if (hair_next && hair_next != hair) { + /* If the modifier returned a new hair, release the old one. */ + if (hair != hair_input) { + BKE_id_free(NULL, hair); + } + hair = hair_next; + } + } + } + + return hair; } void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c index 5a6e8f532c9..fcd3bc9c5b4 100644 --- a/source/blender/blenkernel/intern/idtype.c +++ b/source/blender/blenkernel/intern/idtype.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -92,6 +92,7 @@ static void id_type_init(void) INIT_TYPE(ID_HA); INIT_TYPE(ID_PT); INIT_TYPE(ID_VO); + INIT_TYPE(ID_SIM); /* Special naughty boy... */ BLI_assert(IDType_ID_LINK_PLACEHOLDER.main_listbase_index == INDEX_ID_NULL); @@ -251,6 +252,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode) CASE_IDFILTER(PT); CASE_IDFILTER(LP); CASE_IDFILTER(SCE); + CASE_IDFILTER(SIM); CASE_IDFILTER(SPK); CASE_IDFILTER(SO); CASE_IDFILTER(TE); @@ -302,6 +304,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter) CASE_IDFILTER(PT); CASE_IDFILTER(LP); CASE_IDFILTER(SCE); + CASE_IDFILTER(SIM); CASE_IDFILTER(SPK); CASE_IDFILTER(SO); CASE_IDFILTER(TE); @@ -356,6 +359,7 @@ int BKE_idtype_idcode_to_index(const short idcode) CASE_IDINDEX(LP); CASE_IDINDEX(SCE); CASE_IDINDEX(SCR); + CASE_IDINDEX(SIM); CASE_IDINDEX(SPK); CASE_IDINDEX(SO); CASE_IDINDEX(TE); @@ -417,6 +421,7 @@ short BKE_idtype_idcode_from_index(const int index) CASE_IDCODE(LP); CASE_IDCODE(SCE); CASE_IDCODE(SCR); + CASE_IDCODE(SIM); CASE_IDCODE(SPK); CASE_IDCODE(SO); CASE_IDCODE(TE); diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ee1bd5afa61..f5b28355d85 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -571,7 +571,7 @@ ImageTile *BKE_image_get_tile(Image *ima, int tile_number) return NULL; } -ImageTile *BKE_image_get_tile_from_iuser(Image *ima, ImageUser *iuser) +ImageTile *BKE_image_get_tile_from_iuser(Image *ima, const ImageUser *iuser) { return BKE_image_get_tile(ima, (iuser && iuser->tile) ? iuser->tile : 1001); } @@ -4796,7 +4796,7 @@ static ImBuf *image_get_cached_ibuf(Image *ima, ImageUser *iuser, int *r_entry, return ibuf; } -BLI_INLINE bool image_quick_test(Image *ima, ImageUser *iuser) +BLI_INLINE bool image_quick_test(Image *ima, const ImageUser *iuser) { if (ima == NULL) { return false; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index b0b88a13a75..12c1cf6bafa 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -60,6 +60,7 @@ #include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_ipo.h" diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index d371af93bb7..e7a2421a625 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -52,6 +52,7 @@ #include "BKE_key.h" #include "BKE_lattice.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -121,6 +122,12 @@ static void lattice_free_data(ID *id) } } +static void lattice_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Lattice *lattice = (Lattice *)id; + BKE_LIB_FOREACHID_PROCESS(data, lattice->key, IDWALK_CB_USER); +} + IDTypeInfo IDType_ID_LT = { .id_code = ID_LT, .id_filter = FILTER_ID_LT, @@ -135,6 +142,7 @@ IDTypeInfo IDType_ID_LT = { .copy_data = lattice_copy_data, .free_data = lattice_free_data, .make_local = NULL, + .foreach_id = lattice_foreach_id, }; int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w) @@ -1119,7 +1127,7 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec * otherwise we get already-modified coordinates. */ Object *ob_orig = DEG_get_original_object(ob); VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); float(*vert_coords)[3] = NULL; int numVerts, editmode = (lt->editlatt != NULL); const ModifierEvalContext mectx = {depsgraph, ob, 0}; @@ -1132,9 +1140,9 @@ void BKE_lattice_modifiers_calc(struct Depsgraph *depsgraph, Scene *scene, Objec } for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); - if (!(mti->flags & eModifierTypeFlag_AcceptsLattice)) { + if (!(mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { continue; } if (!(md->mode & eModifierMode_Realtime)) { diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index e976d59ce16..d8b63f0f527 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -36,38 +36,12 @@ #include "MEM_guardedalloc.h" /* all types are needed here, in order to do memory operations */ +#include "DNA_ID.h" #include "DNA_anim_types.h" -#include "DNA_armature_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" -#include "DNA_camera_types.h" -#include "DNA_collection_types.h" #include "DNA_gpencil_types.h" -#include "DNA_hair_types.h" -#include "DNA_ipo_types.h" #include "DNA_key_types.h" -#include "DNA_lattice_types.h" -#include "DNA_light_types.h" -#include "DNA_lightprobe_types.h" -#include "DNA_linestyle_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meta_types.h" -#include "DNA_movieclip_types.h" #include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_pointcloud_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_sound_types.h" -#include "DNA_speaker_types.h" -#include "DNA_text_types.h" -#include "DNA_vfont_types.h" -#include "DNA_volume_types.h" -#include "DNA_windowmanager_types.h" #include "DNA_workspace_types.h" -#include "DNA_world_types.h" #include "BLI_utildefines.h" @@ -80,50 +54,21 @@ #include "BLT_translation.h" -#include "BKE_action.h" #include "BKE_anim_data.h" #include "BKE_armature.h" #include "BKE_bpath.h" -#include "BKE_brush.h" -#include "BKE_cachefile.h" -#include "BKE_camera.h" -#include "BKE_collection.h" #include "BKE_context.h" -#include "BKE_curve.h" -#include "BKE_font.h" #include "BKE_global.h" #include "BKE_gpencil.h" -#include "BKE_hair.h" #include "BKE_idprop.h" #include "BKE_idtype.h" -#include "BKE_image.h" #include "BKE_key.h" -#include "BKE_lattice.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_lib_remap.h" -#include "BKE_light.h" -#include "BKE_lightprobe.h" -#include "BKE_linestyle.h" #include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_movieclip.h" #include "BKE_node.h" -#include "BKE_object.h" -#include "BKE_paint.h" -#include "BKE_particle.h" -#include "BKE_pointcloud.h" #include "BKE_rigidbody.h" -#include "BKE_scene.h" -#include "BKE_sound.h" -#include "BKE_speaker.h" -#include "BKE_text.h" -#include "BKE_texture.h" -#include "BKE_volume.h" -#include "BKE_world.h" #include "DEG_depsgraph.h" @@ -663,7 +608,7 @@ static void id_swap(Main *bmain, ID *id_a, ID *id_b, const bool do_full_id) * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note Most internal ID data itself is not swapped (only IDProperties are). * - * \param bmain May be NULL, in which case there will be no remapping of internal pointers to + * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to * itself. */ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b) @@ -675,7 +620,7 @@ void BKE_lib_id_swap(Main *bmain, ID *id_a, ID *id_b) * Does a mere memory swap over the whole IDs data (including type-specific memory). * \note All internal ID data itself is also swapped. * - * \param bmain May be NULL, in which case there will be no remapping of internal pointers to + * \param bmain: May be NULL, in which case there will be no remapping of internal pointers to * itself. */ void BKE_lib_id_swap_full(Main *bmain, ID *id_a, ID *id_b) @@ -1254,7 +1199,7 @@ ID *BKE_libblock_find_name(struct Main *bmain, const short type, const char *nam * * \note All other IDs beside given one are assumed already properly sorted in the list. * - * \param id_sorting_hint Ignored if NULL. Otherwise, used to check if we can insert \a id + * \param id_sorting_hint: Ignored if NULL. Otherwise, used to check if we can insert \a id * immediately before or after that pointer. It must always be into given \a lb list. */ void id_sort_by_name(ListBase *lb, ID *id, ID *id_sorting_hint) diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index 245e4f43452..fdee5500fbd 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -23,80 +23,20 @@ #include "MEM_guardedalloc.h" /* all types are needed here, in order to do memory operations */ -#include "DNA_armature_types.h" -#include "DNA_brush_types.h" -#include "DNA_cachefile_types.h" -#include "DNA_camera_types.h" -#include "DNA_collection_types.h" -#include "DNA_gpencil_types.h" -#include "DNA_ipo_types.h" -#include "DNA_key_types.h" -#include "DNA_lattice_types.h" -#include "DNA_light_types.h" -#include "DNA_lightprobe_types.h" -#include "DNA_linestyle_types.h" -#include "DNA_mask_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meta_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_node_types.h" -#include "DNA_object_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_sound_types.h" -#include "DNA_speaker_types.h" -#include "DNA_text_types.h" -#include "DNA_vfont_types.h" -#include "DNA_windowmanager_types.h" -#include "DNA_workspace_types.h" -#include "DNA_world_types.h" +#include "DNA_ID.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" -#include "BKE_action.h" #include "BKE_anim_data.h" -#include "BKE_armature.h" -#include "BKE_brush.h" -#include "BKE_cachefile.h" -#include "BKE_camera.h" -#include "BKE_collection.h" -#include "BKE_curve.h" -#include "BKE_font.h" -#include "BKE_gpencil.h" #include "BKE_idprop.h" #include "BKE_idtype.h" -#include "BKE_image.h" -#include "BKE_ipo.h" -#include "BKE_key.h" -#include "BKE_lattice.h" #include "BKE_lib_id.h" #include "BKE_lib_override.h" #include "BKE_lib_remap.h" #include "BKE_library.h" -#include "BKE_light.h" -#include "BKE_lightprobe.h" -#include "BKE_linestyle.h" #include "BKE_main.h" -#include "BKE_mask.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_mesh.h" -#include "BKE_movieclip.h" -#include "BKE_node.h" -#include "BKE_object.h" -#include "BKE_paint.h" -#include "BKE_particle.h" -#include "BKE_scene.h" -#include "BKE_screen.h" -#include "BKE_sound.h" -#include "BKE_speaker.h" -#include "BKE_text.h" -#include "BKE_texture.h" -#include "BKE_workspace.h" -#include "BKE_world.h" #include "lib_intern.h" diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c index 2ca03fd5d7e..8c29209f29d 100644 --- a/source/blender/blenkernel/intern/lib_query.c +++ b/source/blender/blenkernel/intern/lib_query.c @@ -49,6 +49,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" @@ -67,9 +68,10 @@ #include "BKE_anim_data.h" #include "BKE_collection.h" #include "BKE_constraint.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_lib_id.h" #include "BKE_lib_query.h" #include "BKE_main.h" @@ -164,6 +166,38 @@ typedef struct LibraryForeachIDData { BLI_LINKSTACK_DECLARE(ids_todo, ID *); } LibraryForeachIDData; +bool BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, int cb_flag) +{ + if (!(data->status & IDWALK_STOP)) { + const int flag = data->flag; + ID *old_id = *id_pp; + const int callback_return = data->callback(&(struct LibraryIDLinkCallbackData){ + .user_data = data->user_data, + .id_owner = data->owner_id, + .id_self = data->self_id, + .id_pointer = id_pp, + .cb_flag = ((cb_flag | data->cb_flag) & ~data->cb_flag_clear)}); + if (flag & IDWALK_READONLY) { + BLI_assert(*(id_pp) == old_id); + } + if (old_id && (flag & IDWALK_RECURSE)) { + if (BLI_gset_add((data)->ids_handled, old_id)) { + if (!(callback_return & IDWALK_RET_STOP_RECURSION)) { + BLI_LINKSTACK_PUSH(data->ids_todo, old_id); + } + } + } + if (callback_return & IDWALK_RET_STOP_ITER) { + data->status |= IDWALK_STOP; + return false; + } + return true; + } + else { + return false; + } +} + static void library_foreach_ID_link(Main *bmain, ID *id_owner, ID *id, @@ -172,14 +206,12 @@ static void library_foreach_ID_link(Main *bmain, int flag, LibraryForeachIDData *inherit_data); -static void library_foreach_idpropertiesForeachIDLink(IDProperty *id_prop, void *user_data) +void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void *user_data) { BLI_assert(id_prop->type == IDP_ID); LibraryForeachIDData *data = (LibraryForeachIDData *)user_data; - FOREACH_CALLBACK_INVOKE_ID(data, id_prop->data.pointer, IDWALK_CB_USER); - - FOREACH_FINALIZE_VOID; + BKE_LIB_FOREACHID_PROCESS_ID(data, id_prop->data.pointer, IDWALK_CB_USER); } static void library_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw), @@ -305,18 +337,6 @@ static void library_foreach_paint(LibraryForeachIDData *data, Paint *paint) FOREACH_FINALIZE_VOID; } -static void library_foreach_bone(LibraryForeachIDData *data, Bone *bone) -{ - IDP_foreach_property( - bone->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, data); - - LISTBASE_FOREACH (Bone *, curbone, &bone->childbase) { - library_foreach_bone(data, curbone); - } - - FOREACH_FINALIZE_VOID; -} - static void library_foreach_layer_collection(LibraryForeachIDData *data, ListBase *lb) { LISTBASE_FOREACH (LayerCollection *, lc, lb) { @@ -499,17 +519,21 @@ static void library_foreach_screen_area(LibraryForeachIDData *data, ScrArea *are FOREACH_FINALIZE_VOID; } -static void library_foreach_ID_as_subdata_link(ID **id_pp, - LibraryIDLinkCallback callback, - void *user_data, - int flag, - LibraryForeachIDData *data) +bool BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp) { /* Needed e.g. for callbacks handling relationships... This call shall be absolutely readonly. */ ID *id = *id_pp; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pp, IDWALK_CB_EMBEDDED); + const int flag = data->flag; + + if (!BKE_lib_query_foreachid_process(data, id_pp, IDWALK_CB_EMBEDDED)) { + return false; + } BLI_assert(id == *id_pp); + if (id == NULL) { + return true; + } + if (flag & IDWALK_IGNORE_EMBEDDED_ID) { /* Do Nothing. */ } @@ -523,10 +547,11 @@ static void library_foreach_ID_as_subdata_link(ID **id_pp, } } else { - library_foreach_ID_link(data->bmain, data->owner_id, id, callback, user_data, flag, data); + library_foreach_ID_link( + data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data); } - FOREACH_FINALIZE_VOID; + return true; } static void library_foreach_ID_link(Main *bmain, @@ -613,18 +638,33 @@ static void library_foreach_ID_link(Main *bmain, IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE); } - IDP_foreach_property( - id->properties, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); + IDP_foreach_property(id->properties, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + &data); AnimData *adt = BKE_animdata_from_id(id); if (adt) { library_foreach_animationData(&data, adt); } + const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id); + + /* Note: this is temp logic until all code has been ported to IDTypeInfo... */ + if (id_type->foreach_id != NULL) { + id_type->foreach_id(id, &data); + + if (data.status & IDWALK_STOP) { + break; + } + else { + continue; + } + } + switch ((ID_Type)GS(id->name)) { case ID_LI: { - Library *lib = (Library *)id; - CALLBACK_INVOKE(lib->parent, IDWALK_CB_NEVER_SELF); + BLI_assert(0); break; } case ID_SCE: { @@ -639,8 +679,7 @@ static void library_foreach_ID_link(Main *bmain, CALLBACK_INVOKE(scene->r.bake.cage_object, IDWALK_CB_NOP); if (scene->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&scene->nodetree, callback, user_data, flag, &data); + BKE_library_foreach_ID_embedded(&data, (ID **)&scene->nodetree); } if (scene->ed) { Sequence *seq; @@ -650,8 +689,10 @@ static void library_foreach_ID_link(Main *bmain, CALLBACK_INVOKE(seq->clip, IDWALK_CB_USER); CALLBACK_INVOKE(seq->mask, IDWALK_CB_USER); CALLBACK_INVOKE(seq->sound, IDWALK_CB_USER); - IDP_foreach_property( - seq->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); + IDP_foreach_property(seq->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + &data); LISTBASE_FOREACH (SequenceModifierData *, smd, &seq->modifiers) { CALLBACK_INVOKE(smd->mask_id, IDWALK_CB_USER); } @@ -805,8 +846,10 @@ static void library_foreach_ID_link(Main *bmain, if (object->pose) { data.cb_flag |= proxy_cb_flag; LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) { - IDP_foreach_property( - pchan->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); + IDP_foreach_property(pchan->prop, + IDP_TYPE_FILTER_ID, + BKE_lib_query_idpropertiesForeachIDLink_callback, + &data); CALLBACK_INVOKE(pchan->custom, IDWALK_CB_USER); BKE_constraints_id_loop( &pchan->constraints, library_foreach_constraintObjectLooper, &data); @@ -825,12 +868,12 @@ static void library_foreach_ID_link(Main *bmain, } } - modifiers_foreachIDLink(object, library_foreach_modifiersForeachIDLink, &data); - BKE_gpencil_modifiers_foreachIDLink( + BKE_modifiers_foreach_ID_link(object, library_foreach_modifiersForeachIDLink, &data); + BKE_gpencil_modifiers_foreach_ID_link( object, library_foreach_gpencil_modifiersForeachIDLink, &data); BKE_constraints_id_loop( &object->constraints, library_foreach_constraintObjectLooper, &data); - BKE_shaderfx_foreachIDLink(object, library_foreach_shaderfxForeachIDLink, &data); + BKE_shaderfx_foreach_ID_link(object, library_foreach_shaderfxForeachIDLink, &data); LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) { BKE_particlesystem_id_loop(psys, library_foreach_particlesystemsObjectLooper, &data); @@ -847,89 +890,42 @@ static void library_foreach_ID_link(Main *bmain, } case ID_AR: { - bArmature *arm = (bArmature *)id; - - LISTBASE_FOREACH (Bone *, bone, &arm->bonebase) { - library_foreach_bone(&data, bone); - } + BLI_assert(0); break; } case ID_ME: { - Mesh *mesh = (Mesh *)id; - CALLBACK_INVOKE(mesh->texcomesh, IDWALK_CB_NEVER_SELF); - CALLBACK_INVOKE(mesh->key, IDWALK_CB_USER); - for (i = 0; i < mesh->totcol; i++) { - CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER); - } + BLI_assert(0); break; } case ID_CU: { - Curve *curve = (Curve *)id; - CALLBACK_INVOKE(curve->bevobj, IDWALK_CB_NOP); - CALLBACK_INVOKE(curve->taperobj, IDWALK_CB_NOP); - CALLBACK_INVOKE(curve->textoncurve, IDWALK_CB_NOP); - CALLBACK_INVOKE(curve->key, IDWALK_CB_USER); - for (i = 0; i < curve->totcol; i++) { - CALLBACK_INVOKE(curve->mat[i], IDWALK_CB_USER); - } - CALLBACK_INVOKE(curve->vfont, IDWALK_CB_USER); - CALLBACK_INVOKE(curve->vfontb, IDWALK_CB_USER); - CALLBACK_INVOKE(curve->vfonti, IDWALK_CB_USER); - CALLBACK_INVOKE(curve->vfontbi, IDWALK_CB_USER); + BLI_assert(0); break; } case ID_MB: { - MetaBall *metaball = (MetaBall *)id; - for (i = 0; i < metaball->totcol; i++) { - CALLBACK_INVOKE(metaball->mat[i], IDWALK_CB_USER); - } + BLI_assert(0); break; } case ID_MA: { - Material *material = (Material *)id; - if (material->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&material->nodetree, callback, user_data, flag, &data); - } - if (material->texpaintslot != NULL) { - CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP); - } - if (material->gp_style != NULL) { - CALLBACK_INVOKE(material->gp_style->sima, IDWALK_CB_USER); - CALLBACK_INVOKE(material->gp_style->ima, IDWALK_CB_USER); - } + BLI_assert(0); break; } case ID_TE: { - Tex *texture = (Tex *)id; - if (texture->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&texture->nodetree, callback, user_data, flag, &data); - } - CALLBACK_INVOKE(texture->ima, IDWALK_CB_USER); + BLI_assert(0); break; } case ID_LT: { - Lattice *lattice = (Lattice *)id; - CALLBACK_INVOKE(lattice->key, IDWALK_CB_USER); + BLI_assert(0); break; } case ID_LA: { - Light *lamp = (Light *)id; - if (lamp->nodetree) { - /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&lamp->nodetree, callback, user_data, flag, &data); - } + BLI_assert(0); break; } @@ -958,8 +954,7 @@ static void library_foreach_ID_link(Main *bmain, World *world = (World *)id; if (world->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&world->nodetree, callback, user_data, flag, &data); + BKE_library_foreach_ID_embedded(&data, (ID **)&world->nodetree); } break; } @@ -984,33 +979,7 @@ static void library_foreach_ID_link(Main *bmain, } case ID_NT: { - bNodeTree *ntree = (bNodeTree *)id; - - CALLBACK_INVOKE(ntree->gpd, IDWALK_CB_USER); - - LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { - CALLBACK_INVOKE_ID(node->id, IDWALK_CB_USER); - - IDP_foreach_property( - node->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } - } - - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { - IDP_foreach_property( - sock->prop, IDP_TYPE_FILTER_ID, library_foreach_idpropertiesForeachIDLink, &data); - } + BLI_assert(0); break; } @@ -1119,8 +1088,7 @@ static void library_foreach_ID_link(Main *bmain, } if (linestyle->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ - library_foreach_ID_as_subdata_link( - (ID **)&linestyle->nodetree, callback, user_data, flag, &data); + BKE_library_foreach_ID_embedded(&data, (ID **)&linestyle->nodetree); } LISTBASE_FOREACH (LineStyleModifier *, lsm, &linestyle->color_modifiers) { @@ -1246,6 +1214,14 @@ static void library_foreach_ID_link(Main *bmain, } break; } + case ID_SIM: { + Simulation *simulation = (Simulation *)id; + if (simulation->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(&data, (ID **)&simulation->nodetree); + } + break; + } /* Nothing needed for those... */ case ID_IM: @@ -1300,14 +1276,11 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag) } /** - * Say whether given \a id_type_owner can use (in any way) a data-block of \a id_type_used. + * Say whether given \a id_owner may use (in any way) a data-block of \a id_type_used. * * This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above, - * quite useful to reduce* useless iterations in some cases. + * quite useful to reduce useless iterations in some cases. */ -/* XXX This has to be fully rethink, basing check on ID type is not really working anymore - * (and even worth once IDProps will support ID pointers), - * we'll have to do some quick checks on IDs themselves... */ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) { /* any type of ID can be used in custom props. */ @@ -1417,6 +1390,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) case ID_PAL: case ID_PC: case ID_CF: + case ID_SIM: /* Those types never use/reference other IDs... */ return false; case ID_IP: diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c index 72ae4629dba..ba986b1661b 100644 --- a/source/blender/blenkernel/intern/lib_remap.c +++ b/source/blender/blenkernel/intern/lib_remap.c @@ -334,7 +334,7 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *o default: break; } - test_object_modifiers(ob); + BKE_modifiers_test_object(ob); BKE_object_materials_test(bmain, ob, new_id); } } diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index e3ed21aa536..64ffea22363 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -38,6 +38,7 @@ #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_packedFile.h" @@ -53,6 +54,12 @@ static void library_free_data(ID *id) } } +static void library_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Library *lib = (Library *)id; + BKE_LIB_FOREACHID_PROCESS(data, lib->parent, IDWALK_CB_NEVER_SELF); +} + IDTypeInfo IDType_ID_LI = { .id_code = ID_LI, .id_filter = 0, @@ -67,6 +74,7 @@ IDTypeInfo IDType_ID_LI = { .copy_data = NULL, .free_data = library_free_data, .make_local = NULL, + .foreach_id = library_foreach_id, }; void BKE_library_filepath_set(Main *bmain, Library *lib, const char *filepath) diff --git a/source/blender/blenkernel/intern/light.c b/source/blender/blenkernel/intern/light.c index 3d0503b2e70..9dc338ce580 100644 --- a/source/blender/blenkernel/intern/light.c +++ b/source/blender/blenkernel/intern/light.c @@ -41,6 +41,7 @@ #include "BKE_icons.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_light.h" #include "BKE_main.h" #include "BKE_node.h" @@ -97,7 +98,7 @@ static void light_free_data(ID *id) /* is no lib link block, but light extension */ if (la->nodetree) { - ntreeFreeNestedTree(la->nodetree); + ntreeFreeEmbeddedTree(la->nodetree); MEM_freeN(la->nodetree); la->nodetree = NULL; } @@ -107,6 +108,15 @@ static void light_free_data(ID *id) la->id.icon_id = 0; } +static void light_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Light *lamp = (Light *)id; + if (lamp->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&lamp->nodetree); + } +} + IDTypeInfo IDType_ID_LA = { .id_code = ID_LA, .id_filter = FILTER_ID_LA, @@ -121,6 +131,7 @@ IDTypeInfo IDType_ID_LA = { .copy_data = light_copy_data, .free_data = light_free_data, .make_local = NULL, + .foreach_id = light_foreach_id, }; Light *BKE_light_add(Main *bmain, const char *name) diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 42506e0d7c8..0401ae48b5c 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -125,7 +125,7 @@ static void linestyle_free_data(ID *id) /* is no lib link block, but linestyle extension */ if (linestyle->nodetree) { - ntreeFreeNestedTree(linestyle->nodetree); + ntreeFreeEmbeddedTree(linestyle->nodetree); MEM_freeN(linestyle->nodetree); linestyle->nodetree = NULL; } diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c index caa29f7817a..ea3bee8b2f6 100644 --- a/source/blender/blenkernel/intern/main.c +++ b/source/blender/blenkernel/intern/main.c @@ -479,6 +479,8 @@ ListBase *which_libbase(Main *bmain, short type) return &(bmain->pointclouds); case ID_VO: return &(bmain->volumes); + case ID_SIM: + return &(bmain->simulations); } return NULL; } @@ -554,6 +556,7 @@ int set_listbasepointers(Main *bmain, ListBase **lb) lb[INDEX_ID_WS] = &(bmain->workspaces); /* before wm, so it's freed after it! */ lb[INDEX_ID_WM] = &(bmain->wm); lb[INDEX_ID_MSK] = &(bmain->masks); + lb[INDEX_ID_SIM] = &(bmain->simulations); lb[INDEX_ID_NULL] = NULL; diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 1b21ff9b36e..d4de04a9e98 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -64,6 +64,7 @@ #include "BKE_idtype.h" #include "BKE_image.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -130,7 +131,7 @@ static void material_free_data(ID *id) /* is no lib link block, but material extension */ if (material->nodetree) { - ntreeFreeNestedTree(material->nodetree); + ntreeFreeEmbeddedTree(material->nodetree); MEM_freeN(material->nodetree); material->nodetree = NULL; } @@ -143,6 +144,22 @@ static void material_free_data(ID *id) BKE_previewimg_free(&material->preview); } +static void material_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Material *material = (Material *)id; + /* Nodetrees **are owned by IDs**, treat them as mere sub-data and not real ID! */ + if (!BKE_library_foreach_ID_embedded(data, (ID **)&material->nodetree)) { + return; + } + if (material->texpaintslot != NULL) { + BKE_LIB_FOREACHID_PROCESS(data, material->texpaintslot->ima, IDWALK_CB_NOP); + } + if (material->gp_style != NULL) { + BKE_LIB_FOREACHID_PROCESS(data, material->gp_style->sima, IDWALK_CB_USER); + BKE_LIB_FOREACHID_PROCESS(data, material->gp_style->ima, IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_MA = { .id_code = ID_MA, .id_filter = FILTER_ID_MA, @@ -157,6 +174,7 @@ IDTypeInfo IDType_ID_MA = { .copy_data = material_copy_data, .free_data = material_free_data, .make_local = NULL, + .foreach_id = material_foreach_id, }; void BKE_gpencil_material_attr_init(Material *ma) @@ -1601,7 +1619,7 @@ void BKE_material_copybuf_paste(Main *bmain, Material *ma) GPU_material_free(&ma->gpumaterial); if (ma->nodetree) { - ntreeFreeNestedTree(ma->nodetree); + ntreeFreeEmbeddedTree(ma->nodetree); MEM_freeN(ma->nodetree); } diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 4294d279c36..94e5f435a43 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -54,6 +54,7 @@ #include "BKE_displist.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_material.h" #include "BKE_mball.h" #include "BKE_object.h" @@ -101,6 +102,14 @@ static void metaball_free_data(ID *id) } } +static void metaball_foreach_id(ID *id, LibraryForeachIDData *data) +{ + MetaBall *metaball = (MetaBall *)id; + for (int i = 0; i < metaball->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, metaball->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_MB = { .id_code = ID_MB, .id_filter = FILTER_ID_MB, @@ -115,6 +124,7 @@ IDTypeInfo IDType_ID_MB = { .copy_data = metaball_copy_data, .free_data = metaball_free_data, .make_local = NULL, + .foreach_id = metaball_foreach_id, }; /* Functions */ diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 2a86b899290..aeef287bb87 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -25,6 +25,7 @@ #include "DNA_defaults.h" #include "DNA_key_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -47,6 +48,7 @@ #include "BKE_idtype.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" #include "BKE_mesh.h" @@ -142,6 +144,16 @@ static void mesh_free_data(ID *id) MEM_SAFE_FREE(mesh->mat); } +static void mesh_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Mesh *mesh = (Mesh *)id; + BKE_LIB_FOREACHID_PROCESS(data, mesh->texcomesh, IDWALK_CB_NEVER_SELF); + BKE_LIB_FOREACHID_PROCESS(data, mesh->key, IDWALK_CB_USER); + for (int i = 0; i < mesh->totcol; i++) { + BKE_LIB_FOREACHID_PROCESS(data, mesh->mat[i], IDWALK_CB_USER); + } +} + IDTypeInfo IDType_ID_ME = { .id_code = ID_ME, .id_filter = FILTER_ID_ME, @@ -156,6 +168,7 @@ IDTypeInfo IDType_ID_ME = { .copy_data = mesh_copy_data, .free_data = mesh_free_data, .make_local = NULL, + .foreach_id = mesh_foreach_id, }; enum { @@ -1128,7 +1141,7 @@ void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me) BKE_object_materials_test(bmain, ob, (ID *)me); - test_object_modifiers(ob); + BKE_modifiers_test_object(ob); } void BKE_mesh_material_index_remove(Mesh *me, short index) diff --git a/source/blender/blenkernel/intern/mesh_convert.c b/source/blender/blenkernel/intern/mesh_convert.c index 28a32e1573b..655c70bcf61 100644 --- a/source/blender/blenkernel/intern/mesh_convert.c +++ b/source/blender/blenkernel/intern/mesh_convert.c @@ -1313,7 +1313,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, int build_shapekey_layers) { Mesh *me = ob_eval->runtime.data_orig ? ob_eval->runtime.data_orig : ob_eval->data; - const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type); Mesh *result; KeyBlock *kb; ModifierEvalContext mectx = {depsgraph, ob_eval, MOD_APPLY_TO_BASE_MESH}; @@ -1353,7 +1353,7 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, add_shapekey_layers(mesh_temp, me); } - result = mti->applyModifier(md_eval, &mectx, mesh_temp); + result = mti->modifyMesh(md_eval, &mectx, mesh_temp); ASSERT_IS_VALID_MESH(result); if (mesh_temp != result) { diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index e5be85b5ec7..f0d19f01aab 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1300,9 +1300,9 @@ static void loop_split_worker_do(LoopSplitTaskDataCommon *common_data, } } -static void loop_split_worker(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) +static void loop_split_worker(TaskPool *__restrict pool, void *taskdata) { - LoopSplitTaskDataCommon *common_data = BLI_task_pool_userdata(pool); + LoopSplitTaskDataCommon *common_data = BLI_task_pool_user_data(pool); LoopSplitTaskData *data = taskdata; /* Temp edge vectors stack, only used when computing lnor spacearr. */ @@ -1704,11 +1704,7 @@ void BKE_mesh_normals_loop_split(const MVert *mverts, loop_split_generator(NULL, &common_data); } else { - TaskScheduler *task_scheduler; - TaskPool *task_pool; - - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &common_data, TASK_PRIORITY_HIGH); + TaskPool *task_pool = BLI_task_pool_create(&common_data, TASK_PRIORITY_HIGH); loop_split_generator(task_pool, &common_data); diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c index a2a198cdb0d..d6f945cf34f 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.c +++ b/source/blender/blenkernel/intern/mesh_tangent.c @@ -452,9 +452,7 @@ finally: pRes[3] = fSign; } -static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void DM_calc_loop_tangents_thread(TaskPool *__restrict UNUSED(pool), void *taskdata) { struct SGLSLMeshToTangent *mesh2tangent = taskdata; /* new computation method */ @@ -658,9 +656,7 @@ void BKE_mesh_calc_loop_tangent_ex(const MVert *mvert, /* Calculation */ if (looptri_len != 0) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL, TASK_PRIORITY_LOW); + TaskPool *task_pool = BLI_task_pool_create(NULL, TASK_PRIORITY_LOW); tangent_mask_curr = 0; /* Calculate tangent layers */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 0a76b61cdb1..e872edf0784 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -59,7 +59,7 @@ #include "BKE_multires.h" #include "BKE_object.h" -/* may move these, only for modifier_path_relbase */ +/* may move these, only for BKE_modifier_path_relbase */ #include "BKE_main.h" /* end */ @@ -82,21 +82,21 @@ void BKE_modifier_init(void) modifier_type_init(modifier_types); /* MOD_utils.c */ /* Initialize global cmmon storage used for virtual modifier list */ - md = modifier_new(eModifierType_Armature); + md = BKE_modifier_new(eModifierType_Armature); virtualModifierCommonData.amd = *((ArmatureModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); - md = modifier_new(eModifierType_Curve); + md = BKE_modifier_new(eModifierType_Curve); virtualModifierCommonData.cmd = *((CurveModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); - md = modifier_new(eModifierType_Lattice); + md = BKE_modifier_new(eModifierType_Lattice); virtualModifierCommonData.lmd = *((LatticeModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); - md = modifier_new(eModifierType_ShapeKey); + md = BKE_modifier_new(eModifierType_ShapeKey); virtualModifierCommonData.smd = *((ShapeKeyModifierData *)md); - modifier_free(md); + BKE_modifier_free(md); virtualModifierCommonData.amd.modifier.mode |= eModifierMode_Virtual; virtualModifierCommonData.cmd.modifier.mode |= eModifierMode_Virtual; @@ -104,7 +104,7 @@ void BKE_modifier_init(void) virtualModifierCommonData.smd.modifier.mode |= eModifierMode_Virtual; } -const ModifierTypeInfo *modifierType_getInfo(ModifierType type) +const ModifierTypeInfo *BKE_modifier_get_info(ModifierType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_MODIFIER_TYPES && modifier_types[type] && modifier_types[type]->name[0] != '\0') { @@ -117,9 +117,9 @@ const ModifierTypeInfo *modifierType_getInfo(ModifierType type) /***/ -ModifierData *modifier_new(int type) +ModifierData *BKE_modifier_new(int type) { - const ModifierTypeInfo *mti = modifierType_getInfo(type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(type); ModifierData *md = MEM_callocN(mti->structSize, mti->structName); /* note, this name must be made unique later */ @@ -151,9 +151,9 @@ static void modifier_free_data_id_us_cb(void *UNUSED(userData), } } -void modifier_free_ex(ModifierData *md, const int flag) +void BKE_modifier_free_ex(ModifierData *md, const int flag) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { if (mti->foreachIDLink) { @@ -174,15 +174,15 @@ void modifier_free_ex(ModifierData *md, const int flag) MEM_freeN(md); } -void modifier_free(ModifierData *md) +void BKE_modifier_free(ModifierData *md) { - modifier_free_ex(md, 0); + BKE_modifier_free_ex(md, 0); } -bool modifier_unique_name(ListBase *modifiers, ModifierData *md) +bool BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md) { if (modifiers && md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return BLI_uniquename( modifiers, md, DATA_(mti->name), '.', offsetof(ModifierData, name), sizeof(md->name)); @@ -190,24 +190,24 @@ bool modifier_unique_name(ListBase *modifiers, ModifierData *md) return false; } -bool modifier_dependsOnTime(ModifierData *md) +bool BKE_modifier_depends_ontime(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return mti->dependsOnTime && mti->dependsOnTime(md); } -bool modifier_supportsMapping(ModifierData *md) +bool BKE_modifier_supports_mapping(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_OnlyDeform || (mti->flags & eModifierTypeFlag_SupportsMapping)); } -bool modifier_isPreview(ModifierData *md) +bool BKE_modifier_is_preview(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); /* Constructive modifiers are highly likely to also modify data like vgroups or vcol! */ if (!((mti->flags & eModifierTypeFlag_UsesPreview) || @@ -222,7 +222,7 @@ bool modifier_isPreview(ModifierData *md) return false; } -ModifierData *modifiers_findByType(Object *ob, ModifierType type) +ModifierData *BKE_modifiers_findby_type(Object *ob, ModifierType type) { ModifierData *md = ob->modifiers.first; @@ -235,12 +235,12 @@ ModifierData *modifiers_findByType(Object *ob, ModifierType type) return md; } -ModifierData *modifiers_findByName(Object *ob, const char *name) +ModifierData *BKE_modifiers_findny_name(Object *ob, const char *name) { return BLI_findstring(&(ob->modifiers), name, offsetof(ModifierData, name)); } -void modifiers_clearErrors(Object *ob) +void BKE_modifiers_clear_errors(Object *ob) { ModifierData *md = ob->modifiers.first; /* int qRedraw = 0; */ @@ -255,12 +255,12 @@ void modifiers_clearErrors(Object *ob) } } -void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, void *userData) +void BKE_modifiers_foreach_object_link(Object *ob, ObjectWalkFunc walk, void *userData) { ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->foreachObjectLink) { mti->foreachObjectLink(md, ob, walk, userData); @@ -268,12 +268,12 @@ void modifiers_foreachObjectLink(Object *ob, ObjectWalkFunc walk, void *userData } } -void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData) +void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *userData) { ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->foreachIDLink) { mti->foreachIDLink(md, ob, walk, userData); @@ -286,12 +286,12 @@ void modifiers_foreachIDLink(Object *ob, IDWalkFunc walk, void *userData) } } -void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData) +void BKE_modifiers_foreach_tex_link(Object *ob, TexWalkFunc walk, void *userData) { ModifierData *md = ob->modifiers.first; for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->foreachTexLink) { mti->foreachTexLink(md, ob, walk, userData); @@ -302,11 +302,11 @@ void modifiers_foreachTexLink(Object *ob, TexWalkFunc walk, void *userData) /* callback's can use this * to avoid copying every member. */ -void modifier_copyData_generic(const ModifierData *md_src, - ModifierData *md_dst, - const int UNUSED(flag)) +void BKE_modifier_copydata_generic(const ModifierData *md_src, + ModifierData *md_dst, + const int UNUSED(flag)) { - const ModifierTypeInfo *mti = modifierType_getInfo(md_src->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_src->type); /* md_dst may have already be fully initialized with some extra allocated data, * we need to free it now to avoid memleak. */ @@ -335,9 +335,9 @@ static void modifier_copy_data_id_us_cb(void *UNUSED(userData), } } -void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag) +void BKE_modifier_copydata_ex(ModifierData *md, ModifierData *target, const int flag) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); target->mode = md->mode; target->flag = md->flag; @@ -356,40 +356,41 @@ void modifier_copyData_ex(ModifierData *md, ModifierData *target, const int flag } } -void modifier_copyData(ModifierData *md, ModifierData *target) +void BKE_modifier_copydata(ModifierData *md, ModifierData *target) { - modifier_copyData_ex(md, target, 0); + BKE_modifier_copydata_ex(md, target, 0); } -bool modifier_supportsCage(struct Scene *scene, ModifierData *md) +bool BKE_modifier_supports_cage(struct Scene *scene, ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return ((!mti->isDisabled || !mti->isDisabled(scene, md, 0)) && - (mti->flags & eModifierTypeFlag_SupportsEditmode) && modifier_supportsMapping(md)); + (mti->flags & eModifierTypeFlag_SupportsEditmode) && BKE_modifier_supports_mapping(md)); } -bool modifier_couldBeCage(struct Scene *scene, ModifierData *md) +bool BKE_modifier_couldbe_cage(struct Scene *scene, ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return ((md->mode & eModifierMode_Realtime) && (md->mode & eModifierMode_Editmode) && - (!mti->isDisabled || !mti->isDisabled(scene, md, 0)) && modifier_supportsMapping(md)); + (!mti->isDisabled || !mti->isDisabled(scene, md, 0)) && + BKE_modifier_supports_mapping(md)); } -bool modifier_isSameTopology(ModifierData *md) +bool BKE_modifier_is_same_topology(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return ELEM(mti->type, eModifierTypeType_OnlyDeform, eModifierTypeType_NonGeometrical); } -bool modifier_isNonGeometrical(ModifierData *md) +bool BKE_modifier_is_non_geometrical(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return (mti->type == eModifierTypeType_NonGeometrical); } -void modifier_setError(ModifierData *md, const char *_format, ...) +void BKE_modifier_set_error(ModifierData *md, const char *_format, ...) { char buffer[512]; va_list ap; @@ -416,14 +417,15 @@ void modifier_setError(ModifierData *md, const char *_format, ...) * then is NULL) * also used for some mesh tools to give warnings */ -int modifiers_getCageIndex(struct Scene *scene, - Object *ob, - int *r_lastPossibleCageIndex, - bool is_virtual) +int BKE_modifiers_get_cage_index(struct Scene *scene, + Object *ob, + int *r_lastPossibleCageIndex, + bool is_virtual) { VirtualModifierData virtualModifierData; - ModifierData *md = (is_virtual) ? modifiers_getVirtualModifierList(ob, &virtualModifierData) : - ob->modifiers.first; + ModifierData *md = (is_virtual) ? + BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData) : + ob->modifiers.first; int i, cageIndex = -1; if (r_lastPossibleCageIndex) { @@ -433,7 +435,7 @@ int modifiers_getCageIndex(struct Scene *scene, /* Find the last modifier acting on the cage. */ for (i = 0; md; i++, md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); bool supports_mapping; if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { @@ -446,7 +448,7 @@ int modifiers_getCageIndex(struct Scene *scene, continue; } - supports_mapping = modifier_supportsMapping(md); + supports_mapping = BKE_modifier_supports_mapping(md); if (r_lastPossibleCageIndex && supports_mapping) { *r_lastPossibleCageIndex = i; } @@ -470,30 +472,30 @@ int modifiers_getCageIndex(struct Scene *scene, return cageIndex; } -bool modifiers_isSoftbodyEnabled(Object *ob) +bool BKE_modifiers_is_softbody_enabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Softbody); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -bool modifiers_isClothEnabled(Object *ob) +bool BKE_modifiers_is_cloth_enabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -bool modifiers_isModifierEnabled(Object *ob, int modifierType) +bool BKE_modifiers_is_modifier_enabled(Object *ob, int modifierType) { - ModifierData *md = modifiers_findByType(ob, modifierType); + ModifierData *md = BKE_modifiers_findby_type(ob, modifierType); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } -bool modifiers_isParticleEnabled(Object *ob) +bool BKE_modifiers_is_particle_enabled(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleSystem); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_ParticleSystem); return (md && md->mode & (eModifierMode_Realtime | eModifierMode_Render)); } @@ -504,9 +506,9 @@ bool modifiers_isParticleEnabled(Object *ob) * \param scene: Current scene, may be NULL, * in which case isDisabled callback of the modifier is never called. */ -bool modifier_isEnabled(const struct Scene *scene, ModifierData *md, int required_mode) +bool BKE_modifier_is_enabled(const struct Scene *scene, ModifierData *md, int required_mode) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if ((md->mode & required_mode) != required_mode) { return false; @@ -526,13 +528,13 @@ bool modifier_isEnabled(const struct Scene *scene, ModifierData *md, int require return true; } -CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, - Object *ob, - ModifierData *md, - CustomData_MeshMasks *final_datamask, - int required_mode, - ModifierData *previewmd, - const CustomData_MeshMasks *previewmask) +CDMaskLink *BKE_modifier_calc_data_masks(struct Scene *scene, + Object *ob, + ModifierData *md, + CustomData_MeshMasks *final_datamask, + int required_mode, + ModifierData *previewmd, + const CustomData_MeshMasks *previewmask) { CDMaskLink *dataMasks = NULL; CDMaskLink *curr, *prev; @@ -540,11 +542,11 @@ CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, /* build a list of modifier data requirements in reverse order */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); curr = MEM_callocN(sizeof(CDMaskLink), "CDMaskLink"); - if (modifier_isEnabled(scene, md, required_mode)) { + if (BKE_modifier_is_enabled(scene, md, required_mode)) { if (mti->type == eModifierTypeType_OnlyDeform) { have_deform_modifier = true; } @@ -594,7 +596,9 @@ CDMaskLink *modifiers_calcDataMasks(struct Scene *scene, return dataMasks; } -ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, int required_mode) +ModifierData *BKE_modifier_get_last_preview(struct Scene *scene, + ModifierData *md, + int required_mode) { ModifierData *tmp_md = NULL; @@ -604,7 +608,7 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in /* Find the latest modifier in stack generating preview. */ for (; md; md = md->next) { - if (modifier_isEnabled(scene, md, required_mode) && modifier_isPreview(md)) { + if (BKE_modifier_is_enabled(scene, md, required_mode) && BKE_modifier_is_preview(md)) { tmp_md = md; } } @@ -613,8 +617,8 @@ ModifierData *modifiers_getLastPreview(struct Scene *scene, ModifierData *md, in /* This is to include things that are not modifiers in the evaluation of the modifier stack, for * example parenting to an armature. */ -ModifierData *modifiers_getVirtualModifierList(const Object *ob, - VirtualModifierData *virtualModifierData) +ModifierData *BKE_modifiers_get_virtual_modifierlist(const Object *ob, + VirtualModifierData *virtualModifierData) { ModifierData *md; @@ -661,10 +665,10 @@ ModifierData *modifiers_getVirtualModifierList(const Object *ob, /* Takes an object and returns its first selected armature, else just its armature * This should work for multiple armatures per object */ -Object *modifiers_isDeformedByArmature(Object *ob) +Object *BKE_modifiers_is_deformed_by_armature(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); ArmatureModifierData *amd = NULL; /* return the first selected armature, this lets us use multiple armatures */ @@ -684,10 +688,10 @@ Object *modifiers_isDeformedByArmature(Object *ob) return NULL; } -Object *modifiers_isDeformedByMeshDeform(Object *ob) +Object *BKE_modifiers_is_deformed_by_meshdeform(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); MeshDeformModifierData *mdmd = NULL; /* return the first selected armature, this lets us use multiple armatures */ @@ -710,10 +714,10 @@ Object *modifiers_isDeformedByMeshDeform(Object *ob) /* Takes an object and returns its first selected lattice, else just its lattice * This should work for multiple lattices per object */ -Object *modifiers_isDeformedByLattice(Object *ob) +Object *BKE_modifiers_is_deformed_by_lattice(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); LatticeModifierData *lmd = NULL; /* return the first selected lattice, this lets us use multiple lattices */ @@ -736,10 +740,10 @@ Object *modifiers_isDeformedByLattice(Object *ob) /* Takes an object and returns its first selected curve, else just its curve * This should work for multiple curves per object */ -Object *modifiers_isDeformedByCurve(Object *ob) +Object *BKE_modifiers_is_deformed_by_curve(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); CurveModifierData *cmd = NULL; /* return the first selected curve, this lets us use multiple curves */ @@ -759,10 +763,10 @@ Object *modifiers_isDeformedByCurve(Object *ob) return NULL; } -bool modifiers_usesMultires(Object *ob) +bool BKE_modifiers_uses_multires(Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); MultiresModifierData *mmd = NULL; for (; md; md = md->next) { @@ -776,10 +780,10 @@ bool modifiers_usesMultires(Object *ob) return false; } -bool modifiers_usesArmature(Object *ob, bArmature *arm) +bool BKE_modifiers_uses_armature(Object *ob, bArmature *arm) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { @@ -793,13 +797,13 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm) return false; } -bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob) +bool BKE_modifiers_uses_subsurf_facedots(struct Scene *scene, Object *ob) { /* Search (backward) in the modifier stack to find if we have a subsurf modifier (enabled) before * the last modifier displayed on cage (or if the subsurf is the last). */ VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); - int cage_index = modifiers_getCageIndex(scene, ob, NULL, 1); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); + int cage_index = BKE_modifiers_get_cage_index(scene, ob, NULL, 1); if (cage_index == -1) { return false; } @@ -809,10 +813,10 @@ bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob) } /* Now from this point, search for subsurf modifier. */ for (; md; md = md->prev) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (md->type == eModifierType_Subsurf) { ModifierMode mode = eModifierMode_Realtime | eModifierMode_Editmode; - if (modifier_isEnabled(scene, md, mode)) { + if (BKE_modifier_is_enabled(scene, md, mode)) { return true; } } @@ -828,48 +832,33 @@ bool modifiers_usesSubsurfFacedots(struct Scene *scene, Object *ob) return false; } -bool modifier_isCorrectableDeformed(ModifierData *md) +bool BKE_modifier_is_correctable_deformed(ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); return mti->deformMatricesEM != NULL; } -bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob) +bool BKE_modifiers_is_correctable_deformed(struct Scene *scene, Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); int required_mode = eModifierMode_Realtime; if (ob->mode == OB_MODE_EDIT) { required_mode |= eModifierMode_Editmode; } for (; md; md = md->next) { - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { /* pass */ } - else if (modifier_isCorrectableDeformed(md)) { + else if (BKE_modifier_is_correctable_deformed(md)) { return true; } } return false; } -/* Check whether the given object has a modifier in its stack that uses WEIGHT_MCOL CD layer - * to preview something... Used by DynamicPaint and WeightVG currently. */ -bool modifiers_isPreview(Object *ob) -{ - ModifierData *md = ob->modifiers.first; - - for (; md; md = md->next) { - if (modifier_isPreview(md)) { - return true; - } - } - - return false; -} - -void modifier_freeTemporaryData(ModifierData *md) +void BKE_modifier_free_temporary_data(ModifierData *md) { if (md->type == eModifierType_Armature) { ArmatureModifierData *amd = (ArmatureModifierData *)md; @@ -882,7 +871,7 @@ void modifier_freeTemporaryData(ModifierData *md) } /* ensure modifier correctness when changing ob->data */ -void test_object_modifiers(Object *ob) +void BKE_modifiers_test_object(Object *ob) { ModifierData *md; @@ -913,7 +902,7 @@ void test_object_modifiers(Object *ob) * - else if the file has been saved return the blend file path. * - else if the file isn't saved and the ID isn't from a library, return the temp dir. */ -const char *modifier_path_relbase(Main *bmain, Object *ob) +const char *BKE_modifier_path_relbase(Main *bmain, Object *ob) { if (G.relbase_valid || ID_IS_LINKED(ob)) { return ID_BLEND_PATH(bmain, &ob->id); @@ -925,7 +914,7 @@ const char *modifier_path_relbase(Main *bmain, Object *ob) } } -const char *modifier_path_relbase_from_global(Object *ob) +const char *BKE_modifier_path_relbase_from_global(Object *ob) { if (G.relbase_valid || ID_IS_LINKED(ob)) { return ID_BLEND_PATH_FROM_GLOBAL(&ob->id); @@ -938,35 +927,35 @@ const char *modifier_path_relbase_from_global(Object *ob) } /* initializes the path with either */ -void modifier_path_init(char *path, int path_maxlen, const char *name) +void BKE_modifier_path_init(char *path, int path_maxlen, const char *name) { /* elubie: changed this to default to the same dir as the render output * to prevent saving to C:\ on Windows */ BLI_join_dirfile(path, path_maxlen, G.relbase_valid ? "//" : BKE_tempdir_session(), name); } -/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ +/* wrapper around ModifierTypeInfo.modifyMesh that ensures valid normals */ -struct Mesh *modwrap_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - struct Mesh *me) +struct Mesh *BKE_modifier_modify_mesh(ModifierData *md, + const ModifierEvalContext *ctx, + struct Mesh *me) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { BKE_mesh_calc_normals(me); } - return mti->applyModifier(md, ctx, me); + return mti->modifyMesh(md, ctx, me); } -void modwrap_deformVerts(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *me, - float (*vertexCos)[3], - int numVerts) +void BKE_modifier_deform_verts(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *me, + float (*vertexCos)[3], + int numVerts) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -975,14 +964,14 @@ void modwrap_deformVerts(ModifierData *md, mti->deformVerts(md, ctx, me, vertexCos, numVerts); } -void modwrap_deformVertsEM(ModifierData *md, - const ModifierEvalContext *ctx, - struct BMEditMesh *em, - Mesh *me, - float (*vertexCos)[3], - int numVerts) +void BKE_modifier_deform_vertsEM(ModifierData *md, + const ModifierEvalContext *ctx, + struct BMEditMesh *em, + Mesh *me, + float (*vertexCos)[3], + int numVerts) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); BLI_assert(!me || CustomData_has_layer(&me->pdata, CD_NORMAL) == false); if (me && mti->dependsOnNormals && mti->dependsOnNormals(md)) { @@ -1025,7 +1014,7 @@ Mesh *BKE_modifier_get_evaluated_mesh_from_evaluated_object(Object *ob_eval, return me; } -ModifierData *modifier_get_original(ModifierData *md) +ModifierData *BKE_modifier_get_original(ModifierData *md) { if (md->orig_modifier_data == NULL) { return md; @@ -1033,11 +1022,13 @@ ModifierData *modifier_get_original(ModifierData *md) return md->orig_modifier_data; } -struct ModifierData *modifier_get_evaluated(Depsgraph *depsgraph, Object *object, ModifierData *md) +struct ModifierData *BKE_modifier_get_evaluated(Depsgraph *depsgraph, + Object *object, + ModifierData *md) { Object *object_eval = DEG_get_evaluated_object(depsgraph, object); if (object_eval == object) { return md; } - return modifiers_findByName(object_eval, md->name); + return BKE_modifiers_findny_name(object_eval, md->name); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 193fe859def..4c7b791f103 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -460,6 +460,7 @@ typedef struct MovieClipCache { float principal[2]; float polynomial_k[3]; float division_k[2]; + float nuke_k[2]; short distortion_model; bool undistortion_used; @@ -908,6 +909,9 @@ static bool check_undistortion_cache_flags(const MovieClip *clip) if (!equals_v2v2(&camera->division_k1, cache->postprocessed.division_k)) { return false; } + if (!equals_v2v2(&camera->nuke_k1, cache->postprocessed.nuke_k)) { + return false; + } return true; } @@ -1010,6 +1014,7 @@ static void put_postprocessed_frame_to_cache( copy_v2_v2(cache->postprocessed.principal, camera->principal); copy_v3_v3(cache->postprocessed.polynomial_k, &camera->k1); copy_v2_v2(cache->postprocessed.division_k, &camera->division_k1); + copy_v2_v2(cache->postprocessed.nuke_k, &camera->nuke_k1); cache->postprocessed.undistortion_used = true; } else { @@ -1512,7 +1517,8 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip undist_marker.pos[0] *= width; undist_marker.pos[1] *= height * aspy; - BKE_tracking_undistort_v2(&clip->tracking, undist_marker.pos, undist_marker.pos); + BKE_tracking_undistort_v2( + &clip->tracking, width, height, undist_marker.pos, undist_marker.pos); undist_marker.pos[0] /= width; undist_marker.pos[1] /= height * aspy; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 69cd338e15f..7e78be6d66e 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2007 by Nicholas Bishop @@ -289,8 +289,8 @@ Mesh *BKE_multires_create_mesh(struct Depsgraph *depsgraph, .flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY, }; - const ModifierTypeInfo *mti = modifierType_getInfo(mmd->modifier.type); - Mesh *result = mti->applyModifier(&mmd->modifier, &modifier_ctx, deformed_mesh); + const ModifierTypeInfo *mti = BKE_modifier_get_info(mmd->modifier.type); + Mesh *result = mti->modifyMesh(&mmd->modifier, &modifier_ctx, deformed_mesh); if (result == deformed_mesh) { result = BKE_mesh_copy_for_eval(deformed_mesh, true); @@ -318,8 +318,8 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; VirtualModifierData virtual_modifier_data; - ModifierData *first_md = modifiers_getVirtualModifierList(&object_for_eval, - &virtual_modifier_data); + ModifierData *first_md = BKE_modifiers_get_virtual_modifierlist(&object_for_eval, + &virtual_modifier_data); Mesh *base_mesh = object->data; @@ -327,13 +327,13 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep float(*deformed_verts)[3] = BKE_mesh_vert_coords_alloc(base_mesh, &num_deformed_verts); for (ModifierData *md = first_md; md != NULL; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (md == &mmd->modifier) { break; } - if (!modifier_isEnabled(scene_eval, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene_eval, md, required_mode)) { continue; } @@ -341,7 +341,8 @@ float (*BKE_multires_create_deformed_base_mesh_vert_coords(struct Depsgraph *dep break; } - modwrap_deformVerts(md, &mesh_eval_context, base_mesh, deformed_verts, num_deformed_verts); + BKE_modifier_deform_verts( + md, &mesh_eval_context, base_mesh, deformed_verts, num_deformed_verts); } if (r_num_deformed_verts != NULL) { @@ -356,7 +357,7 @@ MultiresModifierData *find_multires_modifier_before(Scene *scene, ModifierData * for (md = lastmd; md; md = md->prev) { if (md->type == eModifierType_Multires) { - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { return (MultiresModifierData *)md; } } @@ -380,7 +381,7 @@ MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, bool use_f firstmmd = (MultiresModifierData *)md; } - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { mmd = (MultiresModifierData *)md; break; } @@ -407,7 +408,7 @@ int multires_get_level(const Scene *scene, mmd->renderlvl; } else if (ob->mode == OB_MODE_SCULPT) { - return BKE_multires_sculpt_level_get(mmd); + return mmd->sculptlvl; } else if (ignore_simplify) { return mmd->lvl; @@ -2193,10 +2194,10 @@ void multires_load_old(Object *ob, Mesh *me) /* Add a multires modifier to the object */ md = ob->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } - mmd = (MultiresModifierData *)modifier_new(eModifierType_Multires); + mmd = (MultiresModifierData *)BKE_modifier_new(eModifierType_Multires); BLI_insertlinkbefore(&ob->modifiers, md, mmd); for (i = 0; i < me->mr->level_count - 1; i++) { @@ -2234,7 +2235,14 @@ void multiresModifier_sync_levels_ex(Object *ob_dst, } if (mmd_src->totlvl > mmd_dst->totlvl) { - multiresModifier_subdivide_to_level(ob_dst, mmd_dst, mmd_src->totlvl); + if (mmd_dst->simple) { + multiresModifier_subdivide_to_level( + ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_SIMPLE); + } + else { + multiresModifier_subdivide_to_level( + ob_dst, mmd_dst, mmd_src->totlvl, MULTIRES_SUBDIVIDE_CATMULL_CLARK); + } } else { multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl); @@ -2516,12 +2524,3 @@ int mdisp_rot_face_to_crn(struct MVert *UNUSED(mvert), return S; } - -/* This is a workaround for T58473. - * Force sculpting on the highest level for until the root of the issue is solved. - * - * When that issue is solved simple replace call of this function with mmd->sculptlvl. */ -int BKE_multires_sculpt_level_get(const struct MultiresModifierData *mmd) -{ - return mmd->totlvl; -} diff --git a/source/blender/blenkernel/intern/multires_reshape.c b/source/blender/blenkernel/intern/multires_reshape.c index 02cd5f094a6..e59b19638f8 100644 --- a/source/blender/blenkernel/intern/multires_reshape.c +++ b/source/blender/blenkernel/intern/multires_reshape.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -28,8 +28,6 @@ #include "DNA_modifier_types.h" #include "DNA_scene_types.h" -#include "BLI_math_vector.h" - #include "BKE_customdata.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" @@ -37,14 +35,16 @@ #include "BKE_modifier.h" #include "BKE_multires.h" #include "BKE_subdiv.h" +#include "BKE_subsurf.h" +#include "BLI_math_vector.h" #include "DEG_depsgraph_query.h" #include "multires_reshape.h" -/* ================================================================================================ - * Reshape from object. - */ +/* -------------------------------------------------------------------- */ +/** \name Reshape from object + * \{ */ bool multiresModifier_reshapeFromVertcos(struct Depsgraph *depsgraph, struct Object *object, @@ -93,9 +93,11 @@ bool multiresModifier_reshapeFromObject(struct Depsgraph *depsgraph, return result; } -/* ================================================================================================ - * Reshape from modifier. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reshape from modifier + * \{ */ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, struct Object *object, @@ -119,7 +121,7 @@ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, .object = object, .flag = MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY, }; - modwrap_deformVerts( + BKE_modifier_deform_verts( deform_md, &modifier_ctx, multires_mesh, deformed_verts, multires_mesh->totvert); BKE_id_free(NULL, multires_mesh); @@ -133,9 +135,11 @@ bool multiresModifier_reshapeFromDeformModifier(struct Depsgraph *depsgraph, return result; } -/* ================================================================================================ - * Reshape from grids. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Reshape from grids + * \{ */ bool multiresModifier_reshapeFromCCG(const int tot_level, Mesh *coarse_mesh, @@ -161,19 +165,24 @@ bool multiresModifier_reshapeFromCCG(const int tot_level, return true; } -/* ================================================================================================ - * Subdivision. - */ +/** \} */ -void multiresModifier_subdivide(Object *object, MultiresModifierData *mmd) +/* -------------------------------------------------------------------- */ +/** \name Subdivision + * \{ */ + +void multiresModifier_subdivide(Object *object, + MultiresModifierData *mmd, + const eMultiresSubdivideModeType mode) { const int top_level = mmd->totlvl + 1; - multiresModifier_subdivide_to_level(object, mmd, top_level); + multiresModifier_subdivide_to_level(object, mmd, top_level, mode); } void multiresModifier_subdivide_to_level(struct Object *object, struct MultiresModifierData *mmd, - const int top_level) + const int top_level, + const eMultiresSubdivideModeType mode) { if (top_level <= mmd->totlvl) { return; @@ -190,7 +199,12 @@ void multiresModifier_subdivide_to_level(struct Object *object, } if (!has_mdisps || top_level == 1) { multires_reshape_ensure_grids(coarse_mesh, top_level); - multires_set_tot_level(object, mmd, top_level); + if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) { + multires_subdivide_create_tangent_displacement_linear_grids(object, mmd); + } + else { + multires_set_tot_level(object, mmd, top_level); + } return; } @@ -199,25 +213,34 @@ void multiresModifier_subdivide_to_level(struct Object *object, if (!multires_reshape_context_create_from_subdivide(&reshape_context, object, mmd, top_level)) { return; } + multires_reshape_store_original_grids(&reshape_context); multires_reshape_ensure_grids(coarse_mesh, reshape_context.top.level); - multires_reshape_assign_final_coords_from_orig_mdisps(&reshape_context); + multires_reshape_assign_final_elements_from_orig_mdisps(&reshape_context); /* Free original grids which makes it so smoothing with details thinks all the details were * added against base mesh's limit surface. This is similar behavior to as if we've done all - * displacement in sculpt mode at the old top level and then propagated to the new top level. */ + * displacement in sculpt mode at the old top level and then propagated to the new top level.*/ multires_reshape_free_original_grids(&reshape_context); - multires_reshape_smooth_object_grids_with_details(&reshape_context); + if (ELEM(mode, MULTIRES_SUBDIVIDE_LINEAR, MULTIRES_SUBDIVIDE_SIMPLE)) { + multires_reshape_smooth_object_grids(&reshape_context, mode); + } + else { + multires_reshape_smooth_object_grids_with_details(&reshape_context); + } + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); multires_reshape_context_free(&reshape_context); multires_set_tot_level(object, mmd, top_level); } -/* ================================================================================================ - * Apply base. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Apply base + * \{ */ void multiresModifier_base_apply(struct Depsgraph *depsgraph, Object *object, @@ -263,3 +286,5 @@ void multiresModifier_base_apply(struct Depsgraph *depsgraph, multires_reshape_context_free(&reshape_context); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape.h b/source/blender/blenkernel/intern/multires_reshape.h index adfa2659661..12816a455ee 100644 --- a/source/blender/blenkernel/intern/multires_reshape.h +++ b/source/blender/blenkernel/intern/multires_reshape.h @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -26,6 +26,8 @@ #include "BLI_sys_types.h" +#include "BKE_multires.h" + struct Depsgraph; struct GridPaintMask; struct MDisps; @@ -138,7 +140,7 @@ typedef struct ReshapeConstGridElement { float mask; } ReshapeConstGridElement; -/* ================================================================================================ +/* -------------------------------------------------------------------- * Construct/destruct reshape context. */ @@ -156,6 +158,11 @@ bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape struct Object *object, struct MultiresModifierData *mmd); +bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context, + struct Depsgraph *depsgraph, + struct Object *object, + struct MultiresModifierData *mmd); + bool multires_reshape_context_create_from_ccg(MultiresReshapeContext *reshape_context, struct SubdivCCG *subdiv_ccg, struct Mesh *base_mesh, @@ -169,7 +176,7 @@ bool multires_reshape_context_create_from_subdivide(MultiresReshapeContext *resh void multires_reshape_free_original_grids(MultiresReshapeContext *reshape_context); void multires_reshape_context_free(MultiresReshapeContext *reshape_context); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Helper accessors. */ @@ -214,7 +221,7 @@ ReshapeGridElement multires_reshape_grid_element_for_ptex_coord( ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord( const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Sample limit surface of the base mesh. */ @@ -225,14 +232,14 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha float r_P[3], float r_tangent_matrix[3][3]); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Custom data preparation. */ /* Make sure custom data is allocated for the given level. */ void multires_reshape_ensure_grids(struct Mesh *mesh, const int level); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Functions specific to reshaping from a set of vertices in a object position. */ @@ -245,17 +252,21 @@ bool multires_reshape_assign_final_coords_from_vertcos( const float (*vert_coords)[3], const int num_vert_coords); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Functions specific to reshaping from CCG. */ -/* NOTE: Displacement grids to be at least at a reshape level. +/* Store final object-space coordinates in the displacement grids. + * The reason why displacement grids are used for storage is based on memory + * footprint optimization. + * + * NOTE: Displacement grids to be at least at a reshape level. * * Return truth if all coordinates have been updated. */ bool multires_reshape_assign_final_coords_from_ccg(const MultiresReshapeContext *reshape_context, struct SubdivCCG *subdiv_ccg); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Functions specific to reshaping from MDISPS. */ @@ -264,10 +275,10 @@ void multires_reshape_assign_final_coords_from_mdisps( const MultiresReshapeContext *reshape_context); /* Reads from original CD_MIDTSPS, writes to the current mesh CD_MDISPS. */ -void multires_reshape_assign_final_coords_from_orig_mdisps( +void multires_reshape_assign_final_elements_from_orig_mdisps( const MultiresReshapeContext *reshape_context); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Displacement smooth. */ @@ -284,9 +295,10 @@ void multires_reshape_smooth_object_grids_with_details( * * Makes it so surface on top level looks smooth. Details are not preserved */ -void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context); +void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, + const enum eMultiresSubdivideModeType mode); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Displacement, space conversion. */ @@ -297,7 +309,7 @@ void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_conte void multires_reshape_object_grids_to_tangent_displacement( const MultiresReshapeContext *reshape_context); -/* ================================================================================================ +/* -------------------------------------------------------------------- * Apply base. */ @@ -319,5 +331,4 @@ void multires_reshape_apply_base_refine_from_base(MultiresReshapeContext *reshap * * NOTE: Will re-evaluate all leading modifiers, so it's not cheap. */ void multires_reshape_apply_base_refine_from_deform(MultiresReshapeContext *reshape_context); - #endif /* __BKE_INTERN_MULTIRES_RESHAPE_H__ */ diff --git a/source/blender/blenkernel/intern/multires_reshape_apply_base.c b/source/blender/blenkernel/intern/multires_reshape_apply_base.c index e67e553e8ed..105e56e4219 100644 --- a/source/blender/blenkernel/intern/multires_reshape_apply_base.c +++ b/source/blender/blenkernel/intern/multires_reshape_apply_base.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_reshape_ccg.c b/source/blender/blenkernel/intern/multires_reshape_ccg.c index 1f8c782ed46..8273845e820 100644 --- a/source/blender/blenkernel/intern/multires_reshape_ccg.c +++ b/source/blender/blenkernel/intern/multires_reshape_ccg.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_reshape_smooth.c b/source/blender/blenkernel/intern/multires_reshape_smooth.c index d99e27ad9dd..7312ac2bf5e 100644 --- a/source/blender/blenkernel/intern/multires_reshape_smooth.c +++ b/source/blender/blenkernel/intern/multires_reshape_smooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -48,6 +48,15 @@ #include "atomic_ops.h" #include "subdiv_converter.h" +/* -------------------------------------------------------------------- */ +/** \name Local Structs + * \{ */ + +/* Surface refers to a simplified and lower-memory footprint representation of the limit surface. + * + * Used to store pre-calculated information which is expensive or impossible to evaluate when + * travesing the final limit surface. */ + typedef struct SurfacePoint { float P[3]; float tangent_matrix[3][3]; @@ -57,6 +66,9 @@ typedef struct SurfaceGrid { SurfacePoint *points; } SurfaceGrid; +/* Geometry elements which are used to simplify creation of topology refiner at the sculpt level. + * Contains a limited subset of information needed to construct topology refiner. */ + typedef struct Vertex { /* All grid coordinates which the vertex corresponding to. * For a vertices which are created from inner points of grids there is always one coordinate. */ @@ -83,6 +95,32 @@ typedef struct Edge { float sharpness; } Edge; +/* Storage of data which is linearly interpolated from the reshape level to the top level. */ + +typedef struct LinearGridElement { + float mask; +} LinearGridElement; + +typedef struct LinearGrid { + LinearGridElement *elements; +} LinearGrid; + +typedef struct LinearGrids { + int num_grids; + int level; + + /* Cached size for the grid, for faster lookup. */ + int grid_size; + + /* Indexed by grid index. */ + LinearGrid *grids; + + /* Elements for all grids are allocated in a single array, for the allocation performance. */ + LinearGridElement *elements_storage; +} LinearGrids; + +/* Context which holds all information eeded during propagation and smoothing. */ + typedef struct MultiresReshapeSmoothContext { const MultiresReshapeContext *reshape_context; @@ -108,66 +146,118 @@ typedef struct MultiresReshapeSmoothContext { Face *faces; } geometry; + /* Grids of data which is linearly interpolated between grid elements at the reshape level. + * The data is actually stored as a delta, which is then to be added to the higher levels. */ + LinearGrids linear_delta_grids; + /* Index i of this map indicates that base edge i is adjacent to at least one face. */ BLI_bitmap *non_loose_base_edge_map; /* Subdivision surface created for geometry at a reshape level. */ Subdiv *reshape_subdiv; + /* Limit surface of the base mesh with original sculpt level details on it, subdivided up to the + * top level. + * Is used as a base point to calculate how much displacement has been made in the sculpt mode. + * + * NOTE: Referring to sculpt as it is the main user of this functionality and it is clear to + * understand what it actually means in a concrete example. This is a generic code which is also + * used by Subdivide operation, but the idea is exactly the same as propagation in the sculpt + * mode. */ SurfaceGrid *base_surface_grids; + + /* Defines how displacement is interpolated on the higher levels (for example, whether + * displacement is smoothed in Catmull-Clark mode or interpolated linearly preserving sharp edges + * of the current sculpt level). + * + * NOTE: Uses same enumerator type as Subdivide operator, since the values are the same and + * decoupling type just adds extra headache to convert one enumerator to another. */ + eMultiresSubdivideModeType smoothing_type; } MultiresReshapeSmoothContext; -/* ================================================================================================ - * Masks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Linear grids manipulation + * \{ */ -/* Interpolate mask grid at a reshape level. - * Will return 0 if there is no masks custom data layer. */ -static float interpolate_masks_grid(const MultiresReshapeSmoothContext *reshape_smooth_context, - const GridCoord *grid_coord) +static void linear_grids_init(LinearGrids *linear_grids) { - const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - if (reshape_context->orig.grid_paint_masks == NULL) { - return 0.0f; - } + linear_grids->num_grids = 0; + linear_grids->level = 0; - const GridPaintMask *grid = &reshape_context->orig.grid_paint_masks[grid_coord->grid_index]; - const int grid_size = BKE_subdiv_grid_size_from_level(grid->level); - const int grid_size_1 = grid_size - 1; - const float grid_size_1_inv = 1.0f / (float)(grid_size_1); + linear_grids->grids = NULL; + linear_grids->elements_storage = NULL; +} - const float x_f = grid_coord->u * grid_size_1; - const float y_f = grid_coord->v * grid_size_1; +static void linear_grids_allocate(LinearGrids *linear_grids, int num_grids, int level) +{ + const size_t grid_size = BKE_subdiv_grid_size_from_level(level); + const size_t grid_area = grid_size * grid_size; + const size_t num_grid_elements = num_grids * grid_area; - const int x_i = x_f; - const int y_i = y_f; - const int x_n_i = (x_i == grid_size - 1) ? (x_i) : (x_i + 1); - const int y_n_i = (y_i == grid_size - 1) ? (y_i) : (y_i + 1); + linear_grids->num_grids = num_grids; + linear_grids->level = level; + linear_grids->grid_size = grid_size; - const int corners[4][2] = {{x_i, y_i}, {x_n_i, y_i}, {x_n_i, y_n_i}, {x_i, y_n_i}}; - float mask_elements[4]; - for (int i = 0; i < 4; ++i) { - GridCoord corner_grid_coord; - corner_grid_coord.grid_index = grid_coord->grid_index; - corner_grid_coord.u = corners[i][0] * grid_size_1_inv; - corner_grid_coord.v = corners[i][1] * grid_size_1_inv; + linear_grids->grids = MEM_malloc_arrayN(num_grids, sizeof(LinearGrid), "linear grids"); + linear_grids->elements_storage = MEM_calloc_arrayN( + num_grid_elements, sizeof(LinearGridElement), "linear elements storage"); - ReshapeConstGridElement element = multires_reshape_orig_grid_element_for_grid_coord( - reshape_context, &corner_grid_coord); - mask_elements[i] = element.mask; + for (int i = 0; i < num_grids; ++i) { + const size_t element_offset = grid_area * i; + linear_grids->grids[i].elements = &linear_grids->elements_storage[element_offset]; } +} - const float u = x_f - x_i; - const float v = y_f - y_i; - const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), (1.0f - u) * v, u * v}; +static LinearGridElement *linear_grid_element_get(const LinearGrids *linear_grids, + const GridCoord *grid_coord) +{ + BLI_assert(grid_coord->grid_index >= 0); + BLI_assert(grid_coord->grid_index < linear_grids->num_grids); + + const int grid_size = linear_grids->grid_size; - return mask_elements[0] * weights[0] + mask_elements[1] * weights[1] + - mask_elements[2] * weights[2] + mask_elements[3] * weights[3]; + const int grid_x = lround(grid_coord->u * (grid_size - 1)); + const int grid_y = lround(grid_coord->v * (grid_size - 1)); + const int grid_element_index = grid_y * grid_size + grid_x; + + LinearGrid *grid = &linear_grids->grids[grid_coord->grid_index]; + return &grid->elements[grid_element_index]; } -/* ================================================================================================ - * Surface. - */ +static void linear_grids_free(LinearGrids *linear_grids) +{ + MEM_SAFE_FREE(linear_grids->grids); + MEM_SAFE_FREE(linear_grids->elements_storage); +} + +static void linear_grid_element_init(LinearGridElement *linear_grid_element) +{ + linear_grid_element->mask = 0.0f; +} + +/* result = a - b. */ +static void linear_grid_element_sub(LinearGridElement *result, + const LinearGridElement *a, + const LinearGridElement *b) +{ + result->mask = a->mask - b->mask; +} + +static void linear_grid_element_interpolate(LinearGridElement *result, + const LinearGridElement elements[4], + const float weights[4]) +{ + result->mask = elements[0].mask * weights[0] + elements[1].mask * weights[1] + + elements[2].mask * weights[2] + elements[3].mask * weights[3]; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Surface + * \{ */ static void base_surface_grids_allocate(MultiresReshapeSmoothContext *reshape_smooth_context) { @@ -227,9 +317,11 @@ static void base_surface_grids_write(const MultiresReshapeSmoothContext *reshape copy_m3_m3(point->tangent_matrix, tangent_matrix); } -/* ================================================================================================ - * Evaluation of subdivision surface at a reshape level. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation of subdivision surface at a reshape level + * \{ */ typedef void (*ForeachTopLevelGridCoordCallback)( const MultiresReshapeSmoothContext *reshape_smooth_context, @@ -383,11 +475,14 @@ static void foreach_toplevel_grid_coord(const MultiresReshapeSmoothContext *resh 0, num_faces, &data, foreach_toplevel_grid_coord_task, ¶llel_range_settings); } -/* ================================================================================================ - * Generation of a topology information for OpenSubdiv converter. +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generation of a topology information for OpenSubdiv converter * * Calculates vertices, their coordinates in the original grids, and connections of them so then - * it's easy to create OpenSubdiv's topology refiner. */ + * it's easy to create OpenSubdiv's topology refiner. + * \{ */ static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_context) { @@ -399,15 +494,17 @@ static int get_reshape_level_resolution(const MultiresReshapeContext *reshape_co static char get_effective_edge_crease_char( const MultiresReshapeSmoothContext *reshape_smooth_context, const MEdge *base_edge) { - const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - if (reshape_context->subdiv->settings.is_simple) { + if (ELEM(reshape_smooth_context->smoothing_type, + MULTIRES_SUBDIVIDE_LINEAR, + MULTIRES_SUBDIVIDE_SIMPLE)) { return 255; } return base_edge->crease; } static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, - const MultiresReshapeContext *reshape_context) + const MultiresReshapeContext *reshape_context, + const eMultiresSubdivideModeType mode) { reshape_smooth_context->reshape_context = reshape_context; @@ -424,9 +521,13 @@ static void context_init(MultiresReshapeSmoothContext *reshape_smooth_context, reshape_smooth_context->geometry.num_faces = 0; reshape_smooth_context->geometry.faces = NULL; + linear_grids_init(&reshape_smooth_context->linear_delta_grids); + reshape_smooth_context->non_loose_base_edge_map = NULL; reshape_smooth_context->reshape_subdiv = NULL; reshape_smooth_context->base_surface_grids = NULL; + + reshape_smooth_context->smoothing_type = mode; } static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_context) @@ -440,6 +541,8 @@ static void context_free_geometry(MultiresReshapeSmoothContext *reshape_smooth_c MEM_SAFE_FREE(reshape_smooth_context->geometry.corners); MEM_SAFE_FREE(reshape_smooth_context->geometry.faces); MEM_SAFE_FREE(reshape_smooth_context->geometry.edges); + + linear_grids_free(&reshape_smooth_context->linear_delta_grids); } static void context_free_subdiv(MultiresReshapeSmoothContext *reshape_smooth_context) @@ -461,12 +564,14 @@ static void context_free(MultiresReshapeSmoothContext *reshape_smooth_context) static bool foreach_topology_info(const SubdivForeachContext *foreach_context, const int num_vertices, - const int UNUSED(num_edges), + const int num_edges, const int num_loops, const int num_polygons) { MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data; - const int max_edges = reshape_smooth_context->geometry.max_edges; + const int max_edges = reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR ? + num_edges : + reshape_smooth_context->geometry.max_edges; /* NOTE: Calloc so the counters are re-set to 0 "for free". */ reshape_smooth_context->geometry.num_vertices = num_vertices; @@ -659,6 +764,22 @@ static void foreach_vertex_of_loose_edge(const struct SubdivForeachContext *fore } } +static void store_edge(MultiresReshapeSmoothContext *reshape_smooth_context, + const int subdiv_v1, + const int subdiv_v2, + const char crease) +{ + /* This is a bit overhead to use atomics in such a simple function called from many threads, + * but this allows to save quite measurable amount of memory. */ + const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1); + BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges); + + Edge *edge = &reshape_smooth_context->geometry.edges[edge_index]; + edge->v1 = subdiv_v1; + edge->v2 = subdiv_v2; + edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease); +} + static void foreach_edge(const struct SubdivForeachContext *foreach_context, void *UNUSED(tls), const int coarse_edge_index, @@ -669,8 +790,15 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, MultiresReshapeSmoothContext *reshape_smooth_context = foreach_context->user_data; const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; - /* Ignore all inner face edges as they have sharpness of zero. */ - if (coarse_edge_index == ORIGINDEX_NONE) { + if (reshape_smooth_context->smoothing_type == MULTIRES_SUBDIVIDE_LINEAR) { + store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, (char)255); + return; + } + + /* Ignore all inner face edges as they have sharpness of zero when using Catmull-Clark mode. In + * simple mode, all edges have maximum sharpness, so they can't be skipped. */ + if (coarse_edge_index == ORIGINDEX_NONE && + reshape_smooth_context->smoothing_type != MULTIRES_SUBDIVIDE_SIMPLE) { return; } /* Ignore all loose edges as well, as they are not communicated to the OpenSubdiv. */ @@ -684,16 +812,7 @@ static void foreach_edge(const struct SubdivForeachContext *foreach_context, if (crease == 0) { return; } - - /* This is a bit overhead to use atomics in such a simple function called from many threads, - * but this allows to save quite measurable amount of memory. */ - const int edge_index = atomic_fetch_and_add_z(&reshape_smooth_context->geometry.num_edges, 1); - BLI_assert(edge_index < reshape_smooth_context->geometry.max_edges); - - Edge *edge = &reshape_smooth_context->geometry.edges[edge_index]; - edge->v1 = subdiv_v1; - edge->v2 = subdiv_v2; - edge->sharpness = BKE_subdiv_edge_crease_to_sharpness_char(crease); + store_edge(reshape_smooth_context, subdiv_v1, subdiv_v2, crease); } static void geometry_init_loose_information(MultiresReshapeSmoothContext *reshape_smooth_context) @@ -757,9 +876,11 @@ static void geometry_create(MultiresReshapeSmoothContext *reshape_smooth_context reshape_context->subdiv, &foreach_context, &mesh_settings, reshape_context->base_mesh); } -/* ================================================================================================ - * Generation of OpenSubdiv evaluator for topology created form reshape level. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generation of OpenSubdiv evaluator for topology created form reshape level + * \{ */ static OpenSubdiv_SchemeType get_scheme_type(const OpenSubdiv_Converter *UNUSED(converter)) { @@ -1037,9 +1158,138 @@ static void reshape_subdiv_evaluate_limit_at_grid( BKE_multires_construct_tangent_matrix(r_tangent_matrix, dPdu, dPdv, corner); } -/* ================================================================================================ - * Evaluation of base surface. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Linearly interpolated data + * \{ */ + +static LinearGridElement linear_grid_element_orig_get( + const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord) +{ + const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; + const ReshapeConstGridElement orig_grid_element = + multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord); + + LinearGridElement linear_grid_element; + linear_grid_element_init(&linear_grid_element); + + linear_grid_element.mask = orig_grid_element.mask; + + return linear_grid_element; +} + +static LinearGridElement linear_grid_element_final_get( + const MultiresReshapeSmoothContext *reshape_smooth_context, const GridCoord *grid_coord) +{ + const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; + const ReshapeGridElement final_grid_element = multires_reshape_grid_element_for_grid_coord( + reshape_context, grid_coord); + + LinearGridElement linear_grid_element; + linear_grid_element_init(&linear_grid_element); + + if (final_grid_element.mask != NULL) { + linear_grid_element.mask = *final_grid_element.mask; + } + + return linear_grid_element; +} + +/* Interpolate difference of the linear data. + * + * Will access final data and original data at the grid elements at the reshape level, + * calculate difference between final and original, and linearly interpolate to get value at the + * top level. */ +static void linear_grid_element_delta_interpolate( + const MultiresReshapeSmoothContext *reshape_smooth_context, + const GridCoord *grid_coord, + LinearGridElement *result) +{ + const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; + + const int reshape_level = reshape_context->reshape.level; + const int reshape_level_grid_size = BKE_subdiv_grid_size_from_level(reshape_level); + const int reshape_level_grid_size_1 = reshape_level_grid_size - 1; + const float reshape_level_grid_size_1_inv = 1.0f / (float)(reshape_level_grid_size_1); + + const float x_f = grid_coord->u * reshape_level_grid_size_1; + const float y_f = grid_coord->v * reshape_level_grid_size_1; + + const int x_i = x_f; + const int y_i = y_f; + const int x_n_i = (x_i == reshape_level_grid_size - 1) ? (x_i) : (x_i + 1); + const int y_n_i = (y_i == reshape_level_grid_size - 1) ? (y_i) : (y_i + 1); + + const int corners_int_coords[4][2] = {{x_i, y_i}, {x_n_i, y_i}, {x_n_i, y_n_i}, {x_i, y_n_i}}; + + LinearGridElement corner_elements[4]; + for (int i = 0; i < 4; ++i) { + GridCoord corner_grid_coord; + corner_grid_coord.grid_index = grid_coord->grid_index; + corner_grid_coord.u = corners_int_coords[i][0] * reshape_level_grid_size_1_inv; + corner_grid_coord.v = corners_int_coords[i][1] * reshape_level_grid_size_1_inv; + + const LinearGridElement orig_element = linear_grid_element_orig_get(reshape_smooth_context, + &corner_grid_coord); + const LinearGridElement final_element = linear_grid_element_final_get(reshape_smooth_context, + &corner_grid_coord); + linear_grid_element_sub(&corner_elements[i], &final_element, &orig_element); + } + + const float u = x_f - x_i; + const float v = y_f - y_i; + const float weights[4] = {(1.0f - u) * (1.0f - v), u * (1.0f - v), u * v, (1.0f - u) * v}; + + linear_grid_element_interpolate(result, corner_elements, weights); +} + +static void evaluate_linear_delta_grids_callback( + const MultiresReshapeSmoothContext *reshape_smooth_context, + const PTexCoord *UNUSED(ptex_coord), + const GridCoord *grid_coord, + void *UNUSED(userdata_v)) +{ + LinearGridElement *linear_delta_element = linear_grid_element_get( + &reshape_smooth_context->linear_delta_grids, grid_coord); + + linear_grid_element_delta_interpolate(reshape_smooth_context, grid_coord, linear_delta_element); +} + +static void evaluate_linear_delta_grids(MultiresReshapeSmoothContext *reshape_smooth_context) +{ + const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; + const int num_grids = reshape_context->num_grids; + const int top_level = reshape_context->top.level; + + linear_grids_allocate(&reshape_smooth_context->linear_delta_grids, num_grids, top_level); + + foreach_toplevel_grid_coord(reshape_smooth_context, evaluate_linear_delta_grids_callback, NULL); +} + +static void propagate_linear_data_delta(const MultiresReshapeSmoothContext *reshape_smooth_context, + ReshapeGridElement *final_grid_element, + const GridCoord *grid_coord) +{ + const MultiresReshapeContext *reshape_context = reshape_smooth_context->reshape_context; + + LinearGridElement *linear_delta_element = linear_grid_element_get( + &reshape_smooth_context->linear_delta_grids, grid_coord); + + const ReshapeConstGridElement orig_grid_element = + multires_reshape_orig_grid_element_for_grid_coord(reshape_context, grid_coord); + + if (final_grid_element->mask != NULL) { + *final_grid_element->mask = clamp_f( + orig_grid_element.mask + linear_delta_element->mask, 0.0f, 1.0f); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation of base surface + * \{ */ static void evaluate_base_surface_grids_callback( const MultiresReshapeSmoothContext *reshape_smooth_context, @@ -1060,9 +1310,11 @@ static void evaluate_base_surface_grids(const MultiresReshapeSmoothContext *resh foreach_toplevel_grid_coord(reshape_smooth_context, evaluate_base_surface_grids_callback, NULL); } -/* ================================================================================================ - * Evaluation of new surface. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation of new surface + * \{ */ /* Evaluate final position of the original (pre-sculpt-edit) point position at a given grid * coordinate. */ @@ -1136,7 +1388,11 @@ static void evaluate_higher_grid_positions_with_details_callback( grid_coord); add_v3_v3v3(grid_element.displacement, smooth_limit_P, smooth_delta); + + /* Propagate non-coordinate data. */ + propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord); } + static void evaluate_higher_grid_positions_with_details( const MultiresReshapeSmoothContext *reshape_smooth_context) { @@ -1157,17 +1413,14 @@ static void evaluate_higher_grid_positions_callback( grid_coord); /* Surface. */ - float P[3]; BKE_subdiv_eval_limit_point( reshape_subdiv, ptex_coord->ptex_face_index, ptex_coord->u, ptex_coord->v, P); copy_v3_v3(grid_element.displacement, P); - /* Masks. */ - if (grid_element.mask != NULL) { - *grid_element.mask = interpolate_masks_grid(reshape_smooth_context, grid_coord); - } + /* Propagate non-coordinate data. */ + propagate_linear_data_delta(reshape_smooth_context, &grid_element, grid_coord); } static void evaluate_higher_grid_positions( @@ -1176,9 +1429,12 @@ static void evaluate_higher_grid_positions( foreach_toplevel_grid_coord( reshape_smooth_context, evaluate_higher_grid_positions_callback, NULL); } -/* ================================================================================================ - * Entry point. - */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Entry point + * \{ */ void multires_reshape_smooth_object_grids_with_details( const MultiresReshapeContext *reshape_context) @@ -1190,9 +1446,15 @@ void multires_reshape_smooth_object_grids_with_details( } MultiresReshapeSmoothContext reshape_smooth_context; - context_init(&reshape_smooth_context, reshape_context); + if (reshape_context->subdiv->settings.is_simple) { + context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_SIMPLE); + } + else { + context_init(&reshape_smooth_context, reshape_context, MULTIRES_SUBDIVIDE_CATMULL_CLARK); + } geometry_create(&reshape_smooth_context); + evaluate_linear_delta_grids(&reshape_smooth_context); reshape_subdiv_create(&reshape_smooth_context); @@ -1206,7 +1468,8 @@ void multires_reshape_smooth_object_grids_with_details( context_free(&reshape_smooth_context); } -void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context) +void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_context, + const eMultiresSubdivideModeType mode) { const int level_difference = (reshape_context->top.level - reshape_context->reshape.level); if (level_difference == 0) { @@ -1215,9 +1478,10 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_ } MultiresReshapeSmoothContext reshape_smooth_context; - context_init(&reshape_smooth_context, reshape_context); + context_init(&reshape_smooth_context, reshape_context, mode); geometry_create(&reshape_smooth_context); + evaluate_linear_delta_grids(&reshape_smooth_context); reshape_subdiv_create(&reshape_smooth_context); @@ -1226,3 +1490,5 @@ void multires_reshape_smooth_object_grids(const MultiresReshapeContext *reshape_ context_free(&reshape_smooth_context); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape_subdivide.c b/source/blender/blenkernel/intern/multires_reshape_subdivide.c new file mode 100644 index 00000000000..7b7c1efc533 --- /dev/null +++ b/source/blender/blenkernel/intern/multires_reshape_subdivide.c @@ -0,0 +1,106 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" + +#include "BKE_customdata.h" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_subdiv.h" +#include "BKE_subsurf.h" +#include "BLI_math_vector.h" + +#include "DEG_depsgraph_query.h" + +#include "multires_reshape.h" + +static void multires_subdivide_create_object_space_linear_grids(Mesh *mesh) +{ + MDisps *mdisps = CustomData_get_layer(&mesh->ldata, CD_MDISPS); + const int totpoly = mesh->totpoly; + for (int p = 0; p < totpoly; p++) { + MPoly *poly = &mesh->mpoly[p]; + float poly_center[3]; + BKE_mesh_calc_poly_center(poly, &mesh->mloop[poly->loopstart], mesh->mvert, poly_center); + for (int l = 0; l < poly->totloop; l++) { + const int loop_index = poly->loopstart + l; + + float(*disps)[3] = mdisps[loop_index].disps; + mdisps[loop_index].totdisp = 4; + mdisps[loop_index].level = 1; + + int prev_loop_index = l - 1 >= 0 ? loop_index - 1 : loop_index + poly->totloop - 1; + int next_loop_index = l + 1 < poly->totloop ? loop_index + 1 : poly->loopstart; + + MLoop *loop = &mesh->mloop[loop_index]; + MLoop *loop_next = &mesh->mloop[next_loop_index]; + MLoop *loop_prev = &mesh->mloop[prev_loop_index]; + + copy_v3_v3(disps[0], poly_center); + mid_v3_v3v3(disps[1], mesh->mvert[loop->v].co, mesh->mvert[loop_next->v].co); + mid_v3_v3v3(disps[2], mesh->mvert[loop->v].co, mesh->mvert[loop_prev->v].co); + copy_v3_v3(disps[3], mesh->mvert[loop->v].co); + } + } +} + +void multires_subdivide_create_tangent_displacement_linear_grids(Object *object, + MultiresModifierData *mmd) +{ + Mesh *coarse_mesh = object->data; + multires_force_sculpt_rebuild(object); + + MultiresReshapeContext reshape_context; + + const int new_top_level = mmd->totlvl + 1; + + const bool has_mdisps = CustomData_has_layer(&coarse_mesh->ldata, CD_MDISPS); + if (!has_mdisps) { + CustomData_add_layer(&coarse_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, coarse_mesh->totloop); + } + + if (new_top_level == 1) { + /* No MDISPS. Create new grids for level 1 using the edges mid point and poly centers. */ + multires_reshape_ensure_grids(coarse_mesh, 1); + multires_subdivide_create_object_space_linear_grids(coarse_mesh); + } + + /* Convert the new grids to tangent displacement. */ + multires_set_tot_level(object, mmd, new_top_level); + + if (!multires_reshape_context_create_from_subdivide( + &reshape_context, object, mmd, new_top_level)) { + return; + } + + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_reshape_context_free(&reshape_context); +} diff --git a/source/blender/blenkernel/intern/multires_reshape_util.c b/source/blender/blenkernel/intern/multires_reshape_util.c index 57d790d2c34..e9a779dafeb 100644 --- a/source/blender/blenkernel/intern/multires_reshape_util.c +++ b/source/blender/blenkernel/intern/multires_reshape_util.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -43,9 +43,9 @@ #include "DEG_depsgraph_query.h" -/* ================================================================================================ - * Construct/destruct reshape context. - */ +/* -------------------------------------------------------------------- */ +/** \name Construct/destruct reshape context + * \{ */ /* Create subdivision surface descriptor which is configured for surface evaluation at a given * multires modifier. */ @@ -152,6 +152,39 @@ static bool context_verify_or_free(MultiresReshapeContext *reshape_context) return is_valid; } +bool multires_reshape_context_create_from_base_mesh(MultiresReshapeContext *reshape_context, + Depsgraph *depsgraph, + Object *object, + MultiresModifierData *mmd) +{ + context_zero(reshape_context); + + const bool use_render_params = false; + Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + Mesh *base_mesh = (Mesh *)object->data; + + reshape_context->depsgraph = depsgraph; + reshape_context->object = object; + reshape_context->mmd = mmd; + + reshape_context->base_mesh = base_mesh; + + reshape_context->subdiv = multires_reshape_create_subdiv(NULL, object, mmd); + reshape_context->need_free_subdiv = true; + + reshape_context->reshape.level = multires_get_level( + scene_eval, object, mmd, use_render_params, true); + reshape_context->reshape.grid_size = BKE_subdiv_grid_size_from_level( + reshape_context->reshape.level); + + reshape_context->top.level = mmd->totlvl; + reshape_context->top.grid_size = BKE_subdiv_grid_size_from_level(reshape_context->top.level); + + context_init_commoon(reshape_context); + + return context_verify_or_free(reshape_context); +} + bool multires_reshape_context_create_from_object(MultiresReshapeContext *reshape_context, Depsgraph *depsgraph, Object *object, @@ -272,14 +305,16 @@ void multires_reshape_context_free(MultiresReshapeContext *reshape_context) multires_reshape_free_original_grids(reshape_context); - MEM_freeN(reshape_context->face_start_grid_index); - MEM_freeN(reshape_context->ptex_start_grid_index); - MEM_freeN(reshape_context->grid_to_face_index); + MEM_SAFE_FREE(reshape_context->face_start_grid_index); + MEM_SAFE_FREE(reshape_context->ptex_start_grid_index); + MEM_SAFE_FREE(reshape_context->grid_to_face_index); } -/* ================================================================================================ - * Helper accessors. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Helper accessors + * \{ */ /* For the given grid index get index of face it was created for. */ int multires_reshape_grid_to_face_index(const MultiresReshapeContext *reshape_context, @@ -453,9 +488,11 @@ ReshapeConstGridElement multires_reshape_orig_grid_element_for_grid_coord( return grid_element; } -/* ================================================================================================ - * Sample limit surface of the base mesh. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Sample limit surface of the base mesh + * \{ */ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *reshape_context, const GridCoord *grid_coord, @@ -475,9 +512,11 @@ void multires_reshape_evaluate_limit_at_grid(const MultiresReshapeContext *resha reshape_context, face_index, corner, dPdu, dPdv, r_tangent_matrix); } -/* ================================================================================================ - * Custom data preparation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Custom data preparation + * \{ */ static void allocate_displacement_grid(MDisps *displacement_grid, const int level) { @@ -539,9 +578,11 @@ void multires_reshape_ensure_grids(Mesh *mesh, const int level) ensure_mask_grids(mesh, level); } -/* ================================================================================================ - * Displacement, space conversion. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Displacement, space conversion + * \{ */ void multires_reshape_store_original_grids(MultiresReshapeContext *reshape_context) { @@ -678,10 +719,13 @@ void multires_reshape_object_grids_to_tangent_displacement( NULL); } -/* ================================================================================================ - * MDISPS - * - * TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name MDISPS + * \{ */ + +/* TODO(sergey): Make foreach_grid_coordinate more accessible and move this functionality to * own file. */ static void assign_final_coords_from_mdisps(const MultiresReshapeContext *reshape_context, @@ -707,9 +751,9 @@ void multires_reshape_assign_final_coords_from_mdisps( reshape_context, reshape_context->top.level, assign_final_coords_from_mdisps, NULL); } -static void assign_final_coords_from_orig_mdisps(const MultiresReshapeContext *reshape_context, - const GridCoord *grid_coord, - void *UNUSED(userdata_v)) +static void assign_final_elements_from_orig_mdisps(const MultiresReshapeContext *reshape_context, + const GridCoord *grid_coord, + void *UNUSED(userdata_v)) { float P[3]; float tangent_matrix[3][3]; @@ -724,11 +768,17 @@ static void assign_final_coords_from_orig_mdisps(const MultiresReshapeContext *r ReshapeGridElement grid_element = multires_reshape_grid_element_for_grid_coord(reshape_context, grid_coord); add_v3_v3v3(grid_element.displacement, P, D); + + if (grid_element.mask != NULL) { + *grid_element.mask = orig_grid_element.mask; + } } -void multires_reshape_assign_final_coords_from_orig_mdisps( +void multires_reshape_assign_final_elements_from_orig_mdisps( const MultiresReshapeContext *reshape_context) { foreach_grid_coordinate( - reshape_context, reshape_context->top.level, assign_final_coords_from_orig_mdisps, NULL); + reshape_context, reshape_context->top.level, assign_final_elements_from_orig_mdisps, NULL); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/multires_reshape_vertcos.c b/source/blender/blenkernel/intern/multires_reshape_vertcos.c index 1ece7344f37..04df5698cf9 100644 --- a/source/blender/blenkernel/intern/multires_reshape_vertcos.c +++ b/source/blender/blenkernel/intern/multires_reshape_vertcos.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_subdiv.c b/source/blender/blenkernel/intern/multires_subdiv.c index f7e42942f3e..fc092d3ccce 100644 --- a/source/blender/blenkernel/intern/multires_subdiv.c +++ b/source/blender/blenkernel/intern/multires_subdiv.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018 Blender Foundation. diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c new file mode 100644 index 00000000000..e5000e7774f --- /dev/null +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -0,0 +1,1297 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + * + * This implements the un-subdivide algorithm, which generates a lower resolution base mesh and + * its corresponding grids to match a given original mesh. + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" + +#include "BLI_gsqueue.h" +#include "BLI_math_vector.h" + +#include "BKE_customdata.h" +#include "BKE_lib_id.h" +#include "BKE_mesh.h" +#include "BKE_mesh_runtime.h" +#include "BKE_modifier.h" +#include "BKE_multires.h" +#include "BKE_subdiv.h" +#include "BKE_subsurf.h" + +#include "bmesh.h" + +#include "DEG_depsgraph_query.h" + +#include "multires_reshape.h" +#include "multires_unsubdivide.h" + +/* This is done in the following steps: + * + * - If there are already grids in the original mesh, + * convert them from tangent displacement to object space coordinates. + * - Assign data-layers to the original mesh to map vertices to a new base mesh. + * These data-layers store the indices of the elements in the original mesh. + * This way the original indices are + * preserved when doing mesh modifications (removing and dissolving vertices) + * when building the new base mesh. + * - Try to find a lower resolution base mesh. This is done by flood fill operation that tags the + * center vertices of the lower level grid. + * If the algorithm can tag all vertices correctly, + * the lower level base mesh is generated by dissolving the tagged vertices. + * - Use the data-layers to map vertices from the base mesh to the original mesh and original to + * base mesh. + * - Find two adjacent vertices on the base mesh to a given vertex to map that loop from base mesh + * to original mesh + * - Extract the grid from the original mesh from that loop. If there are no grids in the original + * mesh, build the new grid directly from the vertex coordinates by iterating in a grid pattern + * over them. If there are grids in the original mesh, iterate in a grid pattern over the polys, + * reorder all the coordinates of the grid in that poly and copy those coordinates to the new + * base mesh grid. + * - Copy the new grid data over to a new allocated MDISP layer with the appropriate size to store + * the new levels. + * - Convert the grid data from object space to tangent displacement. + */ + +/** + * Used to check if a vertex is in a disconnected element ID. + */ +static bool is_vertex_in_id(BMVert *v, int *elem_id, int elem) +{ + const int v_index = BM_elem_index_get(v); + return elem_id[v_index] == elem; +} + +static bool is_vertex_pole_three(BMVert *v) +{ + return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3); +} + +static bool is_vertex_pole(BMVert *v) +{ + return !BM_vert_is_boundary(v) && (BM_vert_edge_count(v) == 3 || BM_vert_edge_count(v) >= 5); +} + +/** + * Returns the first pole that is found in an element ID. + * + * Tries to give priority to 3 vert poles as they generally generate better results in cases were + * the un-subdivide solution is ambiguous. + */ +static BMVert *unsubdivide_find_any_pole(BMesh *bm, int *elem_id, int elem) +{ + BMIter iter; + BMVert *v; + BMVert *pole = NULL; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (is_vertex_in_id(v, elem_id, elem) && is_vertex_pole_three(v)) { + return v; + } + else if (is_vertex_in_id(v, elem_id, elem) && is_vertex_pole(v)) { + pole = v; + } + } + return pole; +} + +/** + * Checks if the mesh is all quads. + * + * TODO(pablodp606): This can perform additional checks if they are faster than trying to search + * for an un-subdivide solution. This way it is possible to cancel the operation faster. + */ +static bool unsubdivide_is_all_quads(BMesh *bm) +{ + BMIter iter; + BMIter iter_a; + BMFace *f; + BMVert *v; + int count = 0; + if (bm->totface < 3) { + return false; + } + + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + count = 0; + BM_ITER_ELEM (v, &iter_a, f, BM_VERTS_OF_FACE) { + count++; + } + + if (count != 4) { + return false; + } + } + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (BM_vert_is_wire(v)) { + return false; + } + if (BM_vert_edge_count(v) == 0) { + return false; + } + } + + return true; +} + +/** + * Returns true if from_v and to_v, which should be part of the same quad face, are diagonals. + */ +static bool is_vertex_diagonal(BMVert *from_v, BMVert *to_v) +{ + return !BM_edge_exists(from_v, to_v); +} + +/** + * Generates a possible solution for un-subdivision by tagging the (0,0) + * vertices of the possible grids. + * + * This works using a flood fill operation using the quads diagonals to jump to the next vertex. + * + * If initial_vertex is part of the base mesh solution, the flood fill should tag only the (0.0) + * vertices of the grids that need to be dissolved, and nothing else. + */ +static void unsubdivide_face_center_vertex_tag(BMesh *bm, BMVert *initial_vertex) +{ + bool *visited_vertices = MEM_calloc_arrayN(sizeof(bool), bm->totvert, "visited vertices"); + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(BMVert *)); + + /* Add and tag the vertices connected by a diagonal to initial_vertex to the flood fill queue. If + * initial_vertex is a pole and there is a valid solution, those vertices should be the (0,0) of + * the grids for the loops of initial_vertex. */ + BMIter iter; + BMIter iter_a; + BMFace *f; + BMVert *neighbor_v; + BM_ITER_ELEM (f, &iter, initial_vertex, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_a, f, BM_VERTS_OF_FACE) { + int neighbor_vertex_index = BM_elem_index_get(neighbor_v); + if (neighbor_v != initial_vertex && is_vertex_diagonal(neighbor_v, initial_vertex)) { + BLI_gsqueue_push(queue, &neighbor_v); + visited_vertices[neighbor_vertex_index] = true; + BM_elem_flag_set(neighbor_v, BM_ELEM_TAG, true); + } + } + } + + /* Repeat a similar operation for all vertices in the queue. */ + /* In this case, add to the queue the vertices connected by 2 steps using the diagonals in any + * direction. If a solution exists and intial_vertex was a pole, this is guaranteed that will tag + * all the (0,0) vertices of the grids, and nothing else. */ + /* If it was not a pole, it may or may not find a solution, even if the solution exists. */ + while (!BLI_gsqueue_is_empty(queue)) { + BMVert *from_v; + BLI_gsqueue_pop(queue, &from_v); + + /* Get the diagonals (first connected step) */ + GSQueue *diagonals; + diagonals = BLI_gsqueue_new(sizeof(BMVert *)); + BM_ITER_ELEM (f, &iter, from_v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_a, f, BM_VERTS_OF_FACE) { + if (neighbor_v != from_v && is_vertex_diagonal(neighbor_v, from_v)) { + BLI_gsqueue_push(diagonals, &neighbor_v); + } + } + } + + /* Do the second connected step. This vertices are the ones that are added to the flood fill + * queue. */ + while (!BLI_gsqueue_is_empty(diagonals)) { + BMVert *diagonal_v; + BLI_gsqueue_pop(diagonals, &diagonal_v); + BM_ITER_ELEM (f, &iter, diagonal_v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_a, f, BM_VERTS_OF_FACE) { + int neighbor_vertex_index = BM_elem_index_get(neighbor_v); + if (!visited_vertices[neighbor_vertex_index] && neighbor_v != diagonal_v && + is_vertex_diagonal(neighbor_v, diagonal_v)) { + BLI_gsqueue_push(queue, &neighbor_v); + visited_vertices[neighbor_vertex_index] = true; + BM_elem_flag_set(neighbor_v, BM_ELEM_TAG, true); + } + } + } + } + BLI_gsqueue_free(diagonals); + } + + BLI_gsqueue_free(queue); + MEM_freeN(visited_vertices); +} + +/** + * This function checks if the current status of the #BMVert tags + * corresponds to a valid un-subdivide solution. + * + * This means that all vertices corresponding to the (0,0) grid coordinate should be tagged. + * + * On a valid solution, the following things should happen: + * - No boundary vertices should be tagged + * - No vertices connected by an edge or a quad diagonal to a tagged vertex should be tagged + * - All boundary vertices should have one vertex connected by an edge or a diagonal tagged + */ +static bool unsubdivide_is_center_vertex_tag_valid(BMesh *bm, int *elem_id, int elem) +{ + BMVert *v, *neighbor_v; + BMIter iter, iter_a, iter_b; + BMFace *f; + + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (is_vertex_in_id(v, elem_id, elem)) { + if (BM_elem_flag_test(v, BM_ELEM_TAG)) { + /* Tagged vertex in boundary */ + if (BM_vert_is_boundary(v)) { + return false; + } + /* Tagged vertex with connected tagged vertex. */ + BM_ITER_ELEM (f, &iter_a, v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_b, f, BM_VERTS_OF_FACE) { + if (neighbor_v != v && BM_elem_flag_test(neighbor_v, BM_ELEM_TAG)) { + return false; + } + } + } + } + if (BM_vert_is_boundary(v)) { + /* Un-tagged vertex in boundary without connected tagged vertices. */ + bool any_tagged = false; + BM_ITER_ELEM (f, &iter_a, v, BM_FACES_OF_VERT) { + BM_ITER_ELEM (neighbor_v, &iter_b, f, BM_VERTS_OF_FACE) { + if (neighbor_v != v && BM_elem_flag_test(neighbor_v, BM_ELEM_TAG)) { + any_tagged = true; + } + } + } + if (!any_tagged) { + return false; + } + } + } + } + + return true; +} + +/** + * Search and validates an un-subdivide solution for a given element ID. + */ +static bool unsubdivide_tag_disconnected_mesh_element(BMesh *bm, int *elem_id, int elem) +{ + /* First, get vertex candidates to try to generate possible un-subdivide solution. */ + /* Find a vertex pole. If there is a solution on an all quad base mesh, this vertex should be + * part of the base mesh. If it isn't, then there is no solution. */ + GSQueue *initial_vertex = BLI_gsqueue_new(sizeof(BMVert *)); + BMVert *initial_vertex_pole = unsubdivide_find_any_pole(bm, elem_id, elem); + if (initial_vertex_pole != NULL) { + BLI_gsqueue_push(initial_vertex, &initial_vertex_pole); + } + + /* Also try from the different 4 vertices of a quad in the current + * disconnected element ID. If a solution exists the search should return a valid solution from + * one of these vertices.*/ + BMFace *f, *init_face = NULL; + BMVert *v; + BMIter iter_a, iter_b; + BM_ITER_MESH (f, &iter_a, bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (v, &iter_b, f, BM_VERTS_OF_FACE) { + if (is_vertex_in_id(v, elem_id, elem)) { + init_face = f; + break; + } + } + if (init_face != NULL) { + break; + } + } + + BM_ITER_ELEM (v, &iter_a, init_face, BM_VERTS_OF_FACE) { + BLI_gsqueue_push(initial_vertex, &v); + } + + bool valid_tag_found = false; + + /* Check all vertex candidates to a solution. */ + while (!BLI_gsqueue_is_empty(initial_vertex)) { + + BMVert *iv; + BLI_gsqueue_pop(initial_vertex, &iv); + + /* Generate a possible solution. */ + unsubdivide_face_center_vertex_tag(bm, iv); + + /* Check if the solution is valid. If it is, stop searching. */ + if (unsubdivide_is_center_vertex_tag_valid(bm, elem_id, elem)) { + valid_tag_found = true; + break; + } + + /* If the solution is not valid, reset the state of all tags in this disconnected element ID + * and try again. */ + BMVert *v_reset; + BMIter iter; + BM_ITER_MESH (v_reset, &iter, bm, BM_VERTS_OF_MESH) { + if (is_vertex_in_id(v_reset, elem_id, elem)) { + BM_elem_flag_set(v_reset, BM_ELEM_TAG, false); + } + } + } + BLI_gsqueue_free(initial_vertex); + return valid_tag_found; +} + +/** + * Uses a flood fill operation to generate a different ID for each disconnected mesh element. + */ +static int unsubdivide_init_elem_ids(BMesh *bm, int *elem_id) +{ + bool *visited_vertices = MEM_calloc_arrayN(sizeof(bool), bm->totvert, "visited vertices"); + int current_id = 0; + for (int i = 0; i < bm->totvert; i++) { + if (!visited_vertices[i]) { + GSQueue *queue; + queue = BLI_gsqueue_new(sizeof(BMVert *)); + + visited_vertices[i] = true; + elem_id[i] = current_id; + BMVert *iv = BM_vert_at_index(bm, i); + BLI_gsqueue_push(queue, &iv); + + while (!BLI_gsqueue_is_empty(queue)) { + BMIter iter; + BMVert *current_v, *neighbor_v; + BMEdge *ed; + BLI_gsqueue_pop(queue, ¤t_v); + BM_ITER_ELEM (ed, &iter, current_v, BM_EDGES_OF_VERT) { + neighbor_v = BM_edge_other_vert(ed, current_v); + const int neighbor_index = BM_elem_index_get(neighbor_v); + if (!visited_vertices[neighbor_index]) { + visited_vertices[neighbor_index] = true; + elem_id[neighbor_index] = current_id; + BLI_gsqueue_push(queue, &neighbor_v); + } + } + } + current_id++; + BLI_gsqueue_free(queue); + } + } + MEM_freeN(visited_vertices); + return current_id; +} + +/** + * Builds a base mesh one subdivision level down from the current original mesh if the original + * mesh has a valid solution stored in the #BMVert tags. + */ +static void unsubdivide_build_base_mesh_from_tags(BMesh *bm) +{ + BMVert *v; + BMIter iter; + + /* Stores the vertices which correspond to (1, 0) and (0, 1) of the grids in the select flag. */ + BM_mesh_elem_hflag_enable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + BMVert *v_neighbor; + BMIter iter_a; + BMEdge *ed; + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + BM_ITER_ELEM (ed, &iter_a, v, BM_EDGES_OF_VERT) { + v_neighbor = BM_edge_other_vert(ed, v); + if (BM_elem_flag_test(v_neighbor, BM_ELEM_TAG)) { + BM_elem_flag_set(v, BM_ELEM_SELECT, false); + } + } + } + + /* Dissolves the (0,0) vertices of the grids. */ + BMO_op_callf(bm, + (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_TAG, + false, + true); + + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + + /* Copy the select flag to the tag flag. */ + BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) { + if (!BM_elem_flag_test(v, BM_ELEM_SELECT)) { + BM_elem_flag_set(v, BM_ELEM_TAG, true); + } + } + + /* Dissolves the (1,0) and (0,1) vertices of the grids. */ + BMO_op_callf(bm, + (BMO_FLAG_DEFAULTS & ~BMO_FLAG_RESPECT_HIDE), + "dissolve_verts verts=%hv use_face_split=%b use_boundary_tear=%b", + BM_ELEM_TAG, + false, + true); +} + +/** + * Main function to get a base mesh one level down from the current original mesh if it exists. + * + * This searches for different un-subdivide solutions and stores them as a combination of #BMVert + * flags for each disconnected mesh element. + * + * If the solution for all elements are valid, it builds a new base mesh based on those tags by + * dissolving and merging vertices. + */ +static bool multires_unsubdivide_single_level(BMesh *bm) +{ + + /* Do a first check to make sure that it makes sense to search for un-subdivision in this mesh. + */ + if (!unsubdivide_is_all_quads(bm)) { + return false; + }; + + /* Initialize the vertex table. */ + BM_mesh_elem_table_init(bm, BM_VERT); + BM_mesh_elem_table_ensure(bm, BM_VERT); + + /* Build disconnected elements IDs. Each disconnected mesh element is evaluated separately. */ + int *elem_id = MEM_calloc_arrayN(sizeof(int), bm->totvert, " ELEM ID"); + const int tot_ids = unsubdivide_init_elem_ids(bm, elem_id); + + bool valid_tag_found = true; + + /* Reset the #BMesh flags as they are used to store data during the un-subdivide process. */ + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + + /* For each disconnected mesh element ID, search if an un-subdivide solution is possible. The + * whole un-subdivide process fails if a single disconnected mesh element fails. */ + for (int id = 0; id < tot_ids; id++) { + /* Try to the #BMesh vertex flag tags corresponding to an un-subdivide solution. */ + if (!unsubdivide_tag_disconnected_mesh_element(bm, elem_id, id)) { + valid_tag_found = false; + break; + } + } + + /* If a solution was found for all elements IDs, build the new base mesh using the solution + * stored in the BMVert tags. */ + if (valid_tag_found) { + unsubdivide_build_base_mesh_from_tags(bm); + } + + MEM_freeN(elem_id); + return valid_tag_found; +} + +/** + * Returns the next edge and vertex in the direction of a given edge. + */ +static BMEdge *edge_step(BMVert *v, BMEdge *edge, BMVert **r_next_vertex) +{ + BMIter iter; + BMEdge *test_edge; + if (edge == NULL) { + (*r_next_vertex) = v; + return edge; + } + (*r_next_vertex) = BM_edge_other_vert(edge, v); + BM_ITER_ELEM (test_edge, &iter, (*r_next_vertex), BM_EDGES_OF_VERT) { + if (!BM_edge_share_quad_check(test_edge, edge)) { + return test_edge; + } + } + return NULL; +} + +static BMFace *face_step(BMEdge *edge, BMFace *f) +{ + BMIter iter; + BMFace *face_iter; + + BM_ITER_ELEM (face_iter, &iter, edge, BM_FACES_OF_EDGE) { + if (BM_face_share_edge_check(face_iter, f)) { + return face_iter; + } + } + return f; +} + +/** + * Returns the other edge which belongs to the face f which is different from edge_x and shares + * initial_vertex. + */ +static BMEdge *get_initial_edge_y(BMFace *f, BMEdge *edge_x, BMVert *initial_vertex) +{ + BMIter iter; + BMEdge *test_edge; + BM_ITER_ELEM (test_edge, &iter, f, BM_EDGES_OF_FACE) { + if (edge_x != test_edge) { + if (test_edge->v1 != initial_vertex && test_edge->v2 == initial_vertex) { + return test_edge; + } + if (test_edge->v2 != initial_vertex && test_edge->v1 == initial_vertex) { + return test_edge; + } + } + } + return NULL; +} + +/** + * Writes the current mdisp data into the corresponding area of quad poly giving its corner's loop. + */ +static void write_loop_in_face_grid( + float (*face_grid)[3], MDisps *mdisp, int face_grid_size, int orig_grid_size, int loop) +{ + int origin[2]; + int step_x[2]; + int step_y[2]; + + const int grid_offset = orig_grid_size - 1; + origin[0] = grid_offset; + origin[1] = grid_offset; + + switch (loop) { + case 0: + step_x[0] = -1; + step_x[1] = 0; + + step_y[0] = 0; + step_y[1] = -1; + + break; + case 1: + step_x[0] = 0; + step_x[1] = 1; + + step_y[0] = -1; + step_y[1] = -0; + break; + case 2: + step_x[0] = 1; + step_x[1] = 0; + + step_y[0] = 0; + step_y[1] = 1; + break; + case 3: + step_x[0] = 0; + step_x[1] = -1; + + step_y[0] = 1; + step_y[1] = 0; + break; + default: + BLI_assert(!"Should never happen"); + break; + } + + for (int y = 0; y < orig_grid_size; y++) { + for (int x = 0; x < orig_grid_size; x++) { + const int remap_x = origin[1] + (step_x[1] * x) + (step_y[1] * y); + const int remap_y = origin[0] + (step_x[0] * x) + (step_y[0] * y); + + const int final_index = remap_x + remap_y * face_grid_size; + copy_v3_v3(face_grid[final_index], mdisp->disps[x + y * orig_grid_size]); + } + } +} + +/** + * Writes a buffer containing the 4 grids in the correct orientation of the 4 loops of a face into + * the main #MultiresUnsubdivideGrid that is being extracted. + */ +static void write_face_grid_in_unsubdivide_grid(MultiresUnsubdivideGrid *grid, + float (*face_grid)[3], + int face_grid_size, + int gunsub_x, + int gunsub_y) +{ + const int grid_it = face_grid_size - 1; + for (int y = 0; y < face_grid_size; y++) { + for (int x = 0; x < face_grid_size; x++) { + const int remap_x = (grid_it * gunsub_x) + x; + const int remap_y = (grid_it * gunsub_y) + y; + + const int remap_index_y = grid->grid_size - remap_x - 1; + const int remap_index_x = grid->grid_size - remap_y - 1; + const int grid_index = remap_index_x + (remap_index_y * grid->grid_size); + copy_v3_v3(grid->grid_co[grid_index], face_grid[x + y * face_grid_size]); + } + } +} + +/** + * Stores the data from the mdisps grids of the loops of the face f + * into the new grid for the new base mesh. + * + * Used when there are already grids in the original mesh. + */ +static void store_grid_data(MultiresUnsubdivideContext *context, + MultiresUnsubdivideGrid *grid, + BMVert *v, + BMFace *f, + int grid_x, + int grid_y) +{ + + Mesh *original_mesh = context->original_mesh; + MPoly *poly = &original_mesh->mpoly[BM_elem_index_get(f)]; + + const int corner_vertex_index = BM_elem_index_get(v); + + /* Calculates an offset to write the grids correctly oriented in the main + * #MultiresUnsubdivideGrid. */ + int loop_offset = 0; + for (int i = 0; i < poly->totloop; i++) { + const int loop_index = poly->loopstart + i; + MLoop *l = &original_mesh->mloop[loop_index]; + if (l->v == corner_vertex_index) { + loop_offset = i; + break; + } + } + + /* Write the 4 grids of the current quad with the right orientation into the face_grid buffer. */ + const int grid_size = BKE_ccg_gridsize(context->num_original_levels); + const int face_grid_size = BKE_ccg_gridsize(context->num_original_levels + 1); + const int face_grid_area = face_grid_size * face_grid_size; + float(*face_grid)[3] = MEM_calloc_arrayN(face_grid_area, 3 * sizeof(float), "face_grid"); + + for (int i = 0; i < poly->totloop; i++) { + const int loop_index = poly->loopstart + i; + MDisps *mdisp = &context->original_mdisp[loop_index]; + int quad_loop = i - loop_offset; + if (quad_loop < 0) { + quad_loop += 4; + } + if (quad_loop >= 4) { + quad_loop -= 4; + } + write_loop_in_face_grid(face_grid, mdisp, face_grid_size, grid_size, quad_loop); + } + + /* Write the face_grid buffer in the correct position in the #MultiresUnsubdivideGrids that is + * being extracted. */ + write_face_grid_in_unsubdivide_grid(grid, face_grid, face_grid_size, grid_x, grid_y); + + MEM_freeN(face_grid); +} + +/** + * Stores the data into the new grid from a #BMVert. + * Used when there are no grids in the original mesh. + */ +static void store_vertex_data(MultiresUnsubdivideGrid *grid, BMVert *v, int grid_x, int grid_y) +{ + const int remap_index_y = grid->grid_size - 1 - grid_x; + const int remap_index_x = grid->grid_size - 1 - grid_y; + + const int grid_index = remap_index_x + (remap_index_y * grid->grid_size); + + copy_v3_v3(grid->grid_co[grid_index], v->co); +} + +/** + * Main function to extract data from the original bmesh and MDISPS as grids for the new base mesh. + */ +static void multires_unsubdivide_extract_single_grid_from_face_edge( + MultiresUnsubdivideContext *context, + BMFace *f1, + BMEdge *e1, + bool flip_grid, + MultiresUnsubdivideGrid *grid) +{ + BMVert *initial_vertex; + BMEdge *initial_edge_x; + BMEdge *initial_edge_y; + + const int grid_size = BKE_ccg_gridsize(context->num_new_levels); + const int unsubdiv_grid_size = grid->grid_size = BKE_ccg_gridsize(context->num_total_levels); + grid->grid_size = unsubdiv_grid_size; + grid->grid_co = MEM_calloc_arrayN( + unsubdiv_grid_size * unsubdiv_grid_size, 3 * sizeof(float), "grids coordinates"); + + /* Get the vertex on the corner of the grid. This vertex was tagged previously as it also exist + * on the base mesh. */ + initial_edge_x = e1; + if (BM_elem_flag_test(initial_edge_x->v1, BM_ELEM_TAG)) { + initial_vertex = initial_edge_x->v1; + } + else { + initial_vertex = initial_edge_x->v2; + } + + /* From that vertex, get the edge that defines the grid Y axis for extraction. */ + initial_edge_y = get_initial_edge_y(f1, initial_edge_x, initial_vertex); + + if (flip_grid) { + BMEdge *edge_temp; + edge_temp = initial_edge_x; + initial_edge_x = initial_edge_y; + initial_edge_y = edge_temp; + } + + int grid_x = 0; + int grid_y = 0; + + BMVert *current_vertex_x = initial_vertex; + BMEdge *edge_x = initial_edge_x; + + BMVert *current_vertex_y = initial_vertex; + BMEdge *edge_y = initial_edge_y; + BMEdge *prev_edge_y = initial_edge_y; + + BMFace *current_face = f1; + BMFace *grid_face = f1; + + /* If the data is going to be extracted from the already existing grids, there is no need to go + * to the last vertex of the iteration as that coordinate is also included in the grids + * corresponding to the loop of the face of the previous iteration. */ + int grid_iteration_max_steps = grid_size; + if (context->num_original_levels > 0) { + grid_iteration_max_steps = grid_size - 1; + } + + /* Iterate over the mesh vertices in a grid pattern using the axis defined by the two initial + * edges. */ + while (grid_y < grid_iteration_max_steps) { + + grid_face = current_face; + + while (grid_x < grid_iteration_max_steps) { + if (context->num_original_levels == 0) { + /* If there were no grids on the original mesh, extract the data directly from the + * vertices. */ + store_vertex_data(grid, current_vertex_x, grid_x, grid_y); + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + } + else { + /* If there were grids in the original mesh, extract the data from the grids and iterate + * over the faces. */ + store_grid_data(context, grid, current_vertex_x, grid_face, grid_x, grid_y); + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + grid_face = face_step(edge_x, grid_face); + } + + grid_x++; + } + grid_x = 0; + + edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y); + current_vertex_x = current_vertex_y; + + /* Get the next edge_x to extract the next row of the grid. This needs to be done because there + * may be two edges connected to current_vertex_x that belong to two different grids. */ + BMIter iter; + BMEdge *ed; + BMFace *f; + BM_ITER_ELEM (ed, &iter, current_vertex_x, BM_EDGES_OF_VERT) { + if (ed != prev_edge_y && BM_edge_in_face(ed, current_face)) { + edge_x = ed; + break; + } + } + BM_ITER_ELEM (f, &iter, edge_x, BM_FACES_OF_EDGE) { + if (f != current_face) { + current_face = f; + break; + } + } + + prev_edge_y = edge_y; + grid_y++; + } +} + +/** + * Returns the l+1 and l-1 vertices of the base mesh poly were the grid from the face f1 and edge + * e1 is going to be extracted. + * + * These vertices should always have an corresponding existing vertex on the base mesh. + */ +static void multires_unsubdivide_get_grid_corners_on_base_mesh(BMFace *f1, + BMEdge *e1, + BMVert **r_corner_x, + BMVert **r_corner_y) +{ + BMVert *initial_vertex; + BMEdge *initial_edge_x; + BMEdge *initial_edge_y; + + initial_edge_x = e1; + if (BM_elem_flag_test(initial_edge_x->v1, BM_ELEM_TAG)) { + initial_vertex = initial_edge_x->v1; + } + else { + initial_vertex = initial_edge_x->v2; + } + + /* From that vertex, get the edge that defines the grid Y axis for extraction. */ + initial_edge_y = get_initial_edge_y(f1, initial_edge_x, initial_vertex); + + BMVert *current_vertex_x = initial_vertex; + BMEdge *edge_x = initial_edge_x; + + BMVert *current_vertex_y = initial_vertex; + BMEdge *edge_y = initial_edge_y; + + /* Do an edge step until it finds a tagged vertex, which is part of the base mesh. */ + /* x axis */ + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + while (!BM_elem_flag_test(current_vertex_x, BM_ELEM_TAG)) { + edge_x = edge_step(current_vertex_x, edge_x, ¤t_vertex_x); + } + (*r_corner_x) = current_vertex_x; + + /* Same for y axis */ + edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y); + while (!BM_elem_flag_test(current_vertex_y, BM_ELEM_TAG)) { + edge_y = edge_step(current_vertex_y, edge_y, ¤t_vertex_y); + } + (*r_corner_y) = current_vertex_y; +} + +static BMesh *get_bmesh_from_mesh(Mesh *mesh) +{ + const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(mesh); + BMesh *bm = BM_mesh_create(&allocsize, + &((struct BMeshCreateParams){ + .use_toolflags = true, + })); + + BM_mesh_bm_from_me(bm, + mesh, + (&(struct BMeshFromMeshParams){ + .calc_face_normal = true, + })); + + return bm; +} + +/* Data-layer names to store the original indices of the elements before modifying the mesh. */ +static const char lname[] = "l_remap_index"; +static const char vname[] = "v_remap_index"; + +static void multires_unsubdivide_free_original_datalayers(Mesh *mesh) +{ + const int l_layer_index = CustomData_get_named_layer_index(&mesh->ldata, CD_PROP_INT, lname); + if (l_layer_index != -1) { + CustomData_free_layer(&mesh->ldata, CD_PROP_INT, mesh->totloop, l_layer_index); + } + + const int v_layer_index = CustomData_get_named_layer_index(&mesh->vdata, CD_PROP_INT, vname); + if (v_layer_index != -1) { + CustomData_free_layer(&mesh->vdata, CD_PROP_INT, mesh->totvert, v_layer_index); + } +} + +/** + * Generates two data-layers to map loops and vertices from base mesh to original mesh after + * dissolving the vertices. + */ +static void multires_unsubdivide_add_original_index_datalayers(Mesh *mesh) +{ + multires_unsubdivide_free_original_datalayers(mesh); + + int *l_index = CustomData_add_layer_named( + &mesh->ldata, CD_PROP_INT, CD_CALLOC, NULL, mesh->totloop, lname); + + int *v_index = CustomData_add_layer_named( + &mesh->vdata, CD_PROP_INT, CD_CALLOC, NULL, mesh->totvert, vname); + + /* Initialize these data-layer with the indices in the current mesh. */ + for (int i = 0; i < mesh->totloop; i++) { + l_index[i] = i; + } + for (int i = 0; i < mesh->totvert; i++) { + v_index[i] = i; + } +} + +static void multires_unsubdivide_prepare_original_bmesh_for_extract( + MultiresUnsubdivideContext *context) +{ + + Mesh *original_mesh = context->original_mesh; + Mesh *base_mesh = context->base_mesh; + + BMesh *bm_original_mesh = context->bm_original_mesh = get_bmesh_from_mesh(original_mesh); + + /* Initialize the elem tables. */ + BM_mesh_elem_table_ensure(bm_original_mesh, BM_EDGE); + BM_mesh_elem_table_ensure(bm_original_mesh, BM_FACE); + BM_mesh_elem_table_ensure(bm_original_mesh, BM_VERT); + + /* Disable all flags. */ + BM_mesh_elem_hflag_disable_all( + bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false); + BM_mesh_elem_hflag_disable_all( + bm_original_mesh, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_SELECT, false); + + /* Get the mapping data-layer. */ + context->base_to_orig_vmap = CustomData_get_layer_named(&base_mesh->vdata, CD_PROP_INT, vname); + + /* Tag the base mesh vertices in the original mesh. */ + for (int i = 0; i < base_mesh->totvert; i++) { + int vert_basemesh_index = context->base_to_orig_vmap[i]; + BMVert *v = BM_vert_at_index(bm_original_mesh, vert_basemesh_index); + BM_elem_flag_set(v, BM_ELEM_TAG, true); + } + + /* Create a map from loop index to poly index for the original mesh. */ + context->loop_to_face_map = MEM_calloc_arrayN(sizeof(int), original_mesh->totloop, "loop map"); + + for (int i = 0; i < original_mesh->totpoly; i++) { + MPoly *poly = &original_mesh->mpoly[i]; + for (int l = 0; l < poly->totloop; l++) { + int original_loop_index = l + poly->loopstart; + context->loop_to_face_map[original_loop_index] = i; + } + } +} + +/** + * Checks the orientation of the loops to flip the x and y axis when extracting the grid if + * necessary. + */ +static bool multires_unsubdivide_flip_grid_x_axis(Mesh *mesh, int poly, int loop, int v_x) +{ + MPoly *p = &mesh->mpoly[poly]; + + MLoop *l_first = &mesh->mloop[p->loopstart]; + if ((loop == (p->loopstart + (p->totloop - 1))) && l_first->v == v_x) { + return true; + } + + int next_l_index = loop + 1; + if (next_l_index < p->loopstart + p->totloop) { + MLoop *l_next = &mesh->mloop[next_l_index]; + if (l_next->v == v_x) { + return true; + } + } + + return false; +} + +static void multires_unsubdivide_extract_grids(MultiresUnsubdivideContext *context) +{ + Mesh *original_mesh = context->original_mesh; + Mesh *base_mesh = context->base_mesh; + + BMesh *bm_original_mesh = context->bm_original_mesh; + + context->num_grids = base_mesh->totloop; + context->base_mesh_grids = MEM_calloc_arrayN( + sizeof(MultiresUnsubdivideGrid), base_mesh->totloop, "grids"); + + /* Based on the existing indices in the data-layers, generate two vertex indices maps. */ + /* From vertex index in original to vertex index in base and from vertex index in base to vertex + * index in original. */ + int *orig_to_base_vmap = MEM_calloc_arrayN(sizeof(int), bm_original_mesh->totvert, "orig vmap"); + int *base_to_orig_vmap = MEM_calloc_arrayN(sizeof(int), base_mesh->totvert, "base vmap"); + + context->base_to_orig_vmap = CustomData_get_layer_named(&base_mesh->vdata, CD_PROP_INT, vname); + for (int i = 0; i < base_mesh->totvert; i++) { + base_to_orig_vmap[i] = context->base_to_orig_vmap[i]; + } + + /* If an index in original does not exist in base (it was dissolved when creating the new base + * mesh, return -1. */ + for (int i = 0; i < original_mesh->totvert; i++) { + orig_to_base_vmap[i] = -1; + } + + for (int i = 0; i < base_mesh->totvert; i++) { + const int orig_vertex_index = context->base_to_orig_vmap[i]; + orig_to_base_vmap[orig_vertex_index] = i; + } + + /* Add the original data-layers to the base mesh to have the loop indices stored in a data-layer, + * so they can be used from #BMesh. */ + multires_unsubdivide_add_original_index_datalayers(base_mesh); + + const int base_l_layer_index = CustomData_get_named_layer_index( + &base_mesh->ldata, CD_PROP_INT, lname); + BMesh *bm_base_mesh = get_bmesh_from_mesh(base_mesh); + BMIter iter, iter_a, iter_b; + BMVert *v; + BMLoop *l, *lb; + + BM_mesh_elem_table_ensure(bm_base_mesh, BM_VERT); + BM_mesh_elem_table_ensure(bm_base_mesh, BM_FACE); + + /* Get the data-layer that contains the loops indices. */ + const int base_l_offset = CustomData_get_n_offset( + &bm_base_mesh->ldata, CD_PROP_INT, base_l_layer_index); + + /* Main loop for extracting the grids. Iterates over the base mesh vertices. */ + BM_ITER_MESH (v, &iter, bm_base_mesh, BM_VERTS_OF_MESH) { + + /* For each base mesh vertex, get the corresponding #BMVert of the original mesh using the + * vertex map. */ + const int orig_vertex_index = base_to_orig_vmap[BM_elem_index_get(v)]; + BMVert *vert_original = BM_vert_at_index(bm_original_mesh, orig_vertex_index); + + /* Iterate over the loops of that vertex in the original mesh. */ + BM_ITER_ELEM (l, &iter_a, vert_original, BM_LOOPS_OF_VERT) { + /* For each loop, get the two vertices that should map to the l+1 and l-1 vertices in the + * base mesh of the poly of grid that is going to be extracted. */ + BMVert *corner_x, *corner_y; + multires_unsubdivide_get_grid_corners_on_base_mesh(l->f, l->e, &corner_x, &corner_y); + + /* Map the two obtained vertices to the base mesh. */ + const int corner_x_index = orig_to_base_vmap[BM_elem_index_get(corner_x)]; + const int corner_y_index = orig_to_base_vmap[BM_elem_index_get(corner_y)]; + + /* Iterate over the loops of the same vertex in the base mesh. With the previously obtained + * vertices and the current vertex it is possible to get the index of the loop in the base + * mesh the grid that is going to be extracted belongs to. */ + BM_ITER_ELEM (lb, &iter_b, v, BM_LOOPS_OF_VERT) { + BMFace *base_face = lb->f; + BMVert *base_corner_x = BM_vert_at_index(bm_base_mesh, corner_x_index); + BMVert *base_corner_y = BM_vert_at_index(bm_base_mesh, corner_y_index); + /* If this is the correct loop in the base mesh, the original vertex and the two corners + * should be in the loop's face. */ + if (BM_vert_in_face(base_corner_x, base_face) && + BM_vert_in_face(base_corner_y, base_face)) { + /* Get the index of the loop. */ + const int base_mesh_loop_index = BM_ELEM_CD_GET_INT(lb, base_l_offset); + const int base_mesh_face_index = BM_elem_index_get(base_face); + + /* Check the orientation of the loops in case that is needed to flip the x and y axis + * when extracting the grid. */ + const bool flip_grid = multires_unsubdivide_flip_grid_x_axis( + base_mesh, base_mesh_face_index, base_mesh_loop_index, corner_x_index); + + /* Extract the grid for that loop. */ + context->base_mesh_grids[base_mesh_loop_index].grid_index = base_mesh_loop_index; + multires_unsubdivide_extract_single_grid_from_face_edge( + context, l->f, l->e, !flip_grid, &context->base_mesh_grids[base_mesh_loop_index]); + + break; + } + } + } + } + + MEM_freeN(orig_to_base_vmap); + MEM_freeN(base_to_orig_vmap); + + BM_mesh_free(bm_base_mesh); + multires_unsubdivide_free_original_datalayers(base_mesh); +} + +static void multires_unsubdivide_private_extract_data_free(MultiresUnsubdivideContext *context) +{ + if (context->bm_original_mesh != NULL) { + BM_mesh_free(context->bm_original_mesh); + } + MEM_SAFE_FREE(context->loop_to_face_map); +} + +void multires_unsubdivide_context_init(MultiresUnsubdivideContext *context, + Mesh *original_mesh, + struct MultiresModifierData *mmd) +{ + context->original_mesh = original_mesh; + context->num_new_levels = 0; + context->num_total_levels = 0; + context->num_original_levels = mmd->totlvl; +} + +bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context) +{ + Mesh *original_mesh = context->original_mesh; + + /* Prepare the data-layers to map base to original. */ + multires_unsubdivide_add_original_index_datalayers(original_mesh); + BMesh *bm_base_mesh = get_bmesh_from_mesh(original_mesh); + + /* Un-subdivide as many iterations as possible. */ + context->num_new_levels = 0; + int num_levels_left = context->max_new_levels; + while (num_levels_left > 0 && multires_unsubdivide_single_level(bm_base_mesh)) { + context->num_new_levels++; + num_levels_left--; + } + + /* If no un-subdivide steps were possible, free the bmesh, the map data-layers and stop. */ + if (context->num_new_levels == 0) { + multires_unsubdivide_free_original_datalayers(original_mesh); + BM_mesh_free(bm_base_mesh); + return false; + } + + /* Calculate the final levels for the new grids over base mesh. */ + context->num_total_levels = context->num_new_levels + context->num_original_levels; + + /* Store the new base-mesh as a mesh in context, free bmesh. */ + context->base_mesh = BKE_mesh_new_nomain(0, 0, 0, 0, 0); + BM_mesh_bm_to_me(NULL, + bm_base_mesh, + context->base_mesh, + (&(struct BMeshToMeshParams){ + .calc_object_remap = true, + })); + BM_mesh_free(bm_base_mesh); + + /* Initialize bmesh and maps for the original mesh and extract the grids. */ + + multires_unsubdivide_prepare_original_bmesh_for_extract(context); + multires_unsubdivide_extract_grids(context); + + return true; +} + +void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context) +{ + multires_unsubdivide_private_extract_data_free(context); + for (int i = 0; i < context->num_grids; i++) { + if (context->base_mesh_grids[i].grid_size > 0) { + MEM_SAFE_FREE(context->base_mesh_grids[i].grid_co); + } + } + MEM_SAFE_FREE(context->base_mesh_grids); +} + +/** + * This function allocates new mdisps with the right size to fit the new extracted grids from the + * base mesh and copies the data to them. + */ +static void multires_create_grids_in_unsubdivided_base_mesh(MultiresUnsubdivideContext *context, + Mesh *base_mesh) +{ + /* Free the current MDISPS and create a new ones. */ + if (CustomData_has_layer(&base_mesh->ldata, CD_MDISPS)) { + CustomData_free_layers(&base_mesh->ldata, CD_MDISPS, base_mesh->totloop); + } + MDisps *mdisps = CustomData_add_layer( + &base_mesh->ldata, CD_MDISPS, CD_CALLOC, NULL, base_mesh->totloop); + + const int totdisp = pow_i(BKE_ccg_gridsize(context->num_total_levels), 2); + const int totloop = base_mesh->totloop; + + BLI_assert(base_mesh->totloop == context->num_grids); + + /* Allocate the MDISPS grids and copy the extracted data from context. */ + for (int i = 0; i < totloop; i++) { + float(*disps)[3] = MEM_calloc_arrayN(totdisp, 3 * sizeof(float), "multires disps"); + + if (mdisps[i].disps) { + MEM_freeN(mdisps[i].disps); + } + + for (int j = 0; j < totdisp; j++) { + if (context->base_mesh_grids[i].grid_co) { + copy_v3_v3(disps[j], context->base_mesh_grids[i].grid_co[j]); + } + } + + mdisps[i].disps = disps; + mdisps[i].totdisp = totdisp; + mdisps[i].level = context->num_total_levels; + } +} + +int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, + struct Object *object, + struct MultiresModifierData *mmd, + int rebuild_limit, + bool switch_view_to_lower_level) +{ + Mesh *mesh = object->data; + + multires_force_sculpt_rebuild(object); + + MultiresUnsubdivideContext unsubdiv_context = {0}; + MultiresReshapeContext reshape_context = {0}; + + multires_unsubdivide_context_init(&unsubdiv_context, mesh, mmd); + + /* Convert and store the existing grids in object space if available. */ + if (mmd->totlvl != 0) { + if (!multires_reshape_context_create_from_object(&reshape_context, depsgraph, object, mmd)) { + return 0; + } + + multires_reshape_store_original_grids(&reshape_context); + multires_reshape_assign_final_coords_from_mdisps(&reshape_context); + unsubdiv_context.original_mdisp = reshape_context.mdisps; + } + + /* Set the limit for the levels that should be rebuild. */ + unsubdiv_context.max_new_levels = rebuild_limit; + + /* Un-subdivide and create the data for the new grids. */ + if (multires_unsubdivide_to_basemesh(&unsubdiv_context) == 0) { + /* If there was no possible to rebuild any level, free the data and return. */ + if (mmd->totlvl != 0) { + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_unsubdivide_context_free(&unsubdiv_context); + } + multires_reshape_context_free(&reshape_context); + return 0; + } + + /* Free the reshape context used to convert the data from the original grids to object space. */ + if (mmd->totlvl != 0) { + multires_reshape_context_free(&reshape_context); + } + + /* Copy the new base mesh to the original mesh. */ + BKE_mesh_nomain_to_mesh(unsubdiv_context.base_mesh, object->data, object, &CD_MASK_MESH, true); + Mesh *base_mesh = object->data; + multires_create_grids_in_unsubdivided_base_mesh(&unsubdiv_context, base_mesh); + + /* Update the levels in the modifier. Force always to display at level 0 as it contains the new + * created level. */ + mmd->totlvl = (char)unsubdiv_context.num_total_levels; + + if (switch_view_to_lower_level) { + mmd->sculptlvl = 0; + mmd->lvl = 0; + } + else { + mmd->sculptlvl = (char)(mmd->sculptlvl + unsubdiv_context.num_new_levels); + mmd->lvl = (char)(mmd->lvl + unsubdiv_context.num_new_levels); + } + + mmd->renderlvl = (char)(mmd->renderlvl + unsubdiv_context.num_new_levels); + + /* Create a reshape context to convert the MDISPS data to tangent displacement. It can be the + * same as the previous one as a new Subdivision needs to be created for the new base mesh. */ + if (!multires_reshape_context_create_from_base_mesh(&reshape_context, depsgraph, object, mmd)) { + return 0; + } + multires_reshape_object_grids_to_tangent_displacement(&reshape_context); + multires_reshape_context_free(&reshape_context); + + /* Free the un-subdivide context and return the total number of levels that were rebuild. */ + const int rebuild_subdvis = unsubdiv_context.num_new_levels; + multires_unsubdivide_context_free(&unsubdiv_context); + + return rebuild_subdvis; +} diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.h b/source/blender/blenkernel/intern/multires_unsubdivide.h new file mode 100644 index 00000000000..e00a1ae6d8b --- /dev/null +++ b/source/blender/blenkernel/intern/multires_unsubdivide.h @@ -0,0 +1,94 @@ +/* + * 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) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup bke + */ + +#ifndef __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ +#define __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ + +#include "BLI_sys_types.h" + +struct BMesh; +struct Depsgraph; +struct Mesh; +struct MultiresModifierData; +struct Object; + +typedef struct MultiresUnsubdivideGrid { + /* For sanity checks. */ + int grid_index; + int grid_size; + + /** Grid coordinates in object space. */ + float (*grid_co)[3]; + +} MultiresUnsubdivideGrid; + +typedef struct MultiresUnsubdivideContext { + /* Input Mesh to un-subdivide. */ + struct Mesh *original_mesh; + struct MDisps *original_mdisp; + + /** Number of subdivision in the grids of the input mesh. */ + int num_original_levels; + + /** Level 0 base mesh after applying the maximum amount of unsubdivisions. */ + struct Mesh *base_mesh; + + /** Limit on how many levels down the unsubdivide operation should create, if possible. */ + int max_new_levels; + + /** New levels that were created after unsubdividing. */ + int num_new_levels; + + /** + * Number of subdivisions that should be applied to the base mesh. + * (num_new_levels + num_original_levels). + */ + int num_total_levels; + + /** Data for the new grids, indexed by base mesh loop index. */ + int num_grids; + struct MultiresUnsubdivideGrid *base_mesh_grids; + + /* Private data. */ + struct BMesh *bm_original_mesh; + int *loop_to_face_map; + int *base_to_orig_vmap; +} MultiresUnsubdivideContext; + +/* -------------------------------------------------------------------- + * Construct/destruct reshape context. + */ + +void multires_unsubdivide_context_init(MultiresUnsubdivideContext *context, + struct Mesh *original_mesh, + struct MultiresModifierData *mmd); +void multires_unsubdivide_context_free(MultiresUnsubdivideContext *context); + +/* -------------------------------------------------------------------- + * Rebuild Lower Subdivisions. + */ + +/* Rebuilds all subdivision to the level 0 base mesh. */ +bool multires_unsubdivide_to_basemesh(MultiresUnsubdivideContext *context); + +#endif /* __BKE_INTERN_MULTIRES_UNSUBDIVIDE_H__ */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 5ae44247e13..48c6727add5 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -32,11 +32,13 @@ #include "DNA_action_types.h" #include "DNA_anim_types.h" +#include "DNA_gpencil_types.h" #include "DNA_light_types.h" #include "DNA_linestyle_types.h" #include "DNA_material_types.h" #include "DNA_node_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" @@ -56,6 +58,7 @@ #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_node.h" @@ -66,7 +69,9 @@ #include "NOD_common.h" #include "NOD_composite.h" +#include "NOD_function.h" #include "NOD_shader.h" +#include "NOD_simulation.h" #include "NOD_socket.h" #include "NOD_texture.h" @@ -86,7 +91,9 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo); static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, const int flag); static void free_localized_node_groups(bNodeTree *ntree); static void node_free_node(bNodeTree *ntree, bNode *node); -static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock); +static void node_socket_interface_free(bNodeTree *UNUSED(ntree), + bNodeSocket *sock, + const bool do_id_user); static void ntree_init_data(ID *id) { @@ -229,12 +236,12 @@ static void ntree_free_data(ID *id) /* free interface sockets */ for (sock = ntree->inputs.first; sock; sock = nextsock) { nextsock = sock->next; - node_socket_interface_free(ntree, sock); + node_socket_interface_free(ntree, sock, false); MEM_freeN(sock); } for (sock = ntree->outputs.first; sock; sock = nextsock) { nextsock = sock->next; - node_socket_interface_free(ntree, sock); + node_socket_interface_free(ntree, sock, false); MEM_freeN(sock); } @@ -248,6 +255,66 @@ static void ntree_free_data(ID *id) } } +static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock) +{ + IDP_foreach_property( + sock->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + BKE_LIB_FOREACHID_PROCESS(data, default_value->value, IDWALK_CB_USER); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + +static void node_foreach_id(ID *id, LibraryForeachIDData *data) +{ + bNodeTree *ntree = (bNodeTree *)id; + + BKE_LIB_FOREACHID_PROCESS(data, ntree->gpd, IDWALK_CB_USER); + + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER); + + IDP_foreach_property( + node->prop, IDP_TYPE_FILTER_ID, BKE_lib_query_idpropertiesForeachIDLink_callback, data); + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + library_foreach_node_socket(data, sock); + } + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + library_foreach_node_socket(data, sock); + } + } + + LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { + library_foreach_node_socket(data, sock); + } + LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { + library_foreach_node_socket(data, sock); + } +} + IDTypeInfo IDType_ID_NT = { .id_code = ID_NT, .id_filter = FILTER_ID_NT, @@ -262,6 +329,7 @@ IDTypeInfo IDType_ID_NT = { .copy_data = ntree_copy_data, .free_data = ntree_free_data, .make_local = NULL, + .foreach_id = node_foreach_id, }; static void node_add_sockets_from_type(bNodeTree *ntree, bNode *node, bNodeType *ntype) @@ -744,6 +812,66 @@ static bNodeSocket *make_socket(bNodeTree *ntree, return sock; } +static void socket_id_user_increment(bNodeSocket *sock) +{ + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + id_us_plus(&default_value->value->id); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + id_us_plus(&default_value->value->id); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + +static void socket_id_user_decrement(bNodeSocket *sock) +{ + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + id_us_min(&default_value->value->id); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + id_us_min(&default_value->value->id); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + void nodeModifySocketType( bNodeTree *ntree, bNode *UNUSED(node), bNodeSocket *sock, int type, int subtype) { @@ -755,6 +883,7 @@ void nodeModifySocketType( } if (sock->default_value) { + socket_id_user_decrement(sock); MEM_freeN(sock->default_value); sock->default_value = NULL; } @@ -862,6 +991,18 @@ const char *nodeStaticSocketType(int type, int subtype) return "NodeSocketString"; case SOCK_SHADER: return "NodeSocketShader"; + case SOCK_OBJECT: + return "NodeSocketObject"; + case SOCK_IMAGE: + return "NodeSocketImage"; + case SOCK_EMITTERS: + return "NodeSocketEmitters"; + case SOCK_EVENTS: + return "NodeSocketEvents"; + case SOCK_FORCES: + return "NodeSocketForces"; + case SOCK_CONTROL_FLOW: + return "NodeSocketControlFlow"; } return NULL; } @@ -923,6 +1064,18 @@ const char *nodeStaticSocketInterfaceType(int type, int subtype) return "NodeSocketInterfaceString"; case SOCK_SHADER: return "NodeSocketInterfaceShader"; + case SOCK_OBJECT: + return "NodeSocketInterfaceObject"; + case SOCK_IMAGE: + return "NodeSocketInterfaceImage"; + case SOCK_EMITTERS: + return "NodeSocketInterfaceEmitters"; + case SOCK_EVENTS: + return "NodeSocketInterfaceEvents"; + case SOCK_FORCES: + return "NodeSocketInterfaceForces"; + case SOCK_CONTROL_FLOW: + return "NodeSocketInterfaceControlFlow"; } return NULL; } @@ -981,6 +1134,9 @@ static void node_socket_free(bNodeTree *UNUSED(ntree), } if (sock->default_value) { + if (do_id_user) { + socket_id_user_decrement(sock); + } MEM_freeN(sock->default_value); } } @@ -1267,6 +1423,10 @@ static void node_socket_copy(bNodeSocket *sock_dst, const bNodeSocket *sock_src, if (sock_src->default_value) { sock_dst->default_value = MEM_dupallocN(sock_src->default_value); + + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + socket_id_user_increment(sock_dst); + } } sock_dst->stack_index = 0; @@ -2087,6 +2247,13 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) if (node->id) { id_us_min(node->id); } + + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + socket_id_user_decrement(sock); + } + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + socket_id_user_decrement(sock); + } } /* Remove animation data. */ @@ -2106,13 +2273,18 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, bool do_id_user) node_free_node(ntree, node); } -static void node_socket_interface_free(bNodeTree *UNUSED(ntree), bNodeSocket *sock) +static void node_socket_interface_free(bNodeTree *UNUSED(ntree), + bNodeSocket *sock, + const bool do_id_user) { if (sock->prop) { - IDP_FreeProperty(sock->prop); + IDP_FreeProperty_ex(sock->prop, do_id_user); } if (sock->default_value) { + if (do_id_user) { + socket_id_user_decrement(sock); + } MEM_freeN(sock->default_value); } } @@ -2147,7 +2319,7 @@ void ntreeFreeTree(bNodeTree *ntree) BKE_animdata_free(&ntree->id, false); } -void ntreeFreeNestedTree(bNodeTree *ntree) +void ntreeFreeEmbeddedTree(bNodeTree *ntree) { ntreeFreeTree(ntree); BKE_libblock_free_data(&ntree->id, true); @@ -2270,6 +2442,8 @@ bNodeTree **BKE_ntree_ptr_from_id(ID *id) return &((Scene *)id)->nodetree; case ID_LS: return &((FreestyleLineStyle *)id)->nodetree; + case ID_SIM: + return &((Simulation *)id)->nodetree; default: return NULL; } @@ -2533,7 +2707,7 @@ void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock) BLI_remlink(&ntree->inputs, sock); BLI_remlink(&ntree->outputs, sock); - node_socket_interface_free(ntree, sock); + node_socket_interface_free(ntree, sock, true); MEM_freeN(sock); ntree->update |= NTREE_UPDATE_GROUP; @@ -4118,6 +4292,33 @@ static void registerTextureNodes(void) register_node_type_tex_proc_distnoise(); } +static void registerSimulationNodes(void) +{ + register_node_type_sim_group(); + + register_node_type_sim_particle_simulation(); + register_node_type_sim_force(); + register_node_type_sim_set_particle_attribute(); + register_node_type_sim_particle_birth_event(); + register_node_type_sim_particle_time_step_event(); + register_node_type_sim_execute_condition(); + register_node_type_sim_multi_execute(); + register_node_type_sim_particle_mesh_emitter(); + register_node_type_sim_particle_mesh_collision_event(); + register_node_type_sim_emit_particles(); + register_node_type_sim_time(); + register_node_type_sim_particle_attribute(); +} + +static void registerFunctionNodes(void) +{ + register_node_type_fn_boolean_math(); + register_node_type_fn_float_compare(); + register_node_type_fn_switch(); + register_node_type_fn_group_instance_id(); + register_node_type_fn_combine_strings(); +} + void init_nodesystem(void) { nodetreetypes_hash = BLI_ghash_str_new("nodetreetypes_hash gh"); @@ -4131,6 +4332,7 @@ void init_nodesystem(void) register_node_tree_type_cmp(); register_node_tree_type_sh(); register_node_tree_type_tex(); + register_node_tree_type_sim(); register_node_type_frame(); register_node_type_reroute(); @@ -4140,6 +4342,8 @@ void init_nodesystem(void) registerCompositNodes(); registerShaderNodes(); registerTextureNodes(); + registerSimulationNodes(); + registerFunctionNodes(); } void free_nodesystem(void) @@ -4196,6 +4400,7 @@ void BKE_node_tree_iter_init(struct NodeTreeIterStore *ntreeiter, struct Main *b ntreeiter->light = bmain->lights.first; ntreeiter->world = bmain->worlds.first; ntreeiter->linestyle = bmain->linestyles.first; + ntreeiter->simulation = bmain->simulations.first; } bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, bNodeTree **r_nodetree, @@ -4236,6 +4441,11 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, *r_id = (ID *)ntreeiter->linestyle; ntreeiter->linestyle = ntreeiter->linestyle->id.next; } + else if (ntreeiter->simulation) { + *r_nodetree = ntreeiter->simulation->nodetree; + *r_id = (ID *)ntreeiter->simulation; + ntreeiter->simulation = ntreeiter->simulation->id.next; + } else { return false; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index de34b0cba69..6bd841ca8e5 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -83,6 +83,7 @@ #include "BKE_editmesh.h" #include "BKE_effect.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -205,9 +206,9 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in BLI_listbase_clear(&ob_dst->modifiers); LISTBASE_FOREACH (ModifierData *, md, &ob_src->modifiers) { - ModifierData *nmd = modifier_new(md->type); + ModifierData *nmd = BKE_modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); - modifier_copyData_ex(md, nmd, flag_subdata); + BKE_modifier_copydata_ex(md, nmd, flag_subdata); BLI_addtail(&ob_dst->modifiers, nmd); } @@ -216,7 +217,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in LISTBASE_FOREACH (GpencilModifierData *, gmd, &ob_src->greasepencil_modifiers) { GpencilModifierData *nmd = BKE_gpencil_modifier_new(gmd->type); BLI_strncpy(nmd->name, gmd->name, sizeof(nmd->name)); - BKE_gpencil_modifier_copyData_ex(gmd, nmd, flag_subdata); + BKE_gpencil_modifier_copydata_ex(gmd, nmd, flag_subdata); BLI_addtail(&ob_dst->greasepencil_modifiers, nmd); } @@ -225,7 +226,7 @@ static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const in LISTBASE_FOREACH (ShaderFxData *, fx, &ob_src->shader_fx) { ShaderFxData *nfx = BKE_shaderfx_new(fx->type); BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); - BKE_shaderfx_copyData_ex(fx, nfx, flag_subdata); + BKE_shaderfx_copydata_ex(fx, nfx, flag_subdata); BLI_addtail(&ob_dst->shader_fx, nfx); } @@ -433,7 +434,7 @@ void BKE_object_free_modifiers(Object *ob, const int flag) GpencilModifierData *gp_md; while ((md = BLI_pophead(&ob->modifiers))) { - modifier_free_ex(md, flag); + BKE_modifier_free_ex(md, flag); } while ((gp_md = BLI_pophead(&ob->greasepencil_modifiers))) { @@ -509,23 +510,33 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type) { const ModifierTypeInfo *mti; - mti = modifierType_getInfo(modifier_type); + mti = BKE_modifier_get_info(modifier_type); - /* only geometry objects should be able to get modifiers [#25291] */ - if (!ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { - return false; + /* Only geometry objects should be able to get modifiers [#25291] */ + if (ob->type == OB_HAIR) { + return (mti->modifyHair != NULL) || (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly); } - - if (ob->type == OB_LATTICE && (mti->flags & eModifierTypeFlag_AcceptsLattice) == 0) { - return false; + else if (ob->type == OB_POINTCLOUD) { + return (mti->modifyPointCloud != NULL) || + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly); + } + else if (ob->type == OB_VOLUME) { + return (mti->modifyVolume != NULL); } + else if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { + if (ob->type == OB_LATTICE && (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly) == 0) { + return false; + } - if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) || - (ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh)))) { - return false; + if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) || + (ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh)))) { + return false; + } + + return true; } - return true; + return false; } void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src) @@ -561,7 +572,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr break; } - nmd = modifier_new(md->type); + nmd = BKE_modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); if (md->type == eModifierType_Multires) { @@ -570,9 +581,9 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd); } - modifier_copyData(md, nmd); + BKE_modifier_copydata(md, nmd); BLI_addtail(&ob_dst->modifiers, nmd); - modifier_unique_name(&ob_dst->modifiers, nmd); + BKE_modifier_unique_name(&ob_dst->modifiers, nmd); } } @@ -584,7 +595,7 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr nmd = BKE_gpencil_modifier_new(md->type); BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); mti->copyData(md, nmd); BLI_addtail(&ob_dst->greasepencil_modifiers, nmd); @@ -1297,8 +1308,8 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f psys_copy_particles(psysn, psys); if (psys->clmd) { - psysn->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); - modifier_copyData_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag); + psysn->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth); + BKE_modifier_copydata_ex((ModifierData *)psys->clmd, (ModifierData *)psysn->clmd, flag); psys->hair_in_mesh = psys->hair_out_mesh = NULL; } @@ -1451,7 +1462,7 @@ Object *BKE_object_pose_armature_get(Object *ob) return ob; } - ob = modifiers_isDeformedByArmature(ob); + ob = BKE_modifiers_is_deformed_by_armature(ob); /* Only use selected check when non-active. */ if (BKE_object_pose_context_check(ob)) { @@ -2692,7 +2703,7 @@ void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *o { /* Execute drivers and animation. */ const bool flush_to_original = DEG_is_active(depsgraph); - BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, ctime, ADT_RECALC_ALL, flush_to_original); object_where_is_calc_ex(depsgraph, scene, ob, ctime, NULL, NULL); } @@ -3885,16 +3896,16 @@ int BKE_object_is_modified(Scene *scene, Object *ob) ModifierData *md; VirtualModifierData virtualModifierData; /* cloth */ - for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { if ((flag & eModifierMode_Render) == 0 && - modifier_isEnabled(scene, md, eModifierMode_Render)) { + BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) { flag |= eModifierMode_Render; } if ((flag & eModifierMode_Realtime) == 0 && - modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { flag |= eModifierMode_Realtime; } } @@ -4023,10 +4034,10 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) } /* cloth */ - for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md && (flag != (eModifierMode_Render | eModifierMode_Realtime)); md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); bool can_deform = mti->type == eModifierTypeType_OnlyDeform || is_modifier_animated; if (!can_deform) { @@ -4034,12 +4045,13 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) } if (can_deform) { - if (!(flag & eModifierMode_Render) && modifier_isEnabled(scene, md, eModifierMode_Render)) { + if (!(flag & eModifierMode_Render) && + BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) { flag |= eModifierMode_Render; } if (!(flag & eModifierMode_Realtime) && - modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { flag |= eModifierMode_Realtime; } } @@ -4374,7 +4386,7 @@ KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot) bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) { - if (modifier_dependsOnTime(md)) { + if (BKE_modifier_depends_ontime(md)) { return true; } @@ -4417,7 +4429,7 @@ bool BKE_object_modifier_use_time(Object *ob, ModifierData *md) bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md) { - if (BKE_gpencil_modifier_dependsOnTime(md)) { + if (BKE_gpencil_modifier_depends_ontime(md)) { return true; } @@ -4452,7 +4464,7 @@ bool BKE_object_modifier_gpencil_use_time(Object *ob, GpencilModifierData *md) bool BKE_object_shaderfx_use_time(Object *ob, ShaderFxData *fx) { - if (BKE_shaderfx_dependsOnTime(fx)) { + if (BKE_shaderfx_depends_ontime(fx)) { return true; } @@ -4518,7 +4530,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, int type) { const bool flush_to_original = DEG_is_active(depsgraph); - ModifierData *md = modifiers_findByType(ob, (ModifierType)type); + ModifierData *md = BKE_modifiers_findby_type(ob, (ModifierType)type); bConstraint *con; if (type == eModifierType_DynamicPaint) { @@ -4582,8 +4594,7 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* TODO(sergey): What about animation? */ ob->id.recalc |= ID_RECALC_ALL; if (update_mesh) { - BKE_animsys_evaluate_animdata( - scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&ob->id, ob->adt, frame, ADT_RECALC_ANIM, flush_to_original); /* ignore cache clear during subframe updates * to not mess up cache validity */ object_cacheIgnoreClear(ob, 1); @@ -4597,14 +4608,12 @@ bool BKE_object_modifier_update_subframe(Depsgraph *depsgraph, /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { Curve *cu = ob->data; - BKE_animsys_evaluate_animdata( - scene, &cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&cu->id, cu->adt, frame, ADT_RECALC_ANIM, flush_to_original); } /* and armatures... */ if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; - BKE_animsys_evaluate_animdata( - scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); + BKE_animsys_evaluate_animdata(&arm->id, arm->adt, frame, ADT_RECALC_ANIM, flush_to_original); BKE_pose_where_is(depsgraph, scene, ob); } diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index a75180867cb..6ca1442497a 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -620,7 +620,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int 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, &virtualModifierData) : + BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData) : md->next) { if (!(md->mode & (eModifierMode_Realtime | eModifierMode_Virtual))) { continue; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 2683d384bc7..8957628c76a 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -453,21 +453,17 @@ static void ocean_compute_htilda(void *__restrict userdata, } } -static void ocean_compute_displacement_y(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_displacement_y(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; fftw_execute(o->_disp_y_plan); } -static void ocean_compute_displacement_x(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_displacement_x(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float scale = osd->scale; const float chop_amount = osd->chop_amount; @@ -494,11 +490,9 @@ static void ocean_compute_displacement_x(TaskPool *__restrict pool, fftw_execute(o->_disp_x_plan); } -static void ocean_compute_displacement_z(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_displacement_z(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float scale = osd->scale; const float chop_amount = osd->chop_amount; @@ -525,11 +519,9 @@ static void ocean_compute_displacement_z(TaskPool *__restrict pool, fftw_execute(o->_disp_z_plan); } -static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float chop_amount = osd->chop_amount; int i, j; @@ -560,11 +552,9 @@ static void ocean_compute_jacobian_jxx(TaskPool *__restrict pool, } } -static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float chop_amount = osd->chop_amount; int i, j; @@ -595,11 +585,9 @@ static void ocean_compute_jacobian_jzz(TaskPool *__restrict pool, } } -static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; const float chop_amount = osd->chop_amount; int i, j; @@ -624,11 +612,9 @@ static void ocean_compute_jacobian_jxz(TaskPool *__restrict pool, fftw_execute(o->_Jxz_plan); } -static void ocean_compute_normal_x(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_normal_x(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; int i, j; @@ -645,11 +631,9 @@ static void ocean_compute_normal_x(TaskPool *__restrict pool, fftw_execute(o->_N_x_plan); } -static void ocean_compute_normal_z(TaskPool *__restrict pool, - void *UNUSED(taskdata), - int UNUSED(threadid)) +static void ocean_compute_normal_z(TaskPool *__restrict pool, void *UNUSED(taskdata)) { - OceanSimulateData *osd = BLI_task_pool_userdata(pool); + OceanSimulateData *osd = BLI_task_pool_user_data(pool); const Ocean *o = osd->o; int i, j; @@ -668,7 +652,6 @@ static void ocean_compute_normal_z(TaskPool *__restrict pool, void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); TaskPool *pool; OceanSimulateData osd; @@ -680,7 +663,7 @@ void BKE_ocean_simulate(struct Ocean *o, float t, float scale, float chop_amount osd.scale = scale; osd.chop_amount = chop_amount; - pool = BLI_task_pool_create(scheduler, &osd, TASK_PRIORITY_HIGH); + pool = BLI_task_pool_create(&osd, TASK_PRIORITY_HIGH); BLI_rw_mutex_lock(&o->oceanmutex, THREAD_LOCK_WRITE); diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 4bbbae7081d..5b608d579e8 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -10,7 +10,7 @@ * 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, + * 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) 2009 by Nicholas Bishop @@ -1406,15 +1406,15 @@ MultiresModifierData *BKE_sculpt_multires_active(Scene *scene, Object *ob) return NULL; } - for (md = modifiers_getVirtualModifierList(ob, &virtualModifierData); md; md = md->next) { + for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); md; md = md->next) { if (md->type == eModifierType_Multires) { MultiresModifierData *mmd = (MultiresModifierData *)md; - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } - if (BKE_multires_sculpt_level_get(mmd) > 0) { + if (mmd->sculptlvl > 0) { return mmd; } else { @@ -1443,12 +1443,12 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) return true; } - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* exception for shape keys because we can edit those */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } if (md->type == eModifierType_Multires && (ob->mode & OB_MODE_SCULPT)) { @@ -1686,7 +1686,7 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) * isn't one already */ if (mmd && !CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) { GridPaintMask *gmask; - int level = max_ii(1, BKE_multires_sculpt_level_get(mmd)); + int level = max_ii(1, mmd->sculptlvl); int gridsize = BKE_ccg_gridsize(level); int gridarea = gridsize * gridsize; int i, j; diff --git a/source/blender/blenkernel/intern/paint_toolslots.c b/source/blender/blenkernel/intern/paint_toolslots.c index ea5cb168b12..df7feed3a53 100644 --- a/source/blender/blenkernel/intern/paint_toolslots.c +++ b/source/blender/blenkernel/intern/paint_toolslots.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 0e35fa5d19f..19342090eb7 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -583,7 +583,7 @@ void free_hair(Object *object, ParticleSystem *psys, int dynamics) if (psys->clmd) { if (dynamics) { - modifier_free((ModifierData *)psys->clmd); + BKE_modifier_free((ModifierData *)psys->clmd); psys->clmd = NULL; PTCacheID pid; BKE_ptcache_id_from_particles(&pid, object, psys); @@ -735,7 +735,7 @@ void psys_free(Object *ob, ParticleSystem *psys) */ free_hair(ob, psys, 0); if (psys->clmd != NULL) { - modifier_free((ModifierData *)psys->clmd); + BKE_modifier_free((ModifierData *)psys->clmd); } psys_free_particles(psys); @@ -2787,9 +2787,7 @@ static void psys_thread_create_path(ParticleTask *task, } } -static void exec_child_path_cache(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void exec_child_path_cache(TaskPool *__restrict UNUSED(pool), void *taskdata) { ParticleTask *task = taskdata; ParticleThreadContext *ctx = task->ctx; @@ -2810,7 +2808,6 @@ void psys_cache_child_paths(ParticleSimulationData *sim, const bool editupdate, const bool use_render_params) { - TaskScheduler *task_scheduler; TaskPool *task_pool; ParticleThreadContext ctx; ParticleTask *tasks_parent, *tasks_child; @@ -2826,8 +2823,7 @@ void psys_cache_child_paths(ParticleSimulationData *sim, return; } - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &ctx, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&ctx, TASK_PRIORITY_LOW); totchild = ctx.totchild; totparent = ctx.totparent; @@ -3377,7 +3373,6 @@ void psys_cache_edit_paths(Depsgraph *depsgraph, TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, psys_cache_edit_paths_iter, &settings); edit->totcached = totpart; @@ -3590,9 +3585,9 @@ ModifierData *object_add_particle_system(Main *bmain, Scene *scene, Object *ob, psys->part = BKE_particlesettings_add(bmain, psys->name); - md = modifier_new(eModifierType_ParticleSystem); + md = BKE_modifier_new(eModifierType_ParticleSystem); BLI_strncpy(md->name, psys->name, sizeof(md->name)); - modifier_unique_name(&ob->modifiers, md); + BKE_modifier_unique_name(&ob->modifiers, md); psmd = (ParticleSystemModifierData *)md; psmd->psys = psys; @@ -3620,7 +3615,7 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } /* Clear particle system in fluid modifier. */ - if ((md = modifiers_findByType(ob, eModifierType_Fluid))) { + if ((md = BKE_modifiers_findby_type(ob, eModifierType_Fluid))) { FluidModifierData *mmd = (FluidModifierData *)md; /* Clear particle system pointer in flow settings. */ @@ -3662,7 +3657,7 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } } - if ((md = modifiers_findByType(ob, eModifierType_DynamicPaint))) { + if ((md = BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint))) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; if (pmd->brush && pmd->brush->psys) { if (pmd->brush->psys == psys) { @@ -3675,7 +3670,7 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob psmd = psys_get_modifier(ob, psys); if (psmd) { BLI_remlink(&ob->modifiers, psmd); - modifier_free((ModifierData *)psmd); + BKE_modifier_free((ModifierData *)psmd); } /* Clear particle system. */ @@ -4009,7 +4004,7 @@ static void get_cpa_texture(Mesh *mesh, break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); + RE_texture_evaluate(mtex, texvec, 0, NULL, false, false, &value, rgba); if ((event & mtex->mapto) & PAMAP_ROUGH) { ptex->rough1 = ptex->rough2 = ptex->roughe = texture_value_blend( @@ -4124,7 +4119,7 @@ void psys_get_texture( break; } - externtex(mtex, texvec, &value, rgba, rgba + 1, rgba + 2, rgba + 3, 0, NULL, false, false); + RE_texture_evaluate(mtex, texvec, 0, NULL, false, false, &value, rgba); if ((event & mtex->mapto) & PAMAP_TIME) { /* the first time has to set the base value for time regardless of blend mode */ diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index d91e27a92d8..7b9b2484dbe 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -773,9 +773,7 @@ static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, i } } -static void exec_distribute_parent(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void exec_distribute_parent(TaskPool *__restrict UNUSED(pool), void *taskdata) { ParticleTask *task = taskdata; ParticleSystem *psys = task->ctx->sim.psys; @@ -804,9 +802,7 @@ static void exec_distribute_parent(TaskPool *__restrict UNUSED(pool), } } -static void exec_distribute_child(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void exec_distribute_child(TaskPool *__restrict UNUSED(pool), void *taskdata) { ParticleTask *task = taskdata; ParticleSystem *psys = task->ctx->sim.psys; @@ -1324,7 +1320,6 @@ static void psys_task_init_distribute(ParticleTask *task, ParticleSimulationData static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) { - TaskScheduler *task_scheduler; TaskPool *task_pool; ParticleThreadContext ctx; ParticleTask *tasks; @@ -1336,8 +1331,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) return; } - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create(task_scheduler, &ctx, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&ctx, TASK_PRIORITY_LOW); totpart = (from == PART_FROM_CHILD ? sim->psys->totchild : sim->psys->totpart); psys_tasks_create(&ctx, 0, totpart, &tasks, &numtasks); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index f7400264131..df74b7a75da 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -3450,7 +3450,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) bool realloc_roots; if (!psys->clmd) { - psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); + psys->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS; psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; @@ -3693,10 +3693,11 @@ typedef struct DynamicStepSolverTaskData { SpinLock spin; } DynamicStepSolverTaskData; -static void dynamics_step_finalize_sphdata(void *__restrict UNUSED(userdata), - void *__restrict tls_userdata_chunk) +static void dynamics_step_sphdata_reduce(const void *__restrict UNUSED(userdata), + void *__restrict UNUSED(join_v), + void *__restrict chunk_v) { - SPHData *sphdata = tls_userdata_chunk; + SPHData *sphdata = chunk_v; psys_sph_flush_springs(sphdata); } @@ -3987,7 +3988,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range( 0, psys->totpart, &task_data, dynamics_step_sph_ddr_task_cb_ex, &settings); @@ -4019,7 +4020,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range(0, psys->totpart, &task_data, @@ -4034,7 +4035,7 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) settings.use_threading = (psys->totpart > 100); settings.userdata_chunk = &sphdata; settings.userdata_chunk_size = sizeof(sphdata); - settings.func_finalize = dynamics_step_finalize_sphdata; + settings.func_reduce = dynamics_step_sphdata_reduce; BLI_task_parallel_range(0, psys->totpart, &task_data, @@ -4182,7 +4183,8 @@ static void particles_fluid_step(ParticleSimulationData *sim, #else { Object *ob = sim->ob; - FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Fluid); if (mmd && mmd->domain && mmd->domain->fluid) { FluidDomainSettings *mds = mmd->domain; @@ -4190,7 +4192,7 @@ static void particles_fluid_step(ParticleSimulationData *sim, ParticleSettings *part = psys->part; ParticleData *pa = NULL; - int p, totpart, tottypepart = 0; + int p, totpart = 0, tottypepart = 0; int flagActivePart, activeParts = 0; float posX, posY, posZ, velX, velY, velZ; float resX, resY, resZ; @@ -4848,7 +4850,7 @@ void particle_system_update(struct Depsgraph *depsgraph, hcfra = 100.0f * (float)i / (float)psys->part->hair_step; if ((part->flag & PART_HAIR_REGROW) == 0) { BKE_animsys_evaluate_animdata( - scene, &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); + &part_local->id, part_local->adt, hcfra, ADT_RECALC_ANIM, false); } system_step(&sim, hcfra, use_render_params); psys->cfra = hcfra; diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index 5756cb8c706..b65089c7599 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -1115,11 +1115,11 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode) .vnors = vnors, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_accum_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_normals_store_task_cb, &settings); MEM_freeN(vnors); } @@ -1169,9 +1169,9 @@ static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, in .flag = flag, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_mask_redraw_task_cb, &settings); } static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata, @@ -1207,9 +1207,9 @@ static void pbvh_update_visibility_redraw(PBVH *bvh, PBVHNode **nodes, int totno .flag = flag, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_redraw_task_cb, &settings); } static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata, @@ -1245,9 +1245,9 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag) .flag = flag, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings); } static int pbvh_get_buffers_update_flags(PBVH *bvh, bool show_vcol) @@ -1365,9 +1365,9 @@ static void pbvh_update_draw_buffers( .show_vcol = show_vcol, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings); } static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) @@ -1558,9 +1558,9 @@ static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode) .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings); } void BKE_pbvh_update_visibility(PBVH *bvh) @@ -1927,7 +1927,7 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node, /** * \note doing a full search on all vertices here seems expensive, - * however this is important to avoid having to recalculate boundbox & sync the buffers to the + * however this is important to avoid having to recalculate bound-box & sync the buffers to the * GPU (which is far more expensive!) See: T47232. */ bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node) @@ -3001,7 +3001,7 @@ void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes) } } -void BKE_pbvh_parallel_range_settings(PBVHParallelSettings *settings, +void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings, bool use_threading, int totnode) { diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index 77b3f1580ac..5ee61667eca 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -583,7 +583,7 @@ static int ptcache_cloth_totpoint(void *cloth_v, int UNUSED(cfra)) static void ptcache_cloth_error(void *cloth_v, const char *message) { ClothModifierData *clmd = cloth_v; - modifier_setError(&clmd->modifier, "%s", message); + BKE_modifier_set_error(&clmd->modifier, "%s", message); } #ifdef WITH_SMOKE @@ -604,7 +604,7 @@ static int ptcache_smoke_totpoint(void *smoke_v, int UNUSED(cfra)) static void ptcache_smoke_error(void *smoke_v, const char *message) { FluidModifierData *mmd = (FluidModifierData *)smoke_v; - modifier_setError(&mmd->modifier, "%s", message); + BKE_modifier_set_error(&mmd->modifier, "%s", message); } # define SMOKE_CACHE_VERSION "1.04" diff --git a/source/blender/blenkernel/intern/pointcloud.c b/source/blender/blenkernel/intern/pointcloud.c index 31b8de53291..79b16443122 100644 --- a/source/blender/blenkernel/intern/pointcloud.c +++ b/source/blender/blenkernel/intern/pointcloud.c @@ -184,7 +184,7 @@ void BKE_pointcloud_update_customdata_pointers(PointCloud *pointcloud) PointCloud *BKE_pointcloud_new_for_eval(const PointCloud *pointcloud_src, int totpoint) { - PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_HA, NULL); + PointCloud *pointcloud_dst = BKE_id_new_nomain(ID_PT, NULL); STRNCPY(pointcloud_dst->id.name, pointcloud_src->id.name); pointcloud_dst->mat = MEM_dupallocN(pointcloud_src->mat); @@ -211,12 +211,65 @@ PointCloud *BKE_pointcloud_copy_for_eval(struct PointCloud *pointcloud_src, bool return result; } -static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph), - struct Scene *UNUSED(scene), - Object *UNUSED(object), +static PointCloud *pointcloud_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, PointCloud *pointcloud_input) { - return pointcloud_input; + PointCloud *pointcloud = pointcloud_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if ((mti->type == eModifierTypeType_OnlyDeform) && + (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) { + /* Ensure we are not modifying the input. */ + if (pointcloud == pointcloud_input) { + pointcloud = BKE_pointcloud_copy_for_eval(pointcloud, true); + } + + /* Ensure we are not overwriting referenced data. */ + CustomData_duplicate_referenced_layer(&pointcloud->pdata, CD_LOCATION, pointcloud->totpoint); + BKE_pointcloud_update_customdata_pointers(pointcloud); + + /* Created deformed coordinates array on demand. */ + mti->deformVerts(md, &mectx, NULL, pointcloud->co, pointcloud->totpoint); + } + else if (mti->modifyPointCloud) { + /* Ensure we are not modifying the input. */ + if (pointcloud == pointcloud_input) { + pointcloud = BKE_pointcloud_copy_for_eval(pointcloud, true); + } + + PointCloud *pointcloud_next = mti->modifyPointCloud(md, &mectx, pointcloud); + + if (pointcloud_next && pointcloud_next != pointcloud) { + /* If the modifier returned a new pointcloud, release the old one. */ + if (pointcloud != pointcloud_input) { + BKE_id_free(NULL, pointcloud); + } + pointcloud = pointcloud_next; + } + } + } + + return pointcloud; } void BKE_pointcloud_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 410d5b41057..be6a4e4022b 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -343,7 +343,7 @@ static void scene_free_data(ID *id) /* is no lib link block, but scene extension */ if (scene->nodetree) { - ntreeFreeNestedTree(scene->nodetree); + ntreeFreeEmbeddedTree(scene->nodetree); MEM_freeN(scene->nodetree); scene->nodetree = NULL; } @@ -2110,7 +2110,7 @@ static Depsgraph **scene_get_depsgraph_p(Main *bmain, if (allocate_depsgraph) { *depsgraph_ptr = DEG_graph_new(bmain, scene, view_layer, DAG_EVAL_VIEWPORT); /* TODO(sergey): Would be cool to avoid string format print, - * but is a bit tricky because we can't know in advance whether + * but is a bit tricky because we can't know in advance whether * we will ever enable debug messages for this depsgraph. */ char name[1024]; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index c1644e39afa..9fa43ed0a5f 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -61,6 +61,8 @@ #include "BLF_api.h" +static struct SeqEffectHandle get_sequence_effect_impl(int seq_type); + static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2, @@ -3118,7 +3120,7 @@ static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(fla static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1)) { - return EARLY_USE_INPUT_1; + return EARLY_DO_EFFECT; } static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float *ymin, float *ymax) @@ -3248,36 +3250,60 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool for } } +/* Override cfra when rendering speed effect input. */ +float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context, + Sequence *seq, + float cfra, + int input) +{ + int nr = BKE_sequencer_give_stripelem_index(seq, cfra); + SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; + BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false); + + /* No interpolation. */ + if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) { + return seq->start + s->frameMap[nr]; + } + + /* We need to provide current and next image for interpolation. */ + if (input == 0) { /* Current frame. */ + return floor(seq->start + s->frameMap[nr]); + } + else { /* Next frame. */ + return ceil(seq->start + s->frameMap[nr]); + } +} + +static float speed_effect_interpolation_ratio_get(SpeedControlVars *s, Sequence *seq, float cfra) +{ + int nr = BKE_sequencer_give_stripelem_index(seq, cfra); + return s->frameMap[nr] - floor(s->frameMap[nr]); +} + static ImBuf *do_speed_effect(const SeqRenderData *context, - Sequence *UNUSED(seq), - float UNUSED(cfra), + Sequence *seq, + float cfra, float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3) { - ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3); + SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; + struct SeqEffectHandle cross_effect = get_sequence_effect_impl(SEQ_TYPE_CROSS); + ImBuf *out; - if (out->rect_float) { - do_cross_effect_float(facf0, - facf1, - context->rectx, - context->recty, - ibuf1->rect_float, - ibuf2->rect_float, - out->rect_float); + if (s->flags & SEQ_SPEED_USE_INTERPOLATION) { + out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3); + facf0 = facf1 = speed_effect_interpolation_ratio_get(s, seq, cfra); + /* Current frame is ibuf1, next frame is ibuf2. */ + out = BKE_sequencer_effect_execute_threaded( + &cross_effect, context, NULL, cfra, facf0, facf1, ibuf1, ibuf2, ibuf3); + return out; } - else { - do_cross_effect_byte(facf0, - facf1, - context->rectx, - context->recty, - (unsigned char *)ibuf1->rect, - (unsigned char *)ibuf2->rect, - (unsigned char *)out->rect); - } - return out; + + /* No interpolation. */ + return IMB_dupImBuf(ibuf1); } /*********************** overdrop *************************/ diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c index d2be7653cee..f00d517940a 100644 --- a/source/blender/blenkernel/intern/seqprefetch.c +++ b/source/blender/blenkernel/intern/seqprefetch.c @@ -412,8 +412,7 @@ static void *seq_prefetch_frames(void *job) seq_prefetch_update_depsgraph(pfjob); AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id); - BKE_animsys_evaluate_animdata(pfjob->context_cpy.scene, - &pfjob->context_cpy.scene->id, + BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id, adt, pfjob->cfra + pfjob->num_frames_prefetched, ADT_RECALC_ALL, diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 53357546669..a14db79ffc6 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1397,7 +1397,7 @@ static void multibuf(ImBuf *ibuf, const float fmul) } } -static float give_stripelem_index(Sequence *seq, float cfra) +float BKE_sequencer_give_stripelem_index(Sequence *seq, float cfra) { float nr; int sta = seq->start; @@ -1455,7 +1455,7 @@ StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra) * all other strips don't use this... */ - int nr = (int)give_stripelem_index(seq, cfra); + int nr = (int)BKE_sequencer_give_stripelem_index(seq, cfra); if (nr == -1 || se == NULL) { return NULL; @@ -1895,7 +1895,7 @@ static bool seq_proxy_get_fname(Editing *ed, frameno = 1; } else { - frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; + frameno = (int)BKE_sequencer_give_stripelem_index(seq, cfra) + seq->anim_startofs; BLI_snprintf(name, PROXY_MAXFILE, "%s/proxy_misc/%d/####%s", dir, proxy_size_number, suffix); } @@ -1928,7 +1928,7 @@ static ImBuf *seq_proxy_fetch(const SeqRenderData *context, Sequence *seq, int c } if (proxy->storage & SEQ_STORAGE_PROXY_CUSTOM_FILE) { - int frameno = (int)give_stripelem_index(seq, cfra) + seq->anim_startofs; + int frameno = (int)BKE_sequencer_give_stripelem_index(seq, cfra) + seq->anim_startofs; if (proxy->anim == NULL) { if (seq_proxy_get_fname(ed, seq, cfra, psize, name, context->view_id) == 0) { return NULL; @@ -2893,15 +2893,15 @@ static void *render_effect_execute_do_thread(void *thread_data_v) return NULL; } -static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, - const SeqRenderData *context, - Sequence *seq, - float cfra, - float facf0, - float facf1, - ImBuf *ibuf1, - ImBuf *ibuf2, - ImBuf *ibuf3) +ImBuf *BKE_sequencer_effect_execute_threaded(struct SeqEffectHandle *sh, + const SeqRenderData *context, + Sequence *seq, + float cfra, + float facf0, + float facf1, + ImBuf *ibuf1, + ImBuf *ibuf2, + ImBuf *ibuf3) { RenderEffectInitData init_data; ImBuf *out = sh->init_execution(context, ibuf1, ibuf2, ibuf3); @@ -2975,14 +2975,21 @@ static ImBuf *seq_render_effect_strip_impl(const SeqRenderData *context, break; case EARLY_DO_EFFECT: for (i = 0; i < 3; i++) { - if (input[i]) { - ibuf[i] = seq_render_strip(context, state, input[i], cfra); + /* Speed effect requires time remapping of cfra for input(s). */ + if (input[1] && seq->type == SEQ_TYPE_SPEED) { + float target_frame = BKE_sequencer_speed_effect_target_frame_get(context, seq, cfra, i); + ibuf[i] = seq_render_strip(context, state, input[i], target_frame); + } + else { /* Other effects. */ + if (input[i]) { + ibuf[i] = seq_render_strip(context, state, input[i], cfra); + } } } if (ibuf[0] && ibuf[1]) { if (sh.multithreaded) { - out = seq_render_effect_execute_threaded( + out = BKE_sequencer_effect_execute_threaded( &sh, context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]); } else { @@ -3336,8 +3343,7 @@ static ImBuf *seq_render_mask(const SeqRenderData *context, Mask *mask, float nr /* anim-data */ adt = BKE_animdata_from_id(&mask->id); - BKE_animsys_evaluate_animdata( - context->scene, &mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&mask_temp->id, adt, mask->sfra + nr, ADT_RECALC_ANIM, false); maskbuf = MEM_mallocN(sizeof(float) * context->rectx * context->recty, __func__); @@ -3671,8 +3677,7 @@ static ImBuf *do_render_strip_seqbase(const SeqRenderData *context, if (seqbase && !BLI_listbase_is_empty(seqbase)) { if (seq->flag & SEQ_SCENE_STRIPS && seq->scene) { - BKE_animsys_evaluate_all_animation( - context->bmain, context->depsgraph, seq->scene, nr + offset); + BKE_animsys_evaluate_all_animation(context->bmain, context->depsgraph, nr + offset); } ibuf = seq_render_strip_stack(context, @@ -3692,9 +3697,8 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, float cfra) { ImBuf *ibuf = NULL; - float nr = give_stripelem_index(seq, cfra); - int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : - seq->type; + float nr = BKE_sequencer_give_stripelem_index(seq, cfra); + int type = (seq->type & SEQ_TYPE_EFFECT) ? SEQ_TYPE_EFFECT : seq->type; switch (type) { case SEQ_TYPE_META: { ibuf = do_render_strip_seqbase(context, state, seq, nr); @@ -3736,21 +3740,8 @@ static ImBuf *do_render_strip_uncached(const SeqRenderData *context, break; } - case SEQ_TYPE_SPEED: { - float f_cfra; - SpeedControlVars *s = (SpeedControlVars *)seq->effectdata; - - BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false); - - /* weeek! */ - f_cfra = seq->start + s->frameMap[(int)nr]; - ibuf = seq_render_strip(context, state, seq->seq1, f_cfra); - - break; - } - case SEQ_TYPE_EFFECT: { - ibuf = seq_render_effect_strip_impl(context, state, seq, seq->start + nr); + ibuf = seq_render_effect_strip_impl(context, state, seq, cfra); break; } @@ -3944,7 +3935,7 @@ static ImBuf *seq_render_strip_stack_apply_effect( if (swap_input) { if (sh.multithreaded) { - out = seq_render_effect_execute_threaded( + out = BKE_sequencer_effect_execute_threaded( &sh, context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL); } else { @@ -3953,7 +3944,7 @@ static ImBuf *seq_render_strip_stack_apply_effect( } else { if (sh.multithreaded) { - out = seq_render_effect_execute_threaded( + out = BKE_sequencer_effect_execute_threaded( &sh, context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL); } else { diff --git a/source/blender/blenkernel/intern/shader_fx.c b/source/blender/blenkernel/intern/shader_fx.c index 8d692782413..0ad61de1ff2 100644 --- a/source/blender/blenkernel/intern/shader_fx.c +++ b/source/blender/blenkernel/intern/shader_fx.c @@ -59,7 +59,7 @@ bool BKE_shaderfx_has_gpencil(Object *ob) { ShaderFxData *fx; for (fx = ob->shader_fx.first; fx; fx = fx->next) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi->type == eShaderFxType_GpencilType) { return true; } @@ -75,7 +75,7 @@ void BKE_shaderfx_init(void) ShaderFxData *BKE_shaderfx_new(int type) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type); ShaderFxData *fx = MEM_callocN(fxi->struct_size, fxi->struct_name); /* note, this name must be made unique later */ @@ -109,7 +109,7 @@ static void shaderfx_free_data_id_us_cb(void *UNUSED(userData), void BKE_shaderfx_free_ex(ShaderFxData *fx, const int flag) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { if (fxi->foreachIDLink) { @@ -139,21 +139,21 @@ void BKE_shaderfx_free(ShaderFxData *fx) bool BKE_shaderfx_unique_name(ListBase *shaders, ShaderFxData *fx) { if (shaders && fx) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); return BLI_uniquename( shaders, fx, DATA_(fxi->name), '.', offsetof(ShaderFxData, name), sizeof(fx->name)); } return false; } -bool BKE_shaderfx_dependsOnTime(ShaderFxData *fx) +bool BKE_shaderfx_depends_ontime(ShaderFxData *fx) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); return fxi->dependsOnTime && fxi->dependsOnTime(fx); } -const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type) +const ShaderFxTypeInfo *BKE_shaderfx_get_info(ShaderFxType type) { /* type unsigned, no need to check < 0 */ if (type < NUM_SHADER_FX_TYPES && shader_fx_types[type]->name[0] != '\0') { @@ -164,9 +164,9 @@ const ShaderFxTypeInfo *BKE_shaderfxType_getInfo(ShaderFxType type) } } -void BKE_shaderfx_copyData_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst) +void BKE_shaderfx_copydata_generic(const ShaderFxData *fx_src, ShaderFxData *fx_dst) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx_src->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx_src->type); /* fx_dst may have already be fully initialized with some extra allocated data, * we need to free it now to avoid memleak. */ @@ -192,9 +192,9 @@ static void shaderfx_copy_data_id_us_cb(void *UNUSED(userData), } } -void BKE_shaderfx_copyData_ex(ShaderFxData *fx, ShaderFxData *target, const int flag) +void BKE_shaderfx_copydata_ex(ShaderFxData *fx, ShaderFxData *target, const int flag) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); target->mode = fx->mode; target->flag = fx->flag; @@ -214,12 +214,12 @@ void BKE_shaderfx_copyData_ex(ShaderFxData *fx, ShaderFxData *target, const int } } -void BKE_shaderfx_copyData(ShaderFxData *fx, ShaderFxData *target) +void BKE_shaderfx_copydata(ShaderFxData *fx, ShaderFxData *target) { - BKE_shaderfx_copyData_ex(fx, target, 0); + BKE_shaderfx_copydata_ex(fx, target, 0); } -ShaderFxData *BKE_shaderfx_findByType(Object *ob, ShaderFxType type) +ShaderFxData *BKE_shaderfx_findby_type(Object *ob, ShaderFxType type) { ShaderFxData *fx = ob->shader_fx.first; @@ -232,12 +232,12 @@ ShaderFxData *BKE_shaderfx_findByType(Object *ob, ShaderFxType type) return fx; } -void BKE_shaderfx_foreachIDLink(Object *ob, ShaderFxIDWalkFunc walk, void *userData) +void BKE_shaderfx_foreach_ID_link(Object *ob, ShaderFxIDWalkFunc walk, void *userData) { ShaderFxData *fx = ob->shader_fx.first; for (; fx; fx = fx->next) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi->foreachIDLink) { fxi->foreachIDLink(fx, ob, walk, userData); @@ -250,7 +250,7 @@ void BKE_shaderfx_foreachIDLink(Object *ob, ShaderFxIDWalkFunc walk, void *userD } } -ShaderFxData *BKE_shaderfx_findByName(Object *ob, const char *name) +ShaderFxData *BKE_shaderfx_findby_name(Object *ob, const char *name) { return BLI_findstring(&(ob->shader_fx), name, offsetof(ShaderFxData, name)); } diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 06086cdf56a..c59042bc045 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -443,7 +443,7 @@ bool BKE_shrinkwrap_project_normal(char options, BVHTreeRayHit *hit) { /* don't use this because this dist value could be incompatible - * this value used by the callback for comparing prev/new dist values. + * this value used by the callback for comparing previous/new dist values. * also, at the moment there is no need to have a corrected 'dist' value */ // #define USE_DIST_CORRECT diff --git a/source/blender/blenkernel/intern/simulation.cc b/source/blender/blenkernel/intern/simulation.cc new file mode 100644 index 00000000000..b4cfa7cf0ef --- /dev/null +++ b/source/blender/blenkernel/intern/simulation.cc @@ -0,0 +1,117 @@ +/* + * 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. + */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_defaults.h" +#include "DNA_scene_types.h" +#include "DNA_simulation_types.h" + +#include "BLI_compiler_compat.h" +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BKE_anim_data.h" +#include "BKE_animsys.h" +#include "BKE_idtype.h" +#include "BKE_lib_id.h" +#include "BKE_lib_query.h" +#include "BKE_lib_remap.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_simulation.h" + +#include "NOD_simulation.h" + +#include "BLT_translation.h" + +#include "DEG_depsgraph.h" + +static void simulation_init_data(ID *id) +{ + Simulation *simulation = (Simulation *)id; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(simulation, id)); + + MEMCPY_STRUCT_AFTER(simulation, DNA_struct_default_get(Simulation), id); + + bNodeTree *ntree = ntreeAddTree(nullptr, "Simulation Nodetree", ntreeType_Simulation->idname); + simulation->nodetree = ntree; +} + +static void simulation_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) +{ + Simulation *simulation_dst = (Simulation *)id_dst; + Simulation *simulation_src = (Simulation *)id_src; + + /* We always need allocation of our private ID data. */ + const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE; + + if (simulation_src->nodetree) { + BKE_id_copy_ex(bmain, + (ID *)simulation_src->nodetree, + (ID **)&simulation_dst->nodetree, + flag_private_id_data); + } +} + +static void simulation_free_data(ID *id) +{ + Simulation *simulation = (Simulation *)id; + + BKE_animdata_free(&simulation->id, false); + + if (simulation->nodetree) { + ntreeFreeEmbeddedTree(simulation->nodetree); + MEM_freeN(simulation->nodetree); + simulation->nodetree = nullptr; + } +} + +void *BKE_simulation_add(Main *bmain, const char *name) +{ + Simulation *simulation = (Simulation *)BKE_libblock_alloc(bmain, ID_SIM, name, 0); + + simulation_init_data(&simulation->id); + + return simulation; +} + +IDTypeInfo IDType_ID_SIM = { + /* id_code */ ID_SIM, + /* id_filter */ FILTER_ID_SIM, + /* main_listbase_index */ INDEX_ID_SIM, + /* struct_size */ sizeof(Simulation), + /* name */ "Simulation", + /* name_plural */ "simulations", + /* translation_context */ BLT_I18NCONTEXT_ID_SIMULATION, + /* flags */ 0, + + /* init_data */ simulation_init_data, + /* copy_data */ simulation_copy_data, + /* free_data */ simulation_free_data, + /* make_local */ nullptr, +}; + +void BKE_simulation_data_update(Depsgraph *UNUSED(depsgraph), Scene *UNUSED(scene)) +{ +} diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index c358dde449f..68d0822a223 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -285,7 +285,7 @@ static ccd_Mesh *ccd_mesh_make(Object *ob) float hull; int i; - cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision); + cmd = (CollisionModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Collision); /* first some paranoia checks */ if (!cmd) { @@ -371,7 +371,7 @@ static void ccd_mesh_update(Object *ob, ccd_Mesh *pccd_M) float hull; int i; - cmd = (CollisionModifierData *)modifiers_findByType(ob, eModifierType_Collision); + cmd = (CollisionModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Collision); /* first some paranoia checks */ if (!cmd) { @@ -3010,7 +3010,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) * (C2= continuous in second derivate -> no jump in bending ) condition. * * Not too hard to do, but needs some more code to care for; - * some one may want look at it JOW 2010/06/12. */ + * some one may want look at it (JOW 2010/06/12). */ for (bezt = nu->bezt, a = 0; a < nu->pntsu; a++, bezt++, bp += 3, curindex += 3) { if (setgoal) { bp->goal *= bezt->weight; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 64fe396d6a3..5500918428f 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -751,12 +751,12 @@ static void sound_start_play_scene(Scene *scene) } } -static float get_cur_time(Scene *scene) +static double get_cur_time(Scene *scene) { /* We divide by the current framelen to take into account time remapping. * Otherwise we will get the wrong starting time which will break A/V sync. * See T74111 for further details. */ - return FRA2TIME((CFRA + SUBFRA) / scene->r.framelen); + return FRA2TIME((CFRA + SUBFRA) / (double)scene->r.framelen); } void BKE_sound_play_scene(Scene *scene) @@ -764,7 +764,7 @@ void BKE_sound_play_scene(Scene *scene) sound_verify_evaluated_id(&scene->id); AUD_Status status; - const float cur_time = get_cur_time(scene); + const double cur_time = get_cur_time(scene); AUD_Device_lock(sound_device); @@ -811,8 +811,8 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) bScreen *screen; int animation_playing; - const float one_frame = (float)(1.0 / FPS); - const float cur_time = FRA2TIME(CFRA); + const double one_frame = 1.0 / FPS; + const double cur_time = FRA2TIME(CFRA); AUD_Device_lock(sound_device); @@ -869,7 +869,7 @@ void BKE_sound_seek_scene(Main *bmain, Scene *scene) AUD_Device_unlock(sound_device); } -float BKE_sound_sync_scene(Scene *scene) +double BKE_sound_sync_scene(Scene *scene) { sound_verify_evaluated_id(&scene->id); @@ -1230,7 +1230,7 @@ void BKE_sound_stop_scene(Scene *UNUSED(scene)) void BKE_sound_seek_scene(Main *UNUSED(bmain), Scene *UNUSED(scene)) { } -float BKE_sound_sync_scene(Scene *UNUSED(scene)) +double BKE_sound_sync_scene(Scene *UNUSED(scene)) { return NAN_FLT; } @@ -1341,7 +1341,7 @@ void BKE_sound_jack_sync_callback_set(SoundJackSyncCallback callback) #endif } -void BKE_sound_jack_scene_update(Scene *scene, int mode, float time) +void BKE_sound_jack_scene_update(Scene *scene, int mode, double time) { sound_verify_evaluated_id(&scene->id); diff --git a/source/blender/blenkernel/intern/subdiv_ccg.c b/source/blender/blenkernel/intern/subdiv_ccg.c index 0ae32701cd5..d5d5530c1ce 100644 --- a/source/blender/blenkernel/intern/subdiv_ccg.c +++ b/source/blender/blenkernel/intern/subdiv_ccg.c @@ -40,9 +40,9 @@ #include "opensubdiv_topology_refiner_capi.h" -/* ============================================================================= - * Various forward declarations. - */ +/* -------------------------------------------------------------------- */ +/** \name Various forward declarations + * \{ */ static void subdiv_ccg_average_all_boundaries_and_corners(SubdivCCG *subdiv_ccg, CCGKey *key); @@ -50,9 +50,11 @@ static void subdiv_ccg_average_inner_face_grids(SubdivCCG *subdiv_ccg, CCGKey *key, SubdivCCGFace *face); -/* ============================================================================= - * Generally useful internal helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Generally useful internal helpers + * \{ */ /* Number of floats in per-vertex elements. */ static int num_element_float_get(const SubdivCCG *subdiv_ccg) @@ -74,9 +76,11 @@ static int element_size_bytes_get(const SubdivCCG *subdiv_ccg) return sizeof(float) * num_element_float_get(subdiv_ccg); } -/* ============================================================================= - * Internal helpers for CCG creation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal helpers for CCG creation + * \{ */ static void subdiv_ccg_init_layers(SubdivCCG *subdiv_ccg, const SubdivToCCGSettings *settings) { @@ -158,9 +162,11 @@ static void subdiv_ccg_alloc_elements(SubdivCCG *subdiv_ccg, Subdiv *subdiv) } } -/* ============================================================================= - * Grids evaluation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Grids evaluation + * \{ */ typedef struct CCGEvalGridsData { SubdivCCG *subdiv_ccg; @@ -556,9 +562,11 @@ static void subdiv_ccg_init_faces_neighborhood(SubdivCCG *subdiv_ccg) subdiv_ccg_init_faces_vertex_neighborhood(subdiv_ccg); } -/* ============================================================================= - * Creation / evaluation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Creation / evaluation + * \{ */ SubdivCCG *BKE_subdiv_to_ccg(Subdiv *subdiv, const SubdivToCCGSettings *settings, @@ -670,9 +678,11 @@ void BKE_subdiv_ccg_key_top_level(CCGKey *key, const SubdivCCG *subdiv_ccg) BKE_subdiv_ccg_key(key, subdiv_ccg, subdiv_ccg->level); } -/* ============================================================================= - * Normals. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Normals + * \{ */ typedef struct RecalcInnerNormalsData { SubdivCCG *subdiv_ccg; @@ -770,8 +780,8 @@ static void subdiv_ccg_recalc_inner_normal_task(void *__restrict userdata_v, subdiv_ccg_average_inner_face_normals(data->subdiv_ccg, data->key, tls, grid_index); } -static void subdiv_ccg_recalc_inner_normal_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_recalc_inner_normal_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { RecalcInnerNormalsTLSData *tls = tls_v; MEM_SAFE_FREE(tls->face_normals); @@ -791,7 +801,7 @@ static void subdiv_ccg_recalc_inner_grid_normals(SubdivCCG *subdiv_ccg) BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_recalc_inner_normal_finalize; + parallel_range_settings.func_free = subdiv_ccg_recalc_inner_normal_free; BLI_task_parallel_range(0, subdiv_ccg->num_grids, &data, @@ -834,8 +844,8 @@ static void subdiv_ccg_recalc_modified_inner_normal_task(void *__restrict userda subdiv_ccg_average_inner_face_grids(subdiv_ccg, key, face); } -static void subdiv_ccg_recalc_modified_inner_normal_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_recalc_modified_inner_normal_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { RecalcInnerNormalsTLSData *tls = tls_v; MEM_SAFE_FREE(tls->face_normals); @@ -857,7 +867,7 @@ static void subdiv_ccg_recalc_modified_inner_grid_normals(SubdivCCG *subdiv_ccg, BLI_parallel_range_settings_defaults(¶llel_range_settings); parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_recalc_modified_inner_normal_finalize; + parallel_range_settings.func_free = subdiv_ccg_recalc_modified_inner_normal_free; BLI_task_parallel_range(0, num_effected_faces, &data, @@ -885,9 +895,11 @@ void BKE_subdiv_ccg_update_normals(SubdivCCG *subdiv_ccg, subdiv_ccg_average_all_boundaries_and_corners(subdiv_ccg, &key); } -/* ============================================================================= - * Boundary averaging/stitching. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Boundary averaging/stitching + * \{ */ typedef struct AverageInnerGridsData { SubdivCCG *subdiv_ccg; @@ -1077,8 +1089,8 @@ static void subdiv_ccg_average_grids_boundaries_task(void *__restrict userdata_v subdiv_ccg_average_grids_boundary(subdiv_ccg, key, adjacent_edge, tls); } -static void subdiv_ccg_average_grids_boundaries_finalize(void *__restrict UNUSED(userdata), - void *__restrict tls_v) +static void subdiv_ccg_average_grids_boundaries_free(const void *__restrict UNUSED(userdata), + void *__restrict tls_v) { AverageGridsBoundariesTLSData *tls = tls_v; MEM_SAFE_FREE(tls->accumulators); @@ -1136,7 +1148,7 @@ static void subdiv_ccg_average_all_boundaries(SubdivCCG *subdiv_ccg, CCGKey *key AverageGridsBoundariesTLSData tls_data = {NULL}; parallel_range_settings.userdata_chunk = &tls_data; parallel_range_settings.userdata_chunk_size = sizeof(tls_data); - parallel_range_settings.func_finalize = subdiv_ccg_average_grids_boundaries_finalize; + parallel_range_settings.func_free = subdiv_ccg_average_grids_boundaries_free; BLI_task_parallel_range(0, subdiv_ccg->num_adjacent_edges, &boundaries_data, @@ -1244,9 +1256,11 @@ void BKE_subdiv_ccg_topology_counters(const SubdivCCG *subdiv_ccg, *r_num_loops = *r_num_faces * 4; } -/* ============================================================================= - * Neighbors. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Neighbors + * \{ */ void BKE_subdiv_ccg_print_coord(const char *message, const SubdivCCGCoord *coord) { @@ -1791,3 +1805,5 @@ int BKE_subdiv_ccg_grid_to_face_index(const SubdivCCG *subdiv_ccg, const int gri const int face_index = face - subdiv_ccg->faces; return face_index; } + +/** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_deform.c b/source/blender/blenkernel/intern/subdiv_deform.c index db0a51c390b..f03cf4c4d21 100644 --- a/source/blender/blenkernel/intern/subdiv_deform.c +++ b/source/blender/blenkernel/intern/subdiv_deform.c @@ -39,9 +39,9 @@ #include "MEM_guardedalloc.h" -/* ================================================================================================ - * Subdivision context. - */ +/* -------------------------------------------------------------------- */ +/** \name Subdivision context + * \{ */ typedef struct SubdivDeformContext { const Mesh *coarse_mesh; @@ -77,9 +77,11 @@ static void subdiv_mesh_context_free(SubdivDeformContext *ctx) MEM_SAFE_FREE(ctx->accumulated_counters); } -/* ================================================================================================ - * Accumulation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Accumulation helpers + * \{ */ static void subdiv_accumulate_vertex_displacement(SubdivDeformContext *ctx, const int ptex_face_index, @@ -105,9 +107,11 @@ static void subdiv_accumulate_vertex_displacement(SubdivDeformContext *ctx, ++ctx->accumulated_counters[vertex_index]; } -/* ================================================================================================ - * Subdivision callbacks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Subdivision callbacks + * \{ */ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context, const int UNUSED(num_vertices), @@ -165,9 +169,11 @@ static void subdiv_mesh_vertex_corner(const SubdivForeachContext *foreach_contex add_v3_v3(vertex_co, D); } -/* ================================================================================================ - * Initialization. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialization + * \{ */ static void setup_foreach_callbacks(const SubdivDeformContext *subdiv_context, SubdivForeachContext *foreach_context) @@ -182,9 +188,11 @@ static void setup_foreach_callbacks(const SubdivDeformContext *subdiv_context, foreach_context->vertex_corner = subdiv_mesh_vertex_corner; } -/* ================================================================================================ - * Public entry point. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public entry point + * \{ */ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv, const struct Mesh *coarse_mesh, @@ -234,3 +242,5 @@ void BKE_subdiv_deform_coarse_vertices(struct Subdiv *subdiv, /* Free used memory. */ subdiv_mesh_context_free(&subdiv_context); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_foreach.c b/source/blender/blenkernel/intern/subdiv_foreach.c index b31fb2c9312..ff7f6fad5f0 100644 --- a/source/blender/blenkernel/intern/subdiv_foreach.c +++ b/source/blender/blenkernel/intern/subdiv_foreach.c @@ -40,9 +40,9 @@ #include "MEM_guardedalloc.h" -/* ============================================================================= - * General helpers. - */ +/* -------------------------------------------------------------------- */ +/** \name General helpers + * \{ */ /* Number of ptex faces for a given polygon. */ BLI_INLINE int num_ptex_faces_per_poly_get(const MPoly *poly) @@ -75,9 +75,11 @@ BLI_INLINE int ptex_face_resolution_get(const MPoly *poly, int resolution) return (poly->totloop == 4) ? (resolution) : ((resolution >> 1) + 1); } -/* ============================================================================= - * Context which is passed to all threaded tasks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Context which is passed to all threaded tasks + * \{ */ typedef struct SubdivForeachTaskContext { const Mesh *coarse_mesh; @@ -122,9 +124,11 @@ typedef struct SubdivForeachTaskContext { BLI_bitmap *coarse_edges_used_map; } SubdivForeachTaskContext; -/* ============================================================================= - * Threading helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Threading helpers + * \{ */ static void *subdiv_foreach_tls_alloc(SubdivForeachTaskContext *ctx) { @@ -148,9 +152,11 @@ static void subdiv_foreach_tls_free(SubdivForeachTaskContext *ctx, void *tls) MEM_freeN(tls); } -/* ============================================================================= - * Initialization. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialization + * \{ */ /* NOTE: Expects edge map to be zeroed. */ static void subdiv_foreach_ctx_count(SubdivForeachTaskContext *ctx) @@ -294,9 +300,11 @@ static void subdiv_foreach_ctx_free(SubdivForeachTaskContext *ctx) MEM_freeN(ctx->subdiv_polygon_offset); } -/* ============================================================================= - * Vertex traversal process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex traversal process + * \{ */ /* Traversal of corner vertices. They are coming from coarse vertices. */ @@ -706,9 +714,11 @@ static void subdiv_foreach_vertices(SubdivForeachTaskContext *ctx, void *tls, co } } -/* ============================================================================= - * Edge traversal process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edge traversal process + * \{ */ /* TODO(sergey): Coarse edge are always NONE, consider getting rid of it. */ static int subdiv_foreach_edges_row(SubdivForeachTaskContext *ctx, @@ -1022,9 +1032,11 @@ static void subdiv_foreach_boundary_edges(SubdivForeachTaskContext *ctx, ctx->foreach_context, tls, coarse_edge_index, subdiv_edge_index, v1, v2); } -/* ============================================================================= - * Loops traversal. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loops traversal + * \{ */ static void rotate_indices(const int rot, int *a, int *b, int *c, int *d) { @@ -1666,9 +1678,11 @@ static void subdiv_foreach_loops(SubdivForeachTaskContext *ctx, void *tls, int p } } -/* ============================================================================= - * Polygons traverse process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Polygons traverse process + * \{ */ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int poly_index) { @@ -1697,9 +1711,11 @@ static void subdiv_foreach_polys(SubdivForeachTaskContext *ctx, void *tls, int p } } -/* ============================================================================= - * Loose elements traverse process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loose elements traverse process + * \{ */ static void subdiv_foreach_loose_vertices_task(void *__restrict userdata, const int coarse_vertex_index, @@ -1754,9 +1770,11 @@ static void subdiv_foreach_vertices_of_loose_edges_task(void *__restrict userdat } } -/* ============================================================================= - * Subdivision process entry points. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Subdivision process entry points + * \{ */ static void subdiv_foreach_single_geometry_vertices(SubdivForeachTaskContext *ctx, void *tls) { @@ -1838,9 +1856,9 @@ static void subdiv_foreach_boundary_edges_task(void *__restrict userdata, subdiv_foreach_boundary_edges(ctx, tls->userdata_chunk, edge_index); } -static void subdiv_foreach_finalize(void *__restrict userdata, void *__restrict userdata_chunk) +static void subdiv_foreach_free(const void *__restrict userdata, void *__restrict userdata_chunk) { - SubdivForeachTaskContext *ctx = userdata; + const SubdivForeachTaskContext *ctx = userdata; ctx->foreach_context->user_data_tls_free(userdata_chunk); } @@ -1873,7 +1891,7 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, parallel_range_settings.userdata_chunk_size = context->user_data_tls_size; parallel_range_settings.min_iter_per_thread = 1; if (context->user_data_tls_free != NULL) { - parallel_range_settings.func_finalize = subdiv_foreach_finalize; + parallel_range_settings.func_free = subdiv_foreach_free; } /* TODO(sergey): Possible optimization is to have a single pool and push all @@ -1908,3 +1926,5 @@ bool BKE_subdiv_foreach_subdiv_geometry(Subdiv *subdiv, subdiv_foreach_ctx_free(&ctx); return true; } + +/** \} */ diff --git a/source/blender/blenkernel/intern/subdiv_mesh.c b/source/blender/blenkernel/intern/subdiv_mesh.c index bd091108b11..987cc0311c7 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.c +++ b/source/blender/blenkernel/intern/subdiv_mesh.c @@ -41,9 +41,9 @@ #include "MEM_guardedalloc.h" -/* ============================================================================= - * Subdivision context. - */ +/* -------------------------------------------------------------------- */ +/** \name Subdivision Context + * \{ */ typedef struct SubdivMeshContext { const SubdivToMeshSettings *settings; @@ -119,9 +119,11 @@ static void subdiv_mesh_context_free(SubdivMeshContext *ctx) MEM_SAFE_FREE(ctx->accumulated_counters); } -/* ============================================================================= - * Loop custom data copy helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop custom data copy helpers + * \{ */ typedef struct LoopsOfPtex { /* First loop of the ptex, starts at ptex (0, 0) and goes in u direction. */ @@ -159,9 +161,11 @@ static void loops_of_ptex_get(const SubdivMeshContext *ctx, } } -/* ============================================================================= - * Vertex custom data interpolation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex custom data interpolation helpers + * \{ */ /* TODO(sergey): Somehow de-duplicate with loops storage, without too much * exception cases all over the code. */ @@ -295,9 +299,11 @@ static void vertex_interpolation_end(VerticesForInterpolation *vertex_interpolat } } -/* ============================================================================= - * Loop custom data interpolation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop custom data interpolation helpers + * \{ */ typedef struct LoopsForInterpolation { /* This field points to a loop data which is to be used for interpolation. @@ -413,9 +419,11 @@ static void loop_interpolation_end(LoopsForInterpolation *loop_interpolation) } } -/* ============================================================================= - * TLS. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name TLS + * \{ */ typedef struct SubdivMeshTLS { bool vertex_interpolation_initialized; @@ -440,9 +448,11 @@ static void subdiv_mesh_tls_free(void *tls_v) } } -/* ============================================================================= - * Evaluation helper functions. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Evaluation helper functions + * \{ */ static void eval_final_point_and_vertex_normal(Subdiv *subdiv, const int ptex_face_index, @@ -459,9 +469,11 @@ static void eval_final_point_and_vertex_normal(Subdiv *subdiv, } } -/* ============================================================================= - * Accumulation helpers. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Accumulation helpers + * \{ */ static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext *ctx, const int ptex_face_index, @@ -490,9 +502,11 @@ static void subdiv_accumulate_vertex_normal_and_displacement(SubdivMeshContext * ++ctx->accumulated_counters[subdiv_vertex_index]; } -/* ============================================================================= - * Callbacks. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks + * \{ */ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_context, const int num_vertices, @@ -513,9 +527,11 @@ static bool subdiv_mesh_topology_info(const SubdivForeachContext *foreach_contex return true; } -/* ============================================================================= - * Vertex subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Vertex subdivision process + * \{ */ static void subdiv_vertex_data_copy(const SubdivMeshContext *ctx, const MVert *coarse_vertex, @@ -778,9 +794,11 @@ static void subdiv_mesh_vertex_inner(const SubdivForeachContext *foreach_context subdiv_mesh_tag_center_vertex(coarse_poly, subdiv_vert, u, v); } -/* ============================================================================= - * Edge subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Edge subdivision process + * \{ */ static void subdiv_copy_edge_data(SubdivMeshContext *ctx, MEdge *subdiv_edge, @@ -827,9 +845,11 @@ static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context, subdiv_edge->v2 = subdiv_v2; } -/* ============================================================================= - * Loops creation/interpolation. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loops creation/interpolation + * \{ */ static void subdiv_interpolate_loop_data(const SubdivMeshContext *ctx, MLoop *subdiv_loop, @@ -921,9 +941,11 @@ static void subdiv_mesh_loop(const SubdivForeachContext *foreach_context, subdiv_loop->e = subdiv_edge_index; } -/* ============================================================================= - * Polygons subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Polygons subdivision process + * \{ */ static void subdiv_copy_poly_data(const SubdivMeshContext *ctx, MPoly *subdiv_poly, @@ -955,9 +977,11 @@ static void subdiv_mesh_poly(const SubdivForeachContext *foreach_context, subdiv_poly->totloop = num_loops; } -/* ============================================================================= - * Loose elements subdivision process. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loose elements subdivision process + * \{ */ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context, void *UNUSED(tls), @@ -1127,9 +1151,11 @@ static void subdiv_mesh_vertex_of_loose_edge(const struct SubdivForeachContext * normal_float_to_short_v3(subdiv_vertex->no, no); } -/* ============================================================================= - * Initialization. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Initialization + * \{ */ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context, SubdivForeachContext *foreach_context) @@ -1157,9 +1183,11 @@ static void setup_foreach_callbacks(const SubdivMeshContext *subdiv_context, foreach_context->user_data_tls_free = subdiv_mesh_tls_free; } -/* ============================================================================= - * Public entry point. - */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Public entry point + * \{ */ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, const SubdivToMeshSettings *settings, @@ -1206,3 +1234,5 @@ Mesh *BKE_subdiv_to_mesh(Subdiv *subdiv, subdiv_mesh_context_free(&subdiv_context); return result; } + +/** \} */ diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index fe10861f96e..49c5c073f49 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -57,6 +57,7 @@ #include "BKE_image.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_query.h" #include "BKE_material.h" #include "BKE_node.h" #include "BKE_scene.h" @@ -112,7 +113,7 @@ static void texture_free_data(ID *id) /* is no lib link block, but texture extension */ if (texture->nodetree) { - ntreeFreeNestedTree(texture->nodetree); + ntreeFreeEmbeddedTree(texture->nodetree); MEM_freeN(texture->nodetree); texture->nodetree = NULL; } @@ -123,6 +124,16 @@ static void texture_free_data(ID *id) BKE_previewimg_free(&texture->preview); } +static void texture_foreach_id(ID *id, LibraryForeachIDData *data) +{ + Tex *texture = (Tex *)id; + if (texture->nodetree) { + /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ + BKE_library_foreach_ID_embedded(data, (ID **)&texture->nodetree); + } + BKE_LIB_FOREACHID_PROCESS(data, texture->ima, IDWALK_CB_USER); +} + IDTypeInfo IDType_ID_TE = { .id_code = ID_TE, .id_filter = FILTER_ID_TE, @@ -137,6 +148,7 @@ IDTypeInfo IDType_ID_TE = { .copy_data = texture_copy_data, .free_data = texture_free_data, .make_local = NULL, + .foreach_id = texture_foreach_id, }; /* ****************** Mapping ******************* */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 0204667b3bd..97d95cb7e46 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -2288,13 +2288,15 @@ void BKE_tracking_distortion_free(MovieDistortion *distortion) MEM_freeN(distortion); } -void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r_co[2]) +void BKE_tracking_distort_v2( + MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2]) { const MovieTrackingCamera *camera = &tracking->camera; const float aspy = 1.0f / tracking->camera.pixel_aspect; libmv_CameraIntrinsicsOptions camera_intrinsics_options; - tracking_cameraIntrinscisOptionsFromTracking(tracking, 0, 0, &camera_intrinsics_options); + tracking_cameraIntrinscisOptionsFromTracking( + tracking, image_width, image_height, &camera_intrinsics_options); libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options); /* Normalize coordinates. */ @@ -2309,13 +2311,15 @@ void BKE_tracking_distort_v2(MovieTracking *tracking, const float co[2], float r r_co[1] = y; } -void BKE_tracking_undistort_v2(MovieTracking *tracking, const float co[2], float r_co[2]) +void BKE_tracking_undistort_v2( + MovieTracking *tracking, int image_width, int image_height, const float co[2], float r_co[2]) { const MovieTrackingCamera *camera = &tracking->camera; const float aspy = 1.0f / tracking->camera.pixel_aspect; libmv_CameraIntrinsicsOptions camera_intrinsics_options; - tracking_cameraIntrinscisOptionsFromTracking(tracking, 0, 0, &camera_intrinsics_options); + tracking_cameraIntrinscisOptionsFromTracking( + tracking, image_width, image_height, &camera_intrinsics_options); libmv_CameraIntrinsics *intrinsics = libmv_cameraIntrinsicsNew(&camera_intrinsics_options); double x = co[0], y = co[1]; @@ -2361,13 +2365,19 @@ ImBuf *BKE_tracking_distort_frame(MovieTracking *tracking, } void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, + int image_width, + int image_height, rcti *rect, bool undistort, float delta[2]) { float pos[2], warped_pos[2]; const int coord_delta = 5; - void (*apply_distortion)(MovieTracking * tracking, const float pos[2], float out[2]); + void (*apply_distortion)(MovieTracking * tracking, + int image_width, + int image_height, + const float pos[2], + float out[2]); if (undistort) { apply_distortion = BKE_tracking_undistort_v2; @@ -2387,7 +2397,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = a; pos[1] = rect->ymin; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2396,7 +2406,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = a; pos[1] = rect->ymax; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2415,7 +2425,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = rect->xmin; pos[1] = a; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); @@ -2424,7 +2434,7 @@ void BKE_tracking_max_distortion_delta_across_bound(MovieTracking *tracking, pos[0] = rect->xmax; pos[1] = a; - apply_distortion(tracking, pos, warped_pos); + apply_distortion(tracking, image_width, image_height, pos, warped_pos); delta[0] = max_ff(delta[0], fabsf(pos[0] - warped_pos[0])); delta[1] = max_ff(delta[1], fabsf(pos[1] - warped_pos[1])); diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 5f7452e4775..629c01ec298 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -451,6 +451,12 @@ static void distortion_model_parameters_from_tracking( camera_intrinsics_options->division_k1 = camera->division_k1; camera_intrinsics_options->division_k2 = camera->division_k2; return; + + case TRACKING_DISTORTION_MODEL_NUKE: + camera_intrinsics_options->distortion_model = LIBMV_DISTORTION_MODEL_NUKE; + camera_intrinsics_options->nuke_k1 = camera->nuke_k1; + camera_intrinsics_options->nuke_k2 = camera->nuke_k2; + return; } /* Unknown distortion model, which might be due to opening newer file in older Blender. @@ -479,6 +485,12 @@ static void distortion_model_parameters_from_options( camera->division_k1 = camera_intrinsics_options->division_k1; camera->division_k2 = camera_intrinsics_options->division_k2; return; + + case LIBMV_DISTORTION_MODEL_NUKE: + camera->distortion_model = TRACKING_DISTORTION_MODEL_NUKE; + camera->nuke_k1 = camera_intrinsics_options->nuke_k1; + camera->nuke_k2 = camera_intrinsics_options->nuke_k2; + return; } /* Libmv returned distortion model which is not known to Blender. This is a logical error in code diff --git a/source/blender/blenkernel/intern/volume.cc b/source/blender/blenkernel/intern/volume.cc index b0b7a60b556..9e636c0ee8b 100644 --- a/source/blender/blenkernel/intern/volume.cc +++ b/source/blender/blenkernel/intern/volume.cc @@ -795,12 +795,52 @@ bool BKE_volume_is_points_only(const Volume *volume) /* Dependency Graph */ -static Volume *volume_evaluate_modifiers(struct Depsgraph *UNUSED(depsgraph), - struct Scene *UNUSED(scene), - Object *UNUSED(object), +static Volume *volume_evaluate_modifiers(struct Depsgraph *depsgraph, + struct Scene *scene, + Object *object, Volume *volume_input) { - return volume_input; + Volume *volume = volume_input; + + /* Modifier evaluation modes. */ + const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; + ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE; + const ModifierEvalContext mectx = {depsgraph, object, apply_flag}; + + /* Get effective list of modifiers to execute. Some effects like shape keys + * are added as virtual modifiers before the user created modifiers. */ + VirtualModifierData virtualModifierData; + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData); + + /* Evaluate modifiers. */ + for (; md; md = md->next) { + const ModifierTypeInfo *mti = (const ModifierTypeInfo *)BKE_modifier_get_info( + (ModifierType)md->type); + + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { + continue; + } + + if (mti->modifyVolume) { + /* Ensure we are not modifying the input. */ + if (volume == volume_input) { + volume = BKE_volume_copy_for_eval(volume, true); + } + + Volume *volume_next = mti->modifyVolume(md, &mectx, volume); + + if (volume_next && volume_next != volume) { + /* If the modifier returned a new volume, release the old one. */ + if (volume != volume_input) { + BKE_id_free(NULL, volume); + } + volume = volume_next; + } + } + } + + return volume; } void BKE_volume_eval_geometry(struct Depsgraph *depsgraph, Volume *volume) diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index f2219ad1cf8..3be62750673 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -59,7 +59,7 @@ static void world_free_data(ID *id) /* is no lib link block, but world extension */ if (wrld->nodetree) { - ntreeFreeNestedTree(wrld->nodetree); + ntreeFreeEmbeddedTree(wrld->nodetree); MEM_freeN(wrld->nodetree); wrld->nodetree = NULL; } diff --git a/source/blender/blenlib/BLI_allocator.h b/source/blender/blenlib/BLI_allocator.hh index e2d39c4e897..c52db4aab53 100644 --- a/source/blender/blenlib/BLI_allocator.h +++ b/source/blender/blenlib/BLI_allocator.hh @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_ALLOCATOR_H__ -#define __BLI_ALLOCATOR_H__ +#ifndef __BLI_ALLOCATOR_HH__ +#define __BLI_ALLOCATOR_HH__ /** \file * \ingroup bli @@ -102,4 +102,4 @@ class RawAllocator { } // namespace BLI -#endif /* __BLI_ALLOCATOR_H__ */ +#endif /* __BLI_ALLOCATOR_HH__ */ diff --git a/source/blender/blenlib/BLI_array_cxx.h b/source/blender/blenlib/BLI_array.hh index 8fc2aec6698..9dd8341aa76 100644 --- a/source/blender/blenlib/BLI_array_cxx.h +++ b/source/blender/blenlib/BLI_array.hh @@ -13,8 +13,8 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_ARRAY_CXX_H__ -#define __BLI_ARRAY_CXX_H__ +#ifndef __BLI_ARRAY_HH__ +#define __BLI_ARRAY_HH__ /** \file * \ingroup bli @@ -23,20 +23,21 @@ * a template argument. Instead it can be specified at the construction time. */ -#include "BLI_allocator.h" -#include "BLI_array_ref.h" -#include "BLI_index_range.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_allocator.hh" +#include "BLI_array_ref.hh" +#include "BLI_index_range.hh" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" namespace BLI { -template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Array { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Array { private: T *m_data; uint m_size; Allocator m_allocator; - AlignedBuffer<sizeof(T) * N, alignof(T)> m_inline_storage; + AlignedBuffer<sizeof(T) * InlineBufferCapacity, alignof(T)> m_inline_storage; public: Array() @@ -79,7 +80,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar m_allocator = other.m_allocator; m_data = this->get_buffer_for_size(other.size()); - copy_n(other.begin(), m_size, m_data); + uninitialized_copy_n(other.begin(), m_size, m_data); } Array(Array &&other) noexcept @@ -201,10 +202,15 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar return IndexRange(m_size); } + Allocator &allocator() + { + return m_allocator; + } + private: T *get_buffer_for_size(uint size) { - if (size <= N) { + if (size <= InlineBufferCapacity) { return this->inline_storage(); } else { @@ -231,4 +237,4 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ar } // namespace BLI -#endif /* __BLI_ARRAY_CXX_H__ */ +#endif /* __BLI_ARRAY_HH__ */ diff --git a/source/blender/blenlib/BLI_array_ref.h b/source/blender/blenlib/BLI_array_ref.hh index 2c2e441a47d..c0484493bda 100644 --- a/source/blender/blenlib/BLI_array_ref.h +++ b/source/blender/blenlib/BLI_array_ref.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_ARRAY_REF_H__ -#define __BLI_ARRAY_REF_H__ +#ifndef __BLI_ARRAY_REF_HH__ +#define __BLI_ARRAY_REF_HH__ /** \file * \ingroup bli @@ -41,8 +41,8 @@ #include <string> #include <vector> -#include "BLI_index_range.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_index_range.hh" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" namespace BLI { @@ -508,6 +508,16 @@ template<typename T> class MutableArrayRef { BLI_assert(m_size > 0); return m_start[m_size - 1]; } + + /** + * Get a new array ref to the same underlying memory buffer. No conversions are done. + */ + template<typename NewT> MutableArrayRef<NewT> cast() const + { + BLI_assert((m_size * sizeof(T)) % sizeof(NewT) == 0); + uint new_size = m_size * sizeof(T) / sizeof(NewT); + return MutableArrayRef<NewT>(reinterpret_cast<NewT *>(m_start), new_size); + } }; /** @@ -542,4 +552,4 @@ void assert_same_size(const T1 &v1, const T2 &v2, const T3 &v3) } /* namespace BLI */ -#endif /* __BLI_ARRAY_REF_H__ */ +#endif /* __BLI_ARRAY_REF_HH__ */ diff --git a/source/blender/blenlib/BLI_bitmap.h b/source/blender/blenlib/BLI_bitmap.h index d67fbabd11c..2b811e50efb 100644 --- a/source/blender/blenlib/BLI_bitmap.h +++ b/source/blender/blenlib/BLI_bitmap.h @@ -24,12 +24,12 @@ * \ingroup bli */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - typedef unsigned int BLI_bitmap; /* warning: the bitmap does not keep track of its own size or check diff --git a/source/blender/blenlib/BLI_blenlib.h b/source/blender/blenlib/BLI_blenlib.h index 41603bb4f06..6dd1abacf78 100644 --- a/source/blender/blenlib/BLI_blenlib.h +++ b/source/blender/blenlib/BLI_blenlib.h @@ -52,10 +52,6 @@ #include <stdlib.h> -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_listbase.h" #include "BLI_string.h" @@ -68,8 +64,4 @@ extern "C" { #include "BLI_rect.h" -#ifdef __cplusplus -} -#endif - #endif diff --git a/source/blender/blenlib/BLI_color.hh b/source/blender/blenlib/BLI_color.hh new file mode 100644 index 00000000000..ff28ae2c076 --- /dev/null +++ b/source/blender/blenlib/BLI_color.hh @@ -0,0 +1,92 @@ +/* + * 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. + */ + +#ifndef __BLI_COLOR_HH__ +#define __BLI_COLOR_HH__ + +#include <iostream> + +#include "BLI_math_color.h" + +namespace BLI { + +struct Color4f { + float r, g, b, a; + + Color4f() = default; + + Color4f(float r, float g, float b, float a) : r(r), g(g), b(b), a(a) + { + } + + operator float *() + { + return &r; + } + + operator const float *() const + { + return &r; + } + + friend std::ostream &operator<<(std::ostream &stream, Color4f c) + { + stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; + return stream; + } +}; + +struct Color4b { + uint8_t r, g, b, a; + + Color4b() = default; + + Color4b(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a) + { + } + + Color4b(Color4f other) + { + rgba_float_to_uchar(*this, other); + } + + operator Color4f() const + { + Color4f result; + rgba_uchar_to_float(result, *this); + return result; + } + + operator uint8_t *() + { + return &r; + } + + operator const uint8_t *() const + { + return &r; + } + + friend std::ostream &operator<<(std::ostream &stream, Color4b c) + { + stream << "(" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ")"; + return stream; + } +}; + +} // namespace BLI + +#endif /* __BLI_COLOR_HH__ */ diff --git a/source/blender/blenlib/BLI_dot_export.hh b/source/blender/blenlib/BLI_dot_export.hh new file mode 100644 index 00000000000..08c37fec01e --- /dev/null +++ b/source/blender/blenlib/BLI_dot_export.hh @@ -0,0 +1,290 @@ +/* + * 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. + */ + +#ifndef __BLI_DOT_EXPORT_HH__ +#define __BLI_DOT_EXPORT_HH__ + +/** + * Language grammar: https://www.graphviz.org/doc/info/lang.html + * Attributes: https://www.graphviz.org/doc/info/attrs.html + * Node Shapes: https://www.graphviz.org/doc/info/shapes.html + * Preview: https://dreampuf.github.io/GraphvizOnline + */ + +#include "BLI_map.hh" +#include "BLI_optional.hh" +#include "BLI_set.hh" +#include "BLI_string_map.hh" +#include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" + +#include "BLI_dot_export_attribute_enums.hh" + +#include <sstream> + +namespace BLI { +namespace DotExport { + +class Graph; +class DirectedGraph; +class UndirectedGraph; +class Node; +class NodePort; +class DirectedEdge; +class UndirectedEdge; +class Cluster; +class AttributeList; + +class AttributeList { + private: + Map<std::string, std::string> m_attributes; + + public: + void export__as_bracket_list(std::stringstream &ss) const; + + void set(StringRef key, StringRef value) + { + m_attributes.add_override(key, value); + } +}; + +class Graph { + private: + AttributeList m_attributes; + Vector<std::unique_ptr<Node>> m_nodes; + Vector<std::unique_ptr<Cluster>> m_clusters; + + Set<Node *> m_top_level_nodes; + Set<Cluster *> m_top_level_clusters; + + friend Cluster; + friend Node; + + public: + Node &new_node(StringRef label); + Cluster &new_cluster(StringRef label = ""); + + void export__declare_nodes_and_clusters(std::stringstream &ss) const; + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_rankdir(Attr_rankdir rankdir) + { + this->set_attribute("rankdir", rankdir_to_string(rankdir)); + } + + void set_random_cluster_bgcolors(); +}; + +class Cluster { + private: + AttributeList m_attributes; + Graph &m_graph; + Cluster *m_parent = nullptr; + Set<Cluster *> m_children; + Set<Node *> m_nodes; + + friend Graph; + friend Node; + + Cluster(Graph &graph) : m_graph(graph) + { + } + + public: + void export__declare_nodes_and_clusters(std::stringstream &ss) const; + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_parent_cluster(Cluster *cluster); + void set_parent_cluster(Cluster &cluster) + { + this->set_parent_cluster(&cluster); + } + + void set_random_cluster_bgcolors(); +}; + +class Node { + private: + AttributeList m_attributes; + Graph &m_graph; + Cluster *m_cluster = nullptr; + + friend Graph; + + Node(Graph &graph) : m_graph(graph) + { + } + + public: + const AttributeList &attributes() const + { + return m_attributes; + } + + AttributeList &attributes() + { + return m_attributes; + } + + void set_parent_cluster(Cluster *cluster); + void set_parent_cluster(Cluster &cluster) + { + this->set_parent_cluster(&cluster); + } + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_shape(Attr_shape shape) + { + this->set_attribute("shape", shape_to_string(shape)); + } + + /* See https://www.graphviz.org/doc/info/attrs.html#k:color. */ + void set_background_color(StringRef name) + { + this->set_attribute("fillcolor", name); + this->set_attribute("style", "filled"); + } + + void export__as_id(std::stringstream &ss) const; + + void export__as_declaration(std::stringstream &ss) const; +}; + +class UndirectedGraph final : public Graph { + private: + Vector<std::unique_ptr<UndirectedEdge>> m_edges; + + public: + std::string to_dot_string() const; + + UndirectedEdge &new_edge(NodePort a, NodePort b); +}; + +class DirectedGraph final : public Graph { + private: + Vector<std::unique_ptr<DirectedEdge>> m_edges; + + public: + std::string to_dot_string() const; + + DirectedEdge &new_edge(NodePort from, NodePort to); +}; + +class NodePort { + private: + Node *m_node; + Optional<std::string> m_port_name; + + public: + NodePort(Node &node, Optional<std::string> port_name = {}) + : m_node(&node), m_port_name(std::move(port_name)) + { + } + + void to_dot_string(std::stringstream &ss) const; +}; + +class Edge : BLI::NonCopyable, BLI::NonMovable { + protected: + AttributeList m_attributes; + NodePort m_a; + NodePort m_b; + + public: + Edge(NodePort a, NodePort b) : m_a(std::move(a)), m_b(std::move(b)) + { + } + + void set_attribute(StringRef key, StringRef value) + { + m_attributes.set(key, value); + } + + void set_arrowhead(Attr_arrowType type) + { + this->set_attribute("arrowhead", arrowType_to_string(type)); + } + + void set_arrowtail(Attr_arrowType type) + { + this->set_attribute("arrowtail", arrowType_to_string(type)); + } + + void set_dir(Attr_dirType type) + { + this->set_attribute("dir", dirType_to_string(type)); + } +}; + +class DirectedEdge : public Edge { + public: + DirectedEdge(NodePort from, NodePort to) : Edge(std::move(from), std::move(to)) + { + } + + void export__as_edge_statement(std::stringstream &ss) const; +}; + +class UndirectedEdge : public Edge { + public: + UndirectedEdge(NodePort a, NodePort b) : Edge(std::move(a), std::move(b)) + { + } + + void export__as_edge_statement(std::stringstream &ss) const; +}; + +std::string color_attr_from_hsv(float h, float s, float v); + +class NodeWithSocketsRef { + private: + Node *m_node; + + public: + NodeWithSocketsRef(Node &node, + StringRef name, + ArrayRef<std::string> input_names, + ArrayRef<std::string> output_names); + + NodePort input(uint index) const + { + std::string port = "\"in" + std::to_string(index) + "\""; + return NodePort(*m_node, port); + } + + NodePort output(uint index) const + { + std::string port = "\"out" + std::to_string(index) + "\""; + return NodePort(*m_node, port); + } +}; + +} // namespace DotExport +} // namespace BLI + +#endif /* __BLI_DOT_EXPORT_HH__ */ diff --git a/source/blender/blenlib/BLI_dot_export_attribute_enums.hh b/source/blender/blenlib/BLI_dot_export_attribute_enums.hh new file mode 100644 index 00000000000..8e61f46dc12 --- /dev/null +++ b/source/blender/blenlib/BLI_dot_export_attribute_enums.hh @@ -0,0 +1,125 @@ +/* + * 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. + */ + +#ifndef __BLI_DOT_EXPORT_ATTRIBUTE_ENUMS_HH__ +#define __BLI_DOT_EXPORT_ATTRIBUTE_ENUMS_HH__ + +#include "BLI_string_ref.hh" + +namespace BLI { +namespace DotExport { + +enum class Attr_rankdir { + LeftToRight, + TopToBottom, +}; + +inline StringRef rankdir_to_string(Attr_rankdir value) +{ + switch (value) { + case Attr_rankdir::LeftToRight: + return "LR"; + case Attr_rankdir::TopToBottom: + return "TB"; + } + return ""; +} + +enum class Attr_shape { + Rectangle, + Ellipse, + Circle, + Point, + Diamond, + Square, +}; + +inline StringRef shape_to_string(Attr_shape value) +{ + switch (value) { + case Attr_shape::Rectangle: + return "rectangle"; + case Attr_shape::Ellipse: + return "ellipse"; + case Attr_shape::Circle: + return "circle"; + case Attr_shape::Point: + return "point"; + case Attr_shape::Diamond: + return "diamond"; + case Attr_shape::Square: + return "square"; + } + return ""; +} + +enum class Attr_arrowType { + Normal, + Inv, + Dot, + None, + Empty, + Box, + Vee, +}; + +inline StringRef arrowType_to_string(Attr_arrowType value) +{ + switch (value) { + case Attr_arrowType::Normal: + return "normal"; + case Attr_arrowType::Inv: + return "inv"; + case Attr_arrowType::Dot: + return "dot"; + case Attr_arrowType::None: + return "none"; + case Attr_arrowType::Empty: + return "empty"; + case Attr_arrowType::Box: + return "box"; + case Attr_arrowType::Vee: + return "vee"; + } + return ""; +} + +enum class Attr_dirType { + Forward, + Back, + Both, + None, +}; + +inline StringRef dirType_to_string(Attr_dirType value) +{ + switch (value) { + case Attr_dirType::Forward: + return "forward"; + case Attr_dirType::Back: + return "back"; + case Attr_dirType::Both: + return "both"; + case Attr_dirType::None: + return "none"; + } + return ""; +} + +} // namespace DotExport +} // namespace BLI + +#endif /* __BLI_DOT_EXPORT_ATTRIBUTE_ENUMS_HH__ */ diff --git a/source/blender/blenlib/BLI_fileops.h b/source/blender/blenlib/BLI_fileops.h index 4eb6f184a76..fe4600b9121 100644 --- a/source/blender/blenlib/BLI_fileops.h +++ b/source/blender/blenlib/BLI_fileops.h @@ -29,10 +29,6 @@ #include <stdio.h> #include <sys/stat.h> -#ifdef __cplusplus -extern "C" { -#endif - /* for size_t (needed on windows) */ #include <stddef.h> @@ -41,6 +37,10 @@ extern "C" { #include "BLI_compiler_attrs.h" #include "BLI_utildefines.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef PATH_MAX # define PATH_MAX 4096 #endif diff --git a/source/blender/blenlib/BLI_float2.hh b/source/blender/blenlib/BLI_float2.hh new file mode 100644 index 00000000000..da12dd7d206 --- /dev/null +++ b/source/blender/blenlib/BLI_float2.hh @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#ifndef __BLI_FLOAT2_HH__ +#define __BLI_FLOAT2_HH__ + +#include "BLI_float3.hh" + +namespace BLI { + +struct float2 { + float x, y; + + float2() = default; + + float2(const float *ptr) : x{ptr[0]}, y{ptr[1]} + { + } + + float2(float x, float y) : x(x), y(y) + { + } + + float2(const float3 &other) : x(other.x), y(other.y) + { + } + + operator float *() + { + return &x; + } + + operator const float *() const + { + return &x; + } + + friend float2 operator+(const float2 &a, const float2 &b) + { + return {a.x + b.x, a.y + b.y}; + } + + friend float2 operator-(const float2 &a, const float2 &b) + { + return {a.x - b.x, a.y - b.y}; + } + + friend float2 operator*(const float2 &a, float b) + { + return {a.x * b, a.y * b}; + } + + friend float2 operator/(const float2 &a, float b) + { + BLI_assert(b != 0.0f); + return {a.x / b, a.y / b}; + } + + friend float2 operator*(float a, const float2 &b) + { + return b * a; + } + + friend std::ostream &operator<<(std::ostream &stream, const float2 &v) + { + stream << "(" << v.x << ", " << v.y << ")"; + return stream; + } +}; + +} // namespace BLI + +#endif /* __BLI_FLOAT2_HH__ */ diff --git a/source/blender/blenlib/BLI_float3.hh b/source/blender/blenlib/BLI_float3.hh new file mode 100644 index 00000000000..9678fa4b2d3 --- /dev/null +++ b/source/blender/blenlib/BLI_float3.hh @@ -0,0 +1,218 @@ +/* + * 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. + */ + +#ifndef __BLI_FLOAT3_HH__ +#define __BLI_FLOAT3_HH__ + +#include <iostream> + +#include "BLI_math_vector.h" + +namespace BLI { + +struct float3 { + float x, y, z; + + float3() = default; + + float3(const float *ptr) : x{ptr[0]}, y{ptr[1]}, z{ptr[2]} + { + } + + float3(const float (*ptr)[3]) : float3((const float *)ptr) + { + } + + explicit float3(float value) : x(value), y(value), z(value) + { + } + + explicit float3(int value) : x(value), y(value), z(value) + { + } + + float3(float x, float y, float z) : x{x}, y{y}, z{z} + { + } + + operator const float *() const + { + return &x; + } + + operator float *() + { + return &x; + } + + float normalize_and_get_length() + { + return normalize_v3(*this); + } + + float3 normalized() const + { + float3 result; + normalize_v3_v3(result, *this); + return result; + } + + float length() const + { + return len_v3(*this); + } + + float length_squared() const + { + return len_squared_v3(*this); + } + + void reflect(const float3 &normal) + { + *this = this->reflected(normal); + } + + float3 reflected(const float3 &normal) const + { + float3 result; + reflect_v3_v3v3(result, *this, normal); + return result; + } + + static float3 safe_divide(const float3 &a, const float3 &b) + { + float3 result; + result.x = (b.x == 0.0f) ? 0.0f : a.x / b.x; + result.y = (b.y == 0.0f) ? 0.0f : a.y / b.y; + result.z = (b.z == 0.0f) ? 0.0f : a.z / b.z; + return result; + } + + void invert() + { + x = -x; + y = -y; + z = -z; + } + + friend float3 operator+(const float3 &a, const float3 &b) + { + return {a.x + b.x, a.y + b.y, a.z + b.z}; + } + + void operator+=(const float3 &b) + { + this->x += b.x; + this->y += b.y; + this->z += b.z; + } + + friend float3 operator-(const float3 &a, const float3 &b) + { + return {a.x - b.x, a.y - b.y, a.z - b.z}; + } + + friend float3 operator-(const float3 &a) + { + return {-a.x, -a.y, -a.z}; + } + + void operator-=(const float3 &b) + { + this->x -= b.x; + this->y -= b.y; + this->z -= b.z; + } + + void operator*=(float scalar) + { + this->x *= scalar; + this->y *= scalar; + this->z *= scalar; + } + + void operator*=(const float3 &other) + { + this->x *= other.x; + this->y *= other.y; + this->z *= other.z; + } + + friend float3 operator*(const float3 &a, const float3 &b) + { + return {a.x * b.x, a.y * b.y, a.z * b.z}; + } + + friend float3 operator*(const float3 &a, float b) + { + return {a.x * b, a.y * b, a.z * b}; + } + + friend float3 operator*(float a, const float3 &b) + { + return b * a; + } + + friend float3 operator/(const float3 &a, float b) + { + BLI_assert(b != 0.0f); + return {a.x / b, a.y / b, a.z / b}; + } + + friend std::ostream &operator<<(std::ostream &stream, const float3 &v) + { + stream << "(" << v.x << ", " << v.y << ", " << v.z << ")"; + return stream; + } + + static float dot(const float3 &a, const float3 &b) + { + return a.x * b.x + a.y * b.y + a.z * b.z; + } + + static float3 cross_high_precision(const float3 &a, const float3 &b) + { + float3 result; + cross_v3_v3v3_hi_prec(result, a, b); + return result; + } + + static float3 project(const float3 &a, const float3 &b) + { + float3 result; + project_v3_v3v3(result, a, b); + return result; + } + + static float distance(const float3 &a, const float3 &b) + { + return (a - b).length(); + } + + static float distance_squared(const float3 &a, const float3 &b) + { + return float3::dot(a, b); + } + + static float3 interpolate(const float3 &a, const float3 &b, float t) + { + return a * (1 - t) + b * t; + } +}; + +} // namespace BLI + +#endif /* __BLI_FLOAT3_HH__ */ diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh new file mode 100644 index 00000000000..36186d319c9 --- /dev/null +++ b/source/blender/blenlib/BLI_float4x4.hh @@ -0,0 +1,115 @@ +/* + * 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. + */ + +#ifndef __BLI_FLOAT4X4_HH__ +#define __BLI_FLOAT4X4_HH__ + +#include "BLI_float3.hh" +#include "BLI_math_matrix.h" + +namespace BLI { + +struct float4x4 { + float values[4][4]; + + float4x4() = default; + + float4x4(const float *matrix) + { + memcpy(values, matrix, sizeof(float) * 16); + } + + float4x4(const float matrix[4][4]) : float4x4((float *)matrix) + { + } + + operator float *() + { + return (float *)this; + } + + operator const float *() const + { + return (const float *)this; + } + + float4x4 inverted() const + { + float result[4][4]; + invert_m4_m4(result, values); + return result; + } + + /** + * Matrix inversion can be implemented more efficiently for affine matrices. + */ + float4x4 inverted_affine() const + { + BLI_assert(values[0][3] == 0.0f && values[1][3] == 0.0f && values[2][3] == 0.0f && + values[3][3] == 1.0f); + return this->inverted(); + } + + friend float4x4 operator*(const float4x4 &a, const float4x4 &b) + { + float4x4 result; + mul_m4_m4m4(result.values, a.values, b.values); + return result; + } + + /** + * This also applies the translation on the vector. Use `m.ref_3x3() * v` if that is not + * intended. + */ + friend float3 operator*(const float4x4 &m, const float3 &v) + { + float3 result; + mul_v3_m4v3(result, m.values, v); + return result; + } + + friend float3 operator*(const float4x4 &m, const float (*v)[3]) + { + return m * float3(v); + } + + struct float3x3_ref { + const float4x4 &data; + + friend float3 operator*(const float3x3_ref &m, const float3 &v) + { + float3 result; + mul_v3_mat3_m4v3(result, m.data.values, v); + return result; + } + }; + + float3x3_ref ref_3x3() const + { + return {*this}; + } + + static float4x4 interpolate(const float4x4 &a, const float4x4 &b, float t) + { + float result[4][4]; + interp_m4_m4m4(result, a.values, b.values, t); + return result; + } +}; + +} // namespace BLI + +#endif /* __BLI_FLOAT4X4_HH__ */ diff --git a/source/blender/blenlib/BLI_gsqueue.h b/source/blender/blenlib/BLI_gsqueue.h index dffb2a165ee..b69bdb7057c 100644 --- a/source/blender/blenlib/BLI_gsqueue.h +++ b/source/blender/blenlib/BLI_gsqueue.h @@ -24,6 +24,8 @@ * \ingroup bli */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif diff --git a/source/blender/blenlib/BLI_hash.h b/source/blender/blenlib/BLI_hash.h index d09291b64be..96111ffaf5a 100644 --- a/source/blender/blenlib/BLI_hash.h +++ b/source/blender/blenlib/BLI_hash.h @@ -21,12 +21,12 @@ * \ingroup bli */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - BLI_INLINE unsigned int BLI_hash_int_2d(unsigned int kx, unsigned int ky) { #define rot(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) @@ -81,7 +81,7 @@ BLI_INLINE void BLI_hash_pointer_to_color(const void *ptr, int *r, int *g, int * { size_t val = (size_t)ptr; const size_t hash_a = BLI_hash_int(val & 0x0000ffff); - const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 32)); + const size_t hash_b = BLI_hash_int((uint)((val & 0xffff0000) >> 16)); const size_t hash = hash_a ^ (hash_b + 0x9e3779b9 + (hash_a << 6) + (hash_a >> 2)); *r = (hash & 0xff0000) >> 16; *g = (hash & 0x00ff00) >> 8; diff --git a/source/blender/blenlib/BLI_hash_cxx.h b/source/blender/blenlib/BLI_hash.hh index 22941a792ba..3b3448f66b1 100644 --- a/source/blender/blenlib/BLI_hash_cxx.h +++ b/source/blender/blenlib/BLI_hash.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_HASH_CXX_H__ -#define __BLI_HASH_CXX_H__ +#ifndef __BLI_HASH_HH__ +#define __BLI_HASH_HH__ /** \file * \ingroup bli @@ -30,6 +30,7 @@ #include <utility> #include "BLI_math_base.h" +#include "BLI_string_ref.hh" #include "BLI_utildefines.h" namespace BLI { @@ -67,14 +68,33 @@ template<> struct DefaultHash<float> { } }; +inline uint32_t hash_string(StringRef str) +{ + uint32_t hash = 5381; + for (char c : str) { + hash = hash * 33 + c; + } + return hash; +} + template<> struct DefaultHash<std::string> { uint32_t operator()(const std::string &value) const { - uint32_t hash = 5381; - for (char c : value) { - hash = hash * 33 + c; - } - return hash; + return hash_string(value); + } +}; + +template<> struct DefaultHash<StringRef> { + uint32_t operator()(const StringRef &value) const + { + return hash_string(value); + } +}; + +template<> struct DefaultHash<StringRefNull> { + uint32_t operator()(const StringRefNull &value) const + { + return hash_string(value); } }; @@ -109,4 +129,4 @@ template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> { } // namespace BLI -#endif /* __BLI_HASH_CXX_H__ */ +#endif /* __BLI_HASH_HH__ */ diff --git a/source/blender/blenlib/BLI_heap.h b/source/blender/blenlib/BLI_heap.h index fa8e49ef376..ca5edcbead5 100644 --- a/source/blender/blenlib/BLI_heap.h +++ b/source/blender/blenlib/BLI_heap.h @@ -22,12 +22,12 @@ * \brief A min-heap / priority queue ADT */ +#include "BLI_math.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math.h" - struct Heap; struct HeapNode; typedef struct Heap Heap; diff --git a/source/blender/blenlib/BLI_index_range.h b/source/blender/blenlib/BLI_index_range.hh index 4553c996454..e24fd567810 100644 --- a/source/blender/blenlib/BLI_index_range.h +++ b/source/blender/blenlib/BLI_index_range.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_INDEX_RANGE_H__ -#define __BLI_INDEX_RANGE_H__ +#ifndef __BLI_INDEX_RANGE_HH__ +#define __BLI_INDEX_RANGE_HH__ /** \file * \ingroup bli @@ -208,4 +208,4 @@ class IndexRange { } // namespace BLI -#endif /* __BLI_INDEX_RANGE_H__ */ +#endif /* __BLI_INDEX_RANGE_HH__ */ diff --git a/source/blender/blenlib/BLI_lasso_2d.h b/source/blender/blenlib/BLI_lasso_2d.h index 56db360dab0..fb661c41784 100644 --- a/source/blender/blenlib/BLI_lasso_2d.h +++ b/source/blender/blenlib/BLI_lasso_2d.h @@ -30,14 +30,14 @@ extern "C" { struct rcti; -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, +void BLI_lasso_boundbox(struct rcti *rect, const int mcoords[][2], const unsigned int mcoords_len); +bool BLI_lasso_is_point_inside(const int mcoords[][2], + const unsigned int mcoords_len, const int sx, const int sy, const int error_value); -bool BLI_lasso_is_edge_inside(const int mcords[][2], - const unsigned int moves, +bool BLI_lasso_is_edge_inside(const int mcoords[][2], + const unsigned int mcoords_len, int x0, int y0, int x1, diff --git a/source/blender/blenlib/BLI_linear_allocator.hh b/source/blender/blenlib/BLI_linear_allocator.hh new file mode 100644 index 00000000000..285af49f500 --- /dev/null +++ b/source/blender/blenlib/BLI_linear_allocator.hh @@ -0,0 +1,220 @@ +/* + * 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. + */ + +/** \file + * \ingroup bli + * + * A linear allocator is the simplest form of an allocator. It never reuses any memory, and + * therefore does not need a deallocation method. It simply hands out consecutive buffers of + * memory. When the current buffer is full, it reallocates a new larger buffer and continues. + */ + +#ifndef __BLI_LINEAR_ALLOCATOR_HH__ +#define __BLI_LINEAR_ALLOCATOR_HH__ + +#include "BLI_string_ref.hh" +#include "BLI_utility_mixins.hh" +#include "BLI_vector.hh" + +namespace BLI { + +template<typename Allocator = GuardedAllocator> class LinearAllocator : NonCopyable, NonMovable { + private: + Allocator m_allocator; + Vector<void *> m_owned_buffers; + Vector<ArrayRef<char>> m_unused_borrowed_buffers; + + uintptr_t m_current_begin; + uintptr_t m_current_end; + uint m_next_min_alloc_size; + +#ifdef DEBUG + uint m_debug_allocated_amount = 0; +#endif + + public: + LinearAllocator() + { + m_current_begin = 0; + m_current_end = 0; + m_next_min_alloc_size = 64; + } + + ~LinearAllocator() + { + for (void *ptr : m_owned_buffers) { + m_allocator.deallocate(ptr); + } + } + + /** + * Get a pointer to a memory buffer with the given size an alignment. The memory buffer will be + * freed when this LinearAllocator is destructed. + * + * The alignment has to be a power of 2. + */ + void *allocate(uint size, uint alignment) + { + BLI_assert(alignment >= 1); + BLI_assert(is_power_of_2_i(alignment)); + +#ifdef DEBUG + m_debug_allocated_amount += size; +#endif + + uintptr_t alignment_mask = alignment - 1; + uintptr_t potential_allocation_begin = (m_current_begin + alignment_mask) & ~alignment_mask; + uintptr_t potential_allocation_end = potential_allocation_begin + size; + + if (potential_allocation_end <= m_current_end) { + m_current_begin = potential_allocation_end; + return (void *)potential_allocation_begin; + } + else { + this->allocate_new_buffer(size + alignment); + return this->allocate(size, alignment); + } + }; + + /** + * Allocate a memory buffer that can hold an instance of T. + * + * This method only allocates memory and does not construct the instance. + */ + template<typename T> T *allocate() + { + return (T *)this->allocate(sizeof(T), alignof(T)); + } + + /** + * Allocate a memory buffer that can hold T array with the given size. + * + * This method only allocates memory and does not construct the instance. + */ + template<typename T> MutableArrayRef<T> allocate_array(uint size) + { + return MutableArrayRef<T>((T *)this->allocate(sizeof(T) * size, alignof(T)), size); + } + + /** + * Construct an instance of T in memory provided by this allocator. + * + * Arguments passed to this method will be forwarded to the constructor of T. + * + * You must not call `delete` on the returned pointer. + * Instead, the destruct has to be called explicitly. + */ + template<typename T, typename... Args> T *construct(Args &&... args) + { + void *buffer = this->allocate(sizeof(T), alignof(T)); + T *value = new (buffer) T(std::forward<Args>(args)...); + return value; + } + + /** + * Copy the given array into a memory buffer provided by this allocator. + */ + template<typename T> MutableArrayRef<T> construct_array_copy(ArrayRef<T> src) + { + MutableArrayRef<T> dst = this->allocate_array<T>(src.size()); + uninitialized_copy_n(src.begin(), src.size(), dst.begin()); + return dst; + } + + /** + * Copy the given string into a memory buffer provided by this allocator. The returned string is + * always null terminated. + */ + StringRefNull copy_string(StringRef str) + { + uint alloc_size = str.size() + 1; + char *buffer = (char *)this->allocate(alloc_size, 1); + str.copy(buffer, alloc_size); + return StringRefNull((const char *)buffer); + } + + MutableArrayRef<void *> allocate_elements_and_pointer_array(uint element_amount, + uint element_size, + uint element_alignment) + { + void *pointer_buffer = this->allocate(element_amount * sizeof(void *), alignof(void *)); + void *elements_buffer = this->allocate(element_amount * element_size, element_alignment); + + MutableArrayRef<void *> pointers((void **)pointer_buffer, element_amount); + void *next_element_buffer = elements_buffer; + for (uint i : IndexRange(element_amount)) { + pointers[i] = next_element_buffer; + next_element_buffer = POINTER_OFFSET(next_element_buffer, element_size); + } + + return pointers; + } + + template<typename T, typename... Args> + ArrayRef<T *> construct_elements_and_pointer_array(uint n, Args &&... args) + { + MutableArrayRef<void *> void_pointers = this->allocate_elements_and_pointer_array( + n, sizeof(T), alignof(T)); + MutableArrayRef<T *> pointers = void_pointers.cast<T *>(); + + for (uint i : IndexRange(n)) { + new (pointers[i]) T(std::forward<Args>(args)...); + } + + return pointers; + } + + /** + * Tell the allocator to use up the given memory buffer, before allocating new memory from the + * system. + */ + void provide_buffer(void *buffer, uint size) + { + m_unused_borrowed_buffers.append(ArrayRef<char>((char *)buffer, size)); + } + + template<uint Size, uint Alignment> + void provide_buffer(AlignedBuffer<Size, Alignment> &aligned_buffer) + { + this->provide_buffer(aligned_buffer.ptr(), Size); + } + + private: + void allocate_new_buffer(uint min_allocation_size) + { + for (uint i : m_unused_borrowed_buffers.index_range()) { + ArrayRef<char> buffer = m_unused_borrowed_buffers[i]; + if (buffer.size() >= min_allocation_size) { + m_unused_borrowed_buffers.remove_and_reorder(i); + m_current_begin = (uintptr_t)buffer.begin(); + m_current_end = (uintptr_t)buffer.end(); + return; + } + } + + uint size_in_bytes = power_of_2_min_u(std::max(min_allocation_size, m_next_min_alloc_size)); + m_next_min_alloc_size = size_in_bytes * 2; + + void *buffer = m_allocator.allocate(size_in_bytes, __func__); + m_owned_buffers.append(buffer); + m_current_begin = (uintptr_t)buffer; + m_current_end = m_current_begin + size_in_bytes; + } +}; + +} // namespace BLI + +#endif /* __BLI_LINEAR_ALLOCATOR_HH__ */ diff --git a/source/blender/blenlib/BLI_listbase_wrapper.h b/source/blender/blenlib/BLI_listbase_wrapper.hh index d6832166e35..02313d9d22d 100644 --- a/source/blender/blenlib/BLI_listbase_wrapper.h +++ b/source/blender/blenlib/BLI_listbase_wrapper.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_LISTBASE_WRAPPER_H__ -#define __BLI_LISTBASE_WRAPPER_H__ +#ifndef __BLI_LISTBASE_WRAPPER_HH__ +#define __BLI_LISTBASE_WRAPPER_HH__ /** \file * \ingroup bli @@ -29,17 +29,17 @@ namespace BLI { -template<typename T> class IntrusiveListBaseWrapper { +template<typename T> class ListBaseWrapper { private: ListBase *m_listbase; public: - IntrusiveListBaseWrapper(ListBase *listbase) : m_listbase(listbase) + ListBaseWrapper(ListBase *listbase) : m_listbase(listbase) { BLI_assert(listbase); } - IntrusiveListBaseWrapper(ListBase &listbase) : IntrusiveListBaseWrapper(&listbase) + ListBaseWrapper(ListBase &listbase) : ListBaseWrapper(&listbase) { } @@ -110,4 +110,4 @@ template<typename T> class IntrusiveListBaseWrapper { } /* namespace BLI */ -#endif /* __BLI_LISTBASE_WRAPPER_H__ */ +#endif /* __BLI_LISTBASE_WRAPPER_HH__ */ diff --git a/source/blender/blenlib/BLI_map.h b/source/blender/blenlib/BLI_map.hh index 4b7ac0791d9..ea5e5da4099 100644 --- a/source/blender/blenlib/BLI_map.h +++ b/source/blender/blenlib/BLI_map.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_MAP_H__ -#define __BLI_MAP_H__ +#ifndef __BLI_MAP_HH__ +#define __BLI_MAP_HH__ /** \file * \ingroup bli @@ -26,9 +26,9 @@ * lookups. Keys and values are stored in groups of four to avoid wasting memory due to padding. */ -#include "BLI_array_ref.h" -#include "BLI_hash_cxx.h" -#include "BLI_open_addressing.h" +#include "BLI_array_ref.hh" +#include "BLI_hash.hh" +#include "BLI_open_addressing.hh" namespace BLI { @@ -53,7 +53,11 @@ namespace BLI { // clang-format on -template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> class Map { +template<typename KeyT, + typename ValueT, + uint32_t InlineBufferCapacity = 4, + typename Allocator = GuardedAllocator> +class Map { private: static constexpr uint OFFSET_MASK = 3; static constexpr uint OFFSET_SHIFT = 2; @@ -65,8 +69,8 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> static constexpr uint8_t IS_DUMMY = 2; uint8_t m_status[4]; - char m_keys[4 * sizeof(KeyT)]; - char m_values[4 * sizeof(ValueT)]; + AlignedBuffer<4 * sizeof(KeyT), alignof(KeyT)> m_keys_buffer; + AlignedBuffer<4 * sizeof(ValueT), alignof(ValueT)> m_values_buffer; public: static constexpr uint slots_per_item = 4; @@ -134,20 +138,18 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> KeyT *key(uint offset) const { - return (KeyT *)(m_keys + offset * sizeof(KeyT)); + return (KeyT *)m_keys_buffer.ptr() + offset; } ValueT *value(uint offset) const { - return (ValueT *)(m_values + offset * sizeof(ValueT)); + return (ValueT *)m_values_buffer.ptr() + offset; } template<typename ForwardKeyT, typename ForwardValueT> void store(uint offset, ForwardKeyT &&key, ForwardValueT &&value) { - BLI_assert(m_status[offset] != IS_SET); - m_status[offset] = IS_SET; - new (this->key(offset)) KeyT(std::forward<ForwardKeyT>(key)); + this->store_without_value(offset, std::forward<ForwardKeyT>(key)); new (this->value(offset)) ValueT(std::forward<ForwardValueT>(value)); } @@ -167,7 +169,7 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> } }; - using ArrayType = OpenAddressingArray<Item, 1, Allocator>; + using ArrayType = OpenAddressingArray<Item, InlineBufferCapacity, Allocator>; ArrayType m_array; public: @@ -351,6 +353,12 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> ITER_SLOTS_END(offset); } + ValueT *lookup_ptr(const KeyT &key) + { + const Map *const_this = this; + return const_cast<ValueT *>(const_this->lookup_ptr(key)); + } + /** * Lookup the value that corresponds to the key. * Asserts when the key does not exist. @@ -362,12 +370,6 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> return *ptr; } - ValueT *lookup_ptr(const KeyT &key) - { - const Map *const_this = this; - return const_cast<ValueT *>(const_this->lookup_ptr(key)); - } - ValueT &lookup(const KeyT &key) { const Map *const_this = this; @@ -406,6 +408,19 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> } /** + * Return the value that corresponds to the given key. + * If it does not exist yet, insert a new default constructed value and return that. + */ + ValueT &lookup_or_add_default(const KeyT &key) + { + return this->lookup_or_add(key, []() { return ValueT(); }); + } + ValueT &lookup_or_add_default(const KeyT &&key) + { + return this->lookup_or_add(std::move(key), []() { return ValueT(); }); + } + + /** * Get the number of elements in the map. */ uint32_t size() const @@ -413,6 +428,17 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> return m_array.slots_set(); } + /** + * Returns true if there are no elements in the map. + */ + bool is_empty() const + { + return this->size() == 0; + } + + /** + * Calls the given function for each key-value-pair. + */ template<typename FuncT> void foreach_item(const FuncT &func) const { for (const Item &item : m_array) { @@ -733,4 +759,4 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> } // namespace BLI -#endif /* __BLI_MAP_H__ */ +#endif /* __BLI_MAP_HH__ */ diff --git a/source/blender/blenlib/BLI_math_base.h b/source/blender/blenlib/BLI_math_base.h index e76c41970c6..c456ab0ecef 100644 --- a/source/blender/blenlib/BLI_math_base.h +++ b/source/blender/blenlib/BLI_math_base.h @@ -93,6 +93,10 @@ static const int NAN_INT = 0x7FC00000; # pragma GCC diagnostic ignored "-Wredundant-decls" #endif +#ifdef __cplusplus +extern "C" { +#endif + /******************************* Float ******************************/ MINLINE float pow2f(float x); @@ -282,4 +286,8 @@ double double_round(double x, int ndigits); # define BLI_ASSERT_UNIT_M3(m) (void)(m) #endif +#ifdef __cplusplus +} +#endif + #endif /* __BLI_MATH_BASE_H__ */ diff --git a/source/blender/blenlib/BLI_math_bits.h b/source/blender/blenlib/BLI_math_bits.h index 71e2d2d9e2c..842fce22f91 100644 --- a/source/blender/blenlib/BLI_math_bits.h +++ b/source/blender/blenlib/BLI_math_bits.h @@ -22,12 +22,12 @@ * \ingroup bli */ +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math_inline.h" - /* Search the value from LSB to MSB for a set bit. Returns index of this bit. */ MINLINE int bitscan_forward_i(int a); MINLINE unsigned int bitscan_forward_uint(unsigned int a); diff --git a/source/blender/blenlib/BLI_math_color.h b/source/blender/blenlib/BLI_math_color.h index 97d0eb1ddda..f247e09a83b 100644 --- a/source/blender/blenlib/BLI_math_color.h +++ b/source/blender/blenlib/BLI_math_color.h @@ -27,12 +27,12 @@ * \ingroup bli */ +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math_inline.h" - /* YCbCr */ #define BLI_YCC_ITU_BT601 0 #define BLI_YCC_ITU_BT709 1 diff --git a/source/blender/blenlib/BLI_math_color_blend.h b/source/blender/blenlib/BLI_math_color_blend.h index 47bafff3a49..60ada1e4509 100644 --- a/source/blender/blenlib/BLI_math_color_blend.h +++ b/source/blender/blenlib/BLI_math_color_blend.h @@ -27,12 +27,12 @@ * \ingroup bli */ +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_math_inline.h" - /******************** Blending Modes ********************** * - byte function assume straight alpha * - float functions assume premultiplied alpha diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index 2049f368578..563bcad5d14 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -27,10 +27,6 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_compiler_attrs.h" #include "BLI_math_inline.h" @@ -39,6 +35,10 @@ extern "C" { # pragma GCC diagnostic ignored "-Wredundant-decls" #endif +#ifdef __cplusplus +extern "C" { +#endif + /********************************** Polygons *********************************/ float normal_tri_v3(float r[3], const float a[3], const float b[3], const float c[3]); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 1221ecfb7b1..2d11797bc34 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -26,13 +26,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_sys_types.h" - /********************************* Init **************************************/ void zero_m2(float R[2][2]); diff --git a/source/blender/blenlib/BLI_math_solvers.h b/source/blender/blenlib/BLI_math_solvers.h index 4bd1a46bb78..193bbdd4e8c 100644 --- a/source/blender/blenlib/BLI_math_solvers.h +++ b/source/blender/blenlib/BLI_math_solvers.h @@ -24,13 +24,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_math_inline.h" - #ifdef BLI_MATH_GCC_WARN_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" diff --git a/source/blender/blenlib/BLI_math_statistics.h b/source/blender/blenlib/BLI_math_statistics.h index b2cc6568abb..a9f9ae39506 100644 --- a/source/blender/blenlib/BLI_math_statistics.h +++ b/source/blender/blenlib/BLI_math_statistics.h @@ -24,13 +24,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_math_inline.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_math_inline.h" - #ifdef BLI_MATH_GCC_WARN_PRAGMA # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wredundant-decls" diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 6cfa2d2ced6..af28e826e84 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -27,14 +27,14 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_compiler_attrs.h" #include "BLI_math_inline.h" #include "BLI_utildefines.h" +#ifdef __cplusplus +extern "C" { +#endif + /************************************* Init ***********************************/ #ifdef BLI_MATH_GCC_WARN_PRAGMA @@ -62,6 +62,11 @@ MINLINE void swap_v4_v4(float a[4], float b[4]); MINLINE void copy_v2_v2_uchar(unsigned char r[2], const unsigned char a[2]); MINLINE void copy_v3_v3_uchar(unsigned char r[3], const unsigned char a[3]); MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4]); + +MINLINE void copy_v2_uchar(unsigned char r[2], const unsigned char a); +MINLINE void copy_v3_uchar(unsigned char r[3], const unsigned char a); +MINLINE void copy_v4_uchar(unsigned char r[4], const unsigned char a); + /* char */ MINLINE void copy_v2_v2_char(char r[2], const char a[2]); MINLINE void copy_v3_v3_char(char r[3], const char a[3]); diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index 5440bdfef60..e0aff82e874 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -24,12 +24,12 @@ #ifndef __BLI_MEMARENA_H__ #define __BLI_MEMARENA_H__ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus 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 diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h index 8bd8642a4e8..8f66ee3b9cb 100644 --- a/source/blender/blenlib/BLI_memblock.h +++ b/source/blender/blenlib/BLI_memblock.h @@ -24,12 +24,12 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" - #define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */ struct BLI_memblock; diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h index fb4a79a491b..4aa9cdb6b6c 100644 --- a/source/blender/blenlib/BLI_memiter.h +++ b/source/blender/blenlib/BLI_memiter.h @@ -21,14 +21,14 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_compiler_attrs.h" #include "BLI_compiler_compat.h" #include "BLI_sys_types.h" +#ifdef __cplusplus +extern "C" { +#endif + /* 512kb, good default for small elems. */ #define BLI_MEMITER_DEFAULT_SIZE (1 << 19) diff --git a/source/blender/blenlib/BLI_memory_utils_cxx.h b/source/blender/blenlib/BLI_memory_utils.hh index 6534138315d..d9acf08a43f 100644 --- a/source/blender/blenlib/BLI_memory_utils_cxx.h +++ b/source/blender/blenlib/BLI_memory_utils.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_MEMORY_UTILS_CXX_H__ -#define __BLI_MEMORY_UTILS_CXX_H__ +#ifndef __BLI_MEMORY_UTILS_HH__ +#define __BLI_MEMORY_UTILS_HH__ /** \file * \ingroup bli @@ -120,4 +120,4 @@ template<uint Size, uint Alignment> class alignas(Alignment) AlignedBuffer { } // namespace BLI -#endif /* __BLI_MEMORY_UTILS_CXX_H__ */ +#endif /* __BLI_MEMORY_UTILS_HH__ */ diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 6491180c2fd..3749f9e1b76 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -24,13 +24,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - struct BLI_mempool; struct BLI_mempool_chunk; diff --git a/source/blender/blenlib/BLI_open_addressing.h b/source/blender/blenlib/BLI_open_addressing.hh index 6a0acd418eb..3bd932350d0 100644 --- a/source/blender/blenlib/BLI_open_addressing.h +++ b/source/blender/blenlib/BLI_open_addressing.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_OPEN_ADDRESSING_H__ -#define __BLI_OPEN_ADDRESSING_H__ +#ifndef __BLI_OPEN_ADDRESSING_HH__ +#define __BLI_OPEN_ADDRESSING_HH__ /** \file * \ingroup bli @@ -33,28 +33,88 @@ #include <cmath> -#include "BLI_allocator.h" +#include "BLI_allocator.hh" +#include "BLI_array.hh" #include "BLI_math_base.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" namespace BLI { -template<typename Item, uint32_t ItemsInSmallStorage = 1, typename Allocator = GuardedAllocator> +/** \name Constexpr utility functions. + * \{ */ + +inline constexpr int is_power_of_2_i_constexpr(int n) +{ + return (n & (n - 1)) == 0; +} + +inline constexpr uint32_t log2_floor_u_constexpr(uint32_t x) +{ + return x <= 1 ? 0 : 1 + log2_floor_u_constexpr(x >> 1); +} + +inline constexpr uint32_t log2_ceil_u_constexpr(uint32_t x) +{ + return (is_power_of_2_i_constexpr((int)x)) ? log2_floor_u_constexpr(x) : + log2_floor_u_constexpr(x) + 1; +} + +template<typename IntT> inline constexpr IntT ceil_division(IntT x, IntT y) +{ + BLI_STATIC_ASSERT(!std::is_signed<IntT>::value, ""); + return x / y + ((x % y) != 0); +} + +template<typename IntT> inline constexpr IntT floor_division(IntT x, IntT y) +{ + BLI_STATIC_ASSERT(!std::is_signed<IntT>::value, ""); + return x / y; +} + +inline constexpr uint8_t compute_item_exponent(uint32_t min_usable_slots, + uint32_t slots_per_item, + uint32_t max_load_factor_numerator, + uint32_t max_load_factor_denominator) +{ + // uint64_t min_total_slots = ceil_division((uint64_t)min_usable_slots * + // (uint64_t)max_load_factor_denominator, + // (uint64_t)max_load_factor_numerator); + // uint32_t min_total_items = (uint32_t)ceil_division(min_total_slots, (uint64_t)slots_per_item); + // uint8_t item_exponent = (uint8_t)log2_ceil_u_constexpr(min_total_items); + // return item_exponent; + + return (uint8_t)log2_ceil_u_constexpr((uint32_t)ceil_division( + ceil_division((uint64_t)min_usable_slots * (uint64_t)max_load_factor_denominator, + (uint64_t)max_load_factor_numerator), + (uint64_t)slots_per_item)); +} + +/** \} */ + +template<typename Item, + uint32_t MinUsableSlotsInSmallStorage = 1, + typename Allocator = GuardedAllocator> class OpenAddressingArray { private: - static constexpr uint32_t slots_per_item = Item::slots_per_item; - static constexpr float max_load_factor = 0.5f; + static constexpr uint32_t s_max_load_factor_numerator = 1; + static constexpr uint32_t s_max_load_factor_denominator = 2; + static constexpr uint32_t s_slots_per_item = Item::slots_per_item; + + static constexpr uint8_t s_small_storage_item_exponent = compute_item_exponent( + MinUsableSlotsInSmallStorage, + s_slots_per_item, + s_max_load_factor_numerator, + s_max_load_factor_denominator); + static constexpr uint32_t s_items_in_small_storage = 1u << s_small_storage_item_exponent; /* Invariants: * 2^m_item_exponent = m_item_amount - * m_item_amount * slots_per_item = m_slots_total + * m_item_amount * s_slots_per_item = m_slots_total * m_slot_mask = m_slots_total - 1 * m_slots_set_or_dummy < m_slots_total */ - /* Array containing the actual hash table. Might be a pointer to the inlined storage. */ - Item *m_items; /* Number of items in the hash table. Must be a power of two. */ uint32_t m_item_amount; /* Exponent of the current item amount. */ @@ -69,65 +129,28 @@ class OpenAddressingArray { uint32_t m_slots_usable; /* Can be used to map a hash value into the range of valid slot indices. */ uint32_t m_slot_mask; - Allocator m_allocator; - AlignedBuffer<sizeof(Item) * ItemsInSmallStorage, alignof(Item)> m_local_storage; + + Array<Item, s_items_in_small_storage, Allocator> m_items; public: - explicit OpenAddressingArray(uint8_t item_exponent = 0) + explicit OpenAddressingArray(uint8_t item_exponent = s_small_storage_item_exponent) { - m_slots_total = ((uint32_t)1 << item_exponent) * slots_per_item; + m_item_exponent = item_exponent; + m_item_amount = 1u << item_exponent; + m_slots_total = m_item_amount * s_slots_per_item; + m_slot_mask = m_slots_total - 1; m_slots_set_or_dummy = 0; m_slots_dummy = 0; - m_slots_usable = (uint32_t)((float)m_slots_total * max_load_factor); - m_slot_mask = m_slots_total - 1; - m_item_amount = m_slots_total / slots_per_item; - m_item_exponent = item_exponent; + m_slots_usable = (uint32_t)floor_division((uint64_t)m_slots_total * + (uint64_t)s_max_load_factor_numerator, + (uint64_t)s_max_load_factor_denominator); - if (m_item_amount <= ItemsInSmallStorage) { - m_items = this->small_storage(); - } - else { - m_items = (Item *)m_allocator.allocate_aligned( - (uint32_t)sizeof(Item) * m_item_amount, std::alignment_of<Item>::value, __func__); - } - - for (uint32_t i = 0; i < m_item_amount; i++) { - new (m_items + i) Item(); - } + m_items = Array<Item, s_items_in_small_storage, Allocator>(m_item_amount); } - ~OpenAddressingArray() - { - if (m_items != nullptr) { - for (uint32_t i = 0; i < m_item_amount; i++) { - m_items[i].~Item(); - } - if (!this->is_in_small_storage()) { - m_allocator.deallocate((void *)m_items); - } - } - } - - OpenAddressingArray(const OpenAddressingArray &other) - { - m_slots_total = other.m_slots_total; - m_slots_set_or_dummy = other.m_slots_set_or_dummy; - m_slots_dummy = other.m_slots_dummy; - m_slots_usable = other.m_slots_usable; - m_slot_mask = other.m_slot_mask; - m_item_amount = other.m_item_amount; - m_item_exponent = other.m_item_exponent; - - if (m_item_amount <= ItemsInSmallStorage) { - m_items = this->small_storage(); - } - else { - m_items = (Item *)m_allocator.allocate_aligned( - sizeof(Item) * m_item_amount, std::alignment_of<Item>::value, __func__); - } + ~OpenAddressingArray() = default; - uninitialized_copy_n(other.m_items, m_item_amount, m_items); - } + OpenAddressingArray(const OpenAddressingArray &other) = default; OpenAddressingArray(OpenAddressingArray &&other) noexcept { @@ -138,15 +161,8 @@ class OpenAddressingArray { m_slot_mask = other.m_slot_mask; m_item_amount = other.m_item_amount; m_item_exponent = other.m_item_exponent; - if (other.is_in_small_storage()) { - m_items = this->small_storage(); - uninitialized_relocate_n(other.m_items, m_item_amount, m_items); - } - else { - m_items = other.m_items; - } + m_items = std::move(other.m_items); - other.m_items = nullptr; other.~OpenAddressingArray(); new (&other) OpenAddressingArray(); } @@ -171,13 +187,19 @@ class OpenAddressingArray { return *this; } + Allocator &allocator() + { + return m_items.allocator(); + } + /* Prepare a new array that can hold a minimum of min_usable_slots elements. All entries are * empty. */ OpenAddressingArray init_reserved(uint32_t min_usable_slots) const { - float min_total_slots = (float)min_usable_slots / max_load_factor; - uint32_t min_total_items = (uint32_t)std::ceil(min_total_slots / (float)slots_per_item); - uint8_t item_exponent = (uint8_t)log2_ceil_u(min_total_items); + uint8_t item_exponent = compute_item_exponent(min_usable_slots, + s_slots_per_item, + s_max_load_factor_numerator, + s_max_load_factor_denominator); OpenAddressingArray grown(item_exponent); grown.m_slots_set_or_dummy = this->slots_set(); return grown; @@ -270,36 +292,25 @@ class OpenAddressingArray { Item *begin() { - return m_items; + return m_items.begin(); } Item *end() { - return m_items + m_item_amount; + return m_items.end(); } const Item *begin() const { - return m_items; + return m_items.begin(); } const Item *end() const { - return m_items + m_item_amount; - } - - private: - Item *small_storage() const - { - return reinterpret_cast<Item *>((char *)m_local_storage.ptr()); - } - - bool is_in_small_storage() const - { - return m_items == this->small_storage(); + return m_items.end(); } }; } // namespace BLI -#endif /* __BLI_OPEN_ADDRESSING_H__ */ +#endif /* __BLI_OPEN_ADDRESSING_HH__ */ diff --git a/source/blender/blenlib/BLI_optional.h b/source/blender/blenlib/BLI_optional.hh index 267c858e0f2..eac11293781 100644 --- a/source/blender/blenlib/BLI_optional.h +++ b/source/blender/blenlib/BLI_optional.hh @@ -20,10 +20,10 @@ * Simple version of std::optional, which is only available since C++17. */ -#ifndef __BLI_OPTIONAL_H__ -#define __BLI_OPTIONAL_H__ +#ifndef __BLI_OPTIONAL_HH__ +#define __BLI_OPTIONAL_HH__ -#include "BLI_memory_utils_cxx.h" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" #include <algorithm> @@ -196,4 +196,4 @@ template<typename T> class Optional { } /* namespace BLI */ -#endif /* __BLI_OPTIONAL_H__ */ +#endif /* __BLI_OPTIONAL_HH__ */ diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 9a6a14547d2..30823773d6c 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -23,13 +23,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1); void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); const char *BLI_getenv(const char *env) ATTR_NONNULL(1); diff --git a/source/blender/blenlib/BLI_scanfill.h b/source/blender/blenlib/BLI_scanfill.h index 39d3a679eb3..376ea9d88de 100644 --- a/source/blender/blenlib/BLI_scanfill.h +++ b/source/blender/blenlib/BLI_scanfill.h @@ -36,7 +36,7 @@ typedef struct ScanFillContext { ListBase fillfacebase; /* increment this value before adding each curve to skip having to calculate - * 'poly_nr' for edges and verts (which can take approx half scanfill time) */ + * 'poly_nr' for edges and verts (which can take approx half scan-fill time) */ unsigned short poly_nr; /* private */ @@ -46,9 +46,9 @@ typedef struct ScanFillContext { #define BLI_SCANFILL_ARENA_SIZE MEM_SIZE_OPTIMAL(1 << 14) /** - * \note this is USHRT_MAX so incrementing will set to zero + * \note this is USHRT_MAX so incrementing will set to zero * which happens if callers choose to increment #ScanFillContext.poly_nr before adding each curve. - * Nowhere else in scanfill do we make use of intentional overflow like this. + * Nowhere else in scan-fill do we make use of intentional overflow like this. */ #define SF_POLY_UNSET ((unsigned short)-1) @@ -64,7 +64,7 @@ typedef struct ScanFillVert { float co[3]; /** 2D projection of vertex location */ float xy[2]; - /** index, caller can use how it likes to match the scanfill result with own data */ + /** index, caller can use how it likes to match the scan-fill result with own data */ unsigned int keyindex; unsigned short poly_nr; /** number of edges using this vertex */ diff --git a/source/blender/blenlib/BLI_set.h b/source/blender/blenlib/BLI_set.hh index dc101add1a7..dc9df5d116a 100644 --- a/source/blender/blenlib/BLI_set.h +++ b/source/blender/blenlib/BLI_set.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_SET_H__ -#define __BLI_SET_H__ +#ifndef __BLI_SET_HH__ +#define __BLI_SET_HH__ /** \file * \ingroup bli @@ -23,9 +23,9 @@ * This file provides a set implementation that uses open addressing with probing. */ -#include "BLI_hash_cxx.h" -#include "BLI_open_addressing.h" -#include "BLI_vector.h" +#include "BLI_hash.hh" +#include "BLI_open_addressing.hh" +#include "BLI_vector.hh" namespace BLI { @@ -50,7 +50,8 @@ namespace BLI { // clang-format on -template<typename T, typename Allocator = GuardedAllocator> class Set { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Set { private: static constexpr uint OFFSET_MASK = 3; static constexpr uint OFFSET_SHIFT = 2; @@ -62,7 +63,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { static constexpr uint8_t IS_DUMMY = 2; uint8_t m_status[4]; - char m_values[4 * sizeof(T)]; + AlignedBuffer<4 * sizeof(T), alignof(T)> m_buffer; public: static constexpr uint slots_per_item = 4; @@ -114,7 +115,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { T *value(uint offset) const { - return (T *)(m_values + offset * sizeof(T)); + return (T *)m_buffer.ptr() + offset; } template<typename ForwardT> void store(uint offset, ForwardT &&value) @@ -153,8 +154,8 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { } }; - using ArrayType = OpenAddressingArray<Item, 1, Allocator>; - ArrayType m_array = OpenAddressingArray<Item>(); + using ArrayType = OpenAddressingArray<Item, InlineBufferCapacity, Allocator>; + ArrayType m_array; public: Set() = default; @@ -202,6 +203,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { /** * Add a new value to the set if it does not exist yet. + * Returns true of the value has been newly added. */ bool add(const T &value) { @@ -266,19 +268,26 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { ITER_SLOTS_END(offset); } - Vector<T> to_small_vector() const + /** + * Get the amount of values stored in the set. + */ + uint32_t size() const { - Vector<T> vector; - vector.reserve(this->size()); - for (const T &value : *this) { - vector.append(value); - } - return vector; + return m_array.slots_set(); } - uint32_t size() const + /** + * Return true if this set contains no elements. + */ + bool is_empty() const { - return m_array.slots_set(); + return this->size() == 0; + } + + void clear() + { + this->~Set(); + new (this) Set(); } /** @@ -480,4 +489,4 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { } // namespace BLI -#endif /* __BLI_SET_H__ */ +#endif /* __BLI_SET_HH__ */ diff --git a/source/blender/blenlib/BLI_stack.h b/source/blender/blenlib/BLI_stack.h index 9d122fdf798..9fc25e378a3 100644 --- a/source/blender/blenlib/BLI_stack.h +++ b/source/blender/blenlib/BLI_stack.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenlib/BLI_stack_cxx.h b/source/blender/blenlib/BLI_stack.hh index a26318a3dcb..7f1f9f9cc10 100644 --- a/source/blender/blenlib/BLI_stack_cxx.h +++ b/source/blender/blenlib/BLI_stack.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_STACK_CXX_H__ -#define __BLI_STACK_CXX_H__ +#ifndef __BLI_STACK_HH__ +#define __BLI_STACK_HH__ /** \file * \ingroup bli @@ -23,13 +23,14 @@ * Basic stack implementation with support for small object optimization. */ -#include "BLI_vector.h" +#include "BLI_vector.hh" namespace BLI { -template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Stack { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Stack { private: - Vector<T, N, Allocator> m_elements; + Vector<T, InlineBufferCapacity, Allocator> m_elements; public: Stack() = default; @@ -147,4 +148,4 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St } /* namespace BLI */ -#endif /* __BLI_STACK_CXX_H__ */ +#endif /* __BLI_STACK_HH__ */ diff --git a/source/blender/blenlib/BLI_string.h b/source/blender/blenlib/BLI_string.h index 6d3f38c7a52..00e4e3485d1 100644 --- a/source/blender/blenlib/BLI_string.h +++ b/source/blender/blenlib/BLI_string.h @@ -27,13 +27,13 @@ #include <inttypes.h> #include <stdarg.h> +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - char *BLI_strdupn(const char *str, const size_t len) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); diff --git a/source/blender/blenlib/BLI_string_map.h b/source/blender/blenlib/BLI_string_map.hh index f304b140bcc..caa7e16d1f3 100644 --- a/source/blender/blenlib/BLI_string_map.h +++ b/source/blender/blenlib/BLI_string_map.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_STRING_MAP_H__ -#define __BLI_STRING_MAP_H__ +#ifndef __BLI_STRING_MAP_HH__ +#define __BLI_STRING_MAP_HH__ /** \file * \ingroup bli @@ -27,10 +27,10 @@ * make it more efficient later on. Also, even if we will never implement this optimization, having * a special map with string keys can be quite handy. */ -#include "BLI_map.h" -#include "BLI_optional.h" -#include "BLI_string_ref.h" -#include "BLI_vector.h" +#include "BLI_map.hh" +#include "BLI_optional.hh" +#include "BLI_string_ref.hh" +#include "BLI_vector.hh" namespace BLI { @@ -156,10 +156,15 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { template<typename ForwardT> void store(uint offset, uint32_t hash, uint32_t index, ForwardT &&value) { + this->store_without_value(offset, hash, index); + new (this->value(offset)) T(std::forward<ForwardT>(value)); + } + + void store_without_value(uint offset, uint32_t hash, uint32_t index) + { BLI_assert(!this->is_set(offset)); m_hashes[offset] = hash; m_indices[offset] = index; - new (this->value(offset)) T(std::forward<ForwardT>(value)); } }; @@ -195,15 +200,51 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { */ void add(StringRef key, const T &value) { - if (!this->contains(key)) { - this->add_new(key, value); - } + this->add__impl(key, value); } void add(StringRef key, T &&value) { - if (!this->contains(key)) { - this->add_new(key, std::move(value)); + this->add__impl(key, std::move(value)); + } + + /** + * First, checks if the key exists in the map. + * If it does exist, call the modify function with a pointer to the corresponding value. + * If it does not exist, call the create function with a pointer to where the value should be + * created. + * + * Returns whatever is returned from one of the callback functions. Both callbacks have to return + * the same type. + * + * CreateValueF: Takes a pointer to where the value should be created. + * ModifyValueF: Takes a pointer to the value that should be modified. + */ + template<typename CreateValueF, typename ModifyValueF> + auto add_or_modify(StringRef key, + const CreateValueF &create_value, + const ModifyValueF &modify_value) -> decltype(create_value(nullptr)) + { + using CreateReturnT = decltype(create_value(nullptr)); + using ModifyReturnT = decltype(modify_value(nullptr)); + BLI_STATIC_ASSERT((std::is_same<CreateReturnT, ModifyReturnT>::value), + "Both callbacks should return the same type."); + + this->ensure_can_add(); + uint32_t hash = this->compute_string_hash(key); + ITER_SLOTS_BEGIN (hash, m_array, , item, offset) { + if (item.is_empty(offset)) { + m_array.update__empty_to_set(); + uint32_t index = this->save_key_in_array(key); + item.store_without_value(offset, hash, index); + T *value_ptr = item.value(offset); + return create_value(value_ptr); + } + else if (item.has_hash(offset, hash) && item.has_exact_key(offset, key, m_chars)) { + T *value_ptr = item.value(offset); + return modify_value(value_ptr); + } } + ITER_SLOTS_END(offset); } /** @@ -301,6 +342,27 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { } /** + * Return the value that corresponds to the given key. + * If it does not exist yet, create and insert it first. + */ + template<typename CreateValueF> T &lookup_or_add(StringRef key, const CreateValueF &create_value) + { + return *this->add_or_modify( + key, + [&](T *value) { return new (value) T(create_value()); }, + [](T *value) { return value; }); + } + + /** + * Return the value that corresponds to the given key. + * If it does not exist yet, insert a new default constructed value and return that. + */ + T &lookup_or_add_default(StringRef key) + { + return this->lookup_or_add(key, []() { return T(); }); + } + + /** * Do a linear search over all items to find a key for a value. */ StringRefNull find_key_for_value(const T &value) const @@ -435,6 +497,24 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { ITER_SLOTS_END(offset); } + template<typename ForwardT> bool add__impl(StringRef key, ForwardT &&value) + { + this->ensure_can_add(); + uint32_t hash = this->compute_string_hash(key); + ITER_SLOTS_BEGIN (hash, m_array, , item, offset) { + if (item.is_empty(offset)) { + uint32_t index = this->save_key_in_array(key); + item.store(offset, hash, index, std::forward<ForwardT>(value)); + m_array.update__empty_to_set(); + return true; + } + else if (item.has_hash(offset, hash) && item.has_exact_key(offset, key, m_chars)) { + return false; + } + } + ITER_SLOTS_END(offset); + } + template<typename ForwardT> void add_new__impl(StringRef key, ForwardT &&value) { BLI_assert(!this->contains(key)); @@ -457,4 +537,4 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { } // namespace BLI -#endif /* __BLI_STRING_MAP_H__ */ +#endif /* __BLI_STRING_MAP_HH__ */ diff --git a/source/blender/blenlib/BLI_string_ref.h b/source/blender/blenlib/BLI_string_ref.hh index 2389542bcea..eacc501375a 100644 --- a/source/blender/blenlib/BLI_string_ref.h +++ b/source/blender/blenlib/BLI_string_ref.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_STRING_REF_H__ -#define __BLI_STRING_REF_H__ +#ifndef __BLI_STRING_REF_HH__ +#define __BLI_STRING_REF_HH__ /** \file * \ingroup bli @@ -32,7 +32,7 @@ #include <sstream> #include <string> -#include "BLI_array_ref.h" +#include "BLI_array_ref.hh" #include "BLI_utildefines.h" namespace BLI { @@ -94,12 +94,28 @@ class StringRefBase { return m_data + m_size; } - void copy_to__with_null(char *dst) const + void unsafe_copy(char *dst) const { memcpy(dst, m_data, m_size); dst[m_size] = '\0'; } + void copy(char *dst, uint dst_size) const + { + if (m_size < dst_size) { + this->unsafe_copy(dst); + } + else { + BLI_assert(false); + dst[0] = '\0'; + } + } + + template<uint N> void copy(char (&dst)[N]) + { + this->copy(dst, N); + } + /** * Returns true when the string begins with the given prefix. Otherwise false. */ @@ -252,4 +268,4 @@ inline StringRef StringRefBase::substr(uint start, uint size) const } // namespace BLI -#endif /* __BLI_STRING_REF_H__ */ +#endif /* __BLI_STRING_REF_HH__ */ diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 8d986d45a17..78e7113b6ef 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -21,13 +21,13 @@ * \ingroup bli */ +#include "BLI_compiler_attrs.h" +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_sys_types.h" - char *BLI_strncpy_utf8(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL(); size_t BLI_strncpy_utf8_rlen(char *__restrict dst, const char *__restrict src, size_t maxncpy) diff --git a/source/blender/blenlib/BLI_string_utils.h b/source/blender/blenlib/BLI_string_utils.h index 7b0dd13e0c7..857b22540e9 100644 --- a/source/blender/blenlib/BLI_string_utils.h +++ b/source/blender/blenlib/BLI_string_utils.h @@ -26,13 +26,13 @@ #include <stdarg.h> +#include "BLI_compiler_attrs.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_compiler_attrs.h" -#include "BLI_utildefines.h" - struct ListBase; typedef bool (*UniquenameCheckCallback)(void *arg, const char *name); diff --git a/source/blender/blenlib/BLI_sys_types.h b/source/blender/blenlib/BLI_sys_types.h index b9e799aa2a9..ef15ce111b6 100644 --- a/source/blender/blenlib/BLI_sys_types.h +++ b/source/blender/blenlib/BLI_sys_types.h @@ -73,7 +73,7 @@ typedef uint64_t u_int64_t; #include <stddef.h> /* size_t define */ #ifndef __cplusplus -# if defined(__APPLE__) +# if defined(__APPLE__) || defined(__NetBSD__) /* The <uchar.h> standard header is missing on macOS. */ typedef unsigned int char32_t; # else diff --git a/source/blender/blenlib/BLI_system.h b/source/blender/blenlib/BLI_system.h index 8c0c9ad99bf..50f8adc20f6 100644 --- a/source/blender/blenlib/BLI_system.h +++ b/source/blender/blenlib/BLI_system.h @@ -53,6 +53,10 @@ int BLI_system_memory_max_in_megabytes_int(void); /* getpid */ #ifdef WIN32 # define BLI_SYSTEM_PID_H <process.h> + +/* void* since we really do not want to drag Windows.h in to get the proper typedef. */ +void BLI_windows_handle_exception(void *exception); + #else # define BLI_SYSTEM_PID_H <unistd.h> #endif diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index 898e4be5f92..64dfdc2ad25 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -25,13 +25,13 @@ struct ListBase; * \ingroup bli */ +#include "BLI_threads.h" +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_threads.h" -#include "BLI_utildefines.h" - struct BLI_mempool; /* Task Scheduler @@ -43,16 +43,13 @@ struct BLI_mempool; * must be called from the main threads. All other scheduler and pool functions * are thread-safe. */ -typedef struct TaskScheduler TaskScheduler; - -TaskScheduler *BLI_task_scheduler_create(int num_threads); -void BLI_task_scheduler_free(TaskScheduler *scheduler); - -int BLI_task_scheduler_num_threads(TaskScheduler *scheduler); +void BLI_task_scheduler_init(void); +void BLI_task_scheduler_exit(void); +int BLI_task_scheduler_num_threads(void); /* Task Pool * - * Pool of tasks that will be executed by the central TaskScheduler. For each + * Pool of tasks that will be executed by the central task scheduler. For each * pool, we can wait for all tasks to be done, or cancel them before they are * done. * @@ -70,16 +67,30 @@ typedef enum TaskPriority { } TaskPriority; typedef struct TaskPool TaskPool; -typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata, int threadid); -typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata, int threadid); - -TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPriority priority); -TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority); -TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority); +typedef void (*TaskRunFunction)(TaskPool *__restrict pool, void *taskdata); +typedef void (*TaskFreeFunction)(TaskPool *__restrict pool, void *taskdata); + +/* Regular task pool that immediately starts executing tasks as soon as they + * are pushed, either on the current or another thread. */ +TaskPool *BLI_task_pool_create(void *userdata, TaskPriority priority); + +/* Background: always run tasks in a background thread, never immediately + * execute them. For running background jobs. */ +TaskPool *BLI_task_pool_create_background(void *userdata, TaskPriority priority); + +/* Background Serial: run tasks one after the other in the background, + * without parallelization between the tasks. */ +TaskPool *BLI_task_pool_create_background_serial(void *userdata, TaskPriority priority); + +/* Suspended: don't execute tasks until work_and_wait is called. This is slower + * as threads can't immediately start working. But it can be used if the data + * structures the threads operate on are not fully initialized until all tasks + * are created. */ +TaskPool *BLI_task_pool_create_suspended(void *userdata, TaskPriority priority); + +/* No threads: immediately executes tasks on the same thread. For debugging. */ +TaskPool *BLI_task_pool_create_no_threads(void *userdata); + void BLI_task_pool_free(TaskPool *pool); void BLI_task_pool_push(TaskPool *pool, @@ -87,17 +98,9 @@ void BLI_task_pool_push(TaskPool *pool, void *taskdata, bool free_taskdata, TaskFreeFunction freedata); -void BLI_task_pool_push_from_thread(TaskPool *pool, - TaskRunFunction run, - void *taskdata, - bool free_taskdata, - TaskFreeFunction freedata, - int thread_id); /* work and wait until all tasks are done */ void BLI_task_pool_work_and_wait(TaskPool *pool); -/* work and wait until all tasks are done, then reset to the initial suspended state */ -void BLI_task_pool_work_wait_and_reset(TaskPool *pool); /* cancel all tasks, keep worker threads running */ void BLI_task_pool_cancel(TaskPool *pool); @@ -105,53 +108,29 @@ void BLI_task_pool_cancel(TaskPool *pool); bool BLI_task_pool_canceled(TaskPool *pool); /* optional userdata pointer to pass along to run function */ -void *BLI_task_pool_userdata(TaskPool *pool); +void *BLI_task_pool_user_data(TaskPool *pool); /* optional mutex to use from run function */ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool); -/* Thread ID of thread that created the task pool. */ -int BLI_task_pool_creator_thread_id(TaskPool *pool); - -/* Delayed push, use that to reduce thread overhead by accumulating - * all new tasks into local queue first and pushing it to scheduler - * from within a single mutex lock. - */ -void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id); -void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id); - /* Parallel for routines */ -typedef enum eTaskSchedulingMode { - /* Task scheduler will divide overall work into equal chunks, scheduling - * even chunks to all worker threads. - * Least run time benefit, ideal for cases when each task requires equal - * amount of compute power. - */ - TASK_SCHEDULING_STATIC, - /* Task scheduler will schedule small amount of work to each worker thread. - * Has more run time overhead, but deals much better with cases when each - * part of the work requires totally different amount of compute power. - */ - TASK_SCHEDULING_DYNAMIC, -} eTaskSchedulingMode; - /* Per-thread specific data passed to the callback. */ typedef struct TaskParallelTLS { - /* Identifier of the thread who this data belongs to. */ - int thread_id; /* Copy of user-specifier chunk, which is copied from original chunk to all * worker threads. This is similar to OpenMP's firstprivate. */ void *userdata_chunk; } TaskParallelTLS; -typedef void (*TaskParallelFinalizeFunc)(void *__restrict userdata, - void *__restrict userdata_chunk); - typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls); +typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, + void *__restrict chunk_join, + void *__restrict chunk); + +typedef void (*TaskParallelFreeFunc)(const void *__restrict userdata, void *__restrict chunk); typedef struct TaskParallelSettings { /* Whether caller allows to do threading of the particular range. @@ -161,8 +140,6 @@ typedef struct TaskParallelSettings { * is higher than a chunk size. As in, threading will always be performed. */ bool use_threading; - /* Scheduling mode to use for this parallel range invocation. */ - eTaskSchedulingMode scheduling_mode; /* Each instance of looping chunks will get a copy of this data * (similar to OpenMP's firstprivate). */ @@ -171,7 +148,13 @@ typedef struct TaskParallelSettings { /* Function called from calling thread once whole range have been * processed. */ - TaskParallelFinalizeFunc func_finalize; + /* Function called to join user data chunk into another, to reduce + * the result to the original userdata_chunk memory. + * The reduce functions should have no side effects, so that they + * can be run on any thread. */ + TaskParallelReduceFunc func_reduce; + /* Function called to free data created by TaskParallelRangeFunc. */ + TaskParallelFreeFunc func_free; /* Minimum allowed number of range iterators to be handled by a single * thread. This allows to achieve following: * - Reduce amount of threading overhead. @@ -191,19 +174,7 @@ void BLI_task_parallel_range(const int start, const int stop, void *userdata, TaskParallelRangeFunc func, - TaskParallelSettings *settings); - -typedef struct TaskParallelRangePool TaskParallelRangePool; -struct TaskParallelRangePool *BLI_task_parallel_range_pool_init( - const struct TaskParallelSettings *settings); -void BLI_task_parallel_range_pool_push(struct TaskParallelRangePool *range_pool, - const int start, - const int stop, - void *userdata, - TaskParallelRangeFunc func, - const struct TaskParallelSettings *settings); -void BLI_task_parallel_range_pool_work_and_wait(struct TaskParallelRangePool *range_pool); -void BLI_task_parallel_range_pool_free(struct TaskParallelRangePool *range_pool); + const TaskParallelSettings *settings); /* This data is shared between all tasks, its access needs thread lock or similar protection. */ @@ -258,11 +229,14 @@ BLI_INLINE void BLI_parallel_range_settings_defaults(TaskParallelSettings *setti { memset(settings, 0, sizeof(*settings)); settings->use_threading = true; - settings->scheduling_mode = TASK_SCHEDULING_STATIC; /* Use default heuristic to define actual chunk size. */ settings->min_iter_per_thread = 0; } +/* Don't use this, store any thread specific data in tls->userdata_chunk instead. + * Only here for code to be removed. */ +int BLI_task_parallel_thread_id(const TaskParallelTLS *tls); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index c2127c1ec3a..c199417017b 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -23,9 +23,6 @@ /** \file * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif #include <pthread.h> @@ -35,6 +32,10 @@ extern "C" { # include <libkern/OSAtomic.h> #endif +#ifdef __cplusplus +extern "C" { +#endif + /* for tables, button in UI, etc */ #define BLENDER_MAX_THREADS 1024 @@ -47,8 +48,6 @@ struct TaskScheduler; void BLI_threadapi_init(void); void BLI_threadapi_exit(void); -struct TaskScheduler *BLI_task_scheduler_get(void); - void BLI_threadpool_init(struct ListBase *threadbase, void *(*do_thread)(void *), int tot); int BLI_available_threads(struct ListBase *threadbase); int BLI_threadpool_available_thread_index(struct ListBase *threadbase); diff --git a/source/blender/blenlib/BLI_timeit.hh b/source/blender/blenlib/BLI_timeit.hh new file mode 100644 index 00000000000..e9f121ec654 --- /dev/null +++ b/source/blender/blenlib/BLI_timeit.hh @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#ifndef __BLI_TIMEIT_HH__ +#define __BLI_TIMEIT_HH__ + +#include <chrono> +#include <iostream> +#include <string> + +#include "BLI_sys_types.h" + +namespace BLI { +namespace Timeit { + +using Clock = std::chrono::steady_clock; +using TimePoint = Clock::time_point; +using Nanoseconds = std::chrono::nanoseconds; + +void print_duration(Nanoseconds duration); + +class ScopedTimer { + private: + std::string m_name; + TimePoint m_start; + + public: + ScopedTimer(std::string name) : m_name(std::move(name)) + { + m_start = Clock::now(); + } + + ~ScopedTimer() + { + TimePoint end = Clock::now(); + Nanoseconds duration = end - m_start; + + std::cout << "Timer '" << m_name << "' took "; + print_duration(duration); + std::cout << '\n'; + } +}; + +} // namespace Timeit +} // namespace BLI + +#define SCOPED_TIMER(name) BLI::Timeit::ScopedTimer scoped_timer(name) + +#endif /* __BLI_TIMEIT_HH__ */ diff --git a/source/blender/blenlib/BLI_utildefines.h b/source/blender/blenlib/BLI_utildefines.h index fb5dbf66819..1f28f7e80c5 100644 --- a/source/blender/blenlib/BLI_utildefines.h +++ b/source/blender/blenlib/BLI_utildefines.h @@ -24,10 +24,6 @@ * \ingroup bli */ -#ifdef __cplusplus -extern "C" { -#endif - /* avoid many includes for now */ #include "BLI_compiler_compat.h" #include "BLI_sys_types.h" @@ -39,6 +35,10 @@ extern "C" { /* include after _VA_NARGS macro */ #include "BLI_compiler_typecheck.h" +#ifdef __cplusplus +extern "C" { +#endif + /* -------------------------------------------------------------------- */ /** \name Min/Max Macros * \{ */ diff --git a/source/blender/blenlib/BLI_utility_mixins.h b/source/blender/blenlib/BLI_utility_mixins.hh index ce7a4ce094a..441575f9111 100644 --- a/source/blender/blenlib/BLI_utility_mixins.h +++ b/source/blender/blenlib/BLI_utility_mixins.hh @@ -18,8 +18,8 @@ * \ingroup bli */ -#ifndef __BLI_UTILITY_MIXINS_H__ -#define __BLI_UTILITY_MIXINS_H__ +#ifndef __BLI_UTILITY_MIXINS_HH__ +#define __BLI_UTILITY_MIXINS_HH__ namespace BLI { @@ -49,4 +49,4 @@ class NonMovable { } // namespace BLI -#endif /* __BLI_UTILITY_MIXINS_H__ */ +#endif /* __BLI_UTILITY_MIXINS_HH__ */ diff --git a/source/blender/blenlib/BLI_vector.h b/source/blender/blenlib/BLI_vector.hh index 6a708759d0e..49cf41c2005 100644 --- a/source/blender/blenlib/BLI_vector.h +++ b/source/blender/blenlib/BLI_vector.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_VECTOR_H__ -#define __BLI_VECTOR_H__ +#ifndef __BLI_VECTOR_HH__ +#define __BLI_VECTOR_HH__ /** \file * \ingroup bli @@ -31,25 +31,26 @@ #include <iostream> #include <memory> -#include "BLI_allocator.h" -#include "BLI_array_ref.h" -#include "BLI_index_range.h" -#include "BLI_listbase_wrapper.h" +#include "BLI_allocator.hh" +#include "BLI_array_ref.hh" +#include "BLI_index_range.hh" +#include "BLI_listbase_wrapper.hh" #include "BLI_math_base.h" -#include "BLI_memory_utils_cxx.h" +#include "BLI_memory_utils.hh" #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" namespace BLI { -template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Vector { +template<typename T, uint InlineBufferCapacity = 4, typename Allocator = GuardedAllocator> +class Vector { private: T *m_begin; T *m_end; T *m_capacity_end; Allocator m_allocator; - AlignedBuffer<sizeof(T) * N, alignof(T)> m_small_buffer; + AlignedBuffer<(uint)sizeof(T) * InlineBufferCapacity, (uint)alignof(T)> m_small_buffer; #ifndef NDEBUG /* Storing size in debug builds, because it makes debugging much easier sometimes. */ @@ -70,7 +71,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve { m_begin = this->small_buffer(); m_end = m_begin; - m_capacity_end = m_begin + N; + m_capacity_end = m_begin + InlineBufferCapacity; UPDATE_VECTOR_SIZE(this); } @@ -130,20 +131,17 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve /** * Create a vector from a ListBase. */ - Vector(ListBase &values, bool intrusive_next_and_prev_pointers) : Vector() + Vector(ListBase &values) : Vector() { - BLI_assert(intrusive_next_and_prev_pointers); - if (intrusive_next_and_prev_pointers) { - for (T value : IntrusiveListBaseWrapper<typename std::remove_pointer<T>::type>(values)) { - this->append(value); - } + for (T value : ListBaseWrapper<typename std::remove_pointer<T>::type>(values)) { + this->append(value); } } /** * Create a copy of another vector. * The other vector will not be changed. - * If the other vector has less than N elements, no allocation will be made. + * If the other vector has less than InlineBufferCapacity elements, no allocation will be made. */ Vector(const Vector &other) : m_allocator(other.m_allocator) { @@ -167,11 +165,11 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve uint size = other.size(); if (other.is_small()) { - if (size <= N) { + if (size <= InlineBufferCapacity) { /* Copy between inline buffers. */ m_begin = this->small_buffer(); m_end = m_begin + size; - m_capacity_end = m_begin + N; + m_capacity_end = m_begin + InlineBufferCapacity; uninitialized_relocate_n(other.m_begin, size, m_begin); } else { @@ -286,7 +284,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve m_begin = this->small_buffer(); m_end = m_begin; - m_capacity_end = m_begin + N; + m_capacity_end = m_begin + InlineBufferCapacity; UPDATE_VECTOR_SIZE(this); } @@ -429,7 +427,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve /** * Returns true when the vector contains no elements, otherwise false. */ - bool empty() const + bool is_empty() const { return m_begin == m_end; } @@ -440,7 +438,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve */ void remove_last() { - BLI_assert(!this->empty()); + BLI_assert(!this->is_empty()); m_end--; destruct(m_end); UPDATE_VECTOR_SIZE(this); @@ -451,7 +449,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve */ T pop_last() { - BLI_assert(!this->empty()); + BLI_assert(!this->is_empty()); m_end--; T value = std::move(*m_end); destruct(m_end); @@ -581,7 +579,8 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve std::cout << "Small Vector at " << (void *)this << ":" << std::endl; std::cout << " Elements: " << this->size() << std::endl; std::cout << " Capacity: " << (m_capacity_end - m_begin) << std::endl; - std::cout << " Small Elements: " << N << " Size on Stack: " << sizeof(*this) << std::endl; + std::cout << " Small Elements: " << InlineBufferCapacity + << " Size on Stack: " << sizeof(*this) << std::endl; } private: @@ -637,9 +636,9 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve uint size = other.size(); uint capacity = size; - if (size <= N) { + if (size <= InlineBufferCapacity) { m_begin = this->small_buffer(); - capacity = N; + capacity = InlineBufferCapacity; } else { m_begin = (T *)m_allocator.allocate_aligned( @@ -661,8 +660,9 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve * Use when the vector is used in the local scope of a function. It has a larger inline storage by * default to make allocations less likely. */ -template<typename T, uint N = 20> using ScopedVector = Vector<T, N, GuardedAllocator>; +template<typename T, uint InlineBufferCapacity = 20> +using ScopedVector = Vector<T, InlineBufferCapacity, GuardedAllocator>; } /* namespace BLI */ -#endif /* __BLI_VECTOR_H__ */ +#endif /* __BLI_VECTOR_HH__ */ diff --git a/source/blender/blenlib/BLI_vector_set.h b/source/blender/blenlib/BLI_vector_set.hh index 99d955c60d8..9f887513816 100644 --- a/source/blender/blenlib/BLI_vector_set.h +++ b/source/blender/blenlib/BLI_vector_set.hh @@ -14,8 +14,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __BLI_VECTOR_SET_H__ -#define __BLI_VECTOR_SET_H__ +#ifndef __BLI_VECTOR_SET_HH__ +#define __BLI_VECTOR_SET_HH__ /** \file * \ingroup bli @@ -25,9 +25,9 @@ * no deletes. The expected time to check if a value is in the VectorSet is O(1). */ -#include "BLI_hash_cxx.h" -#include "BLI_open_addressing.h" -#include "BLI_vector.h" +#include "BLI_hash.hh" +#include "BLI_open_addressing.hh" +#include "BLI_vector.hh" namespace BLI { @@ -76,7 +76,7 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { return m_value == IS_DUMMY; } - bool has_value(const T &value, const Vector<T> &elements) const + bool has_value(const T &value, const T *elements) const { return this->is_set() && elements[this->index()] == value; } @@ -112,12 +112,14 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { using ArrayType = OpenAddressingArray<Slot, 4, Allocator>; ArrayType m_array; - Vector<T, 4, Allocator> m_elements; + + /* The capacity of the array should always be at least m_array.slots_usable(). */ + T *m_elements = nullptr; public: VectorSet() { - BLI_assert(m_array.slots_usable() <= m_elements.capacity()); + m_elements = this->allocate_elements_array(m_array.slots_usable()); } VectorSet(ArrayRef<T> values) : VectorSet() @@ -135,6 +137,43 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { this->add_multiple(values); } + VectorSet(const VectorSet &other) : m_array(other.m_array) + { + m_elements = this->allocate_elements_array(m_array.slots_usable()); + copy_n(other.m_elements, m_array.slots_set(), m_elements); + } + + VectorSet(VectorSet &&other) : m_array(std::move(other.m_array)), m_elements(other.m_elements) + { + other.m_elements = other.allocate_elements_array(other.m_array.slots_usable()); + } + + ~VectorSet() + { + destruct_n(m_elements, this->size()); + this->deallocate_elements_array(m_elements); + } + + VectorSet &operator=(const VectorSet &other) + { + if (this == &other) { + return *this; + } + this->~VectorSet(); + new (this) VectorSet(other); + return *this; + } + + VectorSet &operator=(VectorSet &&other) + { + if (this == &other) { + return *this; + } + this->~VectorSet(); + new (this) VectorSet(std::move(other)); + return *this; + } + /** * Allocate memory such that at least min_usable_slots can be added without having to grow again. */ @@ -203,17 +242,17 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { BLI_assert(this->contains(value)); ITER_SLOTS_BEGIN (value, m_array, , slot) { if (slot.has_value(value, m_elements)) { - uint old_index = m_elements.size() - 1; + uint old_index = this->size() - 1; uint new_index = slot.index(); - m_elements.remove_and_reorder(new_index); + if (new_index < old_index) { + m_elements[new_index] = std::move(m_elements[old_index]); + this->update_slot_index(m_elements[new_index], old_index, new_index); + } + + destruct(m_elements + old_index); slot.set_dummy(); m_array.update__set_to_dummy(); - - if (old_index != new_index) { - T &moved_value = m_elements[new_index]; - this->update_slot_index(moved_value, old_index, new_index); - } return; } } @@ -226,11 +265,12 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { T pop() { BLI_assert(this->size() > 0); - T value = m_elements.pop_last(); - uint old_index = m_elements.size(); + uint index_to_pop = this->size() - 1; + T value = std::move(m_elements[index_to_pop]); + destruct(m_elements + index_to_pop); ITER_SLOTS_BEGIN (value, m_array, , slot) { - if (slot.has_index(old_index)) { + if (slot.has_index(index_to_pop)) { slot.set_dummy(); m_array.update__set_to_dummy(); return value; @@ -277,18 +317,24 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { return m_array.slots_set(); } + bool is_empty() const + { + return this->size() == 0; + } + const T *begin() const { - return m_elements.begin(); + return m_elements; } const T *end() const { - return m_elements.end(); + return m_elements + this->size(); } const T &operator[](uint index) const { + BLI_assert(index <= this->size()); return m_elements[index]; } @@ -299,7 +345,7 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { operator ArrayRef<T>() const { - return m_elements; + return ArrayRef<T>(m_elements, this->size()); } void print_stats() const @@ -326,9 +372,9 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { template<typename ForwardT> void add_new_in_slot(Slot &slot, ForwardT &&value) { - uint index = m_elements.size(); + uint index = this->size(); slot.set_index(index); - m_elements.append_unchecked(std::forward<ForwardT>(value)); + new (m_elements + index) T(std::forward<ForwardT>(value)); m_array.update__empty_to_set(); } @@ -341,14 +387,20 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { BLI_NOINLINE void grow(uint min_usable_slots) { + uint size = this->size(); + ArrayType new_array = m_array.init_reserved(min_usable_slots); + T *new_elements = this->allocate_elements_array(new_array.slots_usable()); - for (uint i = 0; i < m_elements.size(); i++) { + for (uint i : IndexRange(size)) { this->add_after_grow(i, new_array); } + uninitialized_relocate_n(m_elements, size, new_elements); + this->deallocate_elements_array(m_elements); + m_array = std::move(new_array); - m_elements.reserve(m_array.slots_usable()); + m_elements = new_elements; } void add_after_grow(uint index, ArrayType &new_array) @@ -365,15 +417,15 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { float compute_average_collisions() const { - if (m_elements.size() == 0) { + if (this->size() == 0) { return 0.0f; } uint collisions_sum = 0; - for (const T &value : m_elements) { + for (const T &value : this->as_ref()) { collisions_sum += this->count_collisions(value); } - return (float)collisions_sum / (float)m_elements.size(); + return (float)collisions_sum / (float)this->size(); } uint count_collisions(const T &value) const @@ -415,6 +467,16 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { } ITER_SLOTS_END; } + + T *allocate_elements_array(uint size) + { + return (T *)m_array.allocator().allocate_aligned((uint)sizeof(T) * size, alignof(T), __func__); + } + + void deallocate_elements_array(T *elements) + { + m_array.allocator().deallocate(elements); + } }; #undef ITER_SLOTS_BEGIN @@ -422,4 +484,4 @@ template<typename T, typename Allocator = GuardedAllocator> class VectorSet { } // namespace BLI -#endif /* __BLI_VECTOR_SET_H__ */ +#endif /* __BLI_VECTOR_SET_HH__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index bdfe3dd4747..ab9b3e19ab9 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -64,6 +64,7 @@ set(SRC intern/buffer.c intern/convexhull_2d.c intern/delaunay_2d.c + intern/dot_export.cc intern/dynlib.c intern/easing.c intern/edgehash.c @@ -118,11 +119,14 @@ set(SRC intern/string_utf8.c intern/string_utils.c intern/system.c - intern/task_pool.cc intern/task_iterator.c + intern/task_pool.cc + intern/task_range.cc + intern/task_scheduler.cc intern/threads.c intern/time.c intern/timecode.c + intern/timeit.cc intern/uvproject.c intern/voronoi_2d.c intern/voxel.c @@ -136,11 +140,11 @@ set(SRC BLI_alloca.h - BLI_allocator.h + BLI_allocator.hh BLI_args.h BLI_array.h - BLI_array_cxx.h - BLI_array_ref.h + BLI_array.hh + BLI_array_ref.hh BLI_array_store.h BLI_array_store_utils.h BLI_array_utils.h @@ -151,6 +155,7 @@ set(SRC BLI_blenlib.h BLI_boxpack_2d.h BLI_buffer.h + BLI_color.hh BLI_compiler_attrs.h BLI_compiler_compat.h BLI_compiler_typecheck.h @@ -159,6 +164,8 @@ set(SRC BLI_delaunay_2d.h BLI_dial_2d.h BLI_dlrbTree.h + BLI_dot_export.hh + BLI_dot_export_attribute_enums.hh BLI_dynlib.h BLI_dynstr.h BLI_easing.h @@ -168,17 +175,20 @@ set(SRC BLI_expr_pylike_eval.h BLI_fileops.h BLI_fileops_types.h + BLI_float2.hh + BLI_float3.hh + BLI_float4x4.hh BLI_fnmatch.h BLI_ghash.h BLI_gsqueue.h BLI_hash.h - BLI_hash_cxx.h + BLI_hash.hh BLI_hash_md5.h BLI_hash_mm2a.h BLI_hash_mm3.h BLI_heap.h BLI_heap_simple.h - BLI_index_range.h + BLI_index_range.hh BLI_iterator.h BLI_jitter_2d.h BLI_kdopbvh.h @@ -190,8 +200,8 @@ set(SRC BLI_linklist_lockfree.h BLI_linklist_stack.h BLI_listbase.h - BLI_listbase_wrapper.h - BLI_map.h + BLI_listbase_wrapper.hh + BLI_map.hh BLI_math.h BLI_math_base.h BLI_math_bits.h @@ -209,11 +219,11 @@ set(SRC BLI_memblock.h BLI_memiter.h BLI_memory_utils.h - BLI_memory_utils_cxx.h + BLI_memory_utils.hh BLI_mempool.h BLI_noise.h - BLI_open_addressing.h - BLI_optional.h + BLI_open_addressing.hh + BLI_optional.hh BLI_path_util.h BLI_polyfill_2d.h BLI_polyfill_2d_beautify.h @@ -221,17 +231,17 @@ set(SRC BLI_rand.h BLI_rect.h BLI_scanfill.h - BLI_set.h + BLI_set.hh BLI_smallhash.h BLI_sort.h BLI_sort_utils.h BLI_stack.h - BLI_stack_cxx.h + BLI_stack.hh BLI_strict_flags.h BLI_string.h BLI_string_cursor_utf8.h - BLI_string_map.h - BLI_string_ref.h + BLI_string_map.hh + BLI_string_ref.hh BLI_string_utf8.h BLI_string_utils.h BLI_sys_types.h @@ -239,15 +249,16 @@ set(SRC BLI_task.h BLI_threads.h BLI_timecode.h + BLI_timeit.hh BLI_timer.h BLI_utildefines.h BLI_utildefines_iter.h BLI_utildefines_stack.h BLI_utildefines_variadic.h - BLI_utility_mixins.h + BLI_utility_mixins.hh BLI_uvproject.h - BLI_vector.h - BLI_vector_set.h + BLI_vector.hh + BLI_vector_set.hh BLI_vfontdata.h BLI_voronoi_2d.h BLI_voxel.h @@ -269,6 +280,18 @@ if(WITH_MEM_VALGRIND) add_definitions(-DWITH_MEM_VALGRIND) endif() +if(WITH_TBB) + add_definitions(-DWITH_TBB) + + list(APPEND INC_SYS + ${TBB_INCLUDE_DIRS} + ) + + list(APPEND LIB + ${TBB_LIBRARIES} + ) +endif() + if(WIN32) list(APPEND INC ../../../intern/utfconv @@ -276,6 +299,9 @@ if(WIN32) list(APPEND LIB bf_intern_utfconv ) + list(APPEND SRC + intern/system_win32.c + ) endif() diff --git a/source/blender/blenlib/intern/BLI_index_range.cc b/source/blender/blenlib/intern/BLI_index_range.cc index 90eb4e4a89c..fefb6e6598e 100644 --- a/source/blender/blenlib/intern/BLI_index_range.cc +++ b/source/blender/blenlib/intern/BLI_index_range.cc @@ -17,10 +17,10 @@ #include <atomic> #include <mutex> -#include "BLI_array_cxx.h" -#include "BLI_array_ref.h" -#include "BLI_index_range.h" -#include "BLI_vector.h" +#include "BLI_array.hh" +#include "BLI_array_ref.hh" +#include "BLI_index_range.hh" +#include "BLI_vector.hh" namespace BLI { diff --git a/source/blender/blenlib/intern/delaunay_2d.c b/source/blender/blenlib/intern/delaunay_2d.c index 836292e0c88..4e0cd3a78dc 100644 --- a/source/blender/blenlib/intern/delaunay_2d.c +++ b/source/blender/blenlib/intern/delaunay_2d.c @@ -1264,6 +1264,7 @@ static void fill_crossdata_for_intersect(CDT_state *cdt, se_vcva = t->next->next; BLI_assert(se_vcva->vert == vc && se_vcva->next->vert == va); BLI_assert(se_vcvb->vert == vc && se_vcvb->next->vert == vb); + UNUSED_VARS_NDEBUG(vc); isect = isect_seg_seg_v2_lambda_mu_db(va->co, vb->co, curco, v2->co, &lambda, &mu); #ifdef DEBUG_CDT if (dbg_level > 0) { diff --git a/source/blender/blenlib/intern/dot_export.cc b/source/blender/blenlib/intern/dot_export.cc new file mode 100644 index 00000000000..96de4056fc5 --- /dev/null +++ b/source/blender/blenlib/intern/dot_export.cc @@ -0,0 +1,305 @@ +/* + * 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. + */ + +#include <iomanip> + +#include "BLI_dot_export.hh" + +namespace BLI { +namespace DotExport { + +/* Graph Building + ************************************************/ + +Node &Graph::new_node(StringRef label) +{ + Node *node = new Node(*this); + m_nodes.append(std::unique_ptr<Node>(node)); + m_top_level_nodes.add_new(node); + node->set_attribute("label", label); + return *node; +} + +Cluster &Graph::new_cluster(StringRef label) +{ + Cluster *cluster = new Cluster(*this); + m_clusters.append(std::unique_ptr<Cluster>(cluster)); + m_top_level_clusters.add_new(cluster); + cluster->set_attribute("label", label); + return *cluster; +} + +UndirectedEdge &UndirectedGraph::new_edge(NodePort a, NodePort b) +{ + UndirectedEdge *edge = new UndirectedEdge(a, b); + m_edges.append(std::unique_ptr<UndirectedEdge>(edge)); + return *edge; +} + +DirectedEdge &DirectedGraph::new_edge(NodePort from, NodePort to) +{ + DirectedEdge *edge = new DirectedEdge(from, to); + m_edges.append(std::unique_ptr<DirectedEdge>(edge)); + return *edge; +} + +void Cluster::set_parent_cluster(Cluster *new_parent) +{ + if (m_parent == new_parent) { + return; + } + else if (m_parent == nullptr) { + m_graph.m_top_level_clusters.remove(this); + new_parent->m_children.add_new(this); + } + else if (new_parent == nullptr) { + m_parent->m_children.remove(this); + m_graph.m_top_level_clusters.add_new(this); + } + else { + m_parent->m_children.remove(this); + new_parent->m_children.add_new(this); + } + m_parent = new_parent; +} + +void Node::set_parent_cluster(Cluster *cluster) +{ + if (m_cluster == cluster) { + return; + } + else if (m_cluster == nullptr) { + m_graph.m_top_level_nodes.remove(this); + cluster->m_nodes.add_new(this); + } + else if (cluster == nullptr) { + m_cluster->m_nodes.remove(this); + m_graph.m_top_level_nodes.add_new(this); + } + else { + m_cluster->m_nodes.remove(this); + cluster->m_nodes.add_new(this); + } + m_cluster = cluster; +} + +/* Utility methods + **********************************************/ + +void Graph::set_random_cluster_bgcolors() +{ + for (Cluster *cluster : m_top_level_clusters) { + cluster->set_random_cluster_bgcolors(); + } +} + +void Cluster::set_random_cluster_bgcolors() +{ + float hue = rand() / (float)RAND_MAX; + float staturation = 0.3f; + float value = 0.8f; + this->set_attribute("bgcolor", color_attr_from_hsv(hue, staturation, value)); + + for (Cluster *cluster : m_children) { + cluster->set_random_cluster_bgcolors(); + } +} + +/* Dot Generation + **********************************************/ + +std::string DirectedGraph::to_dot_string() const +{ + std::stringstream ss; + ss << "digraph {\n"; + this->export__declare_nodes_and_clusters(ss); + ss << "\n"; + + for (const std::unique_ptr<DirectedEdge> &edge : m_edges) { + edge->export__as_edge_statement(ss); + ss << "\n"; + } + + ss << "}\n"; + return ss.str(); +} + +std::string UndirectedGraph::to_dot_string() const +{ + std::stringstream ss; + ss << "graph {\n"; + this->export__declare_nodes_and_clusters(ss); + ss << "\n"; + + for (const std::unique_ptr<UndirectedEdge> &edge : m_edges) { + edge->export__as_edge_statement(ss); + ss << "\n"; + } + + ss << "}\n"; + return ss.str(); +} + +void Graph::export__declare_nodes_and_clusters(std::stringstream &ss) const +{ + ss << "graph "; + m_attributes.export__as_bracket_list(ss); + ss << "\n\n"; + + for (Node *node : m_top_level_nodes) { + node->export__as_declaration(ss); + } + + for (Cluster *cluster : m_top_level_clusters) { + cluster->export__declare_nodes_and_clusters(ss); + } +} + +void Cluster::export__declare_nodes_and_clusters(std::stringstream &ss) const +{ + ss << "subgraph cluster_" << (uintptr_t)this << " {\n"; + + ss << "graph "; + m_attributes.export__as_bracket_list(ss); + ss << "\n\n"; + + for (Node *node : m_nodes) { + node->export__as_declaration(ss); + } + + for (Cluster *cluster : m_children) { + cluster->export__declare_nodes_and_clusters(ss); + } + + ss << "}\n"; +} + +void DirectedEdge::export__as_edge_statement(std::stringstream &ss) const +{ + m_a.to_dot_string(ss); + ss << " -> "; + m_b.to_dot_string(ss); + ss << " "; + m_attributes.export__as_bracket_list(ss); +} + +void UndirectedEdge::export__as_edge_statement(std::stringstream &ss) const +{ + m_a.to_dot_string(ss); + ss << " -- "; + m_b.to_dot_string(ss); + ss << " "; + m_attributes.export__as_bracket_list(ss); +} + +void AttributeList::export__as_bracket_list(std::stringstream &ss) const +{ + ss << "["; + m_attributes.foreach_item([&](StringRef key, StringRef value) { + if (StringRef(value).startswith("<")) { + /* Don't draw the quotes, this is an html-like value. */ + ss << key << "=" << value << ", "; + } + else { + ss << key << "=\"" << value << "\", "; + } + }); + ss << "]"; +} + +void Node::export__as_id(std::stringstream &ss) const +{ + ss << '"' << (uintptr_t)this << '"'; +} + +void Node::export__as_declaration(std::stringstream &ss) const +{ + this->export__as_id(ss); + ss << " "; + m_attributes.export__as_bracket_list(ss); + ss << "\n"; +} + +void NodePort::to_dot_string(std::stringstream &ss) const +{ + m_node->export__as_id(ss); + if (m_port_name.has_value()) { + ss << ":" << m_port_name.value(); + } +} + +std::string color_attr_from_hsv(float h, float s, float v) +{ + std::stringstream ss; + ss << std::setprecision(4) << h << ' ' << s << ' ' << v; + return ss.str(); +} + +NodeWithSocketsRef::NodeWithSocketsRef(Node &node, + StringRef name, + ArrayRef<std::string> input_names, + ArrayRef<std::string> output_names) + : m_node(&node) +{ + std::stringstream ss; + + ss << "<<table border=\"0\" cellspacing=\"3\">"; + + /* Header */ + ss << "<tr><td colspan=\"3\" align=\"center\"><b>"; + ss << ((name.size() == 0) ? "No Name" : name); + ss << "</b></td></tr>"; + + /* Sockets */ + uint socket_max_amount = std::max(input_names.size(), output_names.size()); + for (uint i = 0; i < socket_max_amount; i++) { + ss << "<tr>"; + if (i < input_names.size()) { + StringRef name = input_names[i]; + if (name.size() == 0) { + name = "No Name"; + } + ss << "<td align=\"left\" port=\"in" << i << "\">"; + ss << name; + ss << "</td>"; + } + else { + ss << "<td></td>"; + } + ss << "<td></td>"; + if (i < output_names.size()) { + StringRef name = output_names[i]; + if (name.size() == 0) { + name = "No Name"; + } + ss << "<td align=\"right\" port=\"out" << i << "\">"; + ss << name; + ss << "</td>"; + } + else { + ss << "<td></td>"; + } + ss << "</tr>"; + } + + ss << "</table>>"; + + m_node->set_attribute("label", ss.str()); + m_node->set_shape(Attr_shape::Rectangle); +} + +} // namespace DotExport +} // namespace BLI diff --git a/source/blender/blenlib/intern/lasso_2d.c b/source/blender/blenlib/intern/lasso_2d.c index f1e9b1e655f..a01adf4fa6a 100644 --- a/source/blender/blenlib/intern/lasso_2d.c +++ b/source/blender/blenlib/intern/lasso_2d.c @@ -28,47 +28,47 @@ #include "BLI_lasso_2d.h" /* own include */ -void BLI_lasso_boundbox(rcti *rect, const int mcords[][2], const unsigned int moves) +void BLI_lasso_boundbox(rcti *rect, const int mcoords[][2], const unsigned int mcoords_len) { unsigned int a; - rect->xmin = rect->xmax = mcords[0][0]; - rect->ymin = rect->ymax = mcords[0][1]; + rect->xmin = rect->xmax = mcoords[0][0]; + rect->ymin = rect->ymax = mcoords[0][1]; - for (a = 1; a < moves; a++) { - if (mcords[a][0] < rect->xmin) { - rect->xmin = mcords[a][0]; + for (a = 1; a < mcoords_len; a++) { + if (mcoords[a][0] < rect->xmin) { + rect->xmin = mcoords[a][0]; } - else if (mcords[a][0] > rect->xmax) { - rect->xmax = mcords[a][0]; + else if (mcoords[a][0] > rect->xmax) { + rect->xmax = mcoords[a][0]; } - if (mcords[a][1] < rect->ymin) { - rect->ymin = mcords[a][1]; + if (mcoords[a][1] < rect->ymin) { + rect->ymin = mcoords[a][1]; } - else if (mcords[a][1] > rect->ymax) { - rect->ymax = mcords[a][1]; + else if (mcoords[a][1] > rect->ymax) { + rect->ymax = mcoords[a][1]; } } } -bool BLI_lasso_is_point_inside(const int mcords[][2], - const unsigned int moves, +bool BLI_lasso_is_point_inside(const int mcoords[][2], + const unsigned int mcoords_len, const int sx, const int sy, const int error_value) { - if (sx == error_value || moves == 0) { + if (sx == error_value || mcoords_len == 0) { return false; } else { int pt[2] = {sx, sy}; - return isect_point_poly_v2_int(pt, mcords, moves, true); + return isect_point_poly_v2_int(pt, mcoords, mcoords_len, true); } } /* edge version for lasso select. we assume boundbox check was done */ -bool BLI_lasso_is_edge_inside(const int mcords[][2], - const unsigned int moves, +bool BLI_lasso_is_edge_inside(const int mcoords[][2], + const unsigned int mcoords_len, int x0, int y0, int x1, @@ -76,27 +76,27 @@ bool BLI_lasso_is_edge_inside(const int mcords[][2], const int error_value) { - if (x0 == error_value || x1 == error_value || moves == 0) { + if (x0 == error_value || x1 == error_value || mcoords_len == 0) { return false; } const int v1[2] = {x0, y0}, v2[2] = {x1, y1}; /* check points in lasso */ - if (BLI_lasso_is_point_inside(mcords, moves, v1[0], v1[1], error_value)) { + if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v1[0], v1[1], error_value)) { return true; } - if (BLI_lasso_is_point_inside(mcords, moves, v2[0], v2[1], error_value)) { + if (BLI_lasso_is_point_inside(mcoords, mcoords_len, v2[0], v2[1], error_value)) { return true; } /* no points in lasso, so we have to intersect with lasso edge */ - if (isect_seg_seg_v2_int(mcords[0], mcords[moves - 1], v1, v2) > 0) { + if (isect_seg_seg_v2_int(mcoords[0], mcoords[mcoords_len - 1], v1, v2) > 0) { return true; } - for (unsigned int a = 0; a < moves - 1; a++) { - if (isect_seg_seg_v2_int(mcords[a], mcords[a + 1], v1, v2) > 0) { + for (unsigned int a = 0; a < mcoords_len - 1; a++) { + if (isect_seg_seg_v2_int(mcoords[a], mcoords[a + 1], v1, v2) > 0) { return true; } } diff --git a/source/blender/blenlib/intern/math_base_inline.c b/source/blender/blenlib/intern/math_base_inline.c index 6db3ea819a4..2ad9b53ba3d 100644 --- a/source/blender/blenlib/intern/math_base_inline.c +++ b/source/blender/blenlib/intern/math_base_inline.c @@ -38,6 +38,10 @@ #include "BLI_math_base.h" +#ifdef __cplusplus +extern "C" { +#endif + /* copied from BLI_utildefines.h */ #ifdef __GNUC__ # define UNLIKELY(x) __builtin_expect(!!(x), 0) @@ -801,4 +805,8 @@ MINLINE unsigned char unit_ushort_to_uchar(unsigned short val) } \ ((void)0) +#ifdef __cplusplus +} +#endif + #endif /* __MATH_BASE_INLINE_C__ */ diff --git a/source/blender/blenlib/intern/math_solvers.c b/source/blender/blenlib/intern/math_solvers.c index 235589abdab..cda3d9b66a2 100644 --- a/source/blender/blenlib/intern/math_solvers.c +++ b/source/blender/blenlib/intern/math_solvers.c @@ -55,7 +55,7 @@ bool BLI_eigen_solve_selfadjoint_m3(const float m3[3][3], } /** - * \brief Compute the SVD (Singular Values Decomposition) of given 3D matrix (m3 = USV*). + * \brief Compute the SVD (Singular Values Decomposition) of given 3D matrix (m3 = USV*). * * \param m3: the matrix to decompose. * \return r_U the computed left singular vector of \a m3 (NULL if not needed). diff --git a/source/blender/blenlib/intern/math_vector_inline.c b/source/blender/blenlib/intern/math_vector_inline.c index d2c55233653..ca405907bdd 100644 --- a/source/blender/blenlib/intern/math_vector_inline.c +++ b/source/blender/blenlib/intern/math_vector_inline.c @@ -123,6 +123,27 @@ MINLINE void copy_v4_v4_uchar(unsigned char r[4], const unsigned char a[4]) r[3] = a[3]; } +MINLINE void copy_v2_uchar(unsigned char r[2], const unsigned char a) +{ + r[0] = a; + r[1] = a; +} + +MINLINE void copy_v3_uchar(unsigned char r[3], const unsigned char a) +{ + r[0] = a; + r[1] = a; + r[2] = a; +} + +MINLINE void copy_v4_uchar(unsigned char r[4], const unsigned char a) +{ + r[0] = a; + r[1] = a; + r[2] = a; + r[3] = a; +} + /* char */ MINLINE void copy_v2_v2_char(char r[2], const char a[2]) { diff --git a/source/blender/blenlib/intern/noise.c b/source/blender/blenlib/intern/noise.c index 229a06948c2..42b5ba28f5a 100644 --- a/source/blender/blenlib/intern/noise.c +++ b/source/blender/blenlib/intern/noise.c @@ -23,6 +23,7 @@ #include <math.h> +#include "BLI_compiler_compat.h" #include "BLI_noise.h" /* local */ @@ -264,17 +265,17 @@ static const float hashvectf[768] = { /* IMPROVED PERLIN NOISE */ /**************************/ -static float lerp(float t, float a, float b) +BLI_INLINE float lerp(float t, float a, float b) { return (a + t * (b - a)); } -static float npfade(float t) +BLI_INLINE float npfade(float t) { return (t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f)); } -static float grad(int hash_val, float x, float y, float z) +BLI_INLINE float grad(int hash_val, float x, float y, float z) { int h = hash_val & 15; /* CONVERT LO 4 BITS OF HASH CODE */ float u = h < 8 ? x : y; /* INTO 12 GRADIENT DIRECTIONS. */ diff --git a/source/blender/blenlib/intern/quadric.c b/source/blender/blenlib/intern/quadric.c index 0a1ff9f8116..3ad1844cfe1 100644 --- a/source/blender/blenlib/intern/quadric.c +++ b/source/blender/blenlib/intern/quadric.c @@ -141,9 +141,14 @@ void BLI_quadric_mul(Quadric *a, const double scalar) double BLI_quadric_evaluate(const Quadric *q, const double v[3]) { - return ((q->a2 * v[0] * v[0]) + (q->ab * 2 * v[0] * v[1]) + (q->ac * 2 * v[0] * v[2]) + - (q->ad * 2 * v[0]) + (q->b2 * v[1] * v[1]) + (q->bc * 2 * v[1] * v[2]) + - (q->bd * 2 * v[1]) + (q->c2 * v[2] * v[2]) + (q->cd * 2 * v[2]) + (q->d2)); + const double v00 = v[0] * v[0], v01 = v[0] * v[1], v02 = v[0] * v[2]; + const double v11 = v[1] * v[1], v12 = v[1] * v[2]; + const double v22 = v[2] * v[2]; + return ((q->a2 * v00) + (q->ab * 2 * v01) + (q->ac * 2 * v02) + (q->ad * 2 * v[0]) + /* a */ + (q->b2 * v11) + (q->bc * 2 * v12) + (q->bd * 2 * v[1]) + /* b */ + (q->c2 * v22) + (q->cd * 2 * v[2]) + /* c */ + (q->d2) /* d */ + ); } bool BLI_quadric_optimize(const Quadric *q, double v[3], const double epsilon) diff --git a/source/blender/blenlib/intern/stack.c b/source/blender/blenlib/intern/stack.c index e75d944c764..f2e8b352aab 100644 --- a/source/blender/blenlib/intern/stack.c +++ b/source/blender/blenlib/intern/stack.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 7d9ed2598a6..53db49aa59c 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -32,11 +32,8 @@ /* for backtrace and gethostname/GetComputerName */ #if defined(WIN32) # include <intrin.h> -# include <windows.h> -# pragma warning(push) -# pragma warning(disable : 4091) -# include <dbghelp.h> -# pragma warning(pop) + +# include "BLI_winstuff.h" #else # include <execinfo.h> # include <unistd.h> @@ -74,6 +71,8 @@ int BLI_cpu_support_sse2(void) #endif } +/* Windows stackwalk lives in system_win32.c */ +#if !defined(_MSC_VER) /** * Write a backtrace into a file for systems which support it. */ @@ -81,9 +80,9 @@ void BLI_system_backtrace(FILE *fp) { /* ------------- */ /* Linux / Apple */ -#if defined(__linux__) || defined(__APPLE__) +# if defined(__linux__) || defined(__APPLE__) -# define SIZE 100 +# define SIZE 100 void *buffer[SIZE]; int nptrs; char **strings; @@ -98,48 +97,15 @@ void BLI_system_backtrace(FILE *fp) } free(strings); -# undef SIZE - - /* -------- */ - /* Windows */ -#elif defined(_MSC_VER) - -# ifndef NDEBUG -# define MAXSYMBOL 256 -# define SIZE 100 - unsigned short i; - void *stack[SIZE]; - unsigned short nframes; - SYMBOL_INFO *symbolinfo; - HANDLE process; - - process = GetCurrentProcess(); - - SymInitialize(process, NULL, TRUE); - - nframes = CaptureStackBackTrace(0, SIZE, stack, NULL); - symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table"); - symbolinfo->MaxNameLen = MAXSYMBOL - 1; - symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); - - for (i = 0; i < nframes; i++) { - SymFromAddr(process, (DWORD64)(stack[i]), 0, symbolinfo); - - fprintf(fp, "%u: %s - 0x%0llX\n", nframes - i - 1, symbolinfo->Name, symbolinfo->Address); - } - - MEM_freeN(symbolinfo); -# undef MAXSYMBOL # undef SIZE + # else - fprintf(fp, "Crash backtrace not supported on release builds\n"); -# endif /* NDEBUG */ -#else /* _MSC_VER */ /* ------------------ */ /* non msvc/osx/linux */ (void)fp; -#endif +# endif } +#endif /* end BLI_system_backtrace */ /* NOTE: The code for CPU brand string is adopted from Cycles. */ diff --git a/source/blender/blenlib/intern/system_win32.c b/source/blender/blenlib/intern/system_win32.c new file mode 100644 index 00000000000..d60f54ebe67 --- /dev/null +++ b/source/blender/blenlib/intern/system_win32.c @@ -0,0 +1,410 @@ +/* + * 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. + */ + +/** \file + * \ingroup bli + */ +#include <Windows.h> +#include <stdio.h> + +#include <dbghelp.h> +#include <shlwapi.h> +#include <tlhelp32.h> + +#include "BLI_string.h" + +#include "MEM_guardedalloc.h" + +static EXCEPTION_POINTERS *current_exception = NULL; + +static const char *bli_windows_get_exception_description(const DWORD exceptioncode) +{ + switch (exceptioncode) { + case EXCEPTION_ACCESS_VIOLATION: + return "EXCEPTION_ACCESS_VIOLATION"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: + return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + case EXCEPTION_BREAKPOINT: + return "EXCEPTION_BREAKPOINT"; + case EXCEPTION_DATATYPE_MISALIGNMENT: + return "EXCEPTION_DATATYPE_MISALIGNMENT"; + case EXCEPTION_FLT_DENORMAL_OPERAND: + return "EXCEPTION_FLT_DENORMAL_OPERAND"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: + return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; + case EXCEPTION_FLT_INEXACT_RESULT: + return "EXCEPTION_FLT_INEXACT_RESULT"; + case EXCEPTION_FLT_INVALID_OPERATION: + return "EXCEPTION_FLT_INVALID_OPERATION"; + case EXCEPTION_FLT_OVERFLOW: + return "EXCEPTION_FLT_OVERFLOW"; + case EXCEPTION_FLT_STACK_CHECK: + return "EXCEPTION_FLT_STACK_CHECK"; + case EXCEPTION_FLT_UNDERFLOW: + return "EXCEPTION_FLT_UNDERFLOW"; + case EXCEPTION_ILLEGAL_INSTRUCTION: + return "EXCEPTION_ILLEGAL_INSTRUCTION"; + case EXCEPTION_IN_PAGE_ERROR: + return "EXCEPTION_IN_PAGE_ERROR"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: + return "EXCEPTION_INT_DIVIDE_BY_ZERO"; + case EXCEPTION_INT_OVERFLOW: + return "EXCEPTION_INT_OVERFLOW"; + case EXCEPTION_INVALID_DISPOSITION: + return "EXCEPTION_INVALID_DISPOSITION"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: + return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + case EXCEPTION_PRIV_INSTRUCTION: + return "EXCEPTION_PRIV_INSTRUCTION"; + case EXCEPTION_SINGLE_STEP: + return "EXCEPTION_SINGLE_STEP"; + case EXCEPTION_STACK_OVERFLOW: + return "EXCEPTION_STACK_OVERFLOW"; + default: + return "UNKNOWN EXCEPTION"; + } +} + +static void bli_windows_get_module_name(LPVOID address, PCHAR buffer, size_t size) +{ + HMODULE mod; + buffer[0] = 0; + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &mod)) { + if (GetModuleFileName(mod, buffer, size)) { + PathStripPath(buffer); + } + } +} + +static void bli_windows_get_module_version(const char *file, char *buffer, size_t buffersize) +{ + buffer[0] = 0; + DWORD verHandle = 0; + UINT size = 0; + LPBYTE lpBuffer = NULL; + DWORD verSize = GetFileVersionInfoSize(file, &verHandle); + if (verSize != 0) { + LPSTR verData = (LPSTR)MEM_callocN(verSize, "crash module version"); + + if (GetFileVersionInfo(file, verHandle, verSize, verData)) { + if (VerQueryValue(verData, "\\", (VOID FAR * FAR *)&lpBuffer, &size)) { + if (size) { + VS_FIXEDFILEINFO *verInfo = (VS_FIXEDFILEINFO *)lpBuffer; + /* Magic value from + * https://docs.microsoft.com/en-us/windows/win32/api/verrsrc/ns-verrsrc-vs_fixedfileinfo + */ + if (verInfo->dwSignature == 0xfeef04bd) { + BLI_snprintf(buffer, + buffersize, + "%d.%d.%d.%d", + (verInfo->dwFileVersionMS >> 16) & 0xffff, + (verInfo->dwFileVersionMS >> 0) & 0xffff, + (verInfo->dwFileVersionLS >> 16) & 0xffff, + (verInfo->dwFileVersionLS >> 0) & 0xffff); + } + } + } + } + MEM_freeN(verData); + } +} + +static void bli_windows_system_backtrace_exception_record(FILE *fp, PEXCEPTION_RECORD record) +{ + char module[MAX_PATH]; + fprintf(fp, "Exception Record:\n\n"); + fprintf(fp, + "ExceptionCode : %s\n", + bli_windows_get_exception_description(record->ExceptionCode)); + fprintf(fp, "Exception Address : 0x%p\n", record->ExceptionAddress); + bli_windows_get_module_name(record->ExceptionAddress, module, sizeof(module)); + fprintf(fp, "Exception Module : %s\n", module); + fprintf(fp, "Exception Flags : 0x%.8x\n", record->ExceptionFlags); + fprintf(fp, "Exception Parameters : 0x%x\n", record->NumberParameters); + for (DWORD idx = 0; idx < record->NumberParameters; idx++) { + fprintf(fp, "\tParameters[%d] : 0x%p\n", idx, (LPVOID *)record->ExceptionInformation[idx]); + } + if (record->ExceptionRecord) { + fprintf(fp, "Nested "); + bli_windows_system_backtrace_exception_record(fp, record->ExceptionRecord); + } + fprintf(fp, "\n\n"); +} + +static bool BLI_windows_system_backtrace_run_trace(FILE *fp, HANDLE hThread, PCONTEXT context) +{ + const int max_symbol_length = 100; + + bool result = true; + + PSYMBOL_INFO symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + max_symbol_length * sizeof(char), + "crash Symbol table"); + symbolinfo->MaxNameLen = max_symbol_length - 1; + symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO); + + STACKFRAME frame = {0}; + frame.AddrPC.Offset = context->Rip; + frame.AddrPC.Mode = AddrModeFlat; + frame.AddrFrame.Offset = context->Rsp; + frame.AddrFrame.Mode = AddrModeFlat; + frame.AddrStack.Offset = context->Rsp; + frame.AddrStack.Mode = AddrModeFlat; + + while (true) { + if (StackWalk64(IMAGE_FILE_MACHINE_AMD64, + GetCurrentProcess(), + hThread, + &frame, + context, + NULL, + SymFunctionTableAccess64, + SymGetModuleBase64, + 0)) { + if (frame.AddrPC.Offset) { + char module[MAX_PATH]; + + bli_windows_get_module_name((LPVOID)frame.AddrPC.Offset, module, sizeof(module)); + + if (SymFromAddr(GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), 0, symbolinfo)) { + fprintf(fp, "%-20s:0x%p %s", module, (LPVOID)symbolinfo->Address, symbolinfo->Name); + IMAGEHLP_LINE lineinfo; + lineinfo.SizeOfStruct = sizeof(lineinfo); + DWORD displacement = 0; + if (SymGetLineFromAddr( + GetCurrentProcess(), (DWORD64)(frame.AddrPC.Offset), &displacement, &lineinfo)) { + fprintf(fp, " %s:%d", lineinfo.FileName, lineinfo.LineNumber); + } + fprintf(fp, "\n"); + } + else { + fprintf(fp, + "%-20s:0x%p %s\n", + module, + (LPVOID)frame.AddrPC.Offset, + "Symbols not available"); + result = false; + break; + } + } + else { + break; + } + } + else { + break; + } + } + MEM_freeN(symbolinfo); + fprintf(fp, "\n\n"); + return result; +} + +static bool bli_windows_system_backtrace_stack_thread(FILE *fp, HANDLE hThread) +{ + CONTEXT context = {0}; + context.ContextFlags = CONTEXT_ALL; + /* GetThreadContext requires the thread to be in a suspended state, which is problematic for the + * currently running thread, RtlCaptureContext is used as an alternative to sidestep this */ + if (hThread != GetCurrentThread()) { + SuspendThread(hThread); + bool success = GetThreadContext(hThread, &context); + ResumeThread(hThread); + if (!success) { + fprintf(fp, "Cannot get thread context : 0x0%.8x\n", GetLastError()); + return false; + } + } + else { + RtlCaptureContext(&context); + } + return BLI_windows_system_backtrace_run_trace(fp, hThread, &context); +} + +static void bli_windows_system_backtrace_modules(FILE *fp) +{ + fprintf(fp, "Loaded Modules :\n"); + HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, 0); + if (hModuleSnap == INVALID_HANDLE_VALUE) + return; + + MODULEENTRY32 me32; + me32.dwSize = sizeof(MODULEENTRY32); + + if (!Module32First(hModuleSnap, &me32)) { + CloseHandle(hModuleSnap); // Must clean up the snapshot object! + fprintf(fp, " Error getting module list.\n"); + return; + } + + do { + if (me32.th32ProcessID == GetCurrentProcessId()) { + char version[MAX_PATH]; + bli_windows_get_module_version(me32.szExePath, version, sizeof(version)); + + IMAGEHLP_MODULE64 m64; + m64.SizeOfStruct = sizeof(m64); + if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)me32.modBaseAddr, &m64)) { + fprintf(fp, + "0x%p %-20s %s %s %s\n", + me32.modBaseAddr, + version, + me32.szModule, + m64.LoadedPdbName, + m64.PdbUnmatched ? "[unmatched]" : ""); + } + else { + fprintf(fp, "0x%p %-20s %s\n", me32.modBaseAddr, version, me32.szModule); + } + } + } while (Module32Next(hModuleSnap, &me32)); +} + +static void bli_windows_system_backtrace_threads(FILE *fp) +{ + fprintf(fp, "Threads:\n"); + HANDLE hThreadSnap = INVALID_HANDLE_VALUE; + THREADENTRY32 te32; + + hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); + if (hThreadSnap == INVALID_HANDLE_VALUE) { + fprintf(fp, "Unable to retrieve threads list.\n"); + return; + } + + te32.dwSize = sizeof(THREADENTRY32); + + if (!Thread32First(hThreadSnap, &te32)) { + CloseHandle(hThreadSnap); + return; + } + do { + if (te32.th32OwnerProcessID == GetCurrentProcessId()) { + if (GetCurrentThreadId() != te32.th32ThreadID) { + fprintf(fp, "Thread : %.8x\n", te32.th32ThreadID); + HANDLE ht = OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID); + bli_windows_system_backtrace_stack_thread(fp, ht); + CloseHandle(ht); + } + } + } while (Thread32Next(hThreadSnap, &te32)); + CloseHandle(hThreadSnap); +} + +static bool BLI_windows_system_backtrace_stack(FILE *fp) +{ + fprintf(fp, "Stack trace:\n"); + /* If we are handling an exception use the context record from that. */ + if (current_exception && current_exception->ExceptionRecord->ExceptionAddress) { + /* The back trace code will write to the context record, to protect the original record from + * modifications give the backtrace a copy to work on. */ + CONTEXT TempContext = *current_exception->ContextRecord; + return BLI_windows_system_backtrace_run_trace(fp, GetCurrentThread(), &TempContext); + } + else { + /* If there is no current exception or the address is not set, walk the current stack. */ + return bli_windows_system_backtrace_stack_thread(fp, GetCurrentThread()); + } +} + +static bool bli_private_symbols_loaded() +{ + IMAGEHLP_MODULE64 m64; + m64.SizeOfStruct = sizeof(m64); + if (SymGetModuleInfo64(GetCurrentProcess(), (DWORD64)GetModuleHandle(NULL), &m64)) { + return m64.GlobalSymbols; + } + return false; +} + +static void bli_load_symbols() +{ + /* If this is a developer station and the private pdb is already loaded leave it be. */ + if (bli_private_symbols_loaded()) { + return; + } + + char pdb_file[MAX_PATH] = {0}; + + /* get the currently executing image */ + if (GetModuleFileNameA(NULL, pdb_file, sizeof(pdb_file))) { + /* remove the filename */ + PathRemoveFileSpecA(pdb_file); + /* append blender.pdb */ + PathAppendA(pdb_file, "blender.pdb"); + if (PathFileExistsA(pdb_file)) { + HMODULE mod = GetModuleHandle(NULL); + if (mod) { + WIN32_FILE_ATTRIBUTE_DATA file_data; + if (GetFileAttributesExA(pdb_file, GetFileExInfoStandard, &file_data)) { + /* SymInitialize will try to load symbols on its own, so we first must unload whatever it + * did trying to help */ + SymUnloadModule64(GetCurrentProcess(), (DWORD64)mod); + + DWORD64 module_base = SymLoadModule(GetCurrentProcess(), + NULL, + pdb_file, + NULL, + (DWORD64)mod, + (DWORD)file_data.nFileSizeLow); + if (module_base == 0) { + fprintf(stderr, + "Error loading symbols %s\n\terror:0x%.8x\n\tsize = %d\n\tbase=0x%p\n", + pdb_file, + GetLastError(), + file_data.nFileSizeLow, + (LPVOID)mod); + } + } + } + } + } +} + +void BLI_system_backtrace(FILE *fp) +{ + SymInitialize(GetCurrentProcess(), NULL, TRUE); + bli_load_symbols(); + if (current_exception) { + bli_windows_system_backtrace_exception_record(fp, current_exception->ExceptionRecord); + } + if (BLI_windows_system_backtrace_stack(fp)) { + /* When the blender symbols are missing the stack traces will be unreliable + * so only run if the previous step completed successfully. */ + bli_windows_system_backtrace_threads(fp); + } + bli_windows_system_backtrace_modules(fp); + fputc(0, fp); /* Give our selves a nice zero terminator for later on */ +} + +void BLI_windows_handle_exception(EXCEPTION_POINTERS *exception) +{ + current_exception = exception; + if (current_exception) { + fprintf(stderr, + "Error : %s\n", + bli_windows_get_exception_description(exception->ExceptionRecord->ExceptionCode)); + fflush(stderr); + + LPVOID address = exception->ExceptionRecord->ExceptionAddress; + fprintf(stderr, "Address : 0x%p\n", address); + + CHAR modulename[MAX_PATH]; + bli_windows_get_module_name(address, modulename, sizeof(modulename)); + fprintf(stderr, "Module : %s\n", modulename); + fprintf(stderr, "Thread : %.8x\n", GetCurrentThreadId()); + } + fflush(stderr); +} diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index 4ac012fa578..ee459ac2548 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -17,7 +17,7 @@ /** \file * \ingroup bli * - * A generic task system which can be used for any task based subsystem. + * Parallel tasks over all elements in a container. */ #include <stdlib.h> @@ -34,77 +34,12 @@ #include "atomic_ops.h" -/* Parallel range routines */ - -/** - * - * Main functions: - * - #BLI_task_parallel_range - * - #BLI_task_parallel_listbase (#ListBase - double linked list) - * - * TODO: - * - #BLI_task_parallel_foreach_link (#Link - single linked list) - * - #BLI_task_parallel_foreach_ghash/gset (#GHash/#GSet - hash & set) - * - #BLI_task_parallel_foreach_mempool (#BLI_mempool - iterate over mempools) - */ - /* Allows to avoid using malloc for userdata_chunk in tasks, when small enough. */ #define MALLOCA(_size) ((_size) <= 8192) ? alloca((_size)) : MEM_mallocN((_size), __func__) #define MALLOCA_FREE(_mem, _size) \ if (((_mem) != NULL) && ((_size) > 8192)) \ MEM_freeN((_mem)) -/* Stores all needed data to perform a parallelized iteration, - * with a same operation (callback function). - * It can be chained with other tasks in a single-linked list way. */ -typedef struct TaskParallelRangeState { - struct TaskParallelRangeState *next; - - /* Start and end point of integer value iteration. */ - int start, stop; - - /* User-defined data, shared between all worker threads. */ - void *userdata_shared; - /* User-defined callback function called for each value in [start, stop[ specified range. */ - TaskParallelRangeFunc func; - - /* Each instance of looping chunks will get a copy of this data - * (similar to OpenMP's firstprivate). - */ - void *initial_tls_memory; /* Pointer to actual user-defined 'tls' data. */ - size_t tls_data_size; /* Size of that data. */ - - void *flatten_tls_storage; /* 'tls' copies of initial_tls_memory for each running task. */ - /* Number of 'tls' copies in the array, i.e. number of worker threads. */ - size_t num_elements_in_tls_storage; - - /* Function called from calling thread once whole range have been processed. */ - TaskParallelFinalizeFunc func_finalize; - - /* Current value of the iterator, shared between all threads (atomically updated). */ - int iter_value; - int iter_chunk_num; /* Amount of iterations to process in a single step. */ -} TaskParallelRangeState; - -/* Stores all the parallel tasks for a single pool. */ -typedef struct TaskParallelRangePool { - /* The workers' task pool. */ - TaskPool *pool; - /* The number of worker tasks we need to create. */ - int num_tasks; - /* The total number of iterations in all the added ranges. */ - int num_total_iters; - /* The size (number of items) processed at once by a worker task. */ - int chunk_size; - - /* Linked list of range tasks to process. */ - TaskParallelRangeState *parallel_range_states; - /* Current range task beeing processed, swapped atomically. */ - TaskParallelRangeState *current_state; - /* Scheduling settings common to all tasks. */ - TaskParallelSettings *settings; -} TaskParallelRangePool; - BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settings, const int tot_items, int num_tasks, @@ -149,429 +84,7 @@ BLI_INLINE void task_parallel_calc_chunk_size(const TaskParallelSettings *settin } BLI_assert(chunk_size > 0); - - if (tot_items > 0) { - switch (settings->scheduling_mode) { - case TASK_SCHEDULING_STATIC: - *r_chunk_size = max_ii(chunk_size, tot_items / num_tasks); - break; - case TASK_SCHEDULING_DYNAMIC: - *r_chunk_size = chunk_size; - break; - } - } - else { - /* If total amount of items is unknown, we can only use dynamic scheduling. */ - *r_chunk_size = chunk_size; - } -} - -BLI_INLINE void task_parallel_range_calc_chunk_size(TaskParallelRangePool *range_pool) -{ - int num_iters = 0; - int min_num_iters = INT_MAX; - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - const int ni = state->stop - state->start; - num_iters += ni; - if (min_num_iters > ni) { - min_num_iters = ni; - } - } - range_pool->num_total_iters = num_iters; - /* Note: Passing min_num_iters here instead of num_iters kind of partially breaks the 'static' - * scheduling, but pooled range iterator is inherently non-static anyway, so adding a small level - * of dynamic scheduling here should be fine. */ - task_parallel_calc_chunk_size( - range_pool->settings, min_num_iters, range_pool->num_tasks, &range_pool->chunk_size); -} - -BLI_INLINE bool parallel_range_next_iter_get(TaskParallelRangePool *__restrict range_pool, - int *__restrict r_iter, - int *__restrict r_count, - TaskParallelRangeState **__restrict r_state) -{ - /* We need an atomic op here as well to fetch the initial state, since some other thread might - * have already updated it. */ - TaskParallelRangeState *current_state = atomic_cas_ptr( - (void **)&range_pool->current_state, NULL, NULL); - - int previter = INT32_MAX; - - while (current_state != NULL && previter >= current_state->stop) { - previter = atomic_fetch_and_add_int32(¤t_state->iter_value, range_pool->chunk_size); - *r_iter = previter; - *r_count = max_ii(0, min_ii(range_pool->chunk_size, current_state->stop - previter)); - - if (previter >= current_state->stop) { - /* At this point the state we got is done, we need to go to the next one. In case some other - * thread already did it, then this does nothing, and we'll just get current valid state - * at start of the next loop. */ - TaskParallelRangeState *current_state_from_atomic_cas = atomic_cas_ptr( - (void **)&range_pool->current_state, current_state, current_state->next); - - if (current_state == current_state_from_atomic_cas) { - /* The atomic CAS operation was successful, we did update range_pool->current_state, so we - * can safely switch to next state. */ - current_state = current_state->next; - } - else { - /* The atomic CAS operation failed, but we still got range_pool->current_state value out of - * it, just use it as our new current state. */ - current_state = current_state_from_atomic_cas; - } - } - } - - *r_state = current_state; - return (current_state != NULL && previter < current_state->stop); -} - -static void parallel_range_func(TaskPool *__restrict pool, void *tls_data_idx, int thread_id) -{ - TaskParallelRangePool *__restrict range_pool = BLI_task_pool_userdata(pool); - TaskParallelTLS tls = { - .thread_id = thread_id, - .userdata_chunk = NULL, - }; - TaskParallelRangeState *state; - int iter, count; - while (parallel_range_next_iter_get(range_pool, &iter, &count, &state)) { - tls.userdata_chunk = (char *)state->flatten_tls_storage + - (((size_t)POINTER_AS_INT(tls_data_idx)) * state->tls_data_size); - for (int i = 0; i < count; i++) { - state->func(state->userdata_shared, iter + i, &tls); - } - } -} - -static void parallel_range_single_thread(TaskParallelRangePool *range_pool) -{ - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - const int start = state->start; - const int stop = state->stop; - void *userdata = state->userdata_shared; - TaskParallelRangeFunc func = state->func; - - void *initial_tls_memory = state->initial_tls_memory; - const size_t tls_data_size = state->tls_data_size; - void *flatten_tls_storage = NULL; - const bool use_tls_data = (tls_data_size != 0) && (initial_tls_memory != NULL); - if (use_tls_data) { - flatten_tls_storage = MALLOCA(tls_data_size); - memcpy(flatten_tls_storage, initial_tls_memory, tls_data_size); - } - TaskParallelTLS tls = { - .thread_id = 0, - .userdata_chunk = flatten_tls_storage, - }; - for (int i = start; i < stop; i++) { - func(userdata, i, &tls); - } - if (state->func_finalize != NULL) { - state->func_finalize(userdata, flatten_tls_storage); - } - MALLOCA_FREE(flatten_tls_storage, tls_data_size); - } -} - -/** - * This function allows to parallelized for loops in a similar way to OpenMP's - * 'parallel for' statement. - * - * See public API doc of ParallelRangeSettings for description of all settings. - */ -void BLI_task_parallel_range(const int start, - const int stop, - void *userdata, - TaskParallelRangeFunc func, - TaskParallelSettings *settings) -{ - if (start == stop) { - return; - } - - BLI_assert(start < stop); - - TaskParallelRangeState state = { - .next = NULL, - .start = start, - .stop = stop, - .userdata_shared = userdata, - .func = func, - .iter_value = start, - .initial_tls_memory = settings->userdata_chunk, - .tls_data_size = settings->userdata_chunk_size, - .func_finalize = settings->func_finalize, - }; - TaskParallelRangePool range_pool = { - .pool = NULL, .parallel_range_states = &state, .current_state = NULL, .settings = settings}; - int i, num_threads, num_tasks; - - void *tls_data = settings->userdata_chunk; - const size_t tls_data_size = settings->userdata_chunk_size; - if (tls_data_size != 0) { - BLI_assert(tls_data != NULL); - } - const bool use_tls_data = (tls_data_size != 0) && (tls_data != NULL); - void *flatten_tls_storage = NULL; - - /* If it's not enough data to be crunched, don't bother with tasks at all, - * do everything from the current thread. - */ - if (!settings->use_threading) { - parallel_range_single_thread(&range_pool); - return; - } - - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - num_threads = BLI_task_scheduler_num_threads(task_scheduler); - - /* The idea here is to prevent creating task for each of the loop iterations - * and instead have tasks which are evenly distributed across CPU cores and - * pull next iter to be crunched using the queue. - */ - range_pool.num_tasks = num_tasks = num_threads + 2; - - task_parallel_range_calc_chunk_size(&range_pool); - range_pool.num_tasks = num_tasks = min_ii(num_tasks, - max_ii(1, (stop - start) / range_pool.chunk_size)); - - if (num_tasks == 1) { - parallel_range_single_thread(&range_pool); - return; - } - - TaskPool *task_pool = range_pool.pool = BLI_task_pool_create_suspended( - task_scheduler, &range_pool, TASK_PRIORITY_HIGH); - - range_pool.current_state = &state; - - if (use_tls_data) { - state.flatten_tls_storage = flatten_tls_storage = MALLOCA(tls_data_size * (size_t)num_tasks); - state.tls_data_size = tls_data_size; - } - - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); - for (i = 0; i < num_tasks; i++) { - if (use_tls_data) { - void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i); - memcpy(userdata_chunk_local, tls_data, tls_data_size); - } - /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread( - task_pool, parallel_range_func, POINTER_FROM_INT(i), false, NULL, thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - - if (use_tls_data) { - if (settings->func_finalize != NULL) { - for (i = 0; i < num_tasks; i++) { - void *userdata_chunk_local = (char *)flatten_tls_storage + (tls_data_size * (size_t)i); - settings->func_finalize(userdata, userdata_chunk_local); - } - } - MALLOCA_FREE(flatten_tls_storage, tls_data_size * (size_t)num_tasks); - } -} - -/** - * Initialize a task pool to parallelize several for loops at the same time. - * - * See public API doc of ParallelRangeSettings for description of all settings. - * Note that loop-specific settings (like 'tls' data or finalize function) must be left NULL here. - * Only settings controlling how iteration is parallelized must be defined, as those will affect - * all loops added to that pool. - */ -TaskParallelRangePool *BLI_task_parallel_range_pool_init(const TaskParallelSettings *settings) -{ - TaskParallelRangePool *range_pool = MEM_callocN(sizeof(*range_pool), __func__); - - BLI_assert(settings->userdata_chunk == NULL); - BLI_assert(settings->func_finalize == NULL); - range_pool->settings = MEM_mallocN(sizeof(*range_pool->settings), __func__); - *range_pool->settings = *settings; - - return range_pool; -} - -/** - * Add a loop task to the pool. It does not execute it at all. - * - * See public API doc of ParallelRangeSettings for description of all settings. - * Note that only 'tls'-related data are used here. - */ -void BLI_task_parallel_range_pool_push(TaskParallelRangePool *range_pool, - const int start, - const int stop, - void *userdata, - TaskParallelRangeFunc func, - const TaskParallelSettings *settings) -{ - BLI_assert(range_pool->pool == NULL); - - if (start == stop) { - return; - } - - BLI_assert(start < stop); - if (settings->userdata_chunk_size != 0) { - BLI_assert(settings->userdata_chunk != NULL); - } - - TaskParallelRangeState *state = MEM_callocN(sizeof(*state), __func__); - state->start = start; - state->stop = stop; - state->userdata_shared = userdata; - state->func = func; - state->iter_value = start; - state->initial_tls_memory = settings->userdata_chunk; - state->tls_data_size = settings->userdata_chunk_size; - state->func_finalize = settings->func_finalize; - - state->next = range_pool->parallel_range_states; - range_pool->parallel_range_states = state; -} - -static void parallel_range_func_finalize(TaskPool *__restrict pool, - void *v_state, - int UNUSED(thread_id)) -{ - TaskParallelRangePool *__restrict range_pool = BLI_task_pool_userdata(pool); - TaskParallelRangeState *state = v_state; - - for (int i = 0; i < range_pool->num_tasks; i++) { - void *tls_data = (char *)state->flatten_tls_storage + (state->tls_data_size * (size_t)i); - state->func_finalize(state->userdata_shared, tls_data); - } -} - -/** - * Run all tasks pushed to the range_pool. - * - * Note that the range pool is re-usable (you may push new tasks into it and call this function - * again). - */ -void BLI_task_parallel_range_pool_work_and_wait(TaskParallelRangePool *range_pool) -{ - BLI_assert(range_pool->pool == NULL); - - /* If it's not enough data to be crunched, don't bother with tasks at all, - * do everything from the current thread. - */ - if (!range_pool->settings->use_threading) { - parallel_range_single_thread(range_pool); - return; - } - - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - const int num_threads = BLI_task_scheduler_num_threads(task_scheduler); - - /* The idea here is to prevent creating task for each of the loop iterations - * and instead have tasks which are evenly distributed across CPU cores and - * pull next iter to be crunched using the queue. - */ - int num_tasks = num_threads + 2; - range_pool->num_tasks = num_tasks; - - task_parallel_range_calc_chunk_size(range_pool); - range_pool->num_tasks = num_tasks = min_ii( - num_tasks, max_ii(1, range_pool->num_total_iters / range_pool->chunk_size)); - - if (num_tasks == 1) { - parallel_range_single_thread(range_pool); - return; - } - - /* We create all 'tls' data here in a single loop. */ - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - void *userdata_chunk = state->initial_tls_memory; - const size_t userdata_chunk_size = state->tls_data_size; - if (userdata_chunk_size == 0) { - BLI_assert(userdata_chunk == NULL); - continue; - } - - void *userdata_chunk_array = NULL; - state->flatten_tls_storage = userdata_chunk_array = MALLOCA(userdata_chunk_size * - (size_t)num_tasks); - for (int i = 0; i < num_tasks; i++) { - void *userdata_chunk_local = (char *)userdata_chunk_array + - (userdata_chunk_size * (size_t)i); - memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); - } - } - - TaskPool *task_pool = range_pool->pool = BLI_task_pool_create_suspended( - task_scheduler, range_pool, TASK_PRIORITY_HIGH); - - range_pool->current_state = range_pool->parallel_range_states; - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); - for (int i = 0; i < num_tasks; i++) { - BLI_task_pool_push_from_thread( - task_pool, parallel_range_func, POINTER_FROM_INT(i), false, NULL, thread_id); - } - - BLI_task_pool_work_and_wait(task_pool); - - BLI_assert(atomic_cas_ptr((void **)&range_pool->current_state, NULL, NULL) == NULL); - - /* Finalize all tasks. */ - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state->next) { - const size_t userdata_chunk_size = state->tls_data_size; - void *userdata_chunk_array = state->flatten_tls_storage; - UNUSED_VARS_NDEBUG(userdata_chunk_array); - if (userdata_chunk_size == 0) { - BLI_assert(userdata_chunk_array == NULL); - continue; - } - - if (state->func_finalize != NULL) { - BLI_task_pool_push_from_thread( - task_pool, parallel_range_func_finalize, state, false, NULL, thread_id); - } - } - - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - range_pool->pool = NULL; - - /* Cleanup all tasks. */ - TaskParallelRangeState *state_next; - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state_next) { - state_next = state->next; - - const size_t userdata_chunk_size = state->tls_data_size; - void *userdata_chunk_array = state->flatten_tls_storage; - if (userdata_chunk_size != 0) { - BLI_assert(userdata_chunk_array != NULL); - MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * (size_t)num_tasks); - } - - MEM_freeN(state); - } - range_pool->parallel_range_states = NULL; -} - -/** - * Clear/free given \a range_pool. - */ -void BLI_task_parallel_range_pool_free(TaskParallelRangePool *range_pool) -{ - TaskParallelRangeState *state_next = NULL; - for (TaskParallelRangeState *state = range_pool->parallel_range_states; state != NULL; - state = state_next) { - state_next = state->next; - MEM_freeN(state); - } - MEM_freeN(range_pool->settings); - MEM_freeN(range_pool); + *r_chunk_size = chunk_size; } typedef struct TaskParallelIteratorState { @@ -586,20 +99,10 @@ typedef struct TaskParallelIteratorState { int tot_items; } TaskParallelIteratorState; -BLI_INLINE void task_parallel_iterator_calc_chunk_size(const TaskParallelSettings *settings, - const int num_tasks, - TaskParallelIteratorState *state) -{ - task_parallel_calc_chunk_size( - settings, state->tot_items, num_tasks, &state->iter_shared.chunk_size); -} - static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict state, - void *userdata_chunk, - int threadid) + void *userdata_chunk) { TaskParallelTLS tls = { - .thread_id = threadid, .userdata_chunk = userdata_chunk, }; @@ -652,11 +155,11 @@ static void parallel_iterator_func_do(TaskParallelIteratorState *__restrict stat MALLOCA_FREE(current_chunk_indices, indices_size); } -static void parallel_iterator_func(TaskPool *__restrict pool, void *userdata_chunk, int threadid) +static void parallel_iterator_func(TaskPool *__restrict pool, void *userdata_chunk) { - TaskParallelIteratorState *__restrict state = BLI_task_pool_userdata(pool); + TaskParallelIteratorState *__restrict state = BLI_task_pool_user_data(pool); - parallel_iterator_func_do(state, userdata_chunk, threadid); + parallel_iterator_func_do(state, userdata_chunk); } static void task_parallel_iterator_no_threads(const TaskParallelSettings *settings, @@ -675,23 +178,21 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin /* Also marking it as non-threaded for the iterator callback. */ state->iter_shared.spin_lock = NULL; - parallel_iterator_func_do(state, userdata_chunk, 0); + parallel_iterator_func_do(state, userdata_chunk); - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - settings->func_finalize(state->userdata, userdata_chunk_local); - } - MALLOCA_FREE(userdata_chunk_local, userdata_chunk_size); + if (use_userdata_chunk && settings->func_free != NULL) { + /* `func_free` should only free data that was created during execution of `func`. */ + settings->func_free(state->userdata, userdata_chunk_local); } } static void task_parallel_iterator_do(const TaskParallelSettings *settings, TaskParallelIteratorState *state) { - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - const int num_threads = BLI_task_scheduler_num_threads(task_scheduler); + const int num_threads = BLI_task_scheduler_num_threads(); - task_parallel_iterator_calc_chunk_size(settings, num_threads, state); + task_parallel_calc_chunk_size( + settings, state->tot_items, num_threads, &state->iter_shared.chunk_size); if (!settings->use_threading) { task_parallel_iterator_no_threads(settings, state); @@ -720,31 +221,32 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, void *userdata_chunk_array = NULL; const bool use_userdata_chunk = (userdata_chunk_size != 0) && (userdata_chunk != NULL); - TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, state, TASK_PRIORITY_HIGH); + TaskPool *task_pool = BLI_task_pool_create(state, TASK_PRIORITY_HIGH); if (use_userdata_chunk) { userdata_chunk_array = MALLOCA(userdata_chunk_size * num_tasks); } - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); for (size_t i = 0; i < num_tasks; i++) { if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); } /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread( - task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL, thread_id); + BLI_task_pool_push(task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL); } BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); - if (use_userdata_chunk) { - if (settings->func_finalize != NULL) { - for (size_t i = 0; i < num_tasks; i++) { - userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); - settings->func_finalize(state->userdata, userdata_chunk_local); + if (use_userdata_chunk && (settings->func_reduce != NULL || settings->func_free != NULL)) { + for (size_t i = 0; i < num_tasks; i++) { + userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); + if (settings->func_reduce != NULL) { + settings->func_reduce(state->userdata, userdata_chunk, userdata_chunk_local); + } + if (settings->func_free != NULL) { + settings->func_free(state->userdata, userdata_chunk_local); } } MALLOCA_FREE(userdata_chunk_array, userdata_chunk_size * num_tasks); @@ -847,9 +349,9 @@ typedef struct ParallelMempoolState { TaskParallelMempoolFunc func; } ParallelMempoolState; -static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) +static void parallel_mempool_func(TaskPool *__restrict pool, void *taskdata) { - ParallelMempoolState *__restrict state = BLI_task_pool_userdata(pool); + ParallelMempoolState *__restrict state = BLI_task_pool_user_data(pool); BLI_mempool_iter *iter = taskdata; MempoolIterData *item; @@ -875,7 +377,6 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, TaskParallelMempoolFunc func, const bool use_threading) { - TaskScheduler *task_scheduler; TaskPool *task_pool; ParallelMempoolState state; int i, num_threads, num_tasks; @@ -895,9 +396,8 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, return; } - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(task_scheduler, &state, TASK_PRIORITY_HIGH); - num_threads = BLI_task_scheduler_num_threads(task_scheduler); + task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); + num_threads = BLI_task_scheduler_num_threads(); /* The idea here is to prevent creating task for each of the loop iterations * and instead have tasks which are evenly distributed across CPU cores and @@ -911,11 +411,9 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, BLI_mempool_iter *mempool_iterators = BLI_mempool_iter_threadsafe_create(mempool, (size_t)num_tasks); - const int thread_id = BLI_task_pool_creator_thread_id(task_pool); for (i = 0; i < num_tasks; i++) { /* Use this pool's pre-allocated tasks. */ - BLI_task_pool_push_from_thread( - task_pool, parallel_mempool_func, &mempool_iterators[i], false, NULL, thread_id); + BLI_task_pool_push(task_pool, parallel_mempool_func, &mempool_iterators[i], false, NULL); } BLI_task_pool_work_and_wait(task_pool); diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 8085d495248..c4d60673492 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -17,731 +17,396 @@ /** \file * \ingroup bli * - * A generic task system which can be used for any task based subsystem. + * Task pool to run tasks in parallel. */ +#include <memory> #include <stdlib.h> +#include <utility> #include "MEM_guardedalloc.h" #include "DNA_listBase.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_mempool.h" #include "BLI_task.h" #include "BLI_threads.h" -#include "atomic_ops.h" - -/* Define this to enable some detailed statistic print. */ -#undef DEBUG_STATS - -/* Types */ - -/* Number of per-thread pre-allocated tasks. - * - * For more details see description of TaskMemPool. - */ -#define MEMPOOL_SIZE 256 - -/* Number of tasks which are pushed directly to local thread queue. - * - * This allows thread to fetch next task without locking the whole queue. - */ -#define LOCAL_QUEUE_SIZE 1 - -/* Number of tasks which are allowed to be scheduled in a delayed manner. - * - * This allows to use less locks per graph node children schedule. More details - * could be found at TaskThreadLocalStorage::do_delayed_push. - */ -#define DELAYED_QUEUE_SIZE 4096 - -#ifndef NDEBUG -# define ASSERT_THREAD_ID(scheduler, thread_id) \ - do { \ - if (!BLI_thread_is_main()) { \ - TaskThread *thread = (TaskThread *)pthread_getspecific(scheduler->tls_id_key); \ - if (thread == NULL) { \ - BLI_assert(thread_id == 0); \ - } \ - else { \ - BLI_assert(thread_id == thread->id); \ - } \ - } \ - else { \ - BLI_assert(thread_id == 0); \ - } \ - } while (false) -#else -# define ASSERT_THREAD_ID(scheduler, thread_id) +#ifdef WITH_TBB +/* Quiet top level deprecation message, unrelated to API usage here. */ +# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 +# include <tbb/tbb.h> #endif -typedef struct Task { - struct Task *next, *prev; +/* Task + * + * Unit of work to execute. This is a C++ class to work with TBB. */ +class Task { + public: + TaskPool *pool; TaskRunFunction run; void *taskdata; bool free_taskdata; TaskFreeFunction freedata; - TaskPool *pool; -} Task; -/* This is a per-thread storage of pre-allocated tasks. - * - * The idea behind this is simple: reduce amount of malloc() calls when pushing - * new task to the pool. This is done by keeping memory from the tasks which - * were finished already, so instead of freeing that memory we put it to the - * pool for the later re-use. - * - * The tricky part here is to avoid any inter-thread synchronization, hence no - * lock must exist around this pool. The pool will become an owner of the pointer - * from freed task, and only corresponding thread will be able to use this pool - * (no memory stealing and such). - * - * This leads to the following use of the pool: - * - * - task_push() should provide proper thread ID from which the task is being - * pushed from. - * - * - Task allocation function which check corresponding memory pool and if there - * is any memory in there it'll mark memory as re-used, remove it from the pool - * and use that memory for the new task. - * - * At this moment task queue owns the memory. - * - * - When task is done and task_free() is called the memory will be put to the - * pool which corresponds to a thread which handled the task. - */ -typedef struct TaskMemPool { - /* Number of pre-allocated tasks in the pool. */ - int num_tasks; - /* Pre-allocated task memory pointers. */ - Task *tasks[MEMPOOL_SIZE]; -} TaskMemPool; - -#ifdef DEBUG_STATS -typedef struct TaskMemPoolStats { - /* Number of allocations. */ - int num_alloc; - /* Number of avoided allocations (pointer was re-used from the pool). */ - int num_reuse; - /* Number of discarded memory due to pool saturation, */ - int num_discard; -} TaskMemPoolStats; -#endif - -typedef struct TaskThreadLocalStorage { - /* Memory pool for faster task allocation. - * The idea is to re-use memory of finished/discarded tasks by this thread. - */ - TaskMemPool task_mempool; - - /* Local queue keeps thread alive by keeping small amount of tasks ready - * to be picked up without causing global thread locks for synchronization. - */ - int num_local_queue; - Task *local_queue[LOCAL_QUEUE_SIZE]; - - /* Thread can be marked for delayed tasks push. This is helpful when it's - * know that lots of subsequent task pushed will happen from the same thread - * without "interrupting" for task execution. - * - * We try to accumulate as much tasks as possible in a local queue without - * any locks first, and then we push all of them into a scheduler's queue - * from within a single mutex lock. - */ - bool do_delayed_push; - int num_delayed_queue; - Task *delayed_queue[DELAYED_QUEUE_SIZE]; -} TaskThreadLocalStorage; - -struct TaskPool { - TaskScheduler *scheduler; - - volatile size_t num; - ThreadMutex num_mutex; - ThreadCondition num_cond; - - void *userdata; - ThreadMutex user_mutex; + Task(TaskPool *pool, + TaskRunFunction run, + void *taskdata, + bool free_taskdata, + TaskFreeFunction freedata) + : pool(pool), run(run), taskdata(taskdata), free_taskdata(free_taskdata), freedata(freedata) + { + } - volatile bool do_cancel; - volatile bool do_work; + ~Task() + { + if (free_taskdata) { + if (freedata) { + freedata(pool, taskdata); + } + else { + MEM_freeN(taskdata); + } + } + } - volatile bool is_suspended; - bool start_suspended; - ListBase suspended_queue; - size_t num_suspended; + /* Move constructor. + * For performance, ensure we never copy the task and only move it. + * For TBB version 2017 and earlier we apply a workaround to make up for + * the lack of move constructor support. */ + Task(Task &&other) + : pool(other.pool), + run(other.run), + taskdata(other.taskdata), + free_taskdata(other.free_taskdata), + freedata(other.freedata) + { + other.pool = NULL; + other.run = NULL; + other.taskdata = NULL; + other.free_taskdata = false; + other.freedata = NULL; + } + +#if defined(WITH_TBB) && TBB_INTERFACE_VERSION_MAJOR < 10 + Task(const Task &other) + : pool(other.pool), + run(other.run), + taskdata(other.taskdata), + free_taskdata(other.free_taskdata), + freedata(other.freedata) + { + ((Task &)other).pool = NULL; + ((Task &)other).run = NULL; + ((Task &)other).taskdata = NULL; + ((Task &)other).free_taskdata = false; + ((Task &)other).freedata = NULL; + } +#else + Task(const Task &other) = delete; +#endif - TaskPriority priority; + Task &operator=(const Task &other) = delete; + Task &operator=(Task &&other) = delete; - /* If set, this pool may never be work_and_wait'ed, which means TaskScheduler - * has to use its special background fallback thread in case we are in - * single-threaded situation. - */ - bool run_in_background; + /* Execute task. */ + void operator()() const + { + run(pool, taskdata); + } +}; - /* This is a task scheduler's ID of a thread at which pool was constructed. - * It will be used to access task TLS. - */ - int thread_id; +/* TBB Task Group. + * + * Subclass since there seems to be no other way to set priority. */ + +#ifdef WITH_TBB +class TBBTaskGroup : public tbb::task_group { + public: + TBBTaskGroup(TaskPriority priority) + { + switch (priority) { + case TASK_PRIORITY_LOW: + my_context.set_priority(tbb::priority_low); + break; + case TASK_PRIORITY_HIGH: + my_context.set_priority(tbb::priority_normal); + break; + } + } - /* For the pools which are created from non-main thread which is not a - * scheduler worker thread we can't re-use any of scheduler's threads TLS - * and have to use our own one. - */ - bool use_local_tls; - TaskThreadLocalStorage local_tls; -#ifndef NDEBUG - pthread_t creator_thread_id; + ~TBBTaskGroup() + { + } +}; #endif -#ifdef DEBUG_STATS - TaskMemPoolStats *mempool_stats; -#endif -}; +/* Task Pool */ -struct TaskScheduler { - pthread_t *threads; - struct TaskThread *task_threads; - int num_threads; - bool background_thread_only; +typedef enum TaskPoolType { + TASK_POOL_TBB, + TASK_POOL_TBB_SUSPENDED, + TASK_POOL_NO_THREADS, + TASK_POOL_BACKGROUND, + TASK_POOL_BACKGROUND_SERIAL, +} TaskPoolType; - ListBase queue; - ThreadMutex queue_mutex; - ThreadCondition queue_cond; +struct TaskPool { + TaskPoolType type; + bool use_threads; - ThreadMutex startup_mutex; - ThreadCondition startup_cond; - volatile int num_thread_started; + ThreadMutex user_mutex; + void *userdata; - volatile bool do_exit; + /* TBB task pool. */ +#ifdef WITH_TBB + TBBTaskGroup tbb_group; +#endif + volatile bool is_suspended; + BLI_mempool *suspended_mempool; - /* NOTE: In pthread's TLS we store the whole TaskThread structure. */ - pthread_key_t tls_id_key; + /* Background task pool. */ + ListBase background_threads; + ThreadQueue *background_queue; + volatile bool background_is_canceling; }; -typedef struct TaskThread { - TaskScheduler *scheduler; - int id; - TaskThreadLocalStorage tls; -} TaskThread; - -/* Helper */ -BLI_INLINE void task_data_free(Task *task, const int thread_id) -{ - if (task->free_taskdata) { - if (task->freedata) { - task->freedata(task->pool, task->taskdata, thread_id); - } - else { - MEM_freeN(task->taskdata); - } - } -} - -BLI_INLINE void initialize_task_tls(TaskThreadLocalStorage *tls) -{ - memset(tls, 0, sizeof(TaskThreadLocalStorage)); -} +/* TBB Task Pool. + * + * Task pool using the TBB scheduler for tasks. When building without TBB + * support or running Blender with -t 1, this reverts to single threaded. + * + * Tasks may be suspended until in all are created, to make it possible to + * initialize data structures and create tasks in a single pass. */ -BLI_INLINE TaskThreadLocalStorage *get_task_tls(TaskPool *pool, const int thread_id) +static void tbb_task_pool_create(TaskPool *pool, TaskPriority priority) { - TaskScheduler *scheduler = pool->scheduler; - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= scheduler->num_threads); - if (pool->use_local_tls && thread_id == 0) { - BLI_assert(pool->thread_id == 0); - BLI_assert(!BLI_thread_is_main()); - BLI_assert(pthread_equal(pthread_self(), pool->creator_thread_id)); - return &pool->local_tls; + if (pool->type == TASK_POOL_TBB_SUSPENDED) { + pool->is_suspended = true; + pool->suspended_mempool = BLI_mempool_create(sizeof(Task), 512, 512, BLI_MEMPOOL_ALLOW_ITER); } - if (thread_id == 0) { - BLI_assert(BLI_thread_is_main()); - return &scheduler->task_threads[pool->thread_id].tls; - } - return &scheduler->task_threads[thread_id].tls; -} -BLI_INLINE void free_task_tls(TaskThreadLocalStorage *tls) -{ - TaskMemPool *task_mempool = &tls->task_mempool; - for (int i = 0; i < task_mempool->num_tasks; i++) { - MEM_freeN(task_mempool->tasks[i]); +#ifdef WITH_TBB + if (pool->use_threads) { + new (&pool->tbb_group) TBBTaskGroup(priority); } -} - -static Task *task_alloc(TaskPool *pool, const int thread_id) -{ - BLI_assert(thread_id <= pool->scheduler->num_threads); - if (thread_id != -1) { - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= pool->scheduler->num_threads); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - TaskMemPool *task_mempool = &tls->task_mempool; - /* Try to re-use task memory from a thread local storage. */ - if (task_mempool->num_tasks > 0) { - --task_mempool->num_tasks; - /* Success! We've just avoided task allocation. */ -#ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_reuse++; -#endif - return task_mempool->tasks[task_mempool->num_tasks]; - } - /* We are doomed to allocate new task data. */ -#ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_alloc++; +#else + UNUSED_VARS(priority); #endif - } - return (Task *)MEM_mallocN(sizeof(Task), "New task"); } -static void task_free(TaskPool *pool, Task *task, const int thread_id) +static void tbb_task_pool_run(TaskPool *pool, Task &&task) { - task_data_free(task, thread_id); - BLI_assert(thread_id >= 0); - BLI_assert(thread_id <= pool->scheduler->num_threads); - if (thread_id == 0) { - BLI_assert(pool->use_local_tls || BLI_thread_is_main()); + if (pool->is_suspended) { + /* Suspended task that will be executed in work_and_wait(). */ + Task *task_mem = (Task *)BLI_mempool_alloc(pool->suspended_mempool); + new (task_mem) Task(std::move(task)); +#ifdef __GNUC__ + /* Work around apparent compiler bug where task is not properly copied + * to task_mem. This appears unrelated to the use of placement new or + * move semantics, happens even writing to a plain C struct. Rather the + * call into TBB seems to have some indirect effect. */ + std::atomic_thread_fence(std::memory_order_release); +#endif } - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - TaskMemPool *task_mempool = &tls->task_mempool; - if (task_mempool->num_tasks < MEMPOOL_SIZE - 1) { - /* Successfully allowed the task to be re-used later. */ - task_mempool->tasks[task_mempool->num_tasks] = task; - ++task_mempool->num_tasks; +#ifdef WITH_TBB + else if (pool->use_threads) { + /* Execute in TBB task group. */ + pool->tbb_group.run(std::move(task)); } - else { - /* Local storage saturated, no other way than just discard - * the memory. - * - * TODO(sergey): We can perhaps store such pointer in a global - * scheduler pool, maybe it'll be faster than discarding and - * allocating again. - */ - MEM_freeN(task); -#ifdef DEBUG_STATS - pool->mempool_stats[thread_id].num_discard++; #endif + else { + /* Execute immediately. */ + task(); } } -/* Task Scheduler */ - -static void task_pool_num_decrease(TaskPool *pool, size_t done) +static void tbb_task_pool_work_and_wait(TaskPool *pool) { - BLI_mutex_lock(&pool->num_mutex); + /* Start any suspended task now. */ + if (pool->suspended_mempool) { + pool->is_suspended = false; - BLI_assert(pool->num >= done); - - pool->num -= done; + BLI_mempool_iter iter; + BLI_mempool_iternew(pool->suspended_mempool, &iter); + while (Task *task = (Task *)BLI_mempool_iterstep(&iter)) { + tbb_task_pool_run(pool, std::move(*task)); + } - if (pool->num == 0) { - BLI_condition_notify_all(&pool->num_cond); + BLI_mempool_clear(pool->suspended_mempool); } - BLI_mutex_unlock(&pool->num_mutex); +#ifdef WITH_TBB + if (pool->use_threads) { + /* This is called wait(), but internally it can actually do work. This + * matters because we don't want recursive usage of task pools to run + * out of threads and get stuck. */ + pool->tbb_group.wait(); + } +#endif } -static void task_pool_num_increase(TaskPool *pool, size_t new_num) +static void tbb_task_pool_cancel(TaskPool *pool) { - BLI_mutex_lock(&pool->num_mutex); - - pool->num += new_num; - BLI_condition_notify_all(&pool->num_cond); - - BLI_mutex_unlock(&pool->num_mutex); +#ifdef WITH_TBB + if (pool->use_threads) { + pool->tbb_group.cancel(); + pool->tbb_group.wait(); + } +#else + UNUSED_VARS(pool); +#endif } -static bool task_scheduler_thread_wait_pop(TaskScheduler *scheduler, Task **task) +static bool tbb_task_pool_canceled(TaskPool *pool) { - bool found_task = false; - BLI_mutex_lock(&scheduler->queue_mutex); - - while (!scheduler->queue.first && !scheduler->do_exit) { - BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); +#ifdef WITH_TBB + if (pool->use_threads) { + return pool->tbb_group.is_canceling(); } +#else + UNUSED_VARS(pool); +#endif - do { - Task *current_task; - - /* Assuming we can only have a void queue in 'exit' case here seems logical - * (we should only be here after our worker thread has been woken up from a - * condition_wait(), which only happens after a new task was added to the queue), - * but it is wrong. - * Waiting on condition may wake up the thread even if condition is not signaled - * (spurious wake-ups), and some race condition may also empty the queue **after** - * condition has been signaled, but **before** awoken thread reaches this point... - * See http://stackoverflow.com/questions/8594591 - * - * So we only abort here if do_exit is set. - */ - if (scheduler->do_exit) { - BLI_mutex_unlock(&scheduler->queue_mutex); - return false; - } - - for (current_task = (Task *)scheduler->queue.first; current_task != NULL; - current_task = current_task->next) { - TaskPool *pool = current_task->pool; - - if (scheduler->background_thread_only && !pool->run_in_background) { - continue; - } - - *task = current_task; - found_task = true; - BLI_remlink(&scheduler->queue, *task); - break; - } - if (!found_task) { - BLI_condition_wait(&scheduler->queue_cond, &scheduler->queue_mutex); - } - } while (!found_task); - - BLI_mutex_unlock(&scheduler->queue_mutex); - - return true; + return false; } -BLI_INLINE void handle_local_queue(TaskThreadLocalStorage *tls, const int thread_id) +static void tbb_task_pool_free(TaskPool *pool) { - BLI_assert(!tls->do_delayed_push); - while (tls->num_local_queue > 0) { - /* We pop task from queue before handling it so handler of the task can - * push next job to the local queue. - */ - tls->num_local_queue--; - Task *local_task = tls->local_queue[tls->num_local_queue]; - /* TODO(sergey): Double-check work_and_wait() doesn't handle other's - * pool tasks. - */ - TaskPool *local_pool = local_task->pool; - local_task->run(local_pool, local_task->taskdata, thread_id); - task_free(local_pool, local_task, thread_id); +#ifdef WITH_TBB + if (pool->use_threads) { + pool->tbb_group.~TBBTaskGroup(); } - BLI_assert(!tls->do_delayed_push); -} +#endif -static void *task_scheduler_thread_run(void *thread_p) -{ - TaskThread *thread = (TaskThread *)thread_p; - TaskThreadLocalStorage *tls = &thread->tls; - TaskScheduler *scheduler = thread->scheduler; - int thread_id = thread->id; - Task *task; - - pthread_setspecific(scheduler->tls_id_key, thread); - - /* signal the main thread when all threads have started */ - BLI_mutex_lock(&scheduler->startup_mutex); - scheduler->num_thread_started++; - if (scheduler->num_thread_started == scheduler->num_threads) { - BLI_condition_notify_one(&scheduler->startup_cond); + if (pool->suspended_mempool) { + BLI_mempool_destroy(pool->suspended_mempool); } - BLI_mutex_unlock(&scheduler->startup_mutex); - - /* keep popping off tasks */ - while (task_scheduler_thread_wait_pop(scheduler, &task)) { - TaskPool *pool = task->pool; - - /* run task */ - BLI_assert(!tls->do_delayed_push); - task->run(pool, task->taskdata, thread_id); - BLI_assert(!tls->do_delayed_push); - - /* delete task */ - task_free(pool, task, thread_id); +} - /* Handle all tasks from local queue. */ - handle_local_queue(tls, thread_id); +/* Background Task Pool. + * + * Fallback for running background tasks when building without TBB. */ - /* notify pool task was done */ - task_pool_num_decrease(pool, 1); +static void *background_task_run(void *userdata) +{ + TaskPool *pool = (TaskPool *)userdata; + while (Task *task = (Task *)BLI_thread_queue_pop(pool->background_queue)) { + (*task)(); + task->~Task(); + MEM_freeN(task); } - return NULL; } -TaskScheduler *BLI_task_scheduler_create(int num_threads) +static void background_task_pool_create(TaskPool *pool) { - TaskScheduler *scheduler = (TaskScheduler *)MEM_callocN(sizeof(TaskScheduler), "TaskScheduler"); - - /* multiple places can use this task scheduler, sharing the same - * threads, so we keep track of the number of users. */ - scheduler->do_exit = false; - - BLI_listbase_clear(&scheduler->queue); - BLI_mutex_init(&scheduler->queue_mutex); - BLI_condition_init(&scheduler->queue_cond); - - BLI_mutex_init(&scheduler->startup_mutex); - BLI_condition_init(&scheduler->startup_cond); - scheduler->num_thread_started = 0; - - if (num_threads == 0) { - /* automatic number of threads will be main thread + num cores */ - num_threads = BLI_system_thread_count(); - } - - /* main thread will also work, so we count it too */ - num_threads -= 1; - - /* Add background-only thread if needed. */ - if (num_threads == 0) { - scheduler->background_thread_only = true; - num_threads = 1; - } - - scheduler->task_threads = (TaskThread *)MEM_mallocN(sizeof(TaskThread) * (num_threads + 1), - "TaskScheduler task threads"); - - /* Initialize TLS for main thread. */ - initialize_task_tls(&scheduler->task_threads[0].tls); - - pthread_key_create(&scheduler->tls_id_key, NULL); - - /* launch threads that will be waiting for work */ - if (num_threads > 0) { - int i; - - scheduler->num_threads = num_threads; - scheduler->threads = (pthread_t *)MEM_callocN(sizeof(pthread_t) * num_threads, - "TaskScheduler threads"); - - for (i = 0; i < num_threads; i++) { - TaskThread *thread = &scheduler->task_threads[i + 1]; - thread->scheduler = scheduler; - thread->id = i + 1; - initialize_task_tls(&thread->tls); - - if (pthread_create(&scheduler->threads[i], NULL, task_scheduler_thread_run, thread) != 0) { - fprintf(stderr, "TaskScheduler failed to launch thread %d/%d\n", i, num_threads); - } - } - } - - /* Wait for all worker threads to start before returning to caller to prevent the case where - * threads are still starting and pthread_join is called, which causes a deadlock on pthreads4w. - */ - BLI_mutex_lock(&scheduler->startup_mutex); - /* NOTE: Use loop here to avoid false-positive everything-is-ready caused by spontaneous thread - * wake up. */ - while (scheduler->num_thread_started != num_threads) { - BLI_condition_wait(&scheduler->startup_cond, &scheduler->startup_mutex); - } - BLI_mutex_unlock(&scheduler->startup_mutex); - - return scheduler; + pool->background_queue = BLI_thread_queue_init(); + BLI_threadpool_init(&pool->background_threads, background_task_run, 1); } -void BLI_task_scheduler_free(TaskScheduler *scheduler) +static void background_task_pool_run(TaskPool *pool, Task &&task) { - Task *task; - - /* stop all waiting threads */ - BLI_mutex_lock(&scheduler->queue_mutex); - scheduler->do_exit = true; - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); - - pthread_key_delete(scheduler->tls_id_key); - - /* delete threads */ - if (scheduler->threads) { - int i; - - for (i = 0; i < scheduler->num_threads; i++) { - if (pthread_join(scheduler->threads[i], NULL) != 0) { - fprintf(stderr, "TaskScheduler failed to join thread %d/%d\n", i, scheduler->num_threads); - } - } + Task *task_mem = (Task *)MEM_mallocN(sizeof(Task), __func__); + new (task_mem) Task(std::move(task)); + BLI_thread_queue_push(pool->background_queue, task_mem); - MEM_freeN(scheduler->threads); + if (BLI_available_threads(&pool->background_threads)) { + BLI_threadpool_insert(&pool->background_threads, pool); } - - /* Delete task thread data */ - if (scheduler->task_threads) { - for (int i = 0; i < scheduler->num_threads + 1; i++) { - TaskThreadLocalStorage *tls = &scheduler->task_threads[i].tls; - free_task_tls(tls); - } - - MEM_freeN(scheduler->task_threads); - } - - /* delete leftover tasks */ - for (task = (Task *)scheduler->queue.first; task; task = task->next) { - task_data_free(task, 0); - } - BLI_freelistN(&scheduler->queue); - - /* delete mutex/condition */ - BLI_mutex_end(&scheduler->queue_mutex); - BLI_condition_end(&scheduler->queue_cond); - BLI_mutex_end(&scheduler->startup_mutex); - BLI_condition_end(&scheduler->startup_cond); - - MEM_freeN(scheduler); } -int BLI_task_scheduler_num_threads(TaskScheduler *scheduler) +static void background_task_pool_work_and_wait(TaskPool *pool) { - return scheduler->num_threads + 1; + /* Signal background thread to stop waiting for new tasks if none are + * left, and wait for tasks and thread to finish. */ + BLI_thread_queue_nowait(pool->background_queue); + BLI_thread_queue_wait_finish(pool->background_queue); + BLI_threadpool_clear(&pool->background_threads); } -static void task_scheduler_push(TaskScheduler *scheduler, Task *task, TaskPriority priority) +static void background_task_pool_cancel(TaskPool *pool) { - task_pool_num_increase(task->pool, 1); + pool->background_is_canceling = true; - /* add task to queue */ - BLI_mutex_lock(&scheduler->queue_mutex); - - if (priority == TASK_PRIORITY_HIGH) { - BLI_addhead(&scheduler->queue, task); - } - else { - BLI_addtail(&scheduler->queue, task); + /* Remove tasks not yet started by background thread. */ + BLI_thread_queue_nowait(pool->background_queue); + while (Task *task = (Task *)BLI_thread_queue_pop(pool->background_queue)) { + task->~Task(); + MEM_freeN(task); } - BLI_condition_notify_one(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + /* Let background thread finish or cancel task it is working on. */ + BLI_threadpool_remove(&pool->background_threads, pool); + pool->background_is_canceling = false; } -static void task_scheduler_push_all(TaskScheduler *scheduler, - TaskPool *pool, - Task **tasks, - int num_tasks) +static bool background_task_pool_canceled(TaskPool *pool) { - if (num_tasks == 0) { - return; - } - - task_pool_num_increase(pool, num_tasks); - - BLI_mutex_lock(&scheduler->queue_mutex); - - for (int i = 0; i < num_tasks; i++) { - BLI_addhead(&scheduler->queue, tasks[i]); - } - - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); + return pool->background_is_canceling; } -static void task_scheduler_clear(TaskScheduler *scheduler, TaskPool *pool) +static void background_task_pool_free(TaskPool *pool) { - Task *task, *nexttask; - size_t done = 0; - - BLI_mutex_lock(&scheduler->queue_mutex); - - /* free all tasks from this pool from the queue */ - for (task = (Task *)scheduler->queue.first; task; task = nexttask) { - nexttask = task->next; - - if (task->pool == pool) { - task_data_free(task, pool->thread_id); - BLI_freelinkN(&scheduler->queue, task); + background_task_pool_work_and_wait(pool); - done++; - } - } - - BLI_mutex_unlock(&scheduler->queue_mutex); - - /* notify done */ - task_pool_num_decrease(pool, done); + BLI_threadpool_end(&pool->background_threads); + BLI_thread_queue_free(pool->background_queue); } /* Task Pool */ -static TaskPool *task_pool_create_ex(TaskScheduler *scheduler, - void *userdata, - const bool is_background, - const bool is_suspended, - TaskPriority priority) +static TaskPool *task_pool_create_ex(void *userdata, TaskPoolType type, TaskPriority priority) { - TaskPool *pool = (TaskPool *)MEM_mallocN(sizeof(TaskPool), "TaskPool"); + /* Ensure malloc will go fine from threads, + * + * This is needed because we could be in main thread here + * and malloc could be non-thread safe at this point because + * no other jobs are running. + */ + BLI_threaded_malloc_begin(); -#ifndef NDEBUG - /* Assert we do not try to create a background pool from some parent task - - * those only work OK from main thread. */ - if (is_background) { - const pthread_t thread_id = pthread_self(); - int i = scheduler->num_threads; + const bool use_threads = BLI_task_scheduler_num_threads() > 1 && type != TASK_POOL_NO_THREADS; - while (i--) { - BLI_assert(!pthread_equal(scheduler->threads[i], thread_id)); - } + /* Background task pool uses regular TBB scheduling if available. Only when + * building without TBB or running with -t 1 do we need to ensure these tasks + * do not block the main thread. */ + if (type == TASK_POOL_BACKGROUND && use_threads) { + type = TASK_POOL_TBB; } -#endif - pool->scheduler = scheduler; - pool->num = 0; - pool->do_cancel = false; - pool->do_work = false; - pool->is_suspended = is_suspended; - pool->start_suspended = is_suspended; - pool->num_suspended = 0; - pool->suspended_queue.first = pool->suspended_queue.last = NULL; - pool->priority = priority; - pool->run_in_background = is_background; - pool->use_local_tls = false; - - BLI_mutex_init(&pool->num_mutex); - BLI_condition_init(&pool->num_cond); + /* Allocate task pool. */ + TaskPool *pool = (TaskPool *)MEM_callocN(sizeof(TaskPool), "TaskPool"); + + pool->type = type; + pool->use_threads = use_threads; pool->userdata = userdata; BLI_mutex_init(&pool->user_mutex); - if (BLI_thread_is_main()) { - pool->thread_id = 0; - } - else { - TaskThread *thread = (TaskThread *)pthread_getspecific(scheduler->tls_id_key); - if (thread == NULL) { - /* NOTE: Task pool is created from non-main thread which is not - * managed by the task scheduler. We identify ourselves as thread ID - * 0 but we do not use scheduler's TLS storage and use our own - * instead to avoid any possible threading conflicts. - */ - pool->thread_id = 0; - pool->use_local_tls = true; -#ifndef NDEBUG - pool->creator_thread_id = pthread_self(); -#endif - initialize_task_tls(&pool->local_tls); - } - else { - pool->thread_id = thread->id; - } + switch (type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_create(pool, priority); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_create(pool); + break; } -#ifdef DEBUG_STATS - pool->mempool_stats = (TaskMemPoolStats *)MEM_callocN( - sizeof(*pool->mempool_stats) * (scheduler->num_threads + 1), "per-taskpool mempool stats"); -#endif - - /* Ensure malloc will go fine from threads, - * - * This is needed because we could be in main thread here - * and malloc could be non-thread safe at this point because - * no other jobs are running. - */ - BLI_threaded_malloc_begin(); - return pool; } /** * Create a normal task pool. Tasks will be executed as soon as they are added. */ -TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPriority priority) +TaskPool *BLI_task_pool_create(void *userdata, TaskPriority priority) { - return task_pool_create_ex(scheduler, userdata, false, false, priority); + return task_pool_create_ex(userdata, TASK_POOL_TBB, priority); } /** @@ -756,11 +421,9 @@ TaskPool *BLI_task_pool_create(TaskScheduler *scheduler, void *userdata, TaskPri * they could end never being executed, since the 'fallback' background thread is already * busy with parent task in single-threaded context). */ -TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority) +TaskPool *BLI_task_pool_create_background(void *userdata, TaskPriority priority) { - return task_pool_create_ex(scheduler, userdata, true, false, priority); + return task_pool_create_ex(userdata, TASK_POOL_BACKGROUND, priority); } /** @@ -768,231 +431,117 @@ TaskPool *BLI_task_pool_create_background(TaskScheduler *scheduler, * for until BLI_task_pool_work_and_wait() is called. This helps reducing threading * overhead when pushing huge amount of small initial tasks from the main thread. */ -TaskPool *BLI_task_pool_create_suspended(TaskScheduler *scheduler, - void *userdata, - TaskPriority priority) +TaskPool *BLI_task_pool_create_suspended(void *userdata, TaskPriority priority) { - return task_pool_create_ex(scheduler, userdata, false, true, priority); + return task_pool_create_ex(userdata, TASK_POOL_TBB_SUSPENDED, priority); } -void BLI_task_pool_free(TaskPool *pool) +/** + * Single threaded task pool that executes pushed task immediately, for + * debugging purposes. + */ +TaskPool *BLI_task_pool_create_no_threads(void *userdata) { - BLI_task_pool_cancel(pool); - - BLI_mutex_end(&pool->num_mutex); - BLI_condition_end(&pool->num_cond); + return task_pool_create_ex(userdata, TASK_POOL_NO_THREADS, TASK_PRIORITY_HIGH); +} - BLI_mutex_end(&pool->user_mutex); +/** + * Task pool that executes one task after the other, possibly on different threads + * but never in parallel. + */ +TaskPool *BLI_task_pool_create_background_serial(void *userdata, TaskPriority priority) +{ + return task_pool_create_ex(userdata, TASK_POOL_BACKGROUND_SERIAL, priority); +} -#ifdef DEBUG_STATS - printf("Thread ID Allocated Reused Discarded\n"); - for (int i = 0; i < pool->scheduler->num_threads + 1; i++) { - printf("%02d %05d %05d %05d\n", - i, - pool->mempool_stats[i].num_alloc, - pool->mempool_stats[i].num_reuse, - pool->mempool_stats[i].num_discard); +void BLI_task_pool_free(TaskPool *pool) +{ + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_free(pool); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_free(pool); + break; } - MEM_freeN(pool->mempool_stats); -#endif - if (pool->use_local_tls) { - free_task_tls(&pool->local_tls); - } + BLI_mutex_end(&pool->user_mutex); MEM_freeN(pool); BLI_threaded_malloc_end(); } -BLI_INLINE bool task_can_use_local_queues(TaskPool *pool, int thread_id) -{ - return (thread_id != -1 && (thread_id != pool->thread_id || pool->do_work)); -} - -static void task_pool_push(TaskPool *pool, - TaskRunFunction run, - void *taskdata, - bool free_taskdata, - TaskFreeFunction freedata, - int thread_id) -{ - /* Allocate task and fill it's properties. */ - Task *task = task_alloc(pool, thread_id); - task->run = run; - task->taskdata = taskdata; - task->free_taskdata = free_taskdata; - task->freedata = freedata; - task->pool = pool; - /* For suspended pools we put everything yo a global queue first - * and exit as soon as possible. - * - * This tasks will be moved to actual execution when pool is - * activated by work_and_wait(). - */ - if (pool->is_suspended) { - BLI_addhead(&pool->suspended_queue, task); - atomic_fetch_and_add_z(&pool->num_suspended, 1); - return; - } - /* Populate to any local queue first, this is cheapest push ever. */ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - /* Try to push to a local execution queue. - * These tasks will be picked up next. - */ - if (tls->num_local_queue < LOCAL_QUEUE_SIZE) { - tls->local_queue[tls->num_local_queue] = task; - tls->num_local_queue++; - return; - } - /* If we are in the delayed tasks push mode, we push tasks to a - * temporary local queue first without any locks, and then move them - * to global execution queue with a single lock. - */ - if (tls->do_delayed_push && tls->num_delayed_queue < DELAYED_QUEUE_SIZE) { - tls->delayed_queue[tls->num_delayed_queue] = task; - tls->num_delayed_queue++; - return; - } - } - /* Do push to a global execution pool, slowest possible method, - * causes quite reasonable amount of threading overhead. - */ - task_scheduler_push(pool->scheduler, task, pool->priority); -} - void BLI_task_pool_push(TaskPool *pool, TaskRunFunction run, void *taskdata, bool free_taskdata, TaskFreeFunction freedata) { - task_pool_push(pool, run, taskdata, free_taskdata, freedata, -1); -} + Task task(pool, run, taskdata, free_taskdata, freedata); -void BLI_task_pool_push_from_thread(TaskPool *pool, - TaskRunFunction run, - void *taskdata, - bool free_taskdata, - TaskFreeFunction freedata, - int thread_id) -{ - task_pool_push(pool, run, taskdata, free_taskdata, freedata, thread_id); + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_run(pool, std::move(task)); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_run(pool, std::move(task)); + break; + } } void BLI_task_pool_work_and_wait(TaskPool *pool) { - TaskThreadLocalStorage *tls = get_task_tls(pool, pool->thread_id); - TaskScheduler *scheduler = pool->scheduler; - - if (atomic_fetch_and_and_uint8((uint8_t *)&pool->is_suspended, 0)) { - if (pool->num_suspended) { - task_pool_num_increase(pool, pool->num_suspended); - BLI_mutex_lock(&scheduler->queue_mutex); - - BLI_movelisttolist(&scheduler->queue, &pool->suspended_queue); - - BLI_condition_notify_all(&scheduler->queue_cond); - BLI_mutex_unlock(&scheduler->queue_mutex); - - pool->num_suspended = 0; - } - } - - pool->do_work = true; - - ASSERT_THREAD_ID(pool->scheduler, pool->thread_id); - - handle_local_queue(tls, pool->thread_id); - - BLI_mutex_lock(&pool->num_mutex); - - while (pool->num != 0) { - Task *task, *work_task = NULL; - bool found_task = false; - - BLI_mutex_unlock(&pool->num_mutex); - - BLI_mutex_lock(&scheduler->queue_mutex); - - /* find task from this pool. if we get a task from another pool, - * we can get into deadlock */ - - for (task = (Task *)scheduler->queue.first; task; task = task->next) { - if (task->pool == pool) { - work_task = task; - found_task = true; - BLI_remlink(&scheduler->queue, task); - break; - } - } - - BLI_mutex_unlock(&scheduler->queue_mutex); - - /* if found task, do it, otherwise wait until other tasks are done */ - if (found_task) { - /* run task */ - BLI_assert(!tls->do_delayed_push); - work_task->run(pool, work_task->taskdata, pool->thread_id); - BLI_assert(!tls->do_delayed_push); - - /* delete task */ - task_free(pool, task, pool->thread_id); - - /* Handle all tasks from local queue. */ - handle_local_queue(tls, pool->thread_id); - - /* notify pool task was done */ - task_pool_num_decrease(pool, 1); - } - - BLI_mutex_lock(&pool->num_mutex); - if (pool->num == 0) { + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_work_and_wait(pool); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_work_and_wait(pool); break; - } - - if (!found_task) { - BLI_condition_wait(&pool->num_cond, &pool->num_mutex); - } } - - BLI_mutex_unlock(&pool->num_mutex); - - BLI_assert(tls->num_local_queue == 0); -} - -void BLI_task_pool_work_wait_and_reset(TaskPool *pool) -{ - BLI_task_pool_work_and_wait(pool); - - pool->do_work = false; - pool->is_suspended = pool->start_suspended; } void BLI_task_pool_cancel(TaskPool *pool) { - pool->do_cancel = true; - - task_scheduler_clear(pool->scheduler, pool); - - /* wait until all entries are cleared */ - BLI_mutex_lock(&pool->num_mutex); - while (pool->num) { - BLI_condition_wait(&pool->num_cond, &pool->num_mutex); + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + tbb_task_pool_cancel(pool); + break; + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + background_task_pool_cancel(pool); + break; } - BLI_mutex_unlock(&pool->num_mutex); - - pool->do_cancel = false; } bool BLI_task_pool_canceled(TaskPool *pool) { - return pool->do_cancel; + switch (pool->type) { + case TASK_POOL_TBB: + case TASK_POOL_TBB_SUSPENDED: + case TASK_POOL_NO_THREADS: + return tbb_task_pool_canceled(pool); + case TASK_POOL_BACKGROUND: + case TASK_POOL_BACKGROUND_SERIAL: + return background_task_pool_canceled(pool); + } + BLI_assert("BLI_task_pool_canceled: Control flow should not come here!"); + return false; } -void *BLI_task_pool_userdata(TaskPool *pool) +void *BLI_task_pool_user_data(TaskPool *pool) { return pool->userdata; } @@ -1001,29 +550,3 @@ ThreadMutex *BLI_task_pool_user_mutex(TaskPool *pool) { return &pool->user_mutex; } - -int BLI_task_pool_creator_thread_id(TaskPool *pool) -{ - return pool->thread_id; -} - -void BLI_task_pool_delayed_push_begin(TaskPool *pool, int thread_id) -{ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - tls->do_delayed_push = true; - } -} - -void BLI_task_pool_delayed_push_end(TaskPool *pool, int thread_id) -{ - if (task_can_use_local_queues(pool, thread_id)) { - ASSERT_THREAD_ID(pool->scheduler, thread_id); - TaskThreadLocalStorage *tls = get_task_tls(pool, thread_id); - BLI_assert(tls->do_delayed_push); - task_scheduler_push_all(pool->scheduler, pool, tls->delayed_queue, tls->num_delayed_queue); - tls->do_delayed_push = false; - tls->num_delayed_queue = 0; - } -} diff --git a/source/blender/blenkernel/intern/pbvh_parallel.cc b/source/blender/blenlib/intern/task_range.cc index 2534fdea3ee..a8447c305e0 100644 --- a/source/blender/blenkernel/intern/pbvh_parallel.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -14,60 +14,72 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/** \file + * \ingroup bli + * + * Task parallel range functions. + */ + +#include <stdlib.h> + #include "MEM_guardedalloc.h" +#include "DNA_listBase.h" + #include "BLI_task.h" #include "BLI_threads.h" -#include "BKE_pbvh.h" - #include "atomic_ops.h" #ifdef WITH_TBB - /* Quiet top level deprecation message, unrelated to API usage here. */ # define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 - # include <tbb/tbb.h> +#endif + +#ifdef WITH_TBB /* Functor for running TBB parallel_for and parallel_reduce. */ -struct PBVHTask { - PBVHParallelRangeFunc func; +struct RangeTask { + TaskParallelRangeFunc func; void *userdata; - const PBVHParallelSettings *settings; + const TaskParallelSettings *settings; void *userdata_chunk; /* Root constructor. */ - PBVHTask(PBVHParallelRangeFunc func, void *userdata, const PBVHParallelSettings *settings) + RangeTask(TaskParallelRangeFunc func, void *userdata, const TaskParallelSettings *settings) : func(func), userdata(userdata), settings(settings) { init_chunk(settings->userdata_chunk); } /* Copy constructor. */ - PBVHTask(const PBVHTask &other) + RangeTask(const RangeTask &other) : func(other.func), userdata(other.userdata), settings(other.settings) { - init_chunk(other.userdata_chunk); + init_chunk(settings->userdata_chunk); } /* Splitting constructor for parallel reduce. */ - PBVHTask(PBVHTask &other, tbb::split) + RangeTask(RangeTask &other, tbb::split) : func(other.func), userdata(other.userdata), settings(other.settings) { init_chunk(settings->userdata_chunk); } - ~PBVHTask() + ~RangeTask() { + if (settings->func_free != NULL) { + settings->func_free(userdata, userdata_chunk); + } MEM_SAFE_FREE(userdata_chunk); } void init_chunk(void *from_chunk) { if (from_chunk) { - userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "PBVHTask"); + userdata_chunk = MEM_mallocN(settings->userdata_chunk_size, "RangeTask"); memcpy(userdata_chunk, from_chunk, settings->userdata_chunk_size); } else { @@ -78,59 +90,41 @@ struct PBVHTask { void operator()(const tbb::blocked_range<int> &r) const { TaskParallelTLS tls; - tls.thread_id = get_thread_id(); tls.userdata_chunk = userdata_chunk; for (int i = r.begin(); i != r.end(); ++i) { func(userdata, i, &tls); } } - void join(const PBVHTask &other) + void join(const RangeTask &other) { settings->func_reduce(userdata, userdata_chunk, other.userdata_chunk); } - - int get_thread_id() const - { - /* Get a unique thread ID for texture nodes. In the future we should get rid - * of the thread ID and change texture evaluation to not require per-thread - * storage that can't be efficiently allocated on the stack. */ - static tbb::enumerable_thread_specific<int> pbvh_thread_id(-1); - static int pbvh_thread_id_counter = 0; - - int &thread_id = pbvh_thread_id.local(); - if (thread_id == -1) { - thread_id = atomic_fetch_and_add_int32(&pbvh_thread_id_counter, 1); - if (thread_id >= BLENDER_MAX_THREADS) { - BLI_assert(!"Maximum number of threads exceeded for sculpting"); - thread_id = thread_id % BLENDER_MAX_THREADS; - } - } - return thread_id; - } }; #endif -void BKE_pbvh_parallel_range(const int start, +void BLI_task_parallel_range(const int start, const int stop, void *userdata, - PBVHParallelRangeFunc func, - const struct PBVHParallelSettings *settings) + TaskParallelRangeFunc func, + const TaskParallelSettings *settings) { #ifdef WITH_TBB /* Multithreading. */ - if (settings->use_threading) { - PBVHTask task(func, userdata, settings); + if (settings->use_threading && BLI_task_scheduler_num_threads() > 1) { + RangeTask task(func, userdata, settings); + const size_t grainsize = MAX2(settings->min_iter_per_thread, 1); + const tbb::blocked_range<int> range(start, stop, grainsize); if (settings->func_reduce) { - parallel_reduce(tbb::blocked_range<int>(start, stop), task); + parallel_reduce(range, task); if (settings->userdata_chunk) { memcpy(settings->userdata_chunk, task.userdata_chunk, settings->userdata_chunk_size); } } else { - parallel_for(tbb::blocked_range<int>(start, stop), task); + parallel_for(range, task); } return; @@ -140,9 +134,34 @@ void BKE_pbvh_parallel_range(const int start, /* Single threaded. Nothing to reduce as everything is accumulated into the * main userdata chunk directly. */ TaskParallelTLS tls; - tls.thread_id = 0; tls.userdata_chunk = settings->userdata_chunk; for (int i = start; i < stop; i++) { func(userdata, i, &tls); } + if (settings->func_free != NULL) { + settings->func_free(userdata, settings->userdata_chunk); + } +} + +int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls)) +{ +#ifdef WITH_TBB + /* Get a unique thread ID for texture nodes. In the future we should get rid + * of the thread ID and change texture evaluation to not require per-thread + * storage that can't be efficiently allocated on the stack. */ + static tbb::enumerable_thread_specific<int> tbb_thread_id(-1); + static int tbb_thread_id_counter = 0; + + int &thread_id = tbb_thread_id.local(); + if (thread_id == -1) { + thread_id = atomic_fetch_and_add_int32(&tbb_thread_id_counter, 1); + if (thread_id >= BLENDER_MAX_THREADS) { + BLI_assert(!"Maximum number of threads exceeded for sculpting"); + thread_id = thread_id % BLENDER_MAX_THREADS; + } + } + return thread_id; +#else + return 0; +#endif } diff --git a/source/blender/blenlib/intern/task_scheduler.cc b/source/blender/blenlib/intern/task_scheduler.cc new file mode 100644 index 00000000000..b0245da0385 --- /dev/null +++ b/source/blender/blenlib/intern/task_scheduler.cc @@ -0,0 +1,78 @@ +/* + * 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. + */ + +/** \file + * \ingroup bli + * + * Task scheduler initialization. + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_task.h" +#include "BLI_threads.h" + +#ifdef WITH_TBB +/* Quiet top level deprecation message, unrelated to API usage here. */ +# define TBB_SUPPRESS_DEPRECATED_MESSAGES 1 +# include <tbb/tbb.h> +# if TBB_INTERFACE_VERSION_MAJOR >= 10 +# define WITH_TBB_GLOBAL_CONTROL +# endif +#endif + +/* Task Scheduler */ + +static int task_scheduler_num_threads = 1; +#ifdef WITH_TBB_GLOBAL_CONTROL +static tbb::global_control *task_scheduler_global_control = nullptr; +#endif + +void BLI_task_scheduler_init() +{ +#ifdef WITH_TBB_GLOBAL_CONTROL + const int num_threads_override = BLI_system_num_threads_override_get(); + + if (num_threads_override > 0) { + /* Override number of threads. This settings is used within the lifetime + * of tbb::global_control, so we allocate it on the heap. */ + task_scheduler_global_control = OBJECT_GUARDED_NEW( + tbb::global_control, tbb::global_control::max_allowed_parallelism, num_threads_override); + task_scheduler_num_threads = num_threads_override; + } + else { + /* Let TBB choose the number of threads. For (legacy) code that calls + * BLI_task_scheduler_num_threads() we provide the system thread count. + * Ideally such code should be rewritten not to use the number of threads + * at all. */ + task_scheduler_num_threads = BLI_system_thread_count(); + } +#else + task_scheduler_num_threads = BLI_system_thread_count(); +#endif +} + +void BLI_task_scheduler_exit() +{ +#ifdef WITH_TBB_GLOBAL_CONTROL + OBJECT_GUARDED_DELETE(task_scheduler_global_control, tbb::global_control); +#endif +} + +int BLI_task_scheduler_num_threads() +{ + return task_scheduler_num_threads; +} diff --git a/source/blender/blenlib/intern/threads.c b/source/blender/blenlib/intern/threads.c index 31e8581590a..f535798f86d 100644 --- a/source/blender/blenlib/intern/threads.c +++ b/source/blender/blenlib/intern/threads.c @@ -61,9 +61,6 @@ extern pthread_key_t gomp_tls_key; static void *thread_tls_data; #endif -/* We're using one global task scheduler for all kind of tasks. */ -static TaskScheduler *task_scheduler = NULL; - /* ********** basic thread control API ************ * * Many thread cases have an X amount of jobs, and only an Y amount of @@ -157,27 +154,9 @@ void BLI_threadapi_init(void) void BLI_threadapi_exit(void) { - if (task_scheduler) { - BLI_task_scheduler_free(task_scheduler); - task_scheduler = NULL; - } BLI_spin_end(&_malloc_lock); } -TaskScheduler *BLI_task_scheduler_get(void) -{ - if (task_scheduler == NULL) { - int tot_thread = BLI_system_thread_count(); - - /* Do a lazy initialization, so it happens after - * command line arguments parsing - */ - task_scheduler = BLI_task_scheduler_create(tot_thread); - } - - return task_scheduler; -} - /* tot = 0 only initializes malloc mutex in a safe way (see sequence.c) * problem otherwise: scene render will kill of the mutex! */ @@ -839,11 +818,6 @@ void BLI_threaded_malloc_begin(void) unsigned int level = atomic_fetch_and_add_u(&thread_levels, 1); if (level == 0) { MEM_set_lock_callback(BLI_lock_malloc_thread, BLI_unlock_malloc_thread); - /* There is a little chance that two threads will need to access to a - * scheduler which was not yet created from main thread. which could - * cause scheduler created multiple times. - */ - BLI_task_scheduler_get(); } } diff --git a/source/blender/blenlib/intern/timeit.cc b/source/blender/blenlib/intern/timeit.cc new file mode 100644 index 00000000000..bab8fd81746 --- /dev/null +++ b/source/blender/blenlib/intern/timeit.cc @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#include "BLI_timeit.hh" + +namespace BLI { +namespace Timeit { + +void print_duration(Nanoseconds duration) +{ + if (duration < std::chrono::microseconds(100)) { + std::cout << duration.count() << " ns"; + } + else if (duration < std::chrono::seconds(5)) { + std::cout << duration.count() / 1.0e6 << " ms"; + } + else { + std::cout << duration.count() / 1.0e9 << " s"; + } +} + +} // namespace Timeit +} // namespace BLI diff --git a/source/blender/blenloader/CMakeLists.txt b/source/blender/blenloader/CMakeLists.txt index 450d3fc2371..1555b9231ed 100644 --- a/source/blender/blenloader/CMakeLists.txt +++ b/source/blender/blenloader/CMakeLists.txt @@ -53,6 +53,7 @@ set(SRC intern/versioning_260.c intern/versioning_270.c intern/versioning_280.c + intern/versioning_290.c intern/versioning_cycles.c intern/versioning_defaults.c intern/versioning_dna.c diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index cb567147224..7a63c2699f3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -86,6 +86,7 @@ #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" @@ -117,7 +118,7 @@ #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_fluid.h" #include "BKE_global.h" // for G #include "BKE_gpencil_modifier.h" @@ -146,6 +147,7 @@ #include "BKE_screen.h" #include "BKE_sequencer.h" #include "BKE_shader_fx.h" +#include "BKE_simulation.h" #include "BKE_sound.h" #include "BKE_volume.h" #include "BKE_workspace.h" @@ -2999,6 +3001,19 @@ static void direct_link_brush(FileData *fd, Brush *brush) brush->gpencil_settings->curve_strength); brush->gpencil_settings->curve_jitter = newdataadr(fd, brush->gpencil_settings->curve_jitter); + brush->gpencil_settings->curve_rand_pressure = newdataadr( + fd, brush->gpencil_settings->curve_rand_pressure); + brush->gpencil_settings->curve_rand_strength = newdataadr( + fd, brush->gpencil_settings->curve_rand_strength); + brush->gpencil_settings->curve_rand_uv = newdataadr(fd, + brush->gpencil_settings->curve_rand_uv); + brush->gpencil_settings->curve_rand_hue = newdataadr(fd, + brush->gpencil_settings->curve_rand_hue); + brush->gpencil_settings->curve_rand_saturation = newdataadr( + fd, brush->gpencil_settings->curve_rand_saturation); + brush->gpencil_settings->curve_rand_value = newdataadr( + fd, brush->gpencil_settings->curve_rand_value); + if (brush->gpencil_settings->curve_sensitivity) { direct_link_curvemapping(fd, brush->gpencil_settings->curve_sensitivity); } @@ -3010,6 +3025,30 @@ static void direct_link_brush(FileData *fd, Brush *brush) if (brush->gpencil_settings->curve_jitter) { direct_link_curvemapping(fd, brush->gpencil_settings->curve_jitter); } + + if (brush->gpencil_settings->curve_rand_pressure) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_pressure); + } + + if (brush->gpencil_settings->curve_rand_strength) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_strength); + } + + if (brush->gpencil_settings->curve_rand_uv) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_uv); + } + + if (brush->gpencil_settings->curve_rand_hue) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_hue); + } + + if (brush->gpencil_settings->curve_rand_saturation) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_saturation); + } + + if (brush->gpencil_settings->curve_rand_value) { + direct_link_curvemapping(fd, brush->gpencil_settings->curve_rand_value); + } } brush->preview = NULL; @@ -3600,6 +3639,45 @@ static void lib_link_workspace_instance_hook(FileData *fd, WorkSpaceInstanceHook /** \name Read ID: Node Tree * \{ */ +static void lib_link_node_socket(FileData *fd, Library *lib, bNodeSocket *sock) +{ + IDP_LibLinkProperty(sock->prop, fd); + + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + default_value->value = newlibadr(fd, lib, default_value->value); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + default_value->value = newlibadr(fd, lib, default_value->value); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } +} + +static void lib_link_node_sockets(FileData *fd, Library *lib, ListBase *sockets) +{ + LISTBASE_FOREACH (bNodeSocket *, sock, sockets) { + lib_link_node_socket(fd, lib, sock); + } +} + /* Single node tree (also used for material/scene trees), ntree is not NULL */ static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree) { @@ -3614,20 +3692,12 @@ static void lib_link_ntree(FileData *fd, Library *lib, bNodeTree *ntree) node->id = newlibadr(fd, lib, node->id); - LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { - IDP_LibLinkProperty(sock->prop, fd); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { - IDP_LibLinkProperty(sock->prop, fd); - } + lib_link_node_sockets(fd, lib, &node->inputs); + lib_link_node_sockets(fd, lib, &node->outputs); } - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->inputs) { - IDP_LibLinkProperty(sock->prop, fd); - } - LISTBASE_FOREACH (bNodeSocket *, sock, &ntree->outputs) { - IDP_LibLinkProperty(sock->prop, fd); - } + lib_link_node_sockets(fd, lib, &ntree->inputs); + lib_link_node_sockets(fd, lib, &ntree->outputs); /* Set node->typeinfo pointers. This is done in lib linking, after the * first versioning that can change types still without functions that @@ -4779,7 +4849,7 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase /* particle modifier must be removed before particle system */ ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); BLI_remlink(&ob->modifiers, psmd); - modifier_free((ModifierData *)psmd); + BKE_modifier_free((ModifierData *)psmd); BLI_remlink(particles, psys); MEM_freeN(psys); @@ -5148,7 +5218,7 @@ static void lib_link_modifiers_common(void *userData, Object *ob, ID **idpoin, i static void lib_link_modifiers(FileData *fd, Object *ob) { - modifiers_foreachIDLink(ob, lib_link_modifiers_common, fd); + BKE_modifiers_foreach_ID_link(ob, lib_link_modifiers_common, fd); /* If linking from a library, clear 'local' library override flag. */ if (ob->id.lib != NULL) { @@ -5160,7 +5230,7 @@ static void lib_link_modifiers(FileData *fd, Object *ob) static void lib_link_gpencil_modifiers(FileData *fd, Object *ob) { - BKE_gpencil_modifiers_foreachIDLink(ob, lib_link_modifiers_common, fd); + BKE_gpencil_modifiers_foreach_ID_link(ob, lib_link_modifiers_common, fd); /* If linking from a library, clear 'local' library override flag. */ if (ob->id.lib != NULL) { @@ -5173,7 +5243,7 @@ static void lib_link_gpencil_modifiers(FileData *fd, Object *ob) static void lib_link_shaderfxs(FileData *fd, Object *ob) { - BKE_shaderfx_foreachIDLink(ob, lib_link_modifiers_common, fd); + BKE_shaderfx_foreach_ID_link(ob, lib_link_modifiers_common, fd); /* If linking from a library, clear 'local' library override flag. */ if (ob->id.lib != NULL) { @@ -5300,7 +5370,7 @@ static void lib_link_object(FileData *fd, Main *bmain, Object *ob) } { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Fluidsim); if (fluidmd && fluidmd->fss) { @@ -5310,7 +5380,8 @@ static void lib_link_object(FileData *fd, Main *bmain, Object *ob) } { - FluidModifierData *mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + FluidModifierData *mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Fluid); if (mmd && (mmd->type == MOD_FLUID_TYPE_DOMAIN) && mmd->domain) { /* Flag for refreshing the simulation after loading */ @@ -5452,7 +5523,7 @@ static ModifierData *modifier_replace_with_fluid(FileData *fd, ListBase *modifiers, ModifierData *old_modifier_data) { - ModifierData *new_modifier_data = modifier_new(eModifierType_Fluid); + ModifierData *new_modifier_data = BKE_modifier_new(eModifierType_Fluid); FluidModifierData *fluid_modifier_data = (FluidModifierData *)new_modifier_data; if (old_modifier_data->type == eModifierType_Fluidsim) { @@ -5575,7 +5646,7 @@ static void direct_link_modifiers(FileData *fd, ListBase *lb, Object *ob) is_allocated = true; } /* if modifiers disappear, or for upward compatibility */ - if (NULL == modifierType_getInfo(md->type)) { + if (NULL == BKE_modifier_get_info(md->type)) { md->type = eModifierType_None; } @@ -5929,7 +6000,7 @@ static void direct_link_gpencil_modifiers(FileData *fd, ListBase *lb) md->error = NULL; /* if modifiers disappear, or for upward compatibility */ - if (NULL == BKE_gpencil_modifierType_getInfo(md->type)) { + if (NULL == BKE_gpencil_modifier_get_info(md->type)) { md->type = eModifierType_None; } @@ -6010,7 +6081,7 @@ static void direct_link_shaderfxs(FileData *fd, ListBase *lb) fx->error = NULL; /* if shader disappear, or for upward compatibility */ - if (NULL == BKE_shaderfxType_getInfo(fx->type)) { + if (NULL == BKE_shaderfx_get_info(fx->type)) { fx->type = eShaderFxType_None; } } @@ -6073,7 +6144,7 @@ static void direct_link_object(FileData *fd, Object *ob) if (paf->type == EFF_WAVE) { WaveEff *wav = (WaveEff *)paf; PartEff *next = paf->next; - WaveModifierData *wmd = (WaveModifierData *)modifier_new(eModifierType_Wave); + WaveModifierData *wmd = (WaveModifierData *)BKE_modifier_new(eModifierType_Wave); wmd->damp = wav->damp; wmd->flag = wav->flag; @@ -6097,7 +6168,7 @@ static void direct_link_object(FileData *fd, Object *ob) if (paf->type == EFF_BUILD) { BuildEff *baf = (BuildEff *)paf; PartEff *next = paf->next; - BuildModifierData *bmd = (BuildModifierData *)modifier_new(eModifierType_Build); + BuildModifierData *bmd = (BuildModifierData *)BKE_modifier_new(eModifierType_Build); bmd->start = baf->sfra; bmd->length = baf->len; @@ -6174,7 +6245,7 @@ static void direct_link_object(FileData *fd, Object *ob) link_list(fd, &ob->hooks); while (ob->hooks.first) { ObHook *hook = ob->hooks.first; - HookModifierData *hmd = (HookModifierData *)modifier_new(eModifierType_Hook); + HookModifierData *hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook); hook->indexar = newdataadr(fd, hook->indexar); if (fd->flags & FD_FLAGS_SWITCH_ENDIAN) { @@ -6196,7 +6267,7 @@ static void direct_link_object(FileData *fd, Object *ob) BLI_addhead(&ob->modifiers, hmd); BLI_remlink(&ob->hooks, hook); - modifier_unique_name(&ob->modifiers, (ModifierData *)hmd); + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)hmd); MEM_freeN(hook); } @@ -9147,6 +9218,24 @@ static void direct_link_volume(FileData *fd, Volume *volume) /** \} */ /* -------------------------------------------------------------------- */ +/** \name Read ID: Simulation + * \{ */ + +static void lib_link_simulation(FileData *UNUSED(fd), + Main *UNUSED(main), + Simulation *UNUSED(simulation)) +{ +} + +static void direct_link_simulation(FileData *fd, Simulation *simulation) +{ + simulation->adt = newdataadr(fd, simulation->adt); + direct_link_animdata(fd, simulation->adt); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name Read Library Data Block * \{ */ @@ -9264,6 +9353,8 @@ static const char *dataname(short id_code) return "Data from PT"; case ID_VO: return "Data from VO"; + case ID_SIM: + return "Data from SIM"; } return "Data from Lib Block"; } @@ -9415,6 +9506,9 @@ static bool direct_link_id(FileData *fd, Main *main, const int tag, ID *id, ID * case ID_VO: direct_link_volume(fd, (Volume *)id); break; + case ID_SIM: + direct_link_simulation(fd, (Simulation *)id); + break; } return success; @@ -9660,7 +9754,7 @@ static bool read_libblock_undo_restore( * this is only for do_version-like code), but for sake of consistency, and also because * it will tell us which ID is re-used from old Main, and which one is actually new. */ /* Also do not add LIB_TAG_NEED_LINK, those IDs will never be re-liblinked, hence that tag will - * never be cleared, leading to critical issue in link/appemd code. */ + * never be cleared, leading to critical issue in link/append code. */ const int id_tag = tag | LIB_TAG_UNDO_OLD_ID_REUSED; read_libblock_undo_restore_identical(fd, main, id, id_old, id_tag); @@ -9933,6 +10027,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) blo_do_versions_260(fd, lib, main); blo_do_versions_270(fd, lib, main); blo_do_versions_280(fd, lib, main); + blo_do_versions_290(fd, lib, main); blo_do_versions_cycles(fd, lib, main); /* WATCH IT!!!: pointers from libdata have not been converted yet here! */ @@ -10105,6 +10200,9 @@ static void lib_link_all(FileData *fd, Main *bmain) case ID_AC: lib_link_action(fd, bmain, (bAction *)id); break; + case ID_SIM: + lib_link_simulation(fd, bmain, (Simulation *)id); + break; case ID_IP: /* XXX deprecated... still needs to be maintained for version patches still. */ lib_link_ipo(fd, bmain, (Ipo *)id); @@ -10956,10 +11054,51 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key) expand_doit(fd, mainvar, key->ipo); // XXX deprecated - old animation system } +static void expand_node_socket(FileData *fd, Main *mainvar, bNodeSocket *sock) +{ + expand_idprops(fd, mainvar, sock->prop); + + if (sock->default_value != NULL) { + + switch ((eNodeSocketDatatype)sock->type) { + case SOCK_OBJECT: { + bNodeSocketValueObject *default_value = sock->default_value; + expand_doit(fd, mainvar, default_value->value); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *default_value = sock->default_value; + expand_doit(fd, mainvar, default_value->value); + break; + } + case SOCK_FLOAT: + case SOCK_VECTOR: + case SOCK_RGBA: + case SOCK_BOOLEAN: + case SOCK_INT: + case SOCK_STRING: + case __SOCK_MESH: + case SOCK_CUSTOM: + case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: + break; + } + } +} + +static void expand_node_sockets(FileData *fd, Main *mainvar, ListBase *sockets) +{ + LISTBASE_FOREACH (bNodeSocket *, sock, sockets) { + expand_node_socket(fd, mainvar, sock); + } +} + static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) { bNode *node; - bNodeSocket *sock; if (ntree->gpd) { expand_doit(fd, mainvar, ntree->gpd); @@ -10972,20 +11111,12 @@ static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree) expand_idprops(fd, mainvar, node->prop); - for (sock = node->inputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } - for (sock = node->outputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } + expand_node_sockets(fd, mainvar, &node->inputs); + expand_node_sockets(fd, mainvar, &node->outputs); } - for (sock = ntree->inputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } - for (sock = ntree->outputs.first; sock; sock = sock->next) { - expand_idprops(fd, mainvar, sock->prop); - } + expand_node_sockets(fd, mainvar, &ntree->inputs); + expand_node_sockets(fd, mainvar, &ntree->outputs); } static void expand_texture(FileData *fd, Main *mainvar, Tex *tex) @@ -11171,7 +11302,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) data.fd = fd; data.mainvar = mainvar; - modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data); + BKE_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, (void *)&data); } /* expand_object_expandModifier() */ @@ -11183,7 +11314,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) data.fd = fd; data.mainvar = mainvar; - BKE_gpencil_modifiers_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data); + BKE_gpencil_modifiers_foreach_ID_link(ob, expand_object_expandModifiers, (void *)&data); } /* expand_object_expandShaderFx() */ @@ -11195,7 +11326,7 @@ static void expand_object(FileData *fd, Main *mainvar, Object *ob) data.fd = fd; data.mainvar = mainvar; - BKE_shaderfx_foreachIDLink(ob, expand_object_expandModifiers, (void *)&data); + BKE_shaderfx_foreach_ID_link(ob, expand_object_expandModifiers, (void *)&data); } expand_pose(fd, mainvar, ob->pose); @@ -11536,6 +11667,13 @@ static void expand_volume(FileData *fd, Main *mainvar, Volume *volume) } } +static void expand_simulation(FileData *fd, Main *mainvar, Simulation *simulation) +{ + if (simulation->adt) { + expand_animdata(fd, mainvar, simulation->adt); + } +} + /** * Set the callback func used over all ID data found by \a BLO_expand_main func. * @@ -11665,6 +11803,9 @@ void BLO_expand_main(void *fdhandle, Main *mainvar) case ID_VO: expand_volume(fd, mainvar, (Volume *)id); break; + case ID_SIM: + expand_simulation(fd, mainvar, (Simulation *)id); + break; default: break; } @@ -11801,6 +11942,7 @@ static void add_collections_to_scene(Main *mainvar, /* BKE_object_add(...) messes with the selection. */ Object *ob = BKE_object_add_only_object(bmain, OB_EMPTY, collection->id.name + 2); ob->type = OB_EMPTY; + ob->empty_drawsize = U.collection_instance_empty_size; BKE_collection_object_add(bmain, active_collection, ob); Base *base = BKE_view_layer_base_find(view_layer, ob); diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index 80f8bfc3f07..55abbe703de 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -199,6 +199,7 @@ void blo_do_versions_250(struct FileData *fd, struct Library *lib, struct Main * void blo_do_versions_260(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_270(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_280(struct FileData *fd, struct Library *lib, struct Main *bmain); +void blo_do_versions_290(struct FileData *fd, struct Library *lib, struct Main *bmain); void blo_do_versions_cycles(struct FileData *fd, struct Library *lib, struct Main *bmain); void do_versions_after_linking_250(struct Main *bmain); diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index fe0d2293243..62cda5d8feb 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -514,7 +514,7 @@ static void do_version_mdef_250(Main *main) mmd->bindcagecos = mmd->bindcos; mmd->bindcos = NULL; - modifier_mdef_compact_influences(md); + BKE_modifier_mdef_compact_influences(md); } } } @@ -871,7 +871,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) for (ob = bmain->objects.first; ob; ob = ob->id.next) { /* fluid-sim stuff */ - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Fluidsim); if (fluidmd) { fluidmd->fss->fmd = fluidmd; @@ -918,8 +918,8 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) if (do_gravity) { for (md = ob->modifiers.first; md; md = md->next) { - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, - eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type( + ob, eModifierType_Cloth); if (clmd) { clmd->sim_parms->effector_weights->global_gravity = clmd->sim_parms->gravity[2] / -9.81f; @@ -1154,7 +1154,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) } for (ob = bmain->objects.first; ob; ob = ob->id.next) { - MultiresModifierData *mmd = (MultiresModifierData *)modifiers_findByType( + MultiresModifierData *mmd = (MultiresModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Multires); if (mmd) { @@ -1625,7 +1625,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) ArmatureModifierData *amd; bArmature *arm = (bArmature *)blo_do_versions_newlibadr(fd, lib, parent->data); - amd = (ArmatureModifierData *)modifier_new(eModifierType_Armature); + amd = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature); amd->object = ob->parent; BLI_addtail((ListBase *)&ob->modifiers, amd); amd->deformflag = arm->deformflag; @@ -1634,7 +1634,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) else if (parent->type == OB_LATTICE && ob->partype == PARSKEL) { LatticeModifierData *lmd; - lmd = (LatticeModifierData *)modifier_new(eModifierType_Lattice); + lmd = (LatticeModifierData *)BKE_modifier_new(eModifierType_Lattice); lmd->object = ob->parent; BLI_addtail((ListBase *)&ob->modifiers, lmd); ob->partype = PAROBJECT; @@ -1642,7 +1642,7 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *bmain) else if (parent->type == OB_CURVE && ob->partype == PARCURVE) { CurveModifierData *cmd; - cmd = (CurveModifierData *)modifier_new(eModifierType_Curve); + cmd = (CurveModifierData *)BKE_modifier_new(eModifierType_Curve); cmd->object = ob->parent; BLI_addtail((ListBase *)&ob->modifiers, cmd); ob->partype = PAROBJECT; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index 98d2acbd938..0ca6fd34535 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -55,7 +55,7 @@ #include "BKE_anim_data.h" #include "BKE_animsys.h" #include "BKE_colortools.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_main.h" #include "BKE_mask.h" #include "BKE_modifier.h" @@ -841,7 +841,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain) for (ob = bmain->objects.first; ob != NULL; ob = ob->id.next) { ModifierData *md; for (md = ob->modifiers.last; md != NULL; md = md->prev) { - if (modifier_unique_name(&ob->modifiers, md)) { + if (BKE_modifier_unique_name(&ob->modifiers, md)) { printf( "Warning: Object '%s' had several modifiers with the " "same name, renamed one of them to '%s'.\n", diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index df6d1ee3c46..91c07d810b7 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -75,6 +75,7 @@ #include "BKE_curveprofile.h" #include "BKE_customdata.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_freestyle.h" #include "BKE_global.h" #include "BKE_gpencil.h" @@ -1749,6 +1750,144 @@ void do_versions_after_linking_280(Main *bmain, ReportList *UNUSED(reports)) } } + if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) { + /* Patch old grease pencil modifiers material filter. */ + LISTBASE_FOREACH (Object *, ob, &bmain->objects) { + LISTBASE_FOREACH (GpencilModifierData *, md, &ob->greasepencil_modifiers) { + switch (md->type) { + case eGpencilModifierType_Array: { + ArrayGpencilModifierData *gpmd = (ArrayGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Color: { + ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Hook: { + HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Lattice: { + LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Mirror: { + MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Multiply: { + MultiplyGpencilModifierData *gpmd = (MultiplyGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Noise: { + NoiseGpencilModifierData *gpmd = (NoiseGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Offset: { + OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Opacity: { + OpacityGpencilModifierData *gpmd = (OpacityGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Simplify: { + SimplifyGpencilModifierData *gpmd = (SimplifyGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Smooth: { + SmoothGpencilModifierData *gpmd = (SmoothGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Subdiv: { + SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Texture: { + TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + case eGpencilModifierType_Thick: { + ThickGpencilModifierData *gpmd = (ThickGpencilModifierData *)md; + if (gpmd->materialname[0] != '\0') { + gpmd->material = BLI_findstring( + &bmain->materials, gpmd->materialname, offsetof(ID, name) + 2); + gpmd->materialname[0] = '\0'; + } + break; + } + default: + break; + } + } + } + } + /** * Versioning code until next subversion bump goes here. * @@ -4647,6 +4786,13 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) brush->gpencil_weight_tool = brush->gpencil_settings->brush_type; } } + /* Tint brush. */ + Brush *brush = BLI_findstring(&bmain->brushes, "Tint", offsetof(ID, name) + 2); + if (brush == NULL) { + brush = BKE_brush_add(bmain, "Tint", OB_MODE_PAINT_GPENCIL); + BKE_brush_init_gpencil_settings(brush); + } + BKE_gpencil_brush_preset_set(bmain, brush, GP_BRUSH_PRESET_TINT); BKE_paint_toolslots_init_from_main(bmain); } diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c new file mode 100644 index 00000000000..40f6689e43b --- /dev/null +++ b/source/blender/blenloader/intern/versioning_290.c @@ -0,0 +1,87 @@ +/* + * 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. + */ + +/** \file + * \ingroup blenloader + */ +/* allow readfile to use deprecated functionality */ +#define DNA_DEPRECATED_ALLOW + +#include "BLI_listbase.h" +#include "BLI_utildefines.h" + +#include "DNA_brush_types.h" +#include "DNA_genfile.h" +#include "DNA_screen_types.h" + +#include "BKE_collection.h" +#include "BKE_colortools.h" +#include "BKE_main.h" + +#include "BLO_readfile.h" +#include "readfile.h" + +/* Make preferences read-only, use versioning_userdef.c. */ +#define U (*((const UserDef *)&U)) + +void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain) +{ + UNUSED_VARS(fd); + /** + * Versioning code until next subversion bump goes here. + * + * \note Be sure to check when bumping the version: + * - "versioning_userdef.c", #BLO_version_defaults_userpref_blend + * - "versioning_userdef.c", #do_versions_theme + * + * \note Keep this message at the bottom of the function. + */ + { + /* Keep this block, even when empty. */ + + if (!DNA_struct_elem_find(fd->filesdna, "SpaceImage", "float", "uv_opacity")) { + for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) { + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) { + if (sl->spacetype == SPACE_IMAGE) { + SpaceImage *sima = (SpaceImage *)sl; + sima->uv_opacity = 1.0f; + } + } + } + } + } + + /* Init Grease Pencil new random curves. */ + if (!DNA_struct_elem_find(fd->filesdna, "BrushGpencilSettings", "float", "random_hue")) { + LISTBASE_FOREACH (Brush *, brush, &bmain->brushes) { + if ((brush->gpencil_settings) && (brush->gpencil_settings->curve_rand_pressure == NULL)) { + brush->gpencil_settings->curve_rand_pressure = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_strength = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_uv = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_hue = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_saturation = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + brush->gpencil_settings->curve_rand_value = BKE_curvemapping_add( + 1, 0.0f, 0.0f, 1.0f, 1.0f); + } + } + } + } +} diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index 9309a529ccf..fb1cda2ff31 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -197,6 +197,7 @@ static void blo_update_defaults_screen(bScreen *screen, v3d->gp_flag |= V3D_GP_SHOW_EDIT_LINES; /* Remove dither pattern in wireframe mode. */ v3d->shading.xray_alpha_wire = 0.0f; + v3d->clip_start = 0.01f; /* Skip startups that use the viewport color by default. */ if (v3d->shading.background_type != V3D_SHADING_BACKGROUND_VIEWPORT) { copy_v3_fl(v3d->shading.background_color, 0.05f); @@ -297,7 +298,7 @@ static void blo_update_defaults_scene(Main *bmain, Scene *scene) /* Don't enable compositing nodes. */ if (scene->nodetree) { - ntreeFreeNestedTree(scene->nodetree); + ntreeFreeEmbeddedTree(scene->nodetree); MEM_freeN(scene->nodetree); scene->nodetree = NULL; scene->use_nodes = false; diff --git a/source/blender/blenloader/intern/versioning_legacy.c b/source/blender/blenloader/intern/versioning_legacy.c index ce039182572..2cc811e213f 100644 --- a/source/blender/blenloader/intern/versioning_legacy.c +++ b/source/blender/blenloader/intern/versioning_legacy.c @@ -1351,7 +1351,8 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) }; if ((me->flag & ME_SUBSURF)) { - SubsurfModifierData *smd = (SubsurfModifierData *)modifier_new(eModifierType_Subsurf); + SubsurfModifierData *smd = (SubsurfModifierData *)BKE_modifier_new( + eModifierType_Subsurf); smd->levels = MAX2(1, me->subdiv); smd->renderLevels = MAX2(1, me->subdivr); @@ -1371,7 +1372,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) BLI_addtail(&ob->modifiers, smd); - modifier_unique_name(&ob->modifiers, (ModifierData *)smd); + BKE_modifier_unique_name(&ob->modifiers, (ModifierData *)smd); } } @@ -1428,18 +1429,19 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } } - if ((ob->softflag & OB_SB_ENABLE) && !modifiers_findByType(ob, eModifierType_Softbody)) { + if ((ob->softflag & OB_SB_ENABLE) && + !BKE_modifiers_findby_type(ob, eModifierType_Softbody)) { if (ob->softflag & OB_SB_POSTDEF) { md = ob->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } - BLI_insertlinkbefore(&ob->modifiers, md, modifier_new(eModifierType_Softbody)); + BLI_insertlinkbefore(&ob->modifiers, md, BKE_modifier_new(eModifierType_Softbody)); } else { - BLI_addhead(&ob->modifiers, modifier_new(eModifierType_Softbody)); + BLI_addhead(&ob->modifiers, BKE_modifier_new(eModifierType_Softbody)); } ob->softflag &= ~OB_SB_ENABLE; @@ -2271,7 +2273,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) BLI_addtail(&ob->particlesystem, psys); - md = modifier_new(eModifierType_ParticleSystem); + md = BKE_modifier_new(eModifierType_ParticleSystem); BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", @@ -2357,7 +2359,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) } { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifiers_findByType( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifiers_findby_type( ob, eModifierType_Fluidsim); if (fluidmd && fluidmd->fss && fluidmd->fss->type == OB_FLUIDSIM_PARTICLE) { part->type = PART_FLUID; @@ -2483,7 +2485,7 @@ void blo_do_versions_pre250(FileData *fd, Library *lib, Main *bmain) for (ob = bmain->objects.first; ob; ob = ob->id.next) { if (ob->fluidsimSettings) { - FluidsimModifierData *fluidmd = (FluidsimModifierData *)modifier_new( + FluidsimModifierData *fluidmd = (FluidsimModifierData *)BKE_modifier_new( eModifierType_Fluidsim); BLI_addhead(&ob->modifiers, (ModifierData *)fluidmd); diff --git a/source/blender/blenloader/intern/versioning_userdef.c b/source/blender/blenloader/intern/versioning_userdef.c index a426e49dd77..1b0e41ec54a 100644 --- a/source/blender/blenloader/intern/versioning_userdef.c +++ b/source/blender/blenloader/intern/versioning_userdef.c @@ -764,6 +764,10 @@ void BLO_version_defaults_userpref_blend(Main *bmain, UserDef *userdef) */ { /* Keep this block, even when empty. */ + + if (userdef->collection_instance_empty_size == 0) { + userdef->collection_instance_empty_size = 1.0f; + } } if (userdef->pixelsize == 0.0f) { diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 2b32621eb37..a54085b3036 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -133,6 +133,7 @@ #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" @@ -156,6 +157,7 @@ #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" // for G #include "BKE_gpencil_modifier.h" #include "BKE_idtype.h" @@ -990,9 +992,19 @@ static void write_node_socket_default_value(WriteData *wd, bNodeSocket *sock) case SOCK_STRING: writestruct(wd, DATA, bNodeSocketValueString, 1, sock->default_value); break; + case SOCK_OBJECT: + writestruct(wd, DATA, bNodeSocketValueObject, 1, sock->default_value); + break; + case SOCK_IMAGE: + writestruct(wd, DATA, bNodeSocketValueImage, 1, sock->default_value); + break; case __SOCK_MESH: case SOCK_CUSTOM: case SOCK_SHADER: + case SOCK_EMITTERS: + case SOCK_EVENTS: + case SOCK_FORCES: + case SOCK_CONTROL_FLOW: BLI_assert(false); break; } @@ -1634,7 +1646,7 @@ static void write_modifiers(WriteData *wd, ListBase *modbase) } for (md = modbase->first; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti == NULL) { return; } @@ -1817,7 +1829,7 @@ static void write_gpencil_modifiers(WriteData *wd, ListBase *modbase) } for (md = modbase->first; md; md = md->next) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti == NULL) { return; } @@ -1884,7 +1896,7 @@ static void write_shaderfxs(WriteData *wd, ListBase *fxbase) } for (fx = fxbase->first; fx; fx = fx->next) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(fx->type); if (fxi == NULL) { return; } @@ -3303,6 +3315,24 @@ static void write_brush(WriteData *wd, Brush *brush, const void *id_address) if (brush->gpencil_settings->curve_jitter) { write_curvemapping(wd, brush->gpencil_settings->curve_jitter); } + if (brush->gpencil_settings->curve_rand_pressure) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_pressure); + } + if (brush->gpencil_settings->curve_rand_strength) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_strength); + } + if (brush->gpencil_settings->curve_rand_uv) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_uv); + } + if (brush->gpencil_settings->curve_rand_hue) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_hue); + } + if (brush->gpencil_settings->curve_rand_saturation) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_saturation); + } + if (brush->gpencil_settings->curve_rand_value) { + write_curvemapping(wd, brush->gpencil_settings->curve_rand_value); + } } if (brush->gradient) { writestruct(wd, DATA, ColorBand, 1, brush->gradient); @@ -3854,6 +3884,24 @@ static void write_volume(WriteData *wd, Volume *volume, const void *id_address) } } +static void write_simulation(WriteData *wd, Simulation *simulation) +{ + if (simulation->id.us > 0 || wd->use_memfile) { + writestruct(wd, ID_SIM, Simulation, 1, simulation); + write_iddata(wd, &simulation->id); + + if (simulation->adt) { + write_animdata(wd, simulation->adt); + } + + /* nodetree is integral part of simulation, no libdata */ + if (simulation->nodetree) { + writestruct(wd, DATA, bNodeTree, 1, simulation->nodetree); + write_nodetree_nolib(wd, simulation->nodetree); + } + } +} + /* Keep it last of write_foodata functions. */ static void write_libraries(WriteData *wd, Main *main) { @@ -4203,6 +4251,9 @@ static bool write_file_handle(Main *mainvar, case ID_VO: write_volume(wd, (Volume *)id_buffer, id); break; + case ID_SIM: + write_simulation(wd, (Simulation *)id); + break; case ID_LI: /* Do nothing, handled below - and should never be reached. */ BLI_assert(0); diff --git a/source/blender/blentranslation/BLT_translation.h b/source/blender/blentranslation/BLT_translation.h index 74c46b1cf3e..817b99e8b91 100644 --- a/source/blender/blentranslation/BLT_translation.h +++ b/source/blender/blentranslation/BLT_translation.h @@ -65,9 +65,9 @@ bool BLT_lang_is_ime_supported(void); # define IFACE_(msgid) msgid # define TIP_(msgid) msgid # define DATA_(msgid) msgid -# define CTX_IFACE_(context, msgid) msgid -# define CTX_TIP_(context, msgid) msgid -# define CTX_DATA_(context, msgid) msgid +# define CTX_IFACE_(context, msgid) ((void)(0 ? (context) : 0), msgid) +# define CTX_TIP_(context, msgid) ((void)(0 ? (context) : 0), msgid) +# define CTX_DATA_(context, msgid) ((void)(0 ? (context) : 0), msgid) #endif /* Helper macro, when we want to define a same msgid for multiple msgctxt... @@ -122,6 +122,7 @@ bool BLT_lang_is_ime_supported(void); #define BLT_I18NCONTEXT_ID_IMAGE "Image" /*#define BLT_I18NCONTEXT_ID_IPO "Ipo"*/ /* Deprecated */ #define BLT_I18NCONTEXT_ID_SHAPEKEY "Key" +#define BLT_I18NCONTEXT_ID_SIMULATION "Simulation" #define BLT_I18NCONTEXT_ID_LIGHT "Light" #define BLT_I18NCONTEXT_ID_LIBRARY "Library" #define BLT_I18NCONTEXT_ID_LATTICE "Lattice" @@ -202,6 +203,7 @@ typedef struct { BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCENE, "id_scene"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SCREEN, "id_screen"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SEQUENCE, "id_sequence"), \ + BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SIMULATION, "id_simulation"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SPEAKER, "id_speaker"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_SOUND, "id_sound"), \ BLT_I18NCONTEXTS_ITEM(BLT_I18NCONTEXT_ID_TEXTURE, "id_texture"), \ diff --git a/source/blender/bmesh/bmesh.h b/source/blender/bmesh/bmesh.h index 7d2100c0f65..9b5072e8e16 100644 --- a/source/blender/bmesh/bmesh.h +++ b/source/blender/bmesh/bmesh.h @@ -188,10 +188,6 @@ * - Use two different iterator types for BMO map/buffer types. */ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_customdata_types.h" /* BMesh struct in bmesh_class.h uses */ #include "DNA_listBase.h" /* selection history uses */ @@ -199,6 +195,10 @@ extern "C" { #include <stdio.h> #include <stdlib.h> +#ifdef __cplusplus +extern "C" { +#endif + #include "bmesh_class.h" /* include the rest of the API */ diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 14e3c57f038..255a52971bb 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1047,6 +1047,7 @@ static BMOpDefine bmo_extrude_face_region_def = { {"use_keep_orig", BMO_OP_SLOT_BOOL}, /* keep original geometry (requires ``geom`` to include edges). */ {"use_normal_flip", BMO_OP_SLOT_BOOL}, /* Create faces with reversed direction. */ {"use_normal_from_adjacent", BMO_OP_SLOT_BOOL}, /* Use winding from surrounding faces instead of this region. */ + {"use_dissolve_ortho_edges", BMO_OP_SLOT_BOOL}, /* Dissolve edges whose faces form a flat surface. */ {"use_select_history", BMO_OP_SLOT_BOOL}, /* pass to duplicate */ {{'\0'}}, }, diff --git a/source/blender/bmesh/intern/bmesh_operator_api.h b/source/blender/bmesh/intern/bmesh_operator_api.h index dbd2bf076c6..5af812d1b1d 100644 --- a/source/blender/bmesh/intern/bmesh_operator_api.h +++ b/source/blender/bmesh/intern/bmesh_operator_api.h @@ -21,14 +21,14 @@ * \ingroup bmesh */ -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_ghash.h" #include <stdarg.h> +#ifdef __cplusplus +extern "C" { +#endif + /** * operators represent logical, executable mesh modules. all topological * operations involving a bmesh has to go through them. diff --git a/source/blender/bmesh/operators/bmo_extrude.c b/source/blender/bmesh/operators/bmo_extrude.c index 7a7f4a14db3..3c63f4a60d6 100644 --- a/source/blender/bmesh/operators/bmo_extrude.c +++ b/source/blender/bmesh/operators/bmo_extrude.c @@ -39,6 +39,7 @@ enum { EXT_INPUT = 1, EXT_KEEP = 2, EXT_DEL = 4, + EXT_TAG = 8, }; #define VERT_MARK 1 @@ -335,6 +336,8 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) const bool use_normal_flip = BMO_slot_bool_get(op->slots_in, "use_normal_flip"); const bool use_normal_from_adjacent = BMO_slot_bool_get(op->slots_in, "use_normal_from_adjacent"); + const bool use_dissolve_ortho_edges = BMO_slot_bool_get(op->slots_in, + "use_dissolve_ortho_edges"); /* initialize our sub-operators */ BMO_op_initf(bm, @@ -442,6 +445,24 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) } } + BMVert **dissolve_verts = NULL; + int dissolve_verts_len = 0; + float average_normal[3]; + if (use_dissolve_ortho_edges) { + /* Calc average normal. */ + zero_v3(average_normal); + BMO_ITER (f, &siter, dupeop.slots_out, "geom.out", BM_FACE) { + add_v3_v3(average_normal, f->no); + } + if (normalize_v3(average_normal) == 0.0f) { + average_normal[2] = 1.0f; + } + + /* Allocate array to store possible vertices that will be dissolved. */ + int boundary_verts_len = BMO_slot_map_count(dupeop.slots_out, "boundary_map.out"); + dissolve_verts = MEM_mallocN((size_t)boundary_verts_len * sizeof(*dissolve_verts), __func__); + } + BMO_slot_copy(&dupeop, slots_out, "geom.out", op, slots_out, "geom.out"); slot_edges_exclude = BMO_slot_get(op->slots_in, "edges_exclude"); @@ -483,6 +504,16 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) continue; } + BMFace *join_face = NULL; + if (use_dissolve_ortho_edges) { + if (BM_edge_is_boundary(e)) { + join_face = e->l->f; + if (fabs(dot_v3v3(average_normal, join_face->no)) > 0.0001f) { + join_face = NULL; + } + } + } + bool edge_normal_flip; if (use_normal_from_adjacent == false) { /* Orient loop to give same normal as a loop of 'e_new' @@ -541,7 +572,22 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) f = BM_face_create_verts(bm, f_verts, 4, NULL, BM_CREATE_NOP, true); #endif - bm_extrude_copy_face_loop_attributes(bm, f); + if (join_face) { + BMVert *v1 = e->v1; + BMVert *v2 = e->v2; + if (!BMO_elem_flag_test(bm, v1, EXT_TAG)) { + BMO_elem_flag_enable(bm, v1, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v1; + } + if (!BMO_elem_flag_test(bm, v2, EXT_TAG)) { + BMO_elem_flag_enable(bm, v2, EXT_TAG); + dissolve_verts[dissolve_verts_len++] = v2; + } + bmesh_kernel_join_face_kill_edge(bm, join_face, f, e); + } + else { + bm_extrude_copy_face_loop_attributes(bm, f); + } } /* link isolated vert */ @@ -559,6 +605,23 @@ void bmo_extrude_face_region_exec(BMesh *bm, BMOperator *op) BM_edge_create(bm, v, v2, NULL, BM_CREATE_NO_DOUBLE); } + if (dissolve_verts) { + BMVert **v_iter = &dissolve_verts[0]; + for (int i = dissolve_verts_len; i--; v_iter++) { + v = *v_iter; + e = v->e; + BMEdge *e_other = BM_DISK_EDGE_NEXT(e, v); + if ((e_other == e) || (BM_DISK_EDGE_NEXT(e_other, v) == e)) { + /* Lose edge or BMVert is edge pair. */ + BM_edge_collapse(bm, e, v, true, false); + } + else { + BLI_assert(!BM_vert_is_edge_pair(v)); + } + } + MEM_freeN(dissolve_verts); + } + /* cleanup */ if (delorig) { BMO_op_finish(bm, &delop); diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index bc127243836..d1ddceb00b0 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -997,10 +997,10 @@ static bool point_between_edges(float co[3], BMVert *v, BMFace *f, EdgeHalf *e1, * record the change in offset_l (or offset_r); later we can tell that a change has happened * because the offset will differ from its original value in offset_l_spec (or offset_r_spec). * - * \param edges_between If this is true, there are edges between e1 and e2 in CCW order so they + * \param edges_between: If this is true, there are edges between e1 and e2 in CCW order so they * don't share a common face. We want the meeting point to be on an existing face so it * should be dropped onto one of the intermediate faces, if possible. - * \param e_in_plane If we need to drop from the calculated offset lines to one of the faces, + * \param e_in_plane: If we need to drop from the calculated offset lines to one of the faces, * we don't want to drop onto the 'in plane' face, so if this is not null skip this edge's faces. */ static void offset_meet(EdgeHalf *e1, @@ -2601,13 +2601,13 @@ static void adjust_miter_inner_coords(BevelParams *bp, BevVert *bv, EdgeHalf *em * to be a subsequent pass to make the widths as consistent as possible. * Doesn't make the actual BMVerts. * - * For a width consistency pass, we just recalculate the coordinates of the BoundVerts. If the + * For a width consistency pass, we just recalculate the coordinates of the #BoundVerts. If the * other ends have been (re)built already, then we copy the offsets from there to match, else we * use the ideal (user-specified) widths. * - * \param construct The first time through, construct will be true and we are making the BoundVerts - * and setting up the BoundVert and EdgeHalf pointers appropriately. Also, if construct, decide on - * the mesh pattern that will be used inside the boundary. + * \param construct: The first time through, construct will be true and we are making the + * #BoundVerts and setting up the #BoundVert and #EdgeHalf pointers appropriately. + * Also, if construct, decide on the mesh pattern that will be used inside the boundary. */ static void build_boundary(BevelParams *bp, BevVert *bv, bool construct) { diff --git a/source/blender/bmesh/tools/bmesh_bevel.h b/source/blender/bmesh/tools/bmesh_bevel.h index 479a8a3f6d6..8562e584ec9 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.h +++ b/source/blender/bmesh/tools/bmesh_bevel.h @@ -47,4 +47,5 @@ void BM_mesh_bevel(BMesh *bm, const bool use_custom_profile, const struct CurveProfile *custom_profile, const int vmesh_method); + #endif /* __BMESH_BEVEL_H__ */ diff --git a/source/blender/bmesh/tools/bmesh_intersect_edges.c b/source/blender/bmesh/tools/bmesh_intersect_edges.c index e2d03a65d46..3f0492aebb6 100644 --- a/source/blender/bmesh/tools/bmesh_intersect_edges.c +++ b/source/blender/bmesh/tools/bmesh_intersect_edges.c @@ -893,7 +893,7 @@ bool BM_mesh_intersect_edges( if (BM_vert_pair_share_face_check(va, va_dest)) { /* Vert par acts on the same face. - * Although there are cases like this where the face can be splitted, + * Although there are cases like this where the face can be split, * for efficiency it is better to ignore then. */ continue; } @@ -909,7 +909,7 @@ bool BM_mesh_intersect_edges( if (BM_vert_pair_share_face_check(v_other, v_other_dest)) { /* Vert par acts on the same face. - * Although there are cases like this where the face can be splitted, + * Although there are cases like this where the face can be split, * for efficiency and to avoid complications, it is better to ignore these cases. */ break; diff --git a/source/blender/compositor/COM_compositor.h b/source/blender/compositor/COM_compositor.h index 55f68f2b5c1..a24904551c6 100644 --- a/source/blender/compositor/COM_compositor.h +++ b/source/blender/compositor/COM_compositor.h @@ -19,13 +19,13 @@ #ifndef __COM_COMPOSITOR_H__ #define __COM_COMPOSITOR_H__ +#include "DNA_color_types.h" +#include "DNA_node_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_color_types.h" -#include "DNA_node_types.h" - /* Keep ascii art. */ /* clang-format off */ /** @@ -295,8 +295,6 @@ extern "C" { * * \section executePixel executing a pixel * Finally the last step, the node functionality :) - * - * \page newnode Creating new nodes */ /** diff --git a/source/blender/compositor/intern/COM_Converter.cpp b/source/blender/compositor/intern/COM_Converter.cpp index e8474ba8318..edfeb3a3a04 100644 --- a/source/blender/compositor/intern/COM_Converter.cpp +++ b/source/blender/compositor/intern/COM_Converter.cpp @@ -18,11 +18,9 @@ #include <string.h> -extern "C" { #include "DNA_node_types.h" #include "BKE_node.h" -} #include "COM_NodeOperation.h" #include "COM_NodeOperationBuilder.h" diff --git a/source/blender/compositor/intern/COM_ExecutionSystem.cpp b/source/blender/compositor/intern/COM_ExecutionSystem.cpp index fa40f150335..34682aae2fd 100644 --- a/source/blender/compositor/intern/COM_ExecutionSystem.cpp +++ b/source/blender/compositor/intern/COM_ExecutionSystem.cpp @@ -20,9 +20,8 @@ #include "BLI_utildefines.h" #include "PIL_time.h" -extern "C" { + #include "BKE_node.h" -} #include "BLT_translation.h" diff --git a/source/blender/compositor/intern/COM_MemoryBuffer.h b/source/blender/compositor/intern/COM_MemoryBuffer.h index 7e5b0264aa3..6ba8f144482 100644 --- a/source/blender/compositor/intern/COM_MemoryBuffer.h +++ b/source/blender/compositor/intern/COM_MemoryBuffer.h @@ -25,10 +25,8 @@ class MemoryBuffer; #include "COM_MemoryProxy.h" #include "COM_SocketReader.h" -extern "C" { #include "BLI_math.h" #include "BLI_rect.h" -} /** * \brief state of a memory buffer diff --git a/source/blender/compositor/intern/COM_Node.cpp b/source/blender/compositor/intern/COM_Node.cpp index df5a8e690d3..31535c5851f 100644 --- a/source/blender/compositor/intern/COM_Node.cpp +++ b/source/blender/compositor/intern/COM_Node.cpp @@ -18,11 +18,9 @@ #include <string.h> -extern "C" { #include "BKE_node.h" #include "RNA_access.h" -} #include "COM_ExecutionSystem.h" #include "COM_NodeOperation.h" diff --git a/source/blender/compositor/intern/COM_NodeConverter.cpp b/source/blender/compositor/intern/COM_NodeConverter.cpp index eff825b075d..2db31bd4133 100644 --- a/source/blender/compositor/intern/COM_NodeConverter.cpp +++ b/source/blender/compositor/intern/COM_NodeConverter.cpp @@ -16,9 +16,7 @@ * Copyright 2013, Blender Foundation. */ -extern "C" { #include "BLI_utildefines.h" -} #include "COM_Debug.h" diff --git a/source/blender/compositor/intern/COM_NodeGraph.cpp b/source/blender/compositor/intern/COM_NodeGraph.cpp index 6640f144518..cb27fa21b4d 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.cpp +++ b/source/blender/compositor/intern/COM_NodeGraph.cpp @@ -18,14 +18,12 @@ #include <cstring> -extern "C" { #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "DNA_node_types.h" #include "BKE_node.h" -} #include "COM_CompositorContext.h" #include "COM_Converter.h" diff --git a/source/blender/compositor/intern/COM_NodeGraph.h b/source/blender/compositor/intern/COM_NodeGraph.h index b005149c839..531832c2c65 100644 --- a/source/blender/compositor/intern/COM_NodeGraph.h +++ b/source/blender/compositor/intern/COM_NodeGraph.h @@ -23,9 +23,7 @@ #include <set> #include <vector> -extern "C" { #include "DNA_node_types.h" -} #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" diff --git a/source/blender/compositor/intern/COM_NodeOperation.h b/source/blender/compositor/intern/COM_NodeOperation.h index b2c4961ca35..07f482f9e5f 100644 --- a/source/blender/compositor/intern/COM_NodeOperation.h +++ b/source/blender/compositor/intern/COM_NodeOperation.h @@ -23,11 +23,9 @@ #include <sstream> #include <string> -extern "C" { #include "BLI_math_color.h" #include "BLI_math_vector.h" #include "BLI_threads.h" -} #include "COM_MemoryBuffer.h" #include "COM_MemoryProxy.h" diff --git a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp index 9f6b91915e0..5ce6ca34b34 100644 --- a/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp +++ b/source/blender/compositor/intern/COM_NodeOperationBuilder.cpp @@ -16,9 +16,7 @@ * Copyright 2013, Blender Foundation. */ -extern "C" { #include "BLI_utildefines.h" -} #include "COM_Converter.h" #include "COM_Debug.h" diff --git a/source/blender/compositor/intern/COM_WorkScheduler.h b/source/blender/compositor/intern/COM_WorkScheduler.h index 5e0675f1833..3a1b4c533bd 100644 --- a/source/blender/compositor/intern/COM_WorkScheduler.h +++ b/source/blender/compositor/intern/COM_WorkScheduler.h @@ -20,9 +20,9 @@ #define __COM_WORKSCHEDULER_H__ #include "COM_ExecutionGroup.h" -extern "C" { + #include "BLI_threads.h" -} + #include "COM_Device.h" #include "COM_WorkPackage.h" #include "COM_defines.h" diff --git a/source/blender/compositor/intern/COM_compositor.cpp b/source/blender/compositor/intern/COM_compositor.cpp index 1793abae134..bccdd026ead 100644 --- a/source/blender/compositor/intern/COM_compositor.cpp +++ b/source/blender/compositor/intern/COM_compositor.cpp @@ -16,13 +16,11 @@ * Copyright 2011, Blender Foundation. */ -extern "C" { -#include "BKE_node.h" #include "BLI_threads.h" -} #include "BLT_translation.h" +#include "BKE_node.h" #include "BKE_scene.h" #include "COM_ExecutionSystem.h" diff --git a/source/blender/compositor/nodes/COM_CornerPinNode.h b/source/blender/compositor/nodes/COM_CornerPinNode.h index ea62dea12de..a8e88a0ef4f 100644 --- a/source/blender/compositor/nodes/COM_CornerPinNode.h +++ b/source/blender/compositor/nodes/COM_CornerPinNode.h @@ -20,9 +20,7 @@ #include "COM_Node.h" -extern "C" { #include "DNA_node_types.h" -} /** * \brief CornerPinNode diff --git a/source/blender/compositor/nodes/COM_ImageNode.h b/source/blender/compositor/nodes/COM_ImageNode.h index 6ed9acd58b8..7883f4d7ab3 100644 --- a/source/blender/compositor/nodes/COM_ImageNode.h +++ b/source/blender/compositor/nodes/COM_ImageNode.h @@ -23,9 +23,8 @@ #include "COM_defines.h" #include "DNA_image_types.h" #include "DNA_node_types.h" -extern "C" { + #include "RE_engine.h" -} /** * \brief ImageNode diff --git a/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp b/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp index 6a005b2b712..93a9a071226 100644 --- a/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp +++ b/source/blender/compositor/nodes/COM_KeyingScreenNode.cpp @@ -20,9 +20,7 @@ #include "COM_ExecutionSystem.h" #include "COM_KeyingScreenOperation.h" -extern "C" { #include "DNA_movieclip_types.h" -} KeyingScreenNode::KeyingScreenNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_MaskNode.cpp b/source/blender/compositor/nodes/COM_MaskNode.cpp index cceeef6b437..b28b849521c 100644 --- a/source/blender/compositor/nodes/COM_MaskNode.cpp +++ b/source/blender/compositor/nodes/COM_MaskNode.cpp @@ -20,9 +20,7 @@ #include "COM_ExecutionSystem.h" #include "COM_MaskOperation.h" -extern "C" { #include "DNA_mask_types.h" -} MaskNode::MaskNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_MovieClipNode.cpp b/source/blender/compositor/nodes/COM_MovieClipNode.cpp index 29fd47f33b3..3366a8c20d6 100644 --- a/source/blender/compositor/nodes/COM_MovieClipNode.cpp +++ b/source/blender/compositor/nodes/COM_MovieClipNode.cpp @@ -22,12 +22,12 @@ #include "COM_MovieClipOperation.h" #include "COM_SetValueOperation.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_tracking.h" + #include "DNA_movieclip_types.h" + #include "IMB_imbuf.h" -} MovieClipNode::MovieClipNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp index 39616bba4f9..6b9b51631ec 100644 --- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp +++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp @@ -21,11 +21,9 @@ #include "COM_PlaneTrackOperation.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h index 6ee73e22af0..2c17739a220 100644 --- a/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h +++ b/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h @@ -21,10 +21,8 @@ #include "COM_Node.h" -extern "C" { #include "DNA_movieclip_types.h" #include "DNA_node_types.h" -} /** * \brief PlaneTrackDeformNode diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp index 0b6cb97b049..7a308ac47b9 100644 --- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp +++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp @@ -24,10 +24,9 @@ #include "COM_SetSamplerOperation.h" #include "COM_TranslateOperation.h" -extern "C" { #include "BKE_tracking.h" + #include "DNA_movieclip_types.h" -} Stabilize2dNode::Stabilize2dNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/nodes/COM_TimeNode.cpp b/source/blender/compositor/nodes/COM_TimeNode.cpp index b6927fb8373..9722ead0716 100644 --- a/source/blender/compositor/nodes/COM_TimeNode.cpp +++ b/source/blender/compositor/nodes/COM_TimeNode.cpp @@ -19,9 +19,9 @@ #include "COM_TimeNode.h" #include "COM_ExecutionSystem.h" #include "COM_SetValueOperation.h" -extern "C" { + #include "BKE_colortools.h" -} + #include "BLI_utildefines.h" TimeNode::TimeNode(bNode *editorNode) : Node(editorNode) diff --git a/source/blender/compositor/nodes/COM_TrackPositionNode.cpp b/source/blender/compositor/nodes/COM_TrackPositionNode.cpp index da9f50a590b..52e7f7d832b 100644 --- a/source/blender/compositor/nodes/COM_TrackPositionNode.cpp +++ b/source/blender/compositor/nodes/COM_TrackPositionNode.cpp @@ -22,11 +22,9 @@ #include "COM_ExecutionSystem.h" #include "COM_TrackPositionOperation.h" -extern "C" { #include "DNA_movieclip_types.h" #include "BKE_node.h" -} TrackPositionNode::TrackPositionNode(bNode *editorNode) : Node(editorNode) { diff --git a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp index de7c43a8751..85725cc1d37 100644 --- a/source/blender/compositor/operations/COM_AntiAliasOperation.cpp +++ b/source/blender/compositor/operations/COM_AntiAliasOperation.cpp @@ -22,9 +22,7 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "RE_render_ext.h" -} /* An implementation of the Scale3X edge-extrapolation algorithm. * diff --git a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp index 44cb4056c99..8168867a522 100644 --- a/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BilateralBlurOperation.cpp @@ -19,9 +19,7 @@ #include "COM_BilateralBlurOperation.h" #include "BLI_math.h" -extern "C" { #include "RE_pipeline.h" -} BilateralBlurOperation::BilateralBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp index 24c68ddbec7..ef0f259c592 100644 --- a/source/blender/compositor/operations/COM_BlurBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_BlurBaseOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} BlurBaseOperation::BlurBaseOperation(DataType data_type) : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp index 4d858934796..c00ef2468c0 100644 --- a/source/blender/compositor/operations/COM_BokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_BokehBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "COM_OpenCLDevice.h" -extern "C" { #include "RE_pipeline.h" -} BokehBlurOperation::BokehBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp index 5d01154bbda..ecd61e95f43 100644 --- a/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateMeanOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern "C" { #include "IMB_colormanagement.h" -} CalculateMeanOperation::CalculateMeanOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp index dfe1a936c9c..059040d6f05 100644 --- a/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp +++ b/source/blender/compositor/operations/COM_CalculateStandardDeviationOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern "C" { #include "IMB_colormanagement.h" -} CalculateStandardDeviationOperation::CalculateStandardDeviationOperation() : CalculateMeanOperation() diff --git a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp index 31567398d98..39ffb690328 100644 --- a/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCorrectionOperation.cpp @@ -19,9 +19,7 @@ #include "COM_ColorCorrectionOperation.h" #include "BLI_math.h" -extern "C" { #include "IMB_colormanagement.h" -} ColorCorrectionOperation::ColorCorrectionOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp index 90d3a60abd0..9d514c872f7 100644 --- a/source/blender/compositor/operations/COM_ColorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorCurveOperation.cpp @@ -18,14 +18,9 @@ #include "COM_ColorCurveOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -# include "MEM_guardedalloc.h" -#endif + +#include "MEM_guardedalloc.h" ColorCurveOperation::ColorCurveOperation() : CurveBaseOperation() { diff --git a/source/blender/compositor/operations/COM_ColorRampOperation.cpp b/source/blender/compositor/operations/COM_ColorRampOperation.cpp index f2c153c5d30..95e0bd2d82b 100644 --- a/source/blender/compositor/operations/COM_ColorRampOperation.cpp +++ b/source/blender/compositor/operations/COM_ColorRampOperation.cpp @@ -18,13 +18,7 @@ #include "COM_ColorRampOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colorband.h" -#ifdef __cplusplus -} -#endif ColorRampOperation::ColorRampOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_CompositorOperation.cpp b/source/blender/compositor/operations/COM_CompositorOperation.cpp index cb41071e6f0..71cef9dc4da 100644 --- a/source/blender/compositor/operations/COM_CompositorOperation.cpp +++ b/source/blender/compositor/operations/COM_CompositorOperation.cpp @@ -22,13 +22,14 @@ #include "BLI_listbase.h" #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_threads.h" + #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" + #include "render_types.h" -} + #include "PIL_time.h" CompositorOperation::CompositorOperation() : NodeOperation() diff --git a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp index 59a605a77c9..6a4c5db856c 100644 --- a/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertColorProfileOperation.cpp @@ -18,9 +18,8 @@ #include "COM_ConvertColorProfileOperation.h" -extern "C" { #include "IMB_imbuf.h" -} + ConvertColorProfileOperation::ConvertColorProfileOperation() : NodeOperation() { this->addInputSocket(COM_DT_COLOR); diff --git a/source/blender/compositor/operations/COM_ConvertOperation.cpp b/source/blender/compositor/operations/COM_ConvertOperation.cpp index 6caccb89046..0bd3f5b8796 100644 --- a/source/blender/compositor/operations/COM_ConvertOperation.cpp +++ b/source/blender/compositor/operations/COM_ConvertOperation.cpp @@ -18,9 +18,7 @@ #include "COM_ConvertOperation.h" -extern "C" { #include "IMB_colormanagement.h" -} ConvertBaseOperation::ConvertBaseOperation() { diff --git a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp index 858931ad46d..b18e77cf0e3 100644 --- a/source/blender/compositor/operations/COM_CurveBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_CurveBaseOperation.cpp @@ -18,13 +18,7 @@ #include "COM_CurveBaseOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -#endif CurveBaseOperation::CurveBaseOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp index 1b590c0c392..31eb74fbc42 100644 --- a/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_DirectionalBlurOperation.cpp @@ -17,11 +17,11 @@ */ #include "COM_DirectionalBlurOperation.h" -#include "BLI_math.h" #include "COM_OpenCLDevice.h" -extern "C" { + +#include "BLI_math.h" + #include "RE_pipeline.h" -} DirectionalBlurOperation::DirectionalBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp index c6239dba604..c028a2c0e4c 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaXBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianAlphaXBlurOperation::GaussianAlphaXBlurOperation() : BlurBaseOperation(COM_DT_VALUE) { diff --git a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp index 37109b4a03e..35abe4cd47b 100644 --- a/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianAlphaYBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianAlphaYBlurOperation::GaussianAlphaYBlurOperation() : BlurBaseOperation(COM_DT_VALUE) { diff --git a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp index 318c182fdff..43e571c4bb7 100644 --- a/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianBokehBlurOperation.cpp @@ -19,9 +19,8 @@ #include "COM_GaussianBokehBlurOperation.h" #include "BLI_math.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" -} GaussianBokehBlurOperation::GaussianBokehBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { diff --git a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp index 68cde0d365f..32ad0482791 100644 --- a/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianXBlurOperation.cpp @@ -21,9 +21,7 @@ #include "COM_OpenCLDevice.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianXBlurOperation::GaussianXBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { diff --git a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp index eeddd98d4a4..3ffa797c0c1 100644 --- a/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_GaussianYBlurOperation.cpp @@ -21,9 +21,7 @@ #include "COM_OpenCLDevice.h" #include "MEM_guardedalloc.h" -extern "C" { #include "RE_pipeline.h" -} GaussianYBlurOperation::GaussianYBlurOperation() : BlurBaseOperation(COM_DT_COLOR) { diff --git a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp index 142c51122a1..d050d9b58a9 100644 --- a/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp +++ b/source/blender/compositor/operations/COM_GlareThresholdOperation.cpp @@ -19,9 +19,7 @@ #include "COM_GlareThresholdOperation.h" #include "BLI_math.h" -extern "C" { #include "IMB_colormanagement.h" -} GlareThresholdOperation::GlareThresholdOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp index fae280249de..8292413f6f1 100644 --- a/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp +++ b/source/blender/compositor/operations/COM_HueSaturationValueCorrectOperation.cpp @@ -20,13 +20,7 @@ #include "BLI_math.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -#endif HueSaturationValueCorrectOperation::HueSaturationValueCorrectOperation() : CurveBaseOperation() { diff --git a/source/blender/compositor/operations/COM_ImageOperation.cpp b/source/blender/compositor/operations/COM_ImageOperation.cpp index d70cab4ad2a..38d2fbf9ed4 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.cpp +++ b/source/blender/compositor/operations/COM_ImageOperation.cpp @@ -24,14 +24,12 @@ #include "BLI_math.h" #include "DNA_image_types.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} BaseImageOperation::BaseImageOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_ImageOperation.h b/source/blender/compositor/operations/COM_ImageOperation.h index 57656d03092..3e081ee0000 100644 --- a/source/blender/compositor/operations/COM_ImageOperation.h +++ b/source/blender/compositor/operations/COM_ImageOperation.h @@ -24,11 +24,10 @@ #include "BLI_utildefines.h" #include "COM_NodeOperation.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} /** * \brief Base class for all image operations diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp index ab9ef0335e0..082091411fb 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.cpp @@ -24,13 +24,11 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_tracking.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} KeyingScreenOperation::KeyingScreenOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_KeyingScreenOperation.h b/source/blender/compositor/operations/COM_KeyingScreenOperation.h index 860a358e79d..593e902117b 100644 --- a/source/blender/compositor/operations/COM_KeyingScreenOperation.h +++ b/source/blender/compositor/operations/COM_KeyingScreenOperation.h @@ -28,9 +28,7 @@ #include "BLI_listbase.h" #include "BLI_string.h" -extern "C" { #include "BLI_voronoi_2d.h" -} /** * Class with implementation of green screen gradient rasterization diff --git a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp index 30ad954e0bc..936ac00a0e8 100644 --- a/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp +++ b/source/blender/compositor/operations/COM_LuminanceMatteOperation.cpp @@ -19,9 +19,7 @@ #include "COM_LuminanceMatteOperation.h" #include "BLI_math.h" -extern "C" { #include "IMB_colormanagement.h" -} LuminanceMatteOperation::LuminanceMatteOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index 88a3a5c535c..bdc954ac081 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -23,9 +23,7 @@ #include "BLI_listbase.h" #include "BLI_math.h" -extern "C" { #include "BKE_mask.h" -} MaskOperation::MaskOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MathBaseOperation.cpp b/source/blender/compositor/operations/COM_MathBaseOperation.cpp index 524812ac992..1363b75433a 100644 --- a/source/blender/compositor/operations/COM_MathBaseOperation.cpp +++ b/source/blender/compositor/operations/COM_MathBaseOperation.cpp @@ -17,9 +17,8 @@ */ #include "COM_MathBaseOperation.h" -extern "C" { + #include "BLI_math.h" -} MathBaseOperation::MathBaseOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MixOperation.cpp b/source/blender/compositor/operations/COM_MixOperation.cpp index 6b8a0caa13b..371da20044f 100644 --- a/source/blender/compositor/operations/COM_MixOperation.cpp +++ b/source/blender/compositor/operations/COM_MixOperation.cpp @@ -18,9 +18,7 @@ #include "COM_MixOperation.h" -extern "C" { #include "BLI_math.h" -} /* ******** Mix Base Operation ******** */ diff --git a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp index 4f5d7f6f00b..34773a1e4f8 100644 --- a/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipAttributeOperation.cpp @@ -17,10 +17,10 @@ */ #include "COM_MovieClipAttributeOperation.h" -extern "C" { + #include "BKE_movieclip.h" #include "BKE_tracking.h" -} + MovieClipAttributeOperation::MovieClipAttributeOperation() : NodeOperation() { this->addOutputSocket(COM_DT_VALUE); diff --git a/source/blender/compositor/operations/COM_MovieClipOperation.cpp b/source/blender/compositor/operations/COM_MovieClipOperation.cpp index c5757274143..17794ae879e 100644 --- a/source/blender/compositor/operations/COM_MovieClipOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieClipOperation.cpp @@ -20,11 +20,11 @@ #include "BLI_listbase.h" #include "BLI_math.h" -extern "C" { + +#include "BKE_image.h" #include "BKE_movieclip.h" + #include "IMB_imbuf.h" -} -#include "BKE_image.h" MovieClipBaseOperation::MovieClipBaseOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index ec858ee2c19..67491d51547 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -18,11 +18,10 @@ #include "COM_MovieDistortionOperation.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_tracking.h" + #include "BLI_linklist.h" -} MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperation() { @@ -50,7 +49,8 @@ void MovieDistortionOperation::initExecution() full_frame.xmin = full_frame.ymin = 0; full_frame.xmax = this->m_width; full_frame.ymax = this->m_height; - BKE_tracking_max_distortion_delta_across_bound(tracking, &full_frame, !this->m_apply, delta); + BKE_tracking_max_distortion_delta_across_bound( + tracking, this->m_width, this->m_height, &full_frame, !this->m_apply, delta); /* 5 is just in case we didn't hit real max of distortion in * BKE_tracking_max_undistortion_delta_across_bound diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 3ca9fe16b1e..799c6385a10 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -23,9 +23,7 @@ #include "DNA_movieclip_types.h" #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_tracking.h" -} class MovieDistortionOperation : public NodeOperation { private: diff --git a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp index 9876c319944..8878b05ade7 100644 --- a/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp +++ b/source/blender/compositor/operations/COM_MultilayerImageOperation.cpp @@ -17,10 +17,9 @@ */ #include "COM_MultilayerImageOperation.h" -extern "C" { + #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} MultilayerBaseOperation::MultilayerBaseOperation(int passindex, int view) : BaseImageOperation() { diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp index 65f4eeeb8bb..c0fe7237687 100644 --- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.cpp @@ -33,11 +33,9 @@ #include "DNA_color_types.h" #include "MEM_guardedalloc.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} /************************************ OpenEXR Singlelayer Multiview ******************************/ diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.cpp b/source/blender/compositor/operations/COM_OutputFileOperation.cpp index efe01d0b5cc..ee3779edcb4 100644 --- a/source/blender/compositor/operations/COM_OutputFileOperation.cpp +++ b/source/blender/compositor/operations/COM_OutputFileOperation.cpp @@ -32,11 +32,9 @@ #include "DNA_color_types.h" #include "MEM_guardedalloc.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} void add_exr_channels(void *exrhandle, const char *layerName, diff --git a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp index 676601d82da..eae576ceb56 100644 --- a/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneCornerPinOperation.cpp @@ -24,9 +24,7 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_node.h" -} static bool check_corners(float corners[4][2]) { diff --git a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp index 07053d01d43..e7574e80c2f 100644 --- a/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneDistortCommonOperation.cpp @@ -20,7 +20,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_jitter_2d.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -29,7 +28,6 @@ extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} /* ******** PlaneDistort WarpImage ******** */ diff --git a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp index cbf5a25fa31..ed9a776d0a3 100644 --- a/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp +++ b/source/blender/compositor/operations/COM_PlaneTrackOperation.cpp @@ -25,11 +25,9 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} /* ******** PlaneTrackCommon ******** */ diff --git a/source/blender/compositor/operations/COM_PreviewOperation.cpp b/source/blender/compositor/operations/COM_PreviewOperation.cpp index e9e1b4a8cd9..30fe2ca824d 100644 --- a/source/blender/compositor/operations/COM_PreviewOperation.cpp +++ b/source/blender/compositor/operations/COM_PreviewOperation.cpp @@ -27,12 +27,11 @@ #include "PIL_time.h" #include "WM_api.h" #include "WM_types.h" -extern "C" { + #include "BKE_node.h" #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} PreviewOperation::PreviewOperation(const ColorManagedViewSettings *viewSettings, const ColorManagedDisplaySettings *displaySettings) diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.cpp b/source/blender/compositor/operations/COM_RenderLayersProg.cpp index 722aab329d7..c8a68c70c4d 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersProg.cpp @@ -22,11 +22,9 @@ #include "BLI_listbase.h" #include "DNA_scene_types.h" -extern "C" { #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} /* ******** Render Layers Base Prog ******** */ diff --git a/source/blender/compositor/operations/COM_RenderLayersProg.h b/source/blender/compositor/operations/COM_RenderLayersProg.h index cb47725b749..6f84eae3252 100644 --- a/source/blender/compositor/operations/COM_RenderLayersProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersProg.h @@ -24,9 +24,8 @@ #include "COM_NodeOperation.h" #include "DNA_scene_types.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" -} /** * Base class for all renderlayeroperations @@ -56,7 +55,7 @@ class RenderLayersProg : public NodeOperation { float *m_inputBuffer; /** - * renderpass where this operation needs to get its data from + * Render-pass where this operation needs to get its data from. */ std::string m_passName; diff --git a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp index 1afc6d9477f..738c51fc719 100644 --- a/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_ScreenLensDistortionOperation.cpp @@ -18,12 +18,11 @@ #include "COM_ScreenLensDistortionOperation.h" -extern "C" { #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" + #include "PIL_time.h" -} ScreenLensDistortionOperation::ScreenLensDistortionOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_SplitOperation.cpp b/source/blender/compositor/operations/COM_SplitOperation.cpp index 1862fde2d40..3eddf033cf4 100644 --- a/source/blender/compositor/operations/COM_SplitOperation.cpp +++ b/source/blender/compositor/operations/COM_SplitOperation.cpp @@ -24,10 +24,8 @@ #include "BLI_utildefines.h" #include "MEM_guardedalloc.h" -extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} SplitOperation::SplitOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_TextureOperation.cpp b/source/blender/compositor/operations/COM_TextureOperation.cpp index 0a27a6916b7..07316280bbc 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.cpp +++ b/source/blender/compositor/operations/COM_TextureOperation.cpp @@ -20,13 +20,11 @@ #include "COM_WorkScheduler.h" #include "BKE_image.h" +#include "BKE_node.h" + #include "BLI_listbase.h" #include "BLI_threads.h" -extern "C" { -#include "BKE_node.h" -} - TextureBaseOperation::TextureBaseOperation() : NodeOperation() { this->addInputSocket(COM_DT_VECTOR); // offset diff --git a/source/blender/compositor/operations/COM_TextureOperation.h b/source/blender/compositor/operations/COM_TextureOperation.h index 0d06ac0bc27..ebfdbb6513a 100644 --- a/source/blender/compositor/operations/COM_TextureOperation.h +++ b/source/blender/compositor/operations/COM_TextureOperation.h @@ -23,11 +23,10 @@ #include "COM_NodeOperation.h" #include "DNA_texture_types.h" #include "MEM_guardedalloc.h" -extern "C" { + #include "RE_pipeline.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" -} /** * Base class for all renderlayeroperations diff --git a/source/blender/compositor/operations/COM_TonemapOperation.cpp b/source/blender/compositor/operations/COM_TonemapOperation.cpp index 6b408a0a791..417fe8713ed 100644 --- a/source/blender/compositor/operations/COM_TonemapOperation.cpp +++ b/source/blender/compositor/operations/COM_TonemapOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "BLI_utildefines.h" -extern "C" { #include "IMB_colormanagement.h" -} TonemapOperation::TonemapOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index e497d58732b..5c4f3b99f58 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -24,11 +24,9 @@ #include "BLI_math.h" #include "BLI_math_color.h" -extern "C" { #include "BKE_movieclip.h" #include "BKE_node.h" #include "BKE_tracking.h" -} TrackPositionOperation::TrackPositionOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp index 02f13effc8f..057dc553f7f 100644 --- a/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VariableSizeBokehBlurOperation.cpp @@ -20,9 +20,7 @@ #include "BLI_math.h" #include "COM_OpenCLDevice.h" -extern "C" { #include "RE_pipeline.h" -} VariableSizeBokehBlurOperation::VariableSizeBokehBlurOperation() : NodeOperation() { diff --git a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp index 83ae1a0526d..7a34c84827e 100644 --- a/source/blender/compositor/operations/COM_VectorBlurOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorBlurOperation.cpp @@ -16,12 +16,13 @@ * Copyright 2011, Blender Foundation. */ -#include "BLI_math.h" -#include "MEM_guardedalloc.h" #include <string.h> -extern "C" { + +#include "MEM_guardedalloc.h" + #include "BLI_jitter_2d.h" -} +#include "BLI_math.h" + #include "COM_VectorBlurOperation.h" /* Defined */ diff --git a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp index 6996c7ecb71..61312355a39 100644 --- a/source/blender/compositor/operations/COM_VectorCurveOperation.cpp +++ b/source/blender/compositor/operations/COM_VectorCurveOperation.cpp @@ -18,13 +18,7 @@ #include "COM_VectorCurveOperation.h" -#ifdef __cplusplus -extern "C" { -#endif #include "BKE_colortools.h" -#ifdef __cplusplus -} -#endif VectorCurveOperation::VectorCurveOperation() : CurveBaseOperation() { diff --git a/source/blender/compositor/operations/COM_ViewerOperation.cpp b/source/blender/compositor/operations/COM_ViewerOperation.cpp index 5c32b9962f4..fc26d6219e1 100644 --- a/source/blender/compositor/operations/COM_ViewerOperation.cpp +++ b/source/blender/compositor/operations/COM_ViewerOperation.cpp @@ -28,11 +28,9 @@ #include "WM_api.h" #include "WM_types.h" -extern "C" { #include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} ViewerOperation::ViewerOperation() : NodeOperation() { diff --git a/source/blender/depsgraph/DEG_depsgraph.h b/source/blender/depsgraph/DEG_depsgraph.h index c94a8876ab0..d735d3b89bc 100644 --- a/source/blender/depsgraph/DEG_depsgraph.h +++ b/source/blender/depsgraph/DEG_depsgraph.h @@ -184,7 +184,7 @@ void DEG_editors_set_update_cb(DEG_EditorUpdateIDCb id_func, DEG_EditorUpdateSce /* Evaluation ----------------------------------- */ -bool DEG_is_evaluating(struct Depsgraph *depsgraph); +bool DEG_is_evaluating(const struct Depsgraph *depsgraph); bool DEG_is_active(const struct Depsgraph *depsgraph); void DEG_make_active(struct Depsgraph *depsgraph); diff --git a/source/blender/depsgraph/DEG_depsgraph_build.h b/source/blender/depsgraph/DEG_depsgraph_build.h index e24fa9e8996..81157102bb1 100644 --- a/source/blender/depsgraph/DEG_depsgraph_build.h +++ b/source/blender/depsgraph/DEG_depsgraph_build.h @@ -39,15 +39,16 @@ struct ID; struct Main; struct Object; struct Scene; +struct Simulation; struct ViewLayer; struct bNodeTree; +#include "BLI_sys_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" - /* Graph Building -------------------------------- */ /* Build depsgraph for the given scene, and dump results in given graph container. */ @@ -153,6 +154,9 @@ void DEG_add_object_relation(struct DepsNodeHandle *node_handle, struct Object *object, eDepsObjectComponentType component, const char *description); +void DEG_add_simulation_relation(struct DepsNodeHandle *node_handle, + struct Simulation *simulation, + const char *description); void DEG_add_bone_relation(struct DepsNodeHandle *handle, struct Object *object, const char *bone_name, diff --git a/source/blender/depsgraph/DEG_depsgraph_query.h b/source/blender/depsgraph/DEG_depsgraph_query.h index 26b46376a0a..3d570536223 100644 --- a/source/blender/depsgraph/DEG_depsgraph_query.h +++ b/source/blender/depsgraph/DEG_depsgraph_query.h @@ -111,14 +111,14 @@ struct ID *DEG_get_original_id(struct ID *id); * * Original IDs are considered all the IDs which are not covered by copy-on-write system and are * not out-of-main localized data-blocks. */ -bool DEG_is_original_id(struct ID *id); -bool DEG_is_original_object(struct Object *object); +bool DEG_is_original_id(const struct ID *id); +bool DEG_is_original_object(const struct Object *object); /* Opposite of the above. * * If the data-block is not original it must be evaluated, and vice versa. */ -bool DEG_is_evaluated_id(struct ID *id); -bool DEG_is_evaluated_object(struct Object *object); +bool DEG_is_evaluated_id(const struct ID *id); +bool DEG_is_evaluated_object(const struct Object *object); /* Check whether depsgraph os fully evaluated. This includes the following checks: * - Relations are up-to-date. diff --git a/source/blender/depsgraph/intern/builder/deg_builder.cc b/source/blender/depsgraph/intern/builder/deg_builder.cc index d880618753c..82f3ea7d182 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder.cc @@ -31,7 +31,6 @@ #include "DNA_layer_types.h" #include "DNA_object_types.h" -#include "BLI_ghash.h" #include "BLI_stack.h" #include "BLI_utildefines.h" @@ -157,10 +156,9 @@ void deg_graph_build_flush_visibility(Depsgraph *graph) BLI_Stack *stack = BLI_stack_new(sizeof(OperationNode *), "DEG flush layers stack"); for (IDNode *id_node : graph->id_nodes) { - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { comp_node->affects_directly_visible |= id_node->is_directly_visible; } - GHASH_FOREACH_END(); } for (OperationNode *op_node : graph->operations) { op_node->custom_flags = 0; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc index fe1886c67e8..ba0238b43c7 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_cache.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_cache.cc @@ -29,9 +29,7 @@ #include "BLI_utildefines.h" -extern "C" { #include "BKE_animsys.h" -} namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index f6834feeeae..44ddd9522e0 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -60,6 +59,7 @@ extern "C" { #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -74,7 +74,7 @@ extern "C" { #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" @@ -97,6 +97,7 @@ extern "C" { #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_shader_fx.h" +#include "BKE_simulation.h" #include "BKE_sound.h" #include "BKE_tracking.h" #include "BKE_volume.h" @@ -104,7 +105,6 @@ extern "C" { #include "RNA_access.h" #include "RNA_types.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -120,20 +120,6 @@ extern "C" { namespace DEG { -namespace { - -void free_copy_on_write_datablock(void *id_info_v) -{ - DepsgraphNodeBuilder::IDInfo *id_info = (DepsgraphNodeBuilder::IDInfo *)id_info_v; - if (id_info->id_cow != nullptr) { - deg_free_copy_on_write_datablock(id_info->id_cow); - MEM_freeN(id_info->id_cow); - } - MEM_freeN(id_info); -} - -} /* namespace */ - /* ************ */ /* Node Builder */ @@ -147,15 +133,18 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, view_layer_(nullptr), view_layer_index_(-1), collection_(nullptr), - is_parent_collection_visible_(true), - id_info_hash_(nullptr) + is_parent_collection_visible_(true) { } DepsgraphNodeBuilder::~DepsgraphNodeBuilder() { - if (id_info_hash_ != nullptr) { - BLI_ghash_free(id_info_hash_, nullptr, free_copy_on_write_datablock); + for (IDInfo *id_info : id_info_hash_.values()) { + if (id_info->id_cow != nullptr) { + deg_free_copy_on_write_datablock(id_info->id_cow); + MEM_freeN(id_info->id_cow); + } + MEM_freeN(id_info); } } @@ -166,7 +155,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) IDComponentsMask previously_visible_components_mask = 0; uint32_t previous_eval_flags = 0; DEGCustomDataMeshMasks previous_customdata_masks; - IDInfo *id_info = (IDInfo *)BLI_ghash_lookup(id_info_hash_, id); + IDInfo *id_info = id_info_hash_.lookup_default(id, nullptr); if (id_info != nullptr) { id_cow = id_info->id_cow; previously_visible_components_mask = id_info->previously_visible_components_mask; @@ -182,7 +171,7 @@ IDNode *DepsgraphNodeBuilder::add_id_node(ID *id) /* Currently all ID nodes are supposed to have copy-on-write logic. * * NOTE: Zero number of components indicates that ID node was just created. */ - if (BLI_ghash_len(id_node->components) == 0) { + if (id_node->components.is_empty()) { ComponentNode *comp_cow = id_node->add_component(NodeType::COPY_ON_WRITE); OperationNode *op_cow = comp_cow->add_operation( function_bind(deg_evaluate_copy_on_write, _1, id_node), @@ -320,7 +309,6 @@ void DepsgraphNodeBuilder::begin_build() { /* Store existing copy-on-write versions of datablock, so we can re-use * them for new ID nodes. */ - id_info_hash_ = BLI_ghash_ptr_new("Depsgraph id hash"); for (IDNode *id_node : graph_->id_nodes) { /* It is possible that the ID does not need to have CoW version in which case id_cow is the * same as id_orig. Additionally, such ID might have been removed, which makes the check @@ -344,11 +332,11 @@ void DepsgraphNodeBuilder::begin_build() id_info->previously_visible_components_mask = id_node->visible_components_mask; id_info->previous_eval_flags = id_node->eval_flags; id_info->previous_customdata_masks = id_node->customdata_masks; - BLI_ghash_insert(id_info_hash_, id_node->id_orig, id_info); + id_info_hash_.add_new(id_node->id_orig, id_info); id_node->id_cow = nullptr; } - GSET_FOREACH_BEGIN (OperationNode *, op_node, graph_->entry_tags) { + for (OperationNode *op_node : graph_->entry_tags) { ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; @@ -360,12 +348,11 @@ void DepsgraphNodeBuilder::begin_build() entry_tag.name_tag = op_node->name_tag; saved_entry_tags_.push_back(entry_tag); } - GSET_FOREACH_END(); /* Make sure graph has no nodes left from previous state. */ graph_->clear_all_nodes(); graph_->operations.clear(); - BLI_gset_clear(graph_->entry_tags, nullptr); + graph_->entry_tags.clear(); } void DepsgraphNodeBuilder::end_build() @@ -482,6 +469,9 @@ void DepsgraphNodeBuilder::build_id(ID *id) case ID_SCE: build_scene_parameters((Scene *)id); break; + case ID_SIM: + build_simulation((Simulation *)id); + break; default: fprintf(stderr, "Unhandled ID %s\n", id->name); BLI_assert(!"Should never happen"); @@ -519,8 +509,7 @@ void DepsgraphNodeBuilder::build_collection(LayerCollection *from_layer_collecti } else if (from_layer_collection == nullptr && !id_node->is_collection_fully_expanded) { /* Initially collection was built from layer now, and was requested - * to not recurs into object. But nw it's asked to recurs into all - * objects. */ + * to not recurs into object. But now it's asked to recurs into all objects. */ } else { return; @@ -616,21 +605,21 @@ void DepsgraphNodeBuilder::build_object(int base_index, BuilderWalkUserData data; data.builder = this; data.is_parent_visible = is_visible; - modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { BuilderWalkUserData data; data.builder = this; data.is_parent_visible = is_visible; - BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Shader FX. */ if (object->shader_fx.first != nullptr) { BuilderWalkUserData data; data.builder = this; data.is_parent_visible = is_visible; - BKE_shaderfx_foreachIDLink(object, modifier_walk, &data); + BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data); } /* Constraints. */ if (object->constraints.first != nullptr) { @@ -1161,8 +1150,8 @@ void DepsgraphNodeBuilder::build_particle_systems(Object *object, bool is_object * evaluation context for an object. It acts as the container * for all the nodes associated with a particular set of particle * systems. - * 2) Particle System Eval Operation - This operation node acts as a - * blackbox evaluation step for one particle system referenced by + * 2) Particle System Evaluation Operation - This operation node acts as a + * black-box evaluation step for one particle system referenced by * the particle systems stack. All dependencies link to this operation. */ /* Component for all particle systems. */ ComponentNode *psys_comp = add_component_node(&object->id, NodeType::PARTICLE_SYSTEM); @@ -1757,6 +1746,21 @@ void DepsgraphNodeBuilder::build_sound(bSound *sound) build_parameters(&sound->id); } +void DepsgraphNodeBuilder::build_simulation(Simulation *simulation) +{ + if (built_map_.checkIsBuiltAndTag(simulation)) { + return; + } + add_id_node(&simulation->id); + build_animdata(&simulation->id); + build_parameters(&simulation->id); + + add_operation_node(&simulation->id, + NodeType::SIMULATION, + OperationCode::SIMULATION_EVAL, + function_bind(BKE_simulation_data_update, _1, get_cow_datablock(scene_))); +} + void DepsgraphNodeBuilder::build_scene_sequencer(Scene *scene) { if (scene->ed == nullptr) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 16beedabc2a..5cd7f7449a2 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -37,7 +37,6 @@ struct Collection; struct FCurve; struct FreestyleLineSet; struct FreestyleLineStyle; -struct GHash; struct ID; struct IDProperty; struct Image; @@ -53,6 +52,7 @@ struct MovieClip; struct Object; struct ParticleSettings; struct Scene; +struct Simulation; struct Speaker; struct Tex; struct World; @@ -221,6 +221,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { virtual void build_lightprobe(LightProbe *probe); virtual void build_speaker(Speaker *speaker); virtual void build_sound(bSound *sound); + virtual void build_simulation(Simulation *simulation); virtual void build_scene_sequencer(Scene *scene); virtual void build_scene_audio(Scene *scene); virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer); @@ -279,7 +280,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { bool is_parent_collection_visible_; /* Indexed by original ID, values are IDInfo. */ - GHash *id_info_hash_; + Map<const ID *, IDInfo *> id_info_hash_; /* Set of IDs which were already build. Makes it easier to keep track of * what was already built and what was not. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc index 7a05ae36ea4..ab0a5c13321 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_rig.cc @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -44,7 +43,6 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -143,8 +141,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object, bool is_object_visible) Scene *scene_cow = get_cow_datablock(scene_); Object *object_cow = get_cow_datablock(object); OperationNode *op_node; - /* Animation and/or drivers linking posebones to base-armature used to - * define them. + /* Animation and/or drivers linking pose-bones to base-armature used to define them. * * NOTE: AnimData here is really used to control animated deform properties, * which ideally should be able to be unique across different diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc index 1aa3c5bf613..58cfb36b4ab 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes_view_layer.cc @@ -34,7 +34,6 @@ #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_freestyle_types.h" #include "DNA_layer_types.h" #include "DNA_linestyle_types.h" @@ -45,7 +44,6 @@ extern "C" { #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc index ecacfcf7ee9..a0179181866 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.cc @@ -26,104 +26,55 @@ #include <stdio.h> #include <string.h> -#include "BLI_ghash.h" #include "BLI_utildefines.h" namespace DEG { -static void free_rootpchanmap_valueset(void *val) -{ - /* Just need to free the set itself - the names stored are all references. */ - GSet *values = (GSet *)val; - BLI_gset_free(values, nullptr); -} - RootPChanMap::RootPChanMap() { - /* Just create empty map. */ - map_ = BLI_ghash_str_new("RootPChanMap"); } RootPChanMap::~RootPChanMap() { - /* Free the map, and all the value sets. */ - BLI_ghash_free(map_, nullptr, free_rootpchanmap_valueset); } /* Debug contents of map */ void RootPChanMap::print_debug() { - GHashIterator it1; - GSetIterator it2; - - printf("Root PChan Map:\n"); - GHASH_ITER (it1, map_) { - const char *item = (const char *)BLI_ghashIterator_getKey(&it1); - GSet *values = (GSet *)BLI_ghashIterator_getValue(&it1); - - printf(" %s : { ", item); - GSET_ITER (it2, values) { - const char *val = (const char *)BLI_gsetIterator_getKey(&it2); - printf("%s, ", val); + map_.foreach_item([](StringRefNull key, const Set<StringRefNull> &values) { + printf(" %s : { ", key.data()); + for (StringRefNull val : values) { + printf("%s, ", val.data()); } printf("}\n"); - } + }); } /* Add a mapping. */ void RootPChanMap::add_bone(const char *bone, const char *root) { - if (BLI_ghash_haskey(map_, bone)) { - /* Add new entry, but only add the root if it doesn't already - * exist in there. */ - GSet *values = (GSet *)BLI_ghash_lookup(map_, bone); - BLI_gset_add(values, (void *)root); - } - else { - /* Create new set and mapping. */ - GSet *values = BLI_gset_new( - BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "RootPChanMap Value Set"); - BLI_ghash_insert(map_, (void *)bone, (void *)values); - - /* Add new entry now. */ - BLI_gset_insert(values, (void *)root); - } + map_.lookup_or_add_default(bone).add(root); } /* Check if there's a common root bone between two bones. */ bool RootPChanMap::has_common_root(const char *bone1, const char *bone2) const { - /* Ensure that both are in the map... */ - if (BLI_ghash_haskey(map_, bone1) == false) { + const Set<StringRefNull> *bone1_roots = map_.lookup_ptr(bone1); + const Set<StringRefNull> *bone2_roots = map_.lookup_ptr(bone2); + + if (bone1_roots == nullptr) { // fprintf("RootPChanMap: bone1 '%s' not found (%s => %s)\n", bone1, bone1, bone2); // print_debug(); return false; } - if (BLI_ghash_haskey(map_, bone2) == false) { + if (bone2_roots == nullptr) { // fprintf("RootPChanMap: bone2 '%s' not found (%s => %s)\n", bone2, bone1, bone2); // print_debug(); return false; } - GSet *bone1_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone1); - GSet *bone2_roots = (GSet *)BLI_ghash_lookup(map_, (void *)bone2); - - GSetIterator it1, it2; - GSET_ITER (it1, bone1_roots) { - GSET_ITER (it2, bone2_roots) { - const char *v1 = (const char *)BLI_gsetIterator_getKey(&it1); - const char *v2 = (const char *)BLI_gsetIterator_getKey(&it2); - - if (strcmp(v1, v2) == 0) { - // fprintf("RootPchanMap: %s in common for %s => %s\n", v1, bone1, bone2); - return true; - } - } - } - - // fprintf("RootPChanMap: No common root found (%s => %s)\n", bone1, bone2); - return false; + return Set<StringRefNull>::Intersects(*bone1_roots, *bone2_roots); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h index 1442f547b08..c3c90e5aae4 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_pchanmap.h @@ -23,7 +23,7 @@ #pragma once -struct GHash; +#include "intern/depsgraph_type.h" namespace DEG { @@ -42,13 +42,11 @@ struct RootPChanMap { bool has_common_root(const char *bone1, const char *bone2) const; protected: - /* The actual map: - * - Keys are "strings" (const char *) - not dynamically allocated. - * - Values are "sets" (const char *) - not dynamically allocated. - * - * We don't use the C++ maps here, as it's more convenient to use - * Blender's GHash and be able to compare by-value instead of by-ref. */ - struct GHash *map_; + /** + * The strings are only referenced by this map. Users of RootPChanMap have to make sure that the + * life-time of the strings is long enough. + */ + Map<StringRefNull, Set<StringRefNull>> map_; }; } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 9bad796c541..8f977e07f17 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -28,14 +28,12 @@ #include <cstring> /* required for STREQ later on. */ #include <stdio.h> #include <stdlib.h> -#include <unordered_set> #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -62,6 +60,7 @@ extern "C" { #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -76,7 +75,7 @@ extern "C" { #include "BKE_constraint.h" #include "BKE_curve.h" #include "BKE_effect.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil_modifier.h" #include "BKE_idprop.h" #include "BKE_image.h" @@ -99,7 +98,6 @@ extern "C" { #include "RNA_access.h" #include "RNA_types.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -122,8 +120,6 @@ extern "C" { namespace DEG { -using std::unordered_set; - /* ***************** */ /* Relations Builder */ @@ -559,6 +555,9 @@ void DepsgraphRelationBuilder::build_id(ID *id) case ID_SCE: build_scene_parameters((Scene *)id); break; + case ID_SIM: + build_simulation((Simulation *)id); + break; default: fprintf(stderr, "Unhandled ID %s\n", id->name); BLI_assert(!"Should never happen"); @@ -659,19 +658,19 @@ void DepsgraphRelationBuilder::build_object(Base *base, Object *object) if (object->modifiers.first != nullptr) { BuilderWalkUserData data; data.builder = this; - modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Grease Pencil Modifiers. */ if (object->greasepencil_modifiers.first != nullptr) { BuilderWalkUserData data; data.builder = this; - BKE_gpencil_modifiers_foreachIDLink(object, modifier_walk, &data); + BKE_gpencil_modifiers_foreach_ID_link(object, modifier_walk, &data); } /* Shader FX. */ if (object->shader_fx.first != nullptr) { BuilderWalkUserData data; data.builder = this; - BKE_shaderfx_foreachIDLink(object, modifier_walk, &data); + BKE_shaderfx_foreach_ID_link(object, modifier_walk, &data); } /* Constraints. */ if (object->constraints.first != nullptr) { @@ -1972,7 +1971,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.scene = scene_; ctx.object = object; LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) { - const ModifierTypeInfo *mti = modifierType_getInfo((ModifierType)md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)md->type); if (mti->updateDepsgraph) { DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); @@ -1990,7 +1989,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.scene = scene_; ctx.object = object; LISTBASE_FOREACH (GpencilModifierData *, md, &object->greasepencil_modifiers) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo( + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info( (GpencilModifierType)md->type); if (mti->updateDepsgraph) { DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); @@ -2009,7 +2008,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) ctx.scene = scene_; ctx.object = object; LISTBASE_FOREACH (ShaderFxData *, fx, &object->shader_fx) { - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo((ShaderFxType)fx->type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info((ShaderFxType)fx->type); if (fxi->updateDepsgraph) { DepsNodeHandle handle = create_node_handle(obdata_ubereval_key); ctx.node = reinterpret_cast<::DepsNodeHandle *>(&handle); @@ -2400,22 +2399,28 @@ void DepsgraphRelationBuilder::build_texture(Tex *texture) return; } /* texture itself */ + ComponentKey texture_key(&texture->id, NodeType::GENERIC_DATABLOCK); build_idproperties(texture->id.properties); build_animdata(&texture->id); build_parameters(&texture->id); + /* texture's nodetree */ build_nodetree(texture->nodetree); + build_nested_nodetree(&texture->id, texture->nodetree); + /* Special cases for different IDs which texture uses. */ if (texture->type == TEX_IMAGE) { if (texture->ima != nullptr) { build_image(texture->ima); + + ComponentKey image_key(&texture->ima->id, NodeType::GENERIC_DATABLOCK); + add_relation(image_key, texture_key, "Texture Image"); } } - build_nested_nodetree(&texture->id, texture->nodetree); + if (check_id_has_anim_component(&texture->id)) { ComponentKey animation_key(&texture->id, NodeType::ANIMATION); - ComponentKey datablock_key(&texture->id, NodeType::GENERIC_DATABLOCK); - add_relation(animation_key, datablock_key, "Datablock Animation"); + add_relation(animation_key, texture_key, "Datablock Animation"); } } @@ -2566,6 +2571,20 @@ void DepsgraphRelationBuilder::build_sound(bSound *sound) build_parameters(&sound->id); } +void DepsgraphRelationBuilder::build_simulation(Simulation *simulation) +{ + if (built_map_.checkIsBuiltAndTag(simulation)) { + return; + } + build_animdata(&simulation->id); + build_parameters(&simulation->id); + + OperationKey simulation_update_key( + &simulation->id, NodeType::SIMULATION, OperationCode::SIMULATION_EVAL); + TimeSourceKey time_src_key; + add_relation(time_src_key, simulation_update_key, "TimeSrc -> Simulation"); +} + void DepsgraphRelationBuilder::build_scene_sequencer(Scene *scene) { if (scene->ed == nullptr) { @@ -2681,7 +2700,7 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) Node *node_cow = find_node(copy_on_write_key); OperationNode *op_cow = node_cow->get_exit_operation(); /* Plug any other components to this one. */ - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { if (comp_node->type == NodeType::COPY_ON_WRITE) { /* Copy-on-write component never depends on itself. */ continue; @@ -2724,11 +2743,11 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) rel->flag |= rel_flag; } /* All dangling operations should also be executed after copy-on-write. */ - GHASH_FOREACH_BEGIN (OperationNode *, op_node, comp_node->operations_map) { + for (OperationNode *op_node : comp_node->operations_map->values()) { if (op_node == op_entry) { continue; } - if (op_node->inlinks.size() == 0) { + if (op_node->inlinks.is_empty()) { Relation *rel = graph_->add_new_relation(op_cow, op_node, "CoW Dependency"); rel->flag |= rel_flag; } @@ -2750,7 +2769,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) } } } - GHASH_FOREACH_END(); /* NOTE: We currently ignore implicit relations to an external * data-blocks for copy-on-write operations. This means, for example, * copy-on-write component of Object will not wait for copy-on-write @@ -2759,7 +2777,6 @@ void DepsgraphRelationBuilder::build_copy_on_write_relations(IDNode *id_node) * evaluation step needs geometry, it will have transitive dependency * to Mesh copy-on-write already. */ } - GHASH_FOREACH_END(); /* TODO(sergey): This solves crash for now, but causes too many * updates potentially. */ if (GS(id_orig->name) == ID_OB) { @@ -2808,7 +2825,7 @@ static bool is_reachable(const Node *const from, const Node *const to) // Perform a graph walk from 'to' towards its incoming connections. // Walking from 'from' towards its outgoing connections is 10x slower on the Spring rig. deque<const Node *> queue; - unordered_set<const Node *> seen; + Set<const Node *> seen; queue.push_back(to); while (!queue.empty()) { // Visit the next node to inspect. @@ -2822,7 +2839,7 @@ static bool is_reachable(const Node *const from, const Node *const to) // Queue all incoming relations that we haven't seen before. for (Relation *relation : visit->inlinks) { const Node *prev_node = relation->from; - if (seen.insert(prev_node).second) { + if (seen.add(prev_node)) { queue.push_back(prev_node); } } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 3c9bd8a9856..aa6d8ababd3 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -69,6 +69,7 @@ struct Object; struct ParticleSettings; struct ParticleSystem; struct Scene; +struct Simulation; struct Speaker; struct Tex; struct ViewLayer; @@ -286,6 +287,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { virtual void build_lightprobe(LightProbe *probe); virtual void build_speaker(Speaker *speaker); virtual void build_sound(bSound *sound); + virtual void build_simulation(Simulation *simulation); virtual void build_scene_sequencer(Scene *scene); virtual void build_scene_audio(Scene *scene); virtual void build_scene_speakers(Scene *scene, ViewLayer *view_layer); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h index eeeb58100b0..5983627fafc 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_impl.h @@ -25,10 +25,8 @@ #include "intern/node/deg_node_id.h" -extern "C" { #include "DNA_ID.h" #include "DNA_object_types.h" -} namespace DEG { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc index ff2bc2ac3ea..fe9adecbf0a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_rig.cc @@ -34,7 +34,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -45,7 +44,6 @@ extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_constraint.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -69,7 +67,7 @@ void DepsgraphRelationBuilder::build_ik_pose(Object *object, RootPChanMap *root_map) { if ((con->flag & CONSTRAINT_DISABLE) != 0) { - /* Do not add disabled IK constraints to the relations. If these needs to be temporarly + /* Do not add disabled IK constraints to the relations. If these needs to be temporarily * enabled, they will be added as temporary constraints during transform. */ return; } diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc index d3bdaccd404..e132ba30e67 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations_view_layer.cc @@ -34,7 +34,6 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_linestyle_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" @@ -43,7 +42,6 @@ extern "C" { #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_node.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc b/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc index 2ce1f1f1c1d..c6545362bb1 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_remove_noop.cc @@ -43,7 +43,7 @@ static inline bool is_unused_noop(OperationNode *op_node) if (op_node->flag & OperationFlag::DEPSOP_FLAG_PINNED) { return false; } - return op_node->is_noop() && op_node->outlinks.empty(); + return op_node->is_noop() && op_node->outlinks.is_empty(); } void deg_graph_remove_unused_noops(Depsgraph *graph) @@ -61,7 +61,7 @@ void deg_graph_remove_unused_noops(Depsgraph *graph) OperationNode *to_remove = queue.front(); queue.pop_front(); - while (!to_remove->inlinks.empty()) { + while (!to_remove->inlinks.is_empty()) { Relation *rel_in = to_remove->inlinks[0]; Node *dependency = rel_in->from; diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc index 73f6730be03..9fa663b9b6d 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.cc @@ -27,18 +27,15 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" #include "DNA_object_types.h" #include "DNA_sequence_types.h" -} #include "BKE_constraint.h" @@ -57,37 +54,33 @@ namespace DEG { class RNANodeQueryIDData { public: - explicit RNANodeQueryIDData(const ID *id) : id_(id), contraint_to_pchan_map_(nullptr) + explicit RNANodeQueryIDData(const ID *id) : id_(id), constraint_to_pchan_map_(nullptr) { } ~RNANodeQueryIDData() { - if (contraint_to_pchan_map_ != nullptr) { - BLI_ghash_free(contraint_to_pchan_map_, nullptr, nullptr); - } + delete constraint_to_pchan_map_; } const bPoseChannel *get_pchan_for_constraint(const bConstraint *constraint) { ensure_constraint_to_pchan_map(); - return static_cast<bPoseChannel *>(BLI_ghash_lookup(contraint_to_pchan_map_, constraint)); + return constraint_to_pchan_map_->lookup_default(constraint, nullptr); } void ensure_constraint_to_pchan_map() { - if (contraint_to_pchan_map_ != nullptr) { + if (constraint_to_pchan_map_ != nullptr) { return; } BLI_assert(GS(id_->name) == ID_OB); const Object *object = reinterpret_cast<const Object *>(id_); - contraint_to_pchan_map_ = BLI_ghash_ptr_new("id data pchan constraint map"); + constraint_to_pchan_map_ = new Map<const bConstraint *, const bPoseChannel *>(); if (object->pose != nullptr) { LISTBASE_FOREACH (const bPoseChannel *, pchan, &object->pose->chanbase) { LISTBASE_FOREACH (const bConstraint *, constraint, &pchan->constraints) { - BLI_ghash_insert(contraint_to_pchan_map_, - const_cast<bConstraint *>(constraint), - const_cast<bPoseChannel *>(pchan)); + constraint_to_pchan_map_->add_new(constraint, pchan); } } } @@ -99,7 +92,7 @@ class RNANodeQueryIDData { /* indexed by bConstraint*, returns pose channel which contains that * constraint. */ - GHash *contraint_to_pchan_map_; + Map<const bConstraint *, const bPoseChannel *> *constraint_to_pchan_map_; }; /* ***************************** Node Identifier **************************** */ @@ -121,26 +114,13 @@ bool RNANodeIdentifier::is_valid() const /* ********************************** Query ********************************* */ -namespace { - -void ghash_id_data_free_func(void *value) -{ - RNANodeQueryIDData *id_data = static_cast<RNANodeQueryIDData *>(value); - OBJECT_GUARDED_DELETE(id_data, RNANodeQueryIDData); -} - -} // namespace - RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph, DepsgraphBuilder *builder) - : depsgraph_(depsgraph), - builder_(builder), - id_data_map_(BLI_ghash_ptr_new("rna node query id data hash")) + : depsgraph_(depsgraph), builder_(builder) { } RNANodeQuery::~RNANodeQuery() { - BLI_ghash_free(id_data_map_, nullptr, ghash_id_data_free_func); } Node *RNANodeQuery::find_node(const PointerRNA *ptr, @@ -384,12 +364,9 @@ RNANodeIdentifier RNANodeQuery::construct_node_identifier(const PointerRNA *ptr, RNANodeQueryIDData *RNANodeQuery::ensure_id_data(const ID *id) { - RNANodeQueryIDData **id_data_ptr; - if (!BLI_ghash_ensure_p( - id_data_map_, const_cast<ID *>(id), reinterpret_cast<void ***>(&id_data_ptr))) { - *id_data_ptr = OBJECT_GUARDED_NEW(RNANodeQueryIDData, id); - } - return *id_data_ptr; + unique_ptr<RNANodeQueryIDData> &id_data = id_data_map_.lookup_or_add( + id, [&]() { return BLI::make_unique<RNANodeQueryIDData>(id); }); + return id_data.get(); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/builder/deg_builder_rna.h b/source/blender/depsgraph/intern/builder/deg_builder_rna.h index 8a79d9abef9..bd806ce058a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_rna.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_rna.h @@ -26,7 +26,6 @@ #include "intern/node/deg_node.h" #include "intern/node/deg_node_operation.h" -struct GHash; struct ID; struct PointerRNA; struct PropertyRNA; @@ -83,7 +82,7 @@ class RNANodeQuery { DepsgraphBuilder *builder_; /* Indexed by an ID, returns RNANodeQueryIDData associated with that ID. */ - GHash *id_data_map_; + Map<const ID *, unique_ptr<RNANodeQueryIDData>> id_data_map_; /* Construct identifier of the node which corresponds given configuration * of RNA property. */ diff --git a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc index 3f828ef5bb0..22ceac899b8 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_transitive.cc @@ -72,6 +72,8 @@ static void deg_graph_tag_paths_recursive(Node *node) void deg_graph_transitive_reduction(Depsgraph *graph) { int num_removed_relations = 0; + Vector<Relation *> relations_to_remove; + for (OperationNode *target : graph->operations) { /* Clear tags. */ for (OperationNode *node : graph->operations) { @@ -85,25 +87,24 @@ void deg_graph_transitive_reduction(Depsgraph *graph) deg_graph_tag_paths_recursive(rel->from); } /* Remove redundant paths to the target. */ - for (Node::Relations::const_iterator it_rel = target->inlinks.begin(); - it_rel != target->inlinks.end();) { - Relation *rel = *it_rel; + for (Relation *rel : target->inlinks) { if (rel->from->type == NodeType::TIMESOURCE) { /* HACK: time source nodes don't get "custom_flags" flag * set/cleared. */ /* TODO: there will be other types in future, so iterators above * need modifying. */ - ++it_rel; + continue; } else if (rel->from->custom_flags & OP_REACHABLE) { - rel->unlink(); - OBJECT_GUARDED_DELETE(rel, Relation); - num_removed_relations++; - } - else { - ++it_rel; + relations_to_remove.append(rel); } } + for (Relation *rel : relations_to_remove) { + rel->unlink(); + OBJECT_GUARDED_DELETE(rel, Relation); + } + num_removed_relations += relations_to_remove.size(); + relations_to_remove.clear(); } DEG_DEBUG_PRINTF((::Depsgraph *)graph, BUILD, "Removed %d relations\n", num_removed_relations); } diff --git a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc index 7080f8a1a9b..dbe88ee92a8 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_relations_graphviz.cc @@ -25,12 +25,9 @@ #include <cstdarg> -#include "BLI_ghash.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_listBase.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -407,15 +404,14 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node) switch (node->type) { case NodeType::ID_REF: { const IDNode *id_node = (const IDNode *)node; - if (BLI_ghash_len(id_node->components) == 0) { + if (id_node->components.is_empty()) { deg_debug_graphviz_node_single(ctx, node); } else { deg_debug_graphviz_node_cluster_begin(ctx, node); - GHASH_FOREACH_BEGIN (const ComponentNode *, comp, id_node->components) { + for (const ComponentNode *comp : id_node->components.values()) { deg_debug_graphviz_node(ctx, comp); } - GHASH_FOREACH_END(); deg_debug_graphviz_node_cluster_end(ctx); } break; @@ -443,7 +439,8 @@ static void deg_debug_graphviz_node(const DebugContext &ctx, const Node *node) case NodeType::SYNCHRONIZATION: case NodeType::AUDIO: case NodeType::ARMATURE: - case NodeType::GENERIC_DATABLOCK: { + case NodeType::GENERIC_DATABLOCK: + case NodeType::SIMULATION: { ComponentNode *comp_node = (ComponentNode *)node; if (!comp_node->operations.empty()) { deg_debug_graphviz_node_cluster_begin(ctx, node); @@ -472,7 +469,7 @@ static bool deg_debug_graphviz_is_cluster(const Node *node) switch (node->type) { case NodeType::ID_REF: { const IDNode *id_node = (const IDNode *)node; - return BLI_ghash_len(id_node->components) > 0; + return !id_node->components.is_empty(); } case NodeType::PARAMETERS: case NodeType::ANIMATION: @@ -568,12 +565,11 @@ static void deg_debug_graphviz_graph_nodes(const DebugContext &ctx, const Depsgr static void deg_debug_graphviz_graph_relations(const DebugContext &ctx, const Depsgraph *graph) { for (IDNode *id_node : graph->id_nodes) { - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { for (OperationNode *op_node : comp_node->operations) { deg_debug_graphviz_node_relations(ctx, op_node); } } - GHASH_FOREACH_END(); } TimeSourceNode *time_source = graph->find_time_source(); diff --git a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc index c37188bc3ca..7bef5fda636 100644 --- a/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc +++ b/source/blender/depsgraph/intern/debug/deg_debug_stats_gnuplot.cc @@ -32,9 +32,7 @@ #include "intern/depsgraph.h" #include "intern/node/deg_node_id.h" -extern "C" { #include "DNA_ID.h" -} /* extern "C" */ #define NL "\r\n" diff --git a/source/blender/depsgraph/intern/depsgraph.cc b/source/blender/depsgraph/intern/depsgraph.cc index 6d88782d68c..d4a6b0a8b76 100644 --- a/source/blender/depsgraph/intern/depsgraph.cc +++ b/source/blender/depsgraph/intern/depsgraph.cc @@ -31,15 +31,12 @@ #include "MEM_guardedalloc.h" #include "BLI_console.h" -#include "BLI_ghash.h" #include "BLI_hash.h" #include "BLI_utildefines.h" -extern "C" { #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_scene.h" -} #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -60,12 +57,6 @@ extern "C" { namespace DEG { -/* TODO(sergey): Find a better place for this. */ -template<typename T> static void remove_from_vector(vector<T> *vector, const T &value) -{ - vector->erase(std::remove(vector->begin(), vector->end(), value), vector->end()); -} - Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode) : time_source(nullptr), need_update(true), @@ -81,8 +72,6 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati is_render_pipeline_depsgraph(false) { BLI_spin_init(&lock); - id_hash = BLI_ghash_ptr_new("Depsgraph id hash"); - entry_tags = BLI_gset_ptr_new("Depsgraph entry_tags"); memset(id_type_updated, 0, sizeof(id_type_updated)); memset(id_type_exist, 0, sizeof(id_type_exist)); memset(physics_relations, 0, sizeof(physics_relations)); @@ -91,8 +80,6 @@ Depsgraph::Depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluati Depsgraph::~Depsgraph() { clear_id_nodes(); - BLI_ghash_free(id_hash, nullptr, nullptr); - BLI_gset_free(entry_tags, nullptr); if (time_source != nullptr) { OBJECT_GUARDED_DELETE(time_source, TimeSourceNode); } @@ -117,7 +104,7 @@ TimeSourceNode *Depsgraph::find_time_source() const IDNode *Depsgraph::find_id_node(const ID *id) const { - return reinterpret_cast<IDNode *>(BLI_ghash_lookup(id_hash, id)); + return id_hash.lookup_default(id, nullptr); } IDNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint) @@ -132,7 +119,7 @@ IDNode *Depsgraph::add_id_node(ID *id, ID *id_cow_hint) * * NOTE: We address ID nodes by the original ID pointer they are * referencing to. */ - BLI_ghash_insert(id_hash, id, id_node); + id_hash.add_new(id, id_node); id_nodes.push_back(id_node); id_type_exist[BKE_idtype_idcode_to_index(GS(id->name))] = 1; @@ -170,7 +157,7 @@ void Depsgraph::clear_id_nodes() OBJECT_GUARDED_DELETE(id_node, IDNode); } /* Clear containers. */ - BLI_ghash_clear(id_hash, nullptr, nullptr); + id_hash.clear(); id_nodes.clear(); /* Clear physics relation caches. */ clear_physics_relations(this); @@ -233,7 +220,7 @@ void Depsgraph::add_entry_tag(OperationNode *node) * from. * NOTE: this is necessary since we have several thousand nodes to play * with. */ - BLI_gset_insert(entry_tags, node); + entry_tags.add(node); } void Depsgraph::clear_all_nodes() @@ -320,9 +307,9 @@ void DEG_graph_free(Depsgraph *graph) OBJECT_GUARDED_DELETE(deg_depsgraph, Depsgraph); } -bool DEG_is_evaluating(struct Depsgraph *depsgraph) +bool DEG_is_evaluating(const struct Depsgraph *depsgraph) { - DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); + const DEG::Depsgraph *deg_graph = reinterpret_cast<const DEG::Depsgraph *>(depsgraph); return deg_graph->is_evaluating; } diff --git a/source/blender/depsgraph/intern/depsgraph.h b/source/blender/depsgraph/intern/depsgraph.h index 7801f95e008..672f202338e 100644 --- a/source/blender/depsgraph/intern/depsgraph.h +++ b/source/blender/depsgraph/intern/depsgraph.h @@ -43,8 +43,6 @@ #include "intern/debug/deg_debug.h" #include "intern/depsgraph_type.h" -struct GHash; -struct GSet; struct ID; struct Scene; struct ViewLayer; @@ -97,7 +95,7 @@ struct Depsgraph { /* <ID : IDNode> mapping from ID blocks to nodes representing these * blocks, used for quick lookups. */ - GHash *id_hash; + Map<const ID *, IDNode *> id_hash; /* Ordered list of ID nodes, order matches ID allocation order. * Used for faster iteration, especially for areas which are critical to @@ -119,7 +117,7 @@ struct Depsgraph { /* Quick-Access Temp Data ............. */ /* Nodes which have been tagged as "directly modified". */ - GSet *entry_tags; + Set<OperationNode *> entry_tags; /* Special entry tag for time source. Allows to tag invisible dependency graphs for update when * scene frame changes, so then when dependency graph becomes visible it is on a proper state. */ @@ -169,7 +167,7 @@ struct Depsgraph { /* Cached list of colliders/effectors for collections and the scene * created along with relations, for fast lookup during evaluation. */ - GHash *physics_relations[DEG_PHYSICS_RELATIONS_NUM]; + Map<const ID *, ListBase *> *physics_relations[DEG_PHYSICS_RELATIONS_NUM]; }; } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_build.cc b/source/blender/depsgraph/intern/depsgraph_build.cc index d78bc07ac5e..9e50bd87d6c 100644 --- a/source/blender/depsgraph/intern/depsgraph_build.cc +++ b/source/blender/depsgraph/intern/depsgraph_build.cc @@ -25,21 +25,19 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "PIL_time.h" #include "PIL_time_utildefines.h" -extern "C" { #include "DNA_cachefile_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "BKE_main.h" #include "BKE_scene.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" @@ -106,6 +104,16 @@ void DEG_add_object_relation(DepsNodeHandle *node_handle, deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description); } +void DEG_add_simulation_relation(DepsNodeHandle *node_handle, + Simulation *simulation, + const char *description) +{ + DEG::OperationKey operation_key( + &simulation->id, DEG::NodeType::SIMULATION, DEG::OperationCode::SIMULATION_EVAL); + DEG::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle); + deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description); +} + void DEG_add_object_cache_relation(DepsNodeHandle *node_handle, CacheFile *cache_file, eDepsObjectComponentType component, diff --git a/source/blender/depsgraph/intern/depsgraph_debug.cc b/source/blender/depsgraph/intern/depsgraph_debug.cc index c713a4a3fb1..8f5117ec0f6 100644 --- a/source/blender/depsgraph/intern/depsgraph_debug.cc +++ b/source/blender/depsgraph/intern/depsgraph_debug.cc @@ -23,12 +23,9 @@ * Implementation of tools for debugging the depsgraph */ -#include "BLI_ghash.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_scene_types.h" -} /* extern "C" */ #include "DNA_object_types.h" @@ -198,10 +195,10 @@ bool DEG_debug_consistency_check(Depsgraph *graph) /* ------------------------------------------------ */ /** - * Obtain simple statistics about the complexity of the depsgraph - * \param[out] r_outer The number of outer nodes in the graph - * \param[out] r_operations The number of operation nodes in the graph - * \param[out] r_relations The number of relations between (executable) nodes in the graph + * Obtain simple statistics about the complexity of the depsgraph. + * \param[out] r_outer: The number of outer nodes in the graph + * \param[out] r_operations: The number of operation nodes in the graph + * \param[out] r_relations: The number of relations between (executable) nodes in the graph */ void DEG_stats_simple(const Depsgraph *graph, size_t *r_outer, @@ -224,13 +221,12 @@ void DEG_stats_simple(const Depsgraph *graph, for (DEG::IDNode *id_node : deg_graph->id_nodes) { tot_outer++; - GHASH_FOREACH_BEGIN (DEG::ComponentNode *, comp_node, id_node->components) { + for (DEG::ComponentNode *comp_node : id_node->components.values()) { tot_outer++; for (DEG::OperationNode *op_node : comp_node->operations) { tot_rels += op_node->inlinks.size(); } } - GHASH_FOREACH_END(); } DEG::TimeSourceNode *time_source = deg_graph->find_time_source(); diff --git a/source/blender/depsgraph/intern/depsgraph_eval.cc b/source/blender/depsgraph/intern/depsgraph_eval.cc index 9251d975125..b6c6129e9ba 100644 --- a/source/blender/depsgraph/intern/depsgraph_eval.cc +++ b/source/blender/depsgraph/intern/depsgraph_eval.cc @@ -25,16 +25,13 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" -extern "C" { #include "BKE_scene.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" @@ -87,5 +84,5 @@ void DEG_evaluate_on_framechange(Main *bmain, Depsgraph *graph, float ctime) bool DEG_needs_eval(Depsgraph *graph) { DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(graph); - return BLI_gset_len(deg_graph->entry_tags) != 0 || deg_graph->need_update_time; + return !deg_graph->entry_tags.is_empty() || deg_graph->need_update_time; } diff --git a/source/blender/depsgraph/intern/depsgraph_physics.cc b/source/blender/depsgraph/intern/depsgraph_physics.cc index d7c09780845..a9391e5fe8b 100644 --- a/source/blender/depsgraph/intern/depsgraph_physics.cc +++ b/source/blender/depsgraph/intern/depsgraph_physics.cc @@ -28,14 +28,11 @@ #include "MEM_guardedalloc.h" #include "BLI_compiler_compat.h" -#include "BLI_ghash.h" #include "BLI_listbase.h" -extern "C" { #include "BKE_collision.h" #include "BKE_effect.h" #include "BKE_modifier.h" -} /* extern "C" */ #include "DNA_collection_types.h" #include "DNA_object_force_types.h" @@ -72,8 +69,8 @@ ListBase *DEG_get_effector_relations(const Depsgraph *graph, Collection *collect } ID *collection_orig = DEG_get_original_id(&collection->id); - return (ListBase *)BLI_ghash_lookup(deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR], - collection_orig); + return deg_graph->physics_relations[DEG_PHYSICS_EFFECTOR]->lookup_default(collection_orig, + nullptr); } ListBase *DEG_get_collision_relations(const Depsgraph *graph, @@ -86,7 +83,7 @@ ListBase *DEG_get_collision_relations(const Depsgraph *graph, return nullptr; } ID *collection_orig = DEG_get_original_id(&collection->id); - return (ListBase *)BLI_ghash_lookup(deg_graph->physics_relations[type], collection_orig); + return deg_graph->physics_relations[type]->lookup_default(collection_orig, nullptr); } /********************** Depsgraph Building API ************************/ @@ -107,7 +104,7 @@ void DEG_add_collision_relations(DepsNodeHandle *handle, continue; } if (filter_function == nullptr || - filter_function(ob1, modifiers_findByType(ob1, (ModifierType)modifier_type))) { + filter_function(ob1, BKE_modifiers_findby_type(ob1, (ModifierType)modifier_type))) { DEG_add_object_pointcache_relation(handle, ob1, DEG_OB_COMP_TRANSFORM, name); DEG_add_object_pointcache_relation(handle, ob1, DEG_OB_COMP_GEOMETRY, name); } @@ -165,19 +162,15 @@ namespace DEG { ListBase *build_effector_relations(Depsgraph *graph, Collection *collection) { - GHash *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR]; + Map<const ID *, ListBase *> *hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR]; if (hash == nullptr) { - graph->physics_relations[DEG_PHYSICS_EFFECTOR] = BLI_ghash_ptr_new( - "Depsgraph physics relations hash"); + graph->physics_relations[DEG_PHYSICS_EFFECTOR] = new Map<const ID *, ListBase *>(); hash = graph->physics_relations[DEG_PHYSICS_EFFECTOR]; } - ListBase *relations = reinterpret_cast<ListBase *>(BLI_ghash_lookup(hash, collection)); - if (relations == nullptr) { + return hash->lookup_or_add(&collection->id, [&]() { ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph); - relations = BKE_effector_relations_create(depsgraph, graph->view_layer, collection); - BLI_ghash_insert(hash, &collection->id, relations); - } - return relations; + return BKE_effector_relations_create(depsgraph, graph->view_layer, collection); + }); } ListBase *build_collision_relations(Depsgraph *graph, @@ -185,52 +178,41 @@ ListBase *build_collision_relations(Depsgraph *graph, unsigned int modifier_type) { const ePhysicsRelationType type = modifier_to_relation_type(modifier_type); - GHash *hash = graph->physics_relations[type]; + Map<const ID *, ListBase *> *hash = graph->physics_relations[type]; if (hash == nullptr) { - graph->physics_relations[type] = BLI_ghash_ptr_new("Depsgraph physics relations hash"); + graph->physics_relations[type] = new Map<const ID *, ListBase *>(); hash = graph->physics_relations[type]; } - ListBase *relations = reinterpret_cast<ListBase *>(BLI_ghash_lookup(hash, collection)); - if (relations == nullptr) { + return hash->lookup_or_add(&collection->id, [&]() { ::Depsgraph *depsgraph = reinterpret_cast<::Depsgraph *>(graph); - relations = BKE_collision_relations_create(depsgraph, collection, modifier_type); - BLI_ghash_insert(hash, &collection->id, relations); - } - return relations; -} - -namespace { - -void free_effector_relations(void *value) -{ - BKE_effector_relations_free(reinterpret_cast<ListBase *>(value)); + return BKE_collision_relations_create(depsgraph, collection, modifier_type); + }); } -void free_collision_relations(void *value) -{ - BKE_collision_relations_free(reinterpret_cast<ListBase *>(value)); -} - -} // namespace - void clear_physics_relations(Depsgraph *graph) { for (int i = 0; i < DEG_PHYSICS_RELATIONS_NUM; i++) { - if (graph->physics_relations[i]) { + Map<const ID *, ListBase *> *hash = graph->physics_relations[i]; + if (hash) { const ePhysicsRelationType type = (ePhysicsRelationType)i; switch (type) { case DEG_PHYSICS_EFFECTOR: - BLI_ghash_free(graph->physics_relations[i], nullptr, free_effector_relations); + for (ListBase *list : hash->values()) { + BKE_effector_relations_free(list); + } break; case DEG_PHYSICS_COLLISION: case DEG_PHYSICS_SMOKE_COLLISION: case DEG_PHYSICS_DYNAMIC_BRUSH: - BLI_ghash_free(graph->physics_relations[i], nullptr, free_collision_relations); + for (ListBase *list : hash->values()) { + BKE_collision_relations_free(list); + } break; case DEG_PHYSICS_RELATIONS_NUM: break; } + delete hash; graph->physics_relations[i] = nullptr; } } diff --git a/source/blender/depsgraph/intern/depsgraph_query.cc b/source/blender/depsgraph/intern/depsgraph_query.cc index 6e85b2e8bd9..3c760e71197 100644 --- a/source/blender/depsgraph/intern/depsgraph_query.cc +++ b/source/blender/depsgraph/intern/depsgraph_query.cc @@ -25,10 +25,8 @@ #include "MEM_guardedalloc.h" -extern "C" { #include <string.h> // XXX: memcpy -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" @@ -37,8 +35,6 @@ extern "C" { #include "BKE_idtype.h" #include "BKE_main.h" -} /* extern "C" */ - #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -271,7 +267,7 @@ ID *DEG_get_original_id(ID *id) return (ID *)id->orig_id; } -bool DEG_is_original_id(ID *id) +bool DEG_is_original_id(const ID *id) { /* Some explanation of the logic. * @@ -296,17 +292,17 @@ bool DEG_is_original_id(ID *id) return true; } -bool DEG_is_original_object(Object *object) +bool DEG_is_original_object(const Object *object) { return DEG_is_original_id(&object->id); } -bool DEG_is_evaluated_id(ID *id) +bool DEG_is_evaluated_id(const ID *id) { return !DEG_is_original_id(id); } -bool DEG_is_evaluated_object(Object *object) +bool DEG_is_evaluated_object(const Object *object) { return !DEG_is_original_object(object); } @@ -319,7 +315,7 @@ bool DEG_is_fully_evaluated(const struct Depsgraph *depsgraph) return false; } /* Check whether IDs are up to date. */ - if (BLI_gset_len(deg_graph->entry_tags) > 0) { + if (!deg_graph->entry_tags.is_empty()) { return false; } return true; diff --git a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc index efd7d6e77ef..b68c4b91fcc 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_foreach.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_foreach.cc @@ -23,14 +23,9 @@ * Implementation of Querying and Filtering API's */ -#include <unordered_set> - #include "MEM_guardedalloc.h" -extern "C" { -#include "BLI_ghash.h" #include "BLI_utildefines.h" -} /* extern "C" */ #include "DNA_object_types.h" #include "DNA_scene_types.h" @@ -50,8 +45,6 @@ extern "C" { namespace DEG { namespace { -using std::unordered_set; - typedef deque<OperationNode *> TraversalQueue; typedef void (*DEGForeachOperation)(OperationNode *op_node, void *user_data); @@ -66,11 +59,12 @@ bool deg_foreach_needs_visit(const OperationNode *op_node, const int flags) return true; } -static void deg_foreach_dependent_operation(const IDNode *target_id_node, - eDepsObjectComponentType source_component_type, - int flags, - DEGForeachOperation callback, - void *user_data) +void deg_foreach_dependent_operation(const Depsgraph *UNUSED(graph), + const IDNode *target_id_node, + eDepsObjectComponentType source_component_type, + int flags, + DEGForeachOperation callback, + void *user_data) { if (target_id_node == nullptr) { /* TODO(sergey): Shall we inform or assert here about attempt to start @@ -79,8 +73,8 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, } /* Start with scheduling all operations from ID node. */ TraversalQueue queue; - unordered_set<OperationNode *> scheduled; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) { + Set<OperationNode *> scheduled; + for (ComponentNode *comp_node : target_id_node->components.values()) { if (source_component_type != DEG_OB_COMP_ANY && nodeTypeToObjectComponent(comp_node->type) != source_component_type) { continue; @@ -90,10 +84,9 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, continue; } queue.push_back(op_node); - scheduled.insert(op_node); + scheduled.add(op_node); } } - GHASH_FOREACH_END(); /* Process the queue. */ while (!queue.empty()) { /* get next operation node to process. */ @@ -104,9 +97,8 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, /* Schedule outgoing operation nodes. */ if (op_node->outlinks.size() == 1) { OperationNode *to_node = (OperationNode *)op_node->outlinks[0]->to; - if (scheduled.find(to_node) == scheduled.end() && - deg_foreach_needs_visit(to_node, flags)) { - scheduled.insert(to_node); + if (!scheduled.contains(to_node) && deg_foreach_needs_visit(to_node, flags)) { + scheduled.add_new(to_node); op_node = to_node; } else { @@ -116,10 +108,9 @@ static void deg_foreach_dependent_operation(const IDNode *target_id_node, else { for (Relation *rel : op_node->outlinks) { OperationNode *to_node = (OperationNode *)rel->to; - if (scheduled.find(to_node) == scheduled.end() && - deg_foreach_needs_visit(to_node, flags)) { + if (!scheduled.contains(to_node) && deg_foreach_needs_visit(to_node, flags)) { queue.push_front(to_node); - scheduled.insert(to_node); + scheduled.add_new(to_node); } } break; @@ -132,7 +123,7 @@ struct ForeachIDComponentData { DEGForeachIDComponentCallback callback; void *user_data; IDNode *target_id_node; - unordered_set<ComponentNode *> visited; + Set<ComponentNode *> visited; }; void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user_data_v) @@ -140,11 +131,10 @@ void deg_foreach_dependent_component_callback(OperationNode *op_node, void *user ForeachIDComponentData *user_data = reinterpret_cast<ForeachIDComponentData *>(user_data_v); ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; - if (id_node != user_data->target_id_node && - user_data->visited.find(comp_node) == user_data->visited.end()) { + if (id_node != user_data->target_id_node && !user_data->visited.contains(comp_node)) { user_data->callback( id_node->id_orig, nodeTypeToObjectComponent(comp_node->type), user_data->user_data); - user_data->visited.insert(comp_node); + user_data->visited.add_new(comp_node); } } @@ -159,7 +149,8 @@ void deg_foreach_dependent_ID_component(const Depsgraph *graph, data.callback = callback; data.user_data = user_data; data.target_id_node = graph->find_id_node(id); - deg_foreach_dependent_operation(data.target_id_node, + deg_foreach_dependent_operation(graph, + data.target_id_node, source_component_type, flags, deg_foreach_dependent_component_callback, @@ -170,7 +161,7 @@ struct ForeachIDData { DEGForeachIDCallback callback; void *user_data; IDNode *target_id_node; - unordered_set<IDNode *> visited; + Set<IDNode *> visited; }; void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v) @@ -178,10 +169,9 @@ void deg_foreach_dependent_ID_callback(OperationNode *op_node, void *user_data_v ForeachIDData *user_data = reinterpret_cast<ForeachIDData *>(user_data_v); ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; - if (id_node != user_data->target_id_node && - user_data->visited.find(id_node) == user_data->visited.end()) { + if (id_node != user_data->target_id_node && !user_data->visited.contains(id_node)) { user_data->callback(id_node->id_orig, user_data->user_data); - user_data->visited.insert(id_node); + user_data->visited.add_new(id_node); } } @@ -195,7 +185,7 @@ void deg_foreach_dependent_ID(const Depsgraph *graph, data.user_data = user_data; data.target_id_node = graph->find_id_node(id); deg_foreach_dependent_operation( - data.target_id_node, DEG_OB_COMP_ANY, 0, deg_foreach_dependent_ID_callback, &data); + graph, data.target_id_node, DEG_OB_COMP_ANY, 0, deg_foreach_dependent_ID_callback, &data); } void deg_foreach_ancestor_ID(const Depsgraph *graph, @@ -212,16 +202,15 @@ void deg_foreach_ancestor_ID(const Depsgraph *graph, } /* Start with scheduling all operations from ID node. */ TraversalQueue queue; - unordered_set<OperationNode *> scheduled; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, target_id_node->components) { + Set<OperationNode *> scheduled; + for (ComponentNode *comp_node : target_id_node->components.values()) { for (OperationNode *op_node : comp_node->operations) { queue.push_back(op_node); - scheduled.insert(op_node); + scheduled.add(op_node); } } - GHASH_FOREACH_END(); - unordered_set<IDNode *> visited; - visited.insert(target_id_node); + Set<IDNode *> visited; + visited.add_new(target_id_node); /* Process the queue. */ while (!queue.empty()) { /* get next operation node to process. */ @@ -231,18 +220,17 @@ void deg_foreach_ancestor_ID(const Depsgraph *graph, /* Check whether we need to inform callee about corresponding ID node. */ ComponentNode *comp_node = op_node->owner; IDNode *id_node = comp_node->owner; - if (visited.find(id_node) == visited.end()) { + if (!visited.contains(id_node)) { /* TODO(sergey): Is it orig or CoW? */ callback(id_node->id_orig, user_data); - visited.insert(id_node); + visited.add_new(id_node); } /* Schedule incoming operation nodes. */ if (op_node->inlinks.size() == 1) { Node *from = op_node->inlinks[0]->from; if (from->get_class() == NodeClass::OPERATION) { OperationNode *from_node = (OperationNode *)from; - if (scheduled.find(from_node) == scheduled.end()) { - scheduled.insert(from_node); + if (scheduled.add(from_node)) { op_node = from_node; } else { @@ -255,9 +243,8 @@ void deg_foreach_ancestor_ID(const Depsgraph *graph, Node *from = rel->from; if (from->get_class() == NodeClass::OPERATION) { OperationNode *from_node = (OperationNode *)from; - if (scheduled.find(from_node) == scheduled.end()) { + if (scheduled.add(from_node)) { queue.push_front(from_node); - scheduled.insert(from_node); } } } diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc index c4b53bd8176..1eb07206465 100644 --- a/source/blender/depsgraph/intern/depsgraph_query_iter.cc +++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc @@ -28,15 +28,14 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_duplilist.h" #include "BKE_idprop.h" #include "BKE_layer.h" #include "BKE_node.h" #include "BKE_object.h" + #include "BLI_math.h" #include "BLI_utildefines.h" -} /* extern "C" */ #include "DNA_object_types.h" #include "DNA_scene_types.h" diff --git a/source/blender/depsgraph/intern/depsgraph_registry.cc b/source/blender/depsgraph/intern/depsgraph_registry.cc index ad60b1bc4cf..3b0a0b3ea19 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.cc +++ b/source/blender/depsgraph/intern/depsgraph_registry.cc @@ -29,46 +29,33 @@ namespace DEG { -typedef set<Depsgraph *> DepsgraphStorage; -typedef map<Main *, DepsgraphStorage> MainDepsgraphMap; - -static MainDepsgraphMap g_graph_registry; +static Map<Main *, VectorSet<Depsgraph *>> g_graph_registry; void register_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - MainDepsgraphMap::iterator it = g_graph_registry.find(bmain); - if (it == g_graph_registry.end()) { - it = g_graph_registry.insert(make_pair(bmain, DepsgraphStorage())).first; - } - DepsgraphStorage &storage = it->second; - storage.insert(depsgraph); + g_graph_registry.lookup_or_add_default(bmain).add_new(depsgraph); } void unregister_graph(Depsgraph *depsgraph) { Main *bmain = depsgraph->bmain; - MainDepsgraphMap::iterator it = g_graph_registry.find(bmain); - BLI_assert(it != g_graph_registry.end()); - - // Remove dependency graph from storage. - DepsgraphStorage &storage = it->second; - storage.erase(depsgraph); + VectorSet<Depsgraph *> &graphs = g_graph_registry.lookup(bmain); + graphs.remove(depsgraph); // If this was the last depsgraph associated with the main, remove the main entry as well. - if (storage.empty()) { - g_graph_registry.erase(bmain); + if (graphs.is_empty()) { + g_graph_registry.remove(bmain); } } -const set<Depsgraph *> &get_all_registered_graphs(Main *bmain) +ArrayRef<Depsgraph *> get_all_registered_graphs(Main *bmain) { - MainDepsgraphMap::iterator it = g_graph_registry.find(bmain); - if (it == g_graph_registry.end()) { - static DepsgraphStorage empty_storage; - return empty_storage; + VectorSet<Depsgraph *> *graphs = g_graph_registry.lookup_ptr(bmain); + if (graphs != nullptr) { + return *graphs; } - return it->second; + return {}; } } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_registry.h b/source/blender/depsgraph/intern/depsgraph_registry.h index 7517b6a0b2a..f8e5b9543f2 100644 --- a/source/blender/depsgraph/intern/depsgraph_registry.h +++ b/source/blender/depsgraph/intern/depsgraph_registry.h @@ -33,6 +33,6 @@ struct Depsgraph; void register_graph(Depsgraph *depsgraph); void unregister_graph(Depsgraph *depsgraph); -const set<Depsgraph *> &get_all_registered_graphs(Main *bmain); +ArrayRef<Depsgraph *> get_all_registered_graphs(Main *bmain); } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_relation.cc b/source/blender/depsgraph/intern/depsgraph_relation.cc index cff62540ca8..a4ec48658f5 100644 --- a/source/blender/depsgraph/intern/depsgraph_relation.cc +++ b/source/blender/depsgraph/intern/depsgraph_relation.cc @@ -30,12 +30,6 @@ namespace DEG { -/* TODO(sergey): Find a better place for this. */ -template<typename T> static void remove_from_vector(vector<T> *vector, const T &value) -{ - vector->erase(std::remove(vector->begin(), vector->end(), value), vector->end()); -} - Relation::Relation(Node *from, Node *to, const char *description) : from(from), to(to), name(description), flag(0) { @@ -52,8 +46,8 @@ Relation::Relation(Node *from, Node *to, const char *description) * * - Un-registering relation is not a cheap operation, so better to have it * as an explicit call if we need this. */ - from->outlinks.push_back(this); - to->inlinks.push_back(this); + from->outlinks.append(this); + to->inlinks.append(this); } Relation::~Relation() @@ -66,8 +60,8 @@ void Relation::unlink() { /* Sanity check. */ BLI_assert(from != nullptr && to != nullptr); - remove_from_vector(&from->outlinks, this); - remove_from_vector(&to->inlinks, this); + from->outlinks.remove_first_occurrence_and_reorder(this); + to->inlinks.remove_first_occurrence_and_reorder(this); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/depsgraph_tag.cc b/source/blender/depsgraph/intern/depsgraph_tag.cc index 1c56808ea82..0ee86088e43 100644 --- a/source/blender/depsgraph/intern/depsgraph_tag.cc +++ b/source/blender/depsgraph/intern/depsgraph_tag.cc @@ -33,7 +33,6 @@ #include "BLI_task.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_key_types.h" @@ -54,7 +53,6 @@ extern "C" { #define new new_ #include "BKE_screen.h" #undef new -} /* extern "C" */ #include "DEG_depsgraph.h" #include "DEG_depsgraph_debug.h" @@ -495,13 +493,13 @@ void deg_graph_node_tag_zero(Main *bmain, ID *id = id_node->id_orig; /* TODO(sergey): Which recalc flags to set here? */ id_node->id_cow->recalc |= deg_recalc_flags_for_legacy_zero(); - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + + for (ComponentNode *comp_node : id_node->components.values()) { if (comp_node->type == NodeType::ANIMATION) { continue; } comp_node->tag_update(graph, update_source); } - GHASH_FOREACH_END(); deg_graph_id_tag_legacy_compat(bmain, graph, id, (IDRecalcFlag)0, update_source); } diff --git a/source/blender/depsgraph/intern/depsgraph_type.cc b/source/blender/depsgraph/intern/depsgraph_type.cc index 559bf8dfdab..92d775b0ae4 100644 --- a/source/blender/depsgraph/intern/depsgraph_type.cc +++ b/source/blender/depsgraph/intern/depsgraph_type.cc @@ -25,7 +25,6 @@ #include <cstdlib> // for BLI_assert() -#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "DNA_customdata_types.h" diff --git a/source/blender/depsgraph/intern/depsgraph_type.h b/source/blender/depsgraph/intern/depsgraph_type.h index fbf5c2fd381..7016d07ae72 100644 --- a/source/blender/depsgraph/intern/depsgraph_type.h +++ b/source/blender/depsgraph/intern/depsgraph_type.h @@ -38,9 +38,14 @@ #include <map> #include <set> #include <string> -#include <unordered_map> #include <vector> +#include "BLI_map.hh" +#include "BLI_set.hh" +#include "BLI_string_ref.hh" +#include "BLI_vector.hh" +#include "BLI_vector_set.hh" + struct Depsgraph; struct CustomData_MeshMasks; @@ -48,12 +53,19 @@ struct CustomData_MeshMasks; namespace DEG { /* Commonly used types. */ +using BLI::ArrayRef; +using BLI::Map; +using BLI::Set; +using BLI::StringRef; +using BLI::StringRefNull; +using BLI::Vector; +using BLI::VectorSet; using std::deque; using std::map; using std::pair; using std::set; using std::string; -using std::unordered_map; +using std::unique_ptr; using std::vector; /* Commonly used functions. */ diff --git a/source/blender/depsgraph/intern/eval/deg_eval.cc b/source/blender/depsgraph/intern/eval/deg_eval.cc index c7f3c5cb2b6..189beb506b3 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval.cc @@ -28,7 +28,6 @@ #include "PIL_time.h" #include "BLI_compiler_attrs.h" -#include "BLI_ghash.h" #include "BLI_gsqueue.h" #include "BLI_task.h" #include "BLI_utildefines.h" @@ -61,18 +60,17 @@ namespace { struct DepsgraphEvalState; -void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id); +void deg_task_run_func(TaskPool *pool, void *taskdata); template<typename ScheduleFunction, typename... ScheduleFunctionArgs> void schedule_children(DepsgraphEvalState *state, OperationNode *node, - const int thread_id, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args); -void schedule_node_to_pool(OperationNode *node, const int thread_id, TaskPool *pool) +void schedule_node_to_pool(OperationNode *node, const int UNUSED(thread_id), TaskPool *pool) { - BLI_task_pool_push_from_thread(pool, deg_task_run_func, node, false, NULL, thread_id); + BLI_task_pool_push(pool, deg_task_run_func, node, false, NULL); } /* Denotes which part of dependency graph is being evaluated. */ @@ -116,9 +114,9 @@ void evaluate_node(const DepsgraphEvalState *state, OperationNode *operation_nod } } -void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id) +void deg_task_run_func(TaskPool *pool, void *taskdata) { - void *userdata_v = BLI_task_pool_userdata(pool); + void *userdata_v = BLI_task_pool_user_data(pool); DepsgraphEvalState *state = (DepsgraphEvalState *)userdata_v; /* Evaluate node. */ @@ -126,9 +124,7 @@ void deg_task_run_func(TaskPool *pool, void *taskdata, int thread_id) evaluate_node(state, operation_node); /* Schedule children. */ - BLI_task_pool_delayed_push_begin(pool, thread_id); - schedule_children(state, operation_node, thread_id, schedule_node_to_pool, pool); - BLI_task_pool_delayed_push_end(pool, thread_id); + schedule_children(state, operation_node, schedule_node_to_pool, pool); } bool check_operation_node_visible(OperationNode *op_node) @@ -238,7 +234,6 @@ template<typename ScheduleFunction, typename... ScheduleFunctionArgs> void schedule_node(DepsgraphEvalState *state, OperationNode *node, bool dec_parents, - const int thread_id, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args) { @@ -271,11 +266,11 @@ void schedule_node(DepsgraphEvalState *state, if (!is_scheduled) { if (node->is_noop()) { /* skip NOOP node, schedule children right away */ - schedule_children(state, node, thread_id, schedule_function, schedule_function_args...); + schedule_children(state, node, schedule_function, schedule_function_args...); } else { /* children are scheduled once this task is completed */ - schedule_function(node, thread_id, schedule_function_args...); + schedule_function(node, 0, schedule_function_args...); } } } @@ -286,14 +281,13 @@ void schedule_graph(DepsgraphEvalState *state, ScheduleFunctionArgs... schedule_function_args) { for (OperationNode *node : state->graph->operations) { - schedule_node(state, node, false, -1, schedule_function, schedule_function_args...); + schedule_node(state, node, false, schedule_function, schedule_function_args...); } } template<typename ScheduleFunction, typename... ScheduleFunctionArgs> void schedule_children(DepsgraphEvalState *state, OperationNode *node, - const int thread_id, ScheduleFunction *schedule_function, ScheduleFunctionArgs... schedule_function_args) { @@ -307,7 +301,6 @@ void schedule_children(DepsgraphEvalState *state, schedule_node(state, child, (rel->flag & RELATION_FLAG_CYCLIC) == 0, - thread_id, schedule_function, schedule_function_args...); } @@ -330,7 +323,7 @@ void evaluate_graph_single_threaded(DepsgraphEvalState *state) BLI_gsqueue_pop(evaluation_queue, &operation_node); evaluate_node(state, operation_node); - schedule_children(state, operation_node, 0, schedule_node_to_queue, evaluation_queue); + schedule_children(state, operation_node, schedule_node_to_queue, evaluation_queue); } BLI_gsqueue_free(evaluation_queue); @@ -354,6 +347,16 @@ void depsgraph_ensure_view_layer(Depsgraph *graph) } // namespace +static TaskPool *deg_evaluate_task_pool_create(DepsgraphEvalState *state) +{ + if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { + return BLI_task_pool_create_no_threads(state); + } + else { + return BLI_task_pool_create_suspended(state, TASK_PRIORITY_HIGH); + } +} + /** * Evaluate all nodes tagged for updating, * \warning This is usually done as part of main loop, but may also be @@ -364,7 +367,7 @@ void depsgraph_ensure_view_layer(Depsgraph *graph) void deg_evaluate_on_refresh(Depsgraph *graph) { /* Nothing to update, early out. */ - if (BLI_gset_len(graph->entry_tags) == 0) { + if (graph->entry_tags.is_empty()) { return; } @@ -377,30 +380,20 @@ void deg_evaluate_on_refresh(Depsgraph *graph) state.graph = graph; state.do_stats = graph->debug.do_time_debug(); state.need_single_thread_pass = false; - /* Set up task scheduler and pull for threaded evaluation. */ - TaskScheduler *task_scheduler; - bool need_free_scheduler; - if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { - task_scheduler = BLI_task_scheduler_create(1); - need_free_scheduler = true; - } - else { - task_scheduler = BLI_task_scheduler_get(); - need_free_scheduler = false; - } - TaskPool *task_pool = BLI_task_pool_create_suspended(task_scheduler, &state, TASK_PRIORITY_HIGH); /* Prepare all nodes for evaluation. */ initialize_execution(&state, graph); /* Do actual evaluation now. */ - /* First, process all Copy-On-Write nodes. */ state.stage = EvaluationStage::COPY_ON_WRITE; + TaskPool *task_pool = deg_evaluate_task_pool_create(&state); schedule_graph(&state, schedule_node_to_pool, task_pool); - BLI_task_pool_work_wait_and_reset(task_pool); + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); /* After that, process all other nodes. */ state.stage = EvaluationStage::THREADED_EVALUATION; + task_pool = deg_evaluate_task_pool_create(&state); schedule_graph(&state, schedule_node_to_pool, task_pool); BLI_task_pool_work_and_wait(task_pool); BLI_task_pool_free(task_pool); @@ -418,9 +411,6 @@ void deg_evaluate_on_refresh(Depsgraph *graph) } /* Clear any uncleared tags - just in case. */ deg_graph_clear_tags(graph); - if (need_free_scheduler) { - BLI_task_scheduler_free(task_scheduler); - } graph->is_evaluating = false; graph->debug.end_graph_evaluation(); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc index b87a877ae99..2f2e05d410e 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_copy_on_write.cc @@ -53,7 +53,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_ID.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -92,7 +91,6 @@ extern "C" { #include "BKE_pointcache.h" #include "BKE_sequencer.h" #include "BKE_sound.h" -} #include "intern/builder/deg_builder.h" #include "intern/builder/deg_builder_nodes.h" diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 990002cf2e8..ee543dcf25d 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -27,7 +27,6 @@ #include <cmath> -#include "BLI_ghash.h" #include "BLI_listbase.h" #include "BLI_math_vector.h" #include "BLI_task.h" @@ -36,12 +35,10 @@ #include "BKE_object.h" #include "BKE_scene.h" -extern "C" { #include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DRW_engine.h" -} /* extern "C" */ #include "DEG_depsgraph.h" @@ -94,9 +91,9 @@ void flush_init_id_node_func(void *__restrict data_v, Depsgraph *graph = (Depsgraph *)data_v; IDNode *id_node = graph->id_nodes[i]; id_node->custom_flags = ID_STATE_NONE; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) + for (ComponentNode *comp_node : id_node->components.values()) { comp_node->custom_flags = COMPONENT_STATE_NONE; - GHASH_FOREACH_END(); + } } BLI_INLINE void flush_prepare(Depsgraph *graph) @@ -116,7 +113,7 @@ BLI_INLINE void flush_prepare(Depsgraph *graph) BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue) { - GSET_FOREACH_BEGIN (OperationNode *, op_node, graph->entry_tags) { + for (OperationNode *op_node : graph->entry_tags) { queue->push_back(op_node); op_node->scheduled = true; DEG_DEBUG_PRINTF((::Depsgraph *)graph, @@ -124,7 +121,6 @@ BLI_INLINE void flush_schedule_entrypoints(Depsgraph *graph, FlushQueue *queue) "Operation is entry point for update: %s\n", op_node->identifier().c_str()); } - GSET_FOREACH_END(); } BLI_INLINE void flush_handle_id_node(IDNode *id_node) @@ -231,7 +227,7 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd ID *id_orig = id_node->id_orig; ID *id_cow = id_node->id_cow; /* Gather recalc flags from all changed components. */ - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (DEG::ComponentNode *comp_node : id_node->components.values()) { if (comp_node->custom_flags != COMPONENT_STATE_DONE) { continue; } @@ -239,7 +235,6 @@ void flush_editors_id_update(Depsgraph *graph, const DEGEditorUpdateContext *upd BLI_assert(factory != nullptr); id_cow->recalc |= factory->id_recalc_tag(); } - GHASH_FOREACH_END(); DEG_DEBUG_PRINTF((::Depsgraph *)graph, EVAL, "Accumulated recalc bits for %s: %u\n", @@ -307,7 +302,7 @@ void invalidate_tagged_evaluated_data(Depsgraph *graph) if (!deg_copy_on_write_is_expanded(id_cow)) { continue; } - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { if (comp_node->custom_flags != COMPONENT_STATE_DONE) { continue; } @@ -322,7 +317,6 @@ void invalidate_tagged_evaluated_data(Depsgraph *graph) break; } } - GHASH_FOREACH_END(); } #else (void)graph; @@ -347,7 +341,7 @@ void deg_graph_flush_updates(Main *bmain, Depsgraph *graph) graph->ctime = ctime; time_source->tag_update(graph, DEG::DEG_UPDATE_SOURCE_TIME); } - if (BLI_gset_len(graph->entry_tags) == 0) { + if (graph->entry_tags.is_empty()) { return; } /* Reset all flags, get ready for the flush. */ @@ -393,7 +387,7 @@ void deg_graph_clear_tags(Depsgraph *graph) DEPSOP_FLAG_USER_MODIFIED); } /* Clear any entry tags which haven't been flushed. */ - BLI_gset_clear(graph->entry_tags, nullptr); + graph->entry_tags.clear(); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc index 2f45ea45197..2b172f824b6 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_runtime_backup_object.cc @@ -166,7 +166,7 @@ void ObjectRuntimeBackup::restore_modifier_runtime_data(Object *object) if (value.second == nullptr) { continue; } - const ModifierTypeInfo *modifier_type_info = modifierType_getInfo(modifier_data_id.type); + const ModifierTypeInfo *modifier_type_info = BKE_modifier_get_info(modifier_data_id.type); BLI_assert(modifier_type_info != nullptr); modifier_type_info->freeRuntimeData(runtime); } diff --git a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc index f164560ac24..9d3b1356570 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_stats.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_stats.cc @@ -23,7 +23,6 @@ #include "intern/eval/deg_eval_stats.h" -#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "intern/depsgraph.h" @@ -41,10 +40,9 @@ void deg_eval_stats_aggregate(Depsgraph *graph) * Those are not filled in by the evaluation engine. */ for (Node *node : graph->id_nodes) { IDNode *id_node = (IDNode *)node; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, id_node->components) { + for (ComponentNode *comp_node : id_node->components.values()) { comp_node->stats.reset_current(); } - GHASH_FOREACH_END(); id_node->stats.reset_current(); } /* Now accumulate operation timings to components and IDs. */ diff --git a/source/blender/depsgraph/intern/node/deg_node.cc b/source/blender/depsgraph/intern/node/deg_node.cc index d95e05a6f4f..10760d3170b 100644 --- a/source/blender/depsgraph/intern/node/deg_node.cc +++ b/source/blender/depsgraph/intern/node/deg_node.cc @@ -114,6 +114,8 @@ const char *nodeTypeAsString(NodeType type) return "ARMATURE"; case NodeType::GENERIC_DATABLOCK: return "GENERIC_DATABLOCK"; + case NodeType::SIMULATION: + return "SIMULATION"; /* Total number of meaningful node types. */ case NodeType::NUM_TYPES: @@ -172,6 +174,7 @@ eDepsSceneComponentType nodeTypeToSceneComponent(NodeType type) case NodeType::SHADING: case NodeType::CACHE: case NodeType::PROXY: + case NodeType::SIMULATION: return DEG_SCENE_COMP_PARAMETERS; } BLI_assert(!"Unhandled node type, not suppsed to happen."); @@ -245,6 +248,7 @@ eDepsObjectComponentType nodeTypeToObjectComponent(NodeType type) case NodeType::BATCH_CACHE: case NodeType::DUPLI: case NodeType::SYNCHRONIZATION: + case NodeType::SIMULATION: case NodeType::UNDEFINED: case NodeType::NUM_TYPES: return DEG_OB_COMP_PARAMETERS; diff --git a/source/blender/depsgraph/intern/node/deg_node.h b/source/blender/depsgraph/intern/node/deg_node.h index ffa37341ea6..f0ce38ddeae 100644 --- a/source/blender/depsgraph/intern/node/deg_node.h +++ b/source/blender/depsgraph/intern/node/deg_node.h @@ -127,6 +127,8 @@ enum class NodeType { DUPLI, /* Synchronization back to original datablock. */ SYNCHRONIZATION, + /* Simulation component. */ + SIMULATION, /* Total number of meaningful node types. */ NUM_TYPES, @@ -163,7 +165,7 @@ struct Node { * The reason why all depsgraph nodes are descended from this type (apart * from basic serialization benefits - from the typeinfo) is that we can * have relationships between these nodes. */ - typedef vector<Relation *> Relations; + typedef Vector<Relation *> Relations; string name; /* Identifier - mainly for debugging purposes. */ NodeType type; /* Structural type of node. */ diff --git a/source/blender/depsgraph/intern/node/deg_node_component.cc b/source/blender/depsgraph/intern/node/deg_node_component.cc index 54796b8965b..f4d042fecf9 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.cc +++ b/source/blender/depsgraph/intern/node/deg_node_component.cc @@ -26,14 +26,11 @@ #include <cstring> /* required for STREQ later on. */ #include <stdio.h> -#include "BLI_ghash.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_object_types.h" #include "BKE_action.h" -} /* extern "C" */ #include "intern/node/deg_node_factory.h" #include "intern/node/deg_node_id.h" @@ -72,41 +69,10 @@ bool ComponentNode::OperationIDKey::operator==(const OperationIDKey &other) cons return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag); } -static unsigned int comp_node_hash_key(const void *key_v) -{ - const ComponentNode::OperationIDKey *key = - reinterpret_cast<const ComponentNode::OperationIDKey *>(key_v); - int opcode_as_int = static_cast<int>(key->opcode); - return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int), - BLI_ghashutil_strhash_p(key->name)); -} - -static bool comp_node_hash_key_cmp(const void *a, const void *b) -{ - const ComponentNode::OperationIDKey *key_a = - reinterpret_cast<const ComponentNode::OperationIDKey *>(a); - const ComponentNode::OperationIDKey *key_b = - reinterpret_cast<const ComponentNode::OperationIDKey *>(b); - return !(*key_a == *key_b); -} - -static void comp_node_hash_key_free(void *key_v) -{ - typedef ComponentNode::OperationIDKey OperationIDKey; - OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v); - OBJECT_GUARDED_DELETE(key, OperationIDKey); -} - -static void comp_node_hash_value_free(void *value_v) -{ - OperationNode *op_node = reinterpret_cast<OperationNode *>(value_v); - OBJECT_GUARDED_DELETE(op_node, OperationNode); -} - ComponentNode::ComponentNode() : entry_operation(nullptr), exit_operation(nullptr), affects_directly_visible(false) { - operations_map = BLI_ghash_new(comp_node_hash_key, comp_node_hash_key_cmp, "Depsgraph id hash"); + operations_map = new Map<ComponentNode::OperationIDKey, OperationNode *>(); } /* Initialize 'component' node - from pointer data given */ @@ -121,7 +87,7 @@ ComponentNode::~ComponentNode() { clear_operations(); if (operations_map != nullptr) { - BLI_ghash_free(operations_map, comp_node_hash_key_free, comp_node_hash_value_free); + delete operations_map; } } @@ -137,7 +103,7 @@ OperationNode *ComponentNode::find_operation(OperationIDKey key) const { OperationNode *node = nullptr; if (operations_map != nullptr) { - node = (OperationNode *)BLI_ghash_lookup(operations_map, &key); + node = operations_map->lookup_default(key, nullptr); } else { for (OperationNode *op_node : operations) { @@ -203,8 +169,8 @@ OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb &op, op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name); /* register opnode in this component's operation set */ - OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag); - BLI_ghash_insert(operations_map, key, op_node); + OperationIDKey key(opcode, name, name_tag); + operations_map->add(key, op_node); /* set backlink */ op_node->owner = this; @@ -242,7 +208,10 @@ void ComponentNode::set_exit_operation(OperationNode *op_node) void ComponentNode::clear_operations() { if (operations_map != nullptr) { - BLI_ghash_clear(operations_map, comp_node_hash_key_free, comp_node_hash_value_free); + for (OperationNode *op_node : operations_map->values()) { + OBJECT_GUARDED_DELETE(op_node, OperationNode); + } + operations_map->clear(); } for (OperationNode *op_node : operations) { OBJECT_GUARDED_DELETE(op_node, OperationNode); @@ -261,10 +230,9 @@ void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source) } // It is possible that tag happens before finalization. if (operations_map != nullptr) { - GHASH_FOREACH_BEGIN (OperationNode *, op_node, operations_map) { + for (OperationNode *op_node : operations_map->values()) { op_node->tag_update(graph, source); } - GHASH_FOREACH_END(); } } @@ -273,13 +241,12 @@ OperationNode *ComponentNode::get_entry_operation() if (entry_operation) { return entry_operation; } - else if (operations_map != nullptr && BLI_ghash_len(operations_map) == 1) { + else if (operations_map != nullptr && operations_map->size() == 1) { OperationNode *op_node = nullptr; /* TODO(sergey): This is somewhat slow. */ - GHASH_FOREACH_BEGIN (OperationNode *, tmp, operations_map) { + for (OperationNode *tmp : operations_map->values()) { op_node = tmp; } - GHASH_FOREACH_END(); /* Cache for the subsequent usage. */ entry_operation = op_node; return op_node; @@ -295,13 +262,12 @@ OperationNode *ComponentNode::get_exit_operation() if (exit_operation) { return exit_operation; } - else if (operations_map != nullptr && BLI_ghash_len(operations_map) == 1) { + else if (operations_map != nullptr && operations_map->size() == 1) { OperationNode *op_node = nullptr; /* TODO(sergey): This is somewhat slow. */ - GHASH_FOREACH_BEGIN (OperationNode *, tmp, operations_map) { + for (OperationNode *tmp : operations_map->values()) { op_node = tmp; } - GHASH_FOREACH_END(); /* Cache for the subsequent usage. */ exit_operation = op_node; return op_node; @@ -314,12 +280,11 @@ OperationNode *ComponentNode::get_exit_operation() void ComponentNode::finalize_build(Depsgraph * /*graph*/) { - operations.reserve(BLI_ghash_len(operations_map)); - GHASH_FOREACH_BEGIN (OperationNode *, op_node, operations_map) { + operations.reserve(operations_map->size()); + for (OperationNode *op_node : operations_map->values()) { operations.push_back(op_node); } - GHASH_FOREACH_END(); - BLI_ghash_free(operations_map, comp_node_hash_key_free, nullptr); + delete operations_map; operations_map = nullptr; } @@ -368,6 +333,7 @@ DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0); DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 0); DEG_COMPONENT_NODE_DEFINE(Armature, ARMATURE, 0); DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0); +DEG_COMPONENT_NODE_DEFINE(Simulation, SIMULATION, 0); /* Node Types Register =================================== */ @@ -397,6 +363,7 @@ void deg_register_component_depsnodes() register_node_typeinfo(&DNTI_AUDIO); register_node_typeinfo(&DNTI_ARMATURE); register_node_typeinfo(&DNTI_GENERIC_DATABLOCK); + register_node_typeinfo(&DNTI_SIMULATION); } } // namespace DEG diff --git a/source/blender/depsgraph/intern/node/deg_node_component.h b/source/blender/depsgraph/intern/node/deg_node_component.h index 38ea4005a72..ca37401d200 100644 --- a/source/blender/depsgraph/intern/node/deg_node_component.h +++ b/source/blender/depsgraph/intern/node/deg_node_component.h @@ -26,10 +26,11 @@ #include "intern/node/deg_node.h" #include "intern/node/deg_node_operation.h" +#include "BLI_ghash.h" +#include "BLI_hash.hh" #include "BLI_string.h" #include "BLI_utildefines.h" -struct GHash; struct ID; struct bPoseChannel; @@ -115,7 +116,7 @@ struct ComponentNode : public Node { /* Operations stored as a hash map, for faster build. * This hash map will be freed when graph is fully built. */ - GHash *operations_map; + Map<ComponentNode::OperationIDKey, OperationNode *> *operations_map; /* This is a "normal" list of operations, used by evaluation * and other routines after construction. */ @@ -190,6 +191,7 @@ DEG_COMPONENT_NODE_DECLARE_GENERIC(Synchronization); DEG_COMPONENT_NODE_DECLARE_GENERIC(Audio); DEG_COMPONENT_NODE_DECLARE_GENERIC(Armature); DEG_COMPONENT_NODE_DECLARE_GENERIC(GenericDatablock); +DEG_COMPONENT_NODE_DECLARE_GENERIC(Simulation); /* Bone Component */ struct BoneComponentNode : public ComponentNode { @@ -203,3 +205,18 @@ struct BoneComponentNode : public ComponentNode { void deg_register_component_depsnodes(); } // namespace DEG + +namespace BLI { + +template<> struct DefaultHash<DEG::ComponentNode::OperationIDKey> { + uint32_t operator()(const DEG::ComponentNode::OperationIDKey &key) const + { + const int opcode_as_int = static_cast<int>(key.opcode); + return BLI_ghashutil_combine_hash( + key.name_tag, + BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int), + BLI_ghashutil_strhash_p(key.name))); + } +}; + +} // namespace BLI diff --git a/source/blender/depsgraph/intern/node/deg_node_id.cc b/source/blender/depsgraph/intern/node/deg_node_id.cc index 4b6120a6985..4a7e5c4568b 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.cc +++ b/source/blender/depsgraph/intern/node/deg_node_id.cc @@ -26,16 +26,13 @@ #include <cstring> /* required for STREQ later on. */ #include <stdio.h> -#include "BLI_ghash.h" #include "BLI_string.h" #include "BLI_utildefines.h" -extern "C" { #include "DNA_ID.h" #include "DNA_anim_types.h" #include "BKE_lib_id.h" -} #include "DEG_depsgraph.h" @@ -69,34 +66,6 @@ bool IDNode::ComponentIDKey::operator==(const ComponentIDKey &other) const return type == other.type && STREQ(name, other.name); } -static unsigned int id_deps_node_hash_key(const void *key_v) -{ - const IDNode::ComponentIDKey *key = reinterpret_cast<const IDNode::ComponentIDKey *>(key_v); - const int type_as_int = static_cast<int>(key->type); - return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), - BLI_ghashutil_strhash_p(key->name)); -} - -static bool id_deps_node_hash_key_cmp(const void *a, const void *b) -{ - const IDNode::ComponentIDKey *key_a = reinterpret_cast<const IDNode::ComponentIDKey *>(a); - const IDNode::ComponentIDKey *key_b = reinterpret_cast<const IDNode::ComponentIDKey *>(b); - return !(*key_a == *key_b); -} - -static void id_deps_node_hash_key_free(void *key_v) -{ - typedef IDNode::ComponentIDKey ComponentIDKey; - ComponentIDKey *key = reinterpret_cast<ComponentIDKey *>(key_v); - OBJECT_GUARDED_DELETE(key, ComponentIDKey); -} - -static void id_deps_node_hash_value_free(void *value_v) -{ - ComponentNode *comp_node = reinterpret_cast<ComponentNode *>(value_v); - OBJECT_GUARDED_DELETE(comp_node, ComponentNode); -} - /* Initialize 'id' node - from pointer data given. */ void IDNode::init(const ID *id, const char *UNUSED(subdata)) { @@ -116,9 +85,6 @@ void IDNode::init(const ID *id, const char *UNUSED(subdata)) visible_components_mask = 0; previously_visible_components_mask = 0; - - components = BLI_ghash_new( - id_deps_node_hash_key, id_deps_node_hash_key_cmp, "Depsgraph id components hash"); } void IDNode::init_copy_on_write(ID *id_cow_hint) @@ -158,7 +124,9 @@ void IDNode::destroy() return; } - BLI_ghash_free(components, id_deps_node_hash_key_free, id_deps_node_hash_value_free); + for (ComponentNode *comp_node : components.values()) { + OBJECT_GUARDED_DELETE(comp_node, ComponentNode); + } /* Free memory used by this CoW ID. */ if (id_cow != id_orig && id_cow != nullptr) { @@ -185,7 +153,7 @@ string IDNode::identifier() const ComponentNode *IDNode::find_component(NodeType type, const char *name) const { ComponentIDKey key(type, name); - return reinterpret_cast<ComponentNode *>(BLI_ghash_lookup(components, &key)); + return components.lookup_default(key, nullptr); } ComponentNode *IDNode::add_component(NodeType type, const char *name) @@ -196,8 +164,8 @@ ComponentNode *IDNode::add_component(NodeType type, const char *name) comp_node = (ComponentNode *)factory->create_node(this->id_orig, "", name); /* Register. */ - ComponentIDKey *key = OBJECT_GUARDED_NEW(ComponentIDKey, type, name); - BLI_ghash_insert(components, key, comp_node); + ComponentIDKey key(type, name); + components.add_new(key, comp_node); comp_node->owner = this; } return comp_node; @@ -205,7 +173,7 @@ ComponentNode *IDNode::add_component(NodeType type, const char *name) void IDNode::tag_update(Depsgraph *graph, eUpdateSource source) { - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) { + for (ComponentNode *comp_node : components.values()) { /* Relations update does explicit animation update when needed. Here we ignore animation * component to avoid loss of possible unkeyed changes. */ if (comp_node->type == NodeType::ANIMATION && source == DEG_UPDATE_SOURCE_RELATIONS) { @@ -213,30 +181,27 @@ void IDNode::tag_update(Depsgraph *graph, eUpdateSource source) } comp_node->tag_update(graph, source); } - GHASH_FOREACH_END(); } void IDNode::finalize_build(Depsgraph *graph) { /* Finalize build of all components. */ - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) { + for (ComponentNode *comp_node : components.values()) { comp_node->finalize_build(graph); } - GHASH_FOREACH_END(); visible_components_mask = get_visible_components_mask(); } IDComponentsMask IDNode::get_visible_components_mask() const { IDComponentsMask result = 0; - GHASH_FOREACH_BEGIN (ComponentNode *, comp_node, components) { + for (ComponentNode *comp_node : components.values()) { if (comp_node->affects_directly_visible) { const int component_type_as_int = static_cast<int>(comp_node->type); BLI_assert(component_type_as_int < 64); result |= (1ULL << component_type_as_int); } } - GHASH_FOREACH_END(); return result; } diff --git a/source/blender/depsgraph/intern/node/deg_node_id.h b/source/blender/depsgraph/intern/node/deg_node_id.h index 80bb67f182f..c7663b50c6f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_id.h +++ b/source/blender/depsgraph/intern/node/deg_node_id.h @@ -23,12 +23,11 @@ #pragma once +#include "BLI_ghash.h" #include "BLI_sys_types.h" #include "DNA_ID.h" #include "intern/node/deg_node.h" -struct GHash; - namespace DEG { struct ComponentNode; @@ -82,7 +81,7 @@ struct IDNode : public Node { ID *id_cow; /* Hash to make it faster to look up components. */ - GHash *components; + Map<ComponentIDKey, ComponentNode *> components; /* Additional flags needed for scene evaluation. * TODO(sergey): Only needed for until really granular updates @@ -116,3 +115,16 @@ struct IDNode : public Node { }; } // namespace DEG + +namespace BLI { + +template<> struct DefaultHash<DEG::IDNode::ComponentIDKey> { + uint32_t operator()(const DEG::IDNode::ComponentIDKey &key) const + { + const int type_as_int = static_cast<int>(key.type); + return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(type_as_int), + BLI_ghashutil_strhash_p(key.name)); + } +}; + +} // namespace BLI diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.cc b/source/blender/depsgraph/intern/node/deg_node_operation.cc index 1e03d51f557..2381076161f 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.cc +++ b/source/blender/depsgraph/intern/node/deg_node_operation.cc @@ -25,7 +25,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_ghash.h" #include "BLI_utildefines.h" #include "intern/depsgraph.h" @@ -195,6 +194,8 @@ const char *operationCodeAsString(OperationCode opcode) /* instancing/duplication. */ case OperationCode::DUPLI: return "DUPLI"; + case OperationCode::SIMULATION_EVAL: + return "SIMULATION_EVAL"; } BLI_assert(!"Unhandled operation code, should never happen."); return "UNKNOWN"; diff --git a/source/blender/depsgraph/intern/node/deg_node_operation.h b/source/blender/depsgraph/intern/node/deg_node_operation.h index 2faf139ec93..865a25d2124 100644 --- a/source/blender/depsgraph/intern/node/deg_node_operation.h +++ b/source/blender/depsgraph/intern/node/deg_node_operation.h @@ -198,6 +198,9 @@ enum class OperationCode { /* Duplication/instancing system. --------------------------------------- */ DUPLI, + + /* Simulation. ---------------------------------------------------------- */ + SIMULATION_EVAL, }; const char *operationCodeAsString(OperationCode opcode); diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 1bdc3bc5a03..6c835c6d7ae 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -23,12 +23,16 @@ #ifndef __DRW_ENGINE_H__ #define __DRW_ENGINE_H__ +#include "BLI_sys_types.h" /* for bool */ + +#include "DNA_object_enums.h" + +#include "DRW_engine_types.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" /* for bool */ - struct ARegion; struct DRWInstanceDataList; struct Depsgraph; @@ -47,9 +51,6 @@ struct ViewLayer; struct bContext; struct rcti; -#include "DNA_object_enums.h" -#include "DRW_engine_types.h" - void DRW_engines_register(void); void DRW_engines_free(void); @@ -77,7 +78,7 @@ typedef bool (*DRW_SelectPassFn)(eDRWSelectStage stage, void *user_data); typedef bool (*DRW_ObjectFilterFn)(struct Object *ob, void *user_data); void DRW_draw_view(const struct bContext *C); -void DRW_draw_region_engine_info(int xoffset, int yoffset); +void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height); void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, struct RenderEngineType *engine_type, diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index 13927cd5124..a6e6b30a6b1 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -73,8 +73,7 @@ static void eevee_motion_blur_camera_get_matrix_at_time(Scene *scene, /* Past matrix */ /* FIXME : This is a temporal solution that does not take care of parent animations */ /* Recalc Anim manually */ - BKE_animsys_evaluate_animdata( - scene, &camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false); + BKE_animsys_evaluate_animdata(&camdata_cpy.id, camdata_cpy.adt, time, ADT_RECALC_ALL, false); BKE_object_where_is_calc_time(draw_ctx->depsgraph, scene, &cam_cpy, time); /* Compute winmat */ diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index 63c96ac8c25..ad90c52b08e 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -487,8 +487,8 @@ static bool eevee_volume_object_mesh_init(Scene *scene, /* Smoke Simulation */ if (((ob->base_flag & BASE_FROM_DUPLI) == 0) && - (md = modifiers_findByType(ob, eModifierType_Fluid)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + (md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && + (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && ((FluidModifierData *)md)->domain != NULL) { FluidModifierData *mmd = (FluidModifierData *)md; FluidDomainSettings *mds = mmd->domain; diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c index bbcfcaf777d..624eef8fa47 100644 --- a/source/blender/draw/engines/overlay/overlay_armature.c +++ b/source/blender/draw/engines/overlay/overlay_armature.c @@ -2204,7 +2204,7 @@ void OVERLAY_armature_cache_populate(OVERLAY_Data *vedata, Object *ob) static bool POSE_is_driven_by_active_armature(Object *ob) { - Object *ob_arm = modifiers_isDeformedByArmature(ob); + Object *ob_arm = BKE_modifiers_is_deformed_by_armature(ob); if (ob_arm) { const DRWContextState *draw_ctx = DRW_context_state_get(); bool is_active = OVERLAY_armature_is_pose_mode(ob_arm, draw_ctx); @@ -2214,7 +2214,7 @@ static bool POSE_is_driven_by_active_armature(Object *ob) return is_active; } else { - Object *ob_mesh_deform = modifiers_isDeformedByMeshDeform(ob); + Object *ob_mesh_deform = BKE_modifiers_is_deformed_by_meshdeform(ob); if (ob_mesh_deform) { /* Recursive. */ return POSE_is_driven_by_active_armature(ob_mesh_deform); diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c index 32085890f20..af54e524445 100644 --- a/source/blender/draw/engines/overlay/overlay_extra.c +++ b/source/blender/draw/engines/overlay/overlay_extra.c @@ -1506,8 +1506,9 @@ void OVERLAY_extra_cache_populate(OVERLAY_Data *vedata, Object *ob) const bool draw_xform = draw_ctx->object_mode == OB_MODE_OBJECT && (scene->toolsettings->transform_flag & SCE_XFORM_DATA_ORIGIN) && (ob->base_flag & BASE_SELECTED) && !is_select_mode; - const bool draw_volume = !from_dupli && (md = modifiers_findByType(ob, eModifierType_Fluid)) && - (modifier_isEnabled(scene, md, eModifierMode_Realtime)) && + const bool draw_volume = !from_dupli && + (md = BKE_modifiers_findby_type(ob, eModifierType_Fluid)) && + (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) && (((FluidModifierData *)md)->domain != NULL); float *color; diff --git a/source/blender/draw/engines/workbench/workbench_data.c b/source/blender/draw/engines/workbench/workbench_data.c index 2e8119fca2f..7b08e97ac31 100644 --- a/source/blender/draw/engines/workbench/workbench_data.c +++ b/source/blender/draw/engines/workbench/workbench_data.c @@ -250,6 +250,8 @@ void workbench_private_data_init(WORKBENCH_PrivateData *wpd) wpd->shading = v3d->shading; if (wpd->shading.type < OB_SOLID) { + wpd->shading.light = V3D_LIGHTING_FLAT; + wpd->shading.color_type = V3D_SHADING_OBJECT_COLOR; wpd->shading.xray_alpha = 0.0f; } else if (XRAY_ENABLED(v3d)) { diff --git a/source/blender/draw/engines/workbench/workbench_engine.c b/source/blender/draw/engines/workbench/workbench_engine.c index cb0dfc0a8bf..e75ba80608b 100644 --- a/source/blender/draw/engines/workbench/workbench_engine.c +++ b/source/blender/draw/engines/workbench/workbench_engine.c @@ -321,8 +321,8 @@ void workbench_cache_populate(void *ved, Object *ob) } if (!(ob->base_flag & BASE_FROM_DUPLI)) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid); - if (md && modifier_isEnabled(wpd->scene, md, eModifierMode_Realtime)) { + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid); + if (md && BKE_modifier_is_enabled(wpd->scene, md, eModifierMode_Realtime)) { FluidModifierData *fmd = (FluidModifierData *)md; if (fmd->domain && fmd->domain->type == FLUID_DOMAIN_TYPE_GAS) { workbench_volume_cache_populate(vedata, wpd->scene, ob, md, V3D_SHADING_SINGLE_COLOR); diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c index 40687306b4e..401f5c76a02 100644 --- a/source/blender/draw/intern/draw_cache_extract_mesh.c +++ b/source/blender/draw/intern/draw_cache_extract_mesh.c @@ -4509,7 +4509,7 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr, } } -static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) +static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata) { ExtractTaskData *data = taskdata; mesh_extract_iter( @@ -4595,7 +4595,7 @@ static void extract_task_create(TaskPool *task_pool, else { /* Single threaded extraction. */ (*task_counter)++; - extract_run(NULL, taskdata, -1); + extract_run(NULL, taskdata); MEM_freeN(taskdata); } } @@ -4685,11 +4685,11 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache, double rdata_end = PIL_check_seconds_timer(); #endif - TaskScheduler *task_scheduler; TaskPool *task_pool; - task_scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(task_scheduler, NULL, TASK_PRIORITY_HIGH); + /* Create a suspended pool as the finalize method could be called too early. + * See `extract_run`. */ + task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH); size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t); int32_t *task_counters = MEM_callocN(counters_size, __func__); diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c index 547a9a54b55..62ce34fe556 100644 --- a/source/blender/draw/intern/draw_cache_impl_gpencil.c +++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c @@ -544,7 +544,7 @@ static void gpencil_sbuffer_stroke_ensure(bGPdata *gpd, bool do_stroke, bool do_ ED_gpencil_tpoint_to_point(region, origin, &tpoints[i], &gps->points[i]); mul_m4_v3(ob->imat, &gps->points[i].x); bGPDspoint *pt = &gps->points[i]; - copy_v4_v4(pt->vert_color, gpd->runtime.vert_color); + copy_v4_v4(pt->vert_color, tpoints[i].vert_color); } /* Calc uv data along the stroke. */ BKE_gpencil_stroke_uv_update(gps); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 1aaead27ee7..649bcd7bbaa 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -1362,7 +1362,8 @@ void DRW_mesh_batch_cache_create_requested( } /* Meh loose Scene const correctness here. */ - const bool use_subsurf_fdots = scene ? modifiers_usesSubsurfFacedots((Scene *)scene, ob) : false; + const bool use_subsurf_fdots = scene ? BKE_modifiers_uses_subsurf_facedots((Scene *)scene, ob) : + false; if (do_uvcage) { mesh_buffer_cache_create_requested(cache, diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 9f84d47a4fb..639c62e5e44 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -1068,7 +1068,7 @@ static void drw_engines_draw_text(void) } /* Draw render engine info. */ -void DRW_draw_region_engine_info(int xoffset, int yoffset) +void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height) { LISTBASE_FOREACH (LinkData *, link, &DST.enabled_engines) { DrawEngineType *engine = link->data; @@ -1091,8 +1091,8 @@ void DRW_draw_region_engine_info(int xoffset, int yoffset) if (*chr_current == '\n') { char info[GPU_INFO_SIZE]; BLI_strncpy(info, chr_start, line_len + 1); - yoffset -= U.widget_unit; - BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info)); + *yoffset -= line_height; + BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); /* Re-start counting. */ chr_start = chr_current + 1; @@ -1102,8 +1102,8 @@ void DRW_draw_region_engine_info(int xoffset, int yoffset) char info[GPU_INFO_SIZE]; BLI_strncpy(info, chr_start, line_len + 1); - yoffset -= U.widget_unit; - BLF_draw_default(xoffset, yoffset, 0.0f, info, sizeof(info)); + *yoffset -= line_height; + BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); BLF_disable(font_id, BLF_SHADOW); } @@ -2027,7 +2027,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph, Object *obweight = OBWEIGHTPAINT_FROM_OBACT(obact); if (obweight) { /* Only use Armature pose selection, when connected armature is in pose mode. */ - Object *ob_armature = modifiers_isDeformedByArmature(obweight); + Object *ob_armature = BKE_modifiers_is_deformed_by_armature(obweight); if (ob_armature && ob_armature->mode == OB_MODE_POSE) { obpose = ob_armature; } diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c index b451cfb1d05..7eac082a9e1 100644 --- a/source/blender/draw/intern/draw_manager_shader.c +++ b/source/blender/draw/intern/draw_manager_shader.c @@ -99,6 +99,10 @@ static void drw_deferred_shader_compilation_exec(void *custom_data, DRWShaderCompiler *comp = (DRWShaderCompiler *)custom_data; void *gl_context = comp->gl_context; +#if TRUST_NO_ONE + BLI_assert(gl_context != NULL); +#endif + WM_opengl_context_activate(gl_context); while (true) { diff --git a/source/blender/editors/animation/anim_channels_defines.c b/source/blender/editors/animation/anim_channels_defines.c index d48e09e0504..cd17a490240 100644 --- a/source/blender/editors/animation/anim_channels_defines.c +++ b/source/blender/editors/animation/anim_channels_defines.c @@ -51,6 +51,7 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" #include "DNA_volume_types.h" @@ -3033,6 +3034,83 @@ static bAnimChannelType ACF_DSVOLUME = { acf_dsvolume_setting_ptr /* pointer for setting */ }; +/* Simulation Expander ----------------------------------------- */ + +static int acf_dssimulation_icon(bAnimListElem *UNUSED(ale)) +{ + /* TODO: Use correct icon. */ + return ICON_PHYSICS; +} + +static int acf_dssimulation_setting_flag(bAnimContext *UNUSED(ac), + eAnimChannel_Settings setting, + bool *neg) +{ + /* clear extra return data first */ + *neg = false; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return SIM_DS_EXPAND; + + case ACHANNEL_SETTING_MUTE: /* mute (only in NLA) */ + return ADT_NLA_EVAL_OFF; + + case ACHANNEL_SETTING_VISIBLE: /* visible (only in Graph Editor) */ + *neg = true; + return ADT_CURVES_NOT_VISIBLE; + + case ACHANNEL_SETTING_SELECT: /* selected */ + return ADT_UI_SELECTED; + + default: /* unsupported */ + return 0; + } +} + +static void *acf_dssimulation_setting_ptr(bAnimListElem *ale, + eAnimChannel_Settings setting, + short *type) +{ + Simulation *simulation = (Simulation *)ale->data; + + /* clear extra return data first */ + *type = 0; + + switch (setting) { + case ACHANNEL_SETTING_EXPAND: /* expanded */ + return GET_ACF_FLAG_PTR(simulation->flag, type); + + case ACHANNEL_SETTING_SELECT: /* selected */ + case ACHANNEL_SETTING_MUTE: /* muted (for NLA only) */ + case ACHANNEL_SETTING_VISIBLE: /* visible (for Graph Editor only) */ + if (simulation->adt) + return GET_ACF_FLAG_PTR(simulation->adt->flag, type); + return NULL; + + default: /* unsupported */ + return NULL; + } +} + +static bAnimChannelType ACF_DSSIMULATION = { + "Simulation Expander", /* type name */ + ACHANNEL_ROLE_EXPANDER, /* role */ + + acf_generic_dataexpand_color, /* backdrop color */ + acf_generic_dataexpand_backdrop, /* backdrop */ + acf_generic_indention_1, /* indent level */ + acf_generic_basic_offset, /* offset */ + + acf_generic_idblock_name, /* name */ + acf_generic_idblock_name_prop, /* name prop */ + acf_dssimulation_icon, /* icon */ + + acf_generic_dataexpand_setting_valid, /* has setting */ + acf_dssimulation_setting_flag, /* flag for setting */ + acf_dssimulation_setting_ptr /* pointer for setting */ +}; + /* GPencil Expander ------------------------------------------- */ // TODO: just get this from RNA? @@ -4049,6 +4127,7 @@ static void ANIM_init_channel_typeinfo_data(void) animchannelTypeInfo[type++] = &ACF_DSHAIR; /* Hair Channel */ animchannelTypeInfo[type++] = &ACF_DSPOINTCLOUD; /* PointCloud Channel */ animchannelTypeInfo[type++] = &ACF_DSVOLUME; /* Volume Channel */ + animchannelTypeInfo[type++] = &ACF_DSSIMULATION; /* Simulation Channel */ animchannelTypeInfo[type++] = &ACF_SHAPEKEY; /* ShapeKey */ diff --git a/source/blender/editors/animation/anim_channels_edit.c b/source/blender/editors/animation/anim_channels_edit.c index 4e3dc3cb220..a7ca84eb6c6 100644 --- a/source/blender/editors/animation/anim_channels_edit.c +++ b/source/blender/editors/animation/anim_channels_edit.c @@ -138,7 +138,8 @@ void ANIM_set_active_channel(bAnimContext *ac, case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* need to verify that this data is valid for now */ if (ale->adt) { ACHANNEL_SET_FLAG(ale->adt, ACHANNEL_SETFLAG_CLEAR, ADT_UI_ACTIVE); @@ -194,7 +195,8 @@ void ANIM_set_active_channel(bAnimContext *ac, case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* need to verify that this data is valid for now */ if (ale && ale->adt) { ale->adt->flag |= ADT_UI_ACTIVE; @@ -332,7 +334,8 @@ void ANIM_deselect_anim_channels( case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { if ((ale->adt) && (ale->adt->flag & ADT_UI_SELECTED)) { sel = ACHANNEL_SETFLAG_CLEAR; } @@ -428,7 +431,8 @@ void ANIM_deselect_anim_channels( case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* need to verify that this data is valid for now */ if (ale->adt) { ACHANNEL_SET_FLAG(ale->adt, sel, ADT_UI_SELECTED); @@ -2965,7 +2969,8 @@ static int mouse_anim_channels(bContext *C, bAnimContext *ac, int channel_index, case ANIMTYPE_DSMCLIP: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* sanity checking... */ if (ale->adt) { /* select/deselect */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 4dc0bef3a1b..2b9dfe105bc 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -67,6 +67,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" #include "DNA_userdef_types.h" @@ -86,6 +87,7 @@ #include "BKE_collection.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_key.h" #include "BKE_layer.h" @@ -826,6 +828,18 @@ static bAnimListElem *make_new_animlistelem(void *data, ale->adt = BKE_animdata_from_id(data); break; } + case ANIMTYPE_DSSIMULATION: { + Simulation *simulation = (Simulation *)data; + AnimData *adt = simulation->adt; + + ale->flag = FILTER_SIMULATION_OBJD(simulation); + + ale->key_data = (adt) ? adt->action : NULL; + ale->datatype = ALE_ACT; + + ale->adt = BKE_animdata_from_id(data); + break; + } case ANIMTYPE_DSSKEY: { Key *key = (Key *)data; AnimData *adt = key->adt; @@ -2414,7 +2428,7 @@ static size_t animdata_filter_ds_modifiers( afm.filter_mode = filter_mode; /* 2) walk over dependencies */ - modifiers_foreachIDLink(ob, animfilter_modifier_idpoin_cb, &afm); + BKE_modifiers_foreach_ID_link(ob, animfilter_modifier_idpoin_cb, &afm); /* 3) extract data from the context, merging it back into the standard list */ if (afm.items) { diff --git a/source/blender/editors/animation/anim_ops.c b/source/blender/editors/animation/anim_ops.c index 2db381dfc69..40cd368e02b 100644 --- a/source/blender/editors/animation/anim_ops.c +++ b/source/blender/editors/animation/anim_ops.c @@ -73,15 +73,9 @@ static bool change_frame_poll(bContext *C) * this shouldn't show up in 3D editor (or others without 2D timeline view) via search */ if (area) { - if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP)) { + if (ELEM(area->spacetype, SPACE_ACTION, SPACE_NLA, SPACE_SEQ, SPACE_CLIP, SPACE_GRAPH)) { return true; } - else if (area->spacetype == SPACE_GRAPH) { - /* NOTE: Graph Editor has special version which does some extra stuff. - * No need to show the generic error message for that case though! - */ - return false; - } } CTX_wm_operator_poll_msg_set(C, "Expected an animation area to be active"); diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c index 3ae4e3bf998..82e24eaa6e3 100644 --- a/source/blender/editors/animation/drivers.c +++ b/source/blender/editors/animation/drivers.c @@ -40,6 +40,7 @@ #include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_report.h" #include "DEG_depsgraph.h" diff --git a/source/blender/editors/animation/keyframes_edit.c b/source/blender/editors/animation/keyframes_edit.c index e22fddc6d67..2dae4e8b4c5 100644 --- a/source/blender/editors/animation/keyframes_edit.c +++ b/source/blender/editors/animation/keyframes_edit.c @@ -633,7 +633,7 @@ bool keyframe_region_lasso_test(const KeyframeEdit_LassoData *data_lasso, const BLI_rctf_transform_pt_v(data_lasso->rectf_view, data_lasso->rectf_scaled, xy_view, xy); if (BLI_lasso_is_point_inside( - data_lasso->mcords, data_lasso->mcords_tot, xy_view[0], xy_view[1], INT_MAX)) { + data_lasso->mcoords, data_lasso->mcoords_len, xy_view[0], xy_view[1], INT_MAX)) { return true; } } diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 49e936d22aa..04061ceea51 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -50,6 +50,7 @@ #include "BKE_armature.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_idtype.h" #include "BKE_key.h" diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c index aa1bceb2674..544d86d4c47 100644 --- a/source/blender/editors/armature/armature_naming.c +++ b/source/blender/editors/armature/armature_naming.c @@ -265,7 +265,7 @@ void ED_armature_bone_rename(Main *bmain, } } - if (modifiers_usesArmature(ob, arm)) { + if (BKE_modifiers_uses_armature(ob, arm)) { bDeformGroup *dg = BKE_object_defgroup_find_name(ob, oldname); if (dg) { BLI_strncpy(dg->name, newname, MAXBONENAME); diff --git a/source/blender/editors/armature/armature_relations.c b/source/blender/editors/armature/armature_relations.c index bc854747a68..5f3b876efaf 100644 --- a/source/blender/editors/armature/armature_relations.c +++ b/source/blender/editors/armature/armature_relations.c @@ -42,7 +42,7 @@ #include "BKE_armature.h" #include "BKE_constraint.h" #include "BKE_context.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_report.h" diff --git a/source/blender/editors/armature/armature_skinning.c b/source/blender/editors/armature/armature_skinning.c index b637a57f7c0..61d8856afbc 100644 --- a/source/blender/editors/armature/armature_skinning.c +++ b/source/blender/editors/armature/armature_skinning.c @@ -418,7 +418,7 @@ static void add_verts_to_dgroups(ReportList *reports, BKE_mesh_foreach_mapped_vert_coords_get(me_eval, verts, mesh->totvert); vertsfilled = 1; } - else if (modifiers_findByType(ob, eModifierType_Subsurf)) { + else if (BKE_modifiers_findby_type(ob, eModifierType_Subsurf)) { /* is subsurf on? Lets use the verts on the limit surface then. * = same amount of vertices as mesh, but vertices moved to the * subsurfed position, like for 'optimal'. */ diff --git a/source/blender/editors/armature/meshlaplacian.c b/source/blender/editors/armature/meshlaplacian.c index 6028ddb216f..d8a6a22a7df 100644 --- a/source/blender/editors/armature/meshlaplacian.c +++ b/source/blender/editors/armature/meshlaplacian.c @@ -1549,7 +1549,7 @@ static void meshdeform_matrix_solve(MeshDeformModifierData *mmd, MeshDeformBind } } else { - modifier_setError(&mmd->modifier, "Failed to find bind solution (increase precision?)"); + BKE_modifier_set_error(&mmd->modifier, "Failed to find bind solution (increase precision?)"); error("Mesh Deform: failed to find bind solution."); break; } @@ -1753,7 +1753,7 @@ void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd, int totvert, float cagemat[4][4]) { - MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)modifier_get_original( + MeshDeformModifierData *mmd_orig = (MeshDeformModifierData *)BKE_modifier_get_original( &mmd->modifier); MeshDeformBind mdb; MVert *mvert; @@ -1799,7 +1799,7 @@ void ED_mesh_deform_bind_callback(MeshDeformModifierData *mmd, MEM_freeN(mdb.vertexcos); /* compact weights */ - modifier_mdef_compact_influences((ModifierData *)mmd_orig); + BKE_modifier_mdef_compact_influences((ModifierData *)mmd_orig); end_progress_bar(); waitcursor(0); diff --git a/source/blender/editors/armature/pose_select.c b/source/blender/editors/armature/pose_select.c index ce652b0eaf4..9525fcf2154 100644 --- a/source/blender/editors/armature/pose_select.c +++ b/source/blender/editors/armature/pose_select.c @@ -263,7 +263,7 @@ void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_se Object *ob_active = OBACT(view_layer); BLI_assert(ob_active && (ob_active->mode & OB_MODE_WEIGHT_PAINT)); VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob_active, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob_active, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { ArmatureModifierData *amd = (ArmatureModifierData *)md; diff --git a/source/blender/editors/armature/pose_slide.c b/source/blender/editors/armature/pose_slide.c index ae08aee3c47..481282d6df3 100644 --- a/source/blender/editors/armature/pose_slide.c +++ b/source/blender/editors/armature/pose_slide.c @@ -544,71 +544,56 @@ static void pose_slide_apply_quat(tPoseSlideOp *pso, tPChanFCurveLink *pfl) /* only if all channels exist, proceed */ if (fcu_w && fcu_x && fcu_y && fcu_z) { - float quat_prev[4], quat_prev_orig[4]; - float quat_next[4], quat_next_orig[4]; - float quat_curr[4], quat_curr_orig[4]; float quat_final[4]; - copy_qt_qt(quat_curr_orig, pchan->quat); - - /* get 2 quats */ - quat_prev_orig[0] = evaluate_fcurve(fcu_w, prevFrameF); - quat_prev_orig[1] = evaluate_fcurve(fcu_x, prevFrameF); - quat_prev_orig[2] = evaluate_fcurve(fcu_y, prevFrameF); - quat_prev_orig[3] = evaluate_fcurve(fcu_z, prevFrameF); - - quat_next_orig[0] = evaluate_fcurve(fcu_w, nextFrameF); - quat_next_orig[1] = evaluate_fcurve(fcu_x, nextFrameF); - quat_next_orig[2] = evaluate_fcurve(fcu_y, nextFrameF); - quat_next_orig[3] = evaluate_fcurve(fcu_z, nextFrameF); - - normalize_qt_qt(quat_prev, quat_prev_orig); - normalize_qt_qt(quat_next, quat_next_orig); - normalize_qt_qt(quat_curr, quat_curr_orig); - /* perform blending */ if (pso->mode == POSESLIDE_BREAKDOWN) { /* Just perform the interpolation between quat_prev and * quat_next using pso->percentage as a guide. */ - interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); - } - else if (pso->mode == POSESLIDE_PUSH) { - float quat_diff[4]; + float quat_prev[4]; + float quat_next[4]; + + quat_prev[0] = evaluate_fcurve(fcu_w, prevFrameF); + quat_prev[1] = evaluate_fcurve(fcu_x, prevFrameF); + quat_prev[2] = evaluate_fcurve(fcu_y, prevFrameF); + quat_prev[3] = evaluate_fcurve(fcu_z, prevFrameF); - /* calculate the delta transform from the previous to the current */ - /* TODO: investigate ways to favor one transform more? */ - sub_qt_qtqt(quat_diff, quat_curr, quat_prev); + quat_next[0] = evaluate_fcurve(fcu_w, nextFrameF); + quat_next[1] = evaluate_fcurve(fcu_x, nextFrameF); + quat_next[2] = evaluate_fcurve(fcu_y, nextFrameF); + quat_next[3] = evaluate_fcurve(fcu_z, nextFrameF); - /* increase the original by the delta transform, by an amount determined by percentage */ - add_qt_qtqt(quat_final, quat_curr, quat_diff, pso->percentage); + normalize_qt(quat_prev); + normalize_qt(quat_next); - normalize_qt(quat_final); + interp_qt_qtqt(quat_final, quat_prev, quat_next, pso->percentage); } else { - BLI_assert(pso->mode == POSESLIDE_RELAX); - float quat_interp[4], quat_final_prev[4]; - /* TODO: maybe a sensitivity ctrl on top of this is needed */ - int iters = (int)ceil(10.0f * pso->percentage); + /* POSESLIDE_PUSH and POSESLIDE_RELAX. */ + float quat_breakdown[4]; + float quat_curr[4]; - copy_qt_qt(quat_final, quat_curr); + copy_qt_qt(quat_curr, pchan->quat); - /* perform this blending several times until a satisfactory result is reached */ - while (iters-- > 0) { - /* calculate the interpolation between the endpoints */ - interp_qt_qtqt(quat_interp, - quat_prev, - quat_next, - (cframe - pso->prevFrame) / (pso->nextFrame - pso->prevFrame)); + quat_breakdown[0] = evaluate_fcurve(fcu_w, cframe); + quat_breakdown[1] = evaluate_fcurve(fcu_x, cframe); + quat_breakdown[2] = evaluate_fcurve(fcu_y, cframe); + quat_breakdown[3] = evaluate_fcurve(fcu_z, cframe); - normalize_qt_qt(quat_final_prev, quat_final); + normalize_qt(quat_breakdown); + normalize_qt(quat_curr); - /* tricky interpolations - blending between original and new */ - interp_qt_qtqt(quat_final, quat_final_prev, quat_interp, 1.0f / 6.0f); + if (pso->mode == POSESLIDE_PUSH) { + interp_qt_qtqt(quat_final, quat_breakdown, quat_curr, 1.0f + pso->percentage); + } + else { + BLI_assert(pso->mode == POSESLIDE_RELAX); + interp_qt_qtqt(quat_final, quat_curr, quat_breakdown, pso->percentage); } } /* Apply final to the pose bone, keeping compatible for similar keyframe positions. */ - quat_to_compatible_quat(pchan->quat, quat_final, quat_curr_orig); + quat_to_compatible_quat(pchan->quat, quat_final, pchan->quat); } /* free the path now */ diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 31c89ca9f43..1d2bf152777 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -1240,7 +1240,7 @@ static int pose_clear_user_transforms_exec(bContext *C, wmOperator *op) workob.adt = ob->adt; workob.pose = dummyPose; - BKE_animsys_evaluate_animdata(scene, &workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata(&workob.id, workob.adt, cframe, ADT_RECALC_ANIM, false); /* copy back values, but on selected bones only */ for (pchan = dummyPose->chanbase.first; pchan; pchan = pchan->next) { diff --git a/source/blender/editors/gpencil/annotate_draw.c b/source/blender/editors/gpencil/annotate_draw.c index adaf4ab2459..22df7bbbf31 100644 --- a/source/blender/editors/gpencil/annotate_draw.c +++ b/source/blender/editors/gpencil/annotate_draw.c @@ -90,14 +90,54 @@ typedef enum eDrawStrokeFlags { /* ----- Tool Buffer Drawing ------ */ +static void annotation_draw_stroke_arrow_buffer(uint pos, + const float *corner_point, + const float *arrow_coords, + const int arrow_style) +{ + immBeginAtMost(GPU_PRIM_LINE_STRIP, arrow_style); + + switch (arrow_style) { + case GP_STROKE_ARROWSTYLE_SEGMENT: + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + break; + case GP_STROKE_ARROWSTYLE_CLOSED: + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + immVertex2f(pos, arrow_coords[4], arrow_coords[5]); + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + break; + case GP_STROKE_ARROWSTYLE_OPEN: + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, corner_point[0], corner_point[1]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + break; + case GP_STROKE_ARROWSTYLE_SQUARE: + immVertex2f(pos, corner_point[0], corner_point[1]); + immVertex2f(pos, arrow_coords[0], arrow_coords[1]); + immVertex2f(pos, arrow_coords[4], arrow_coords[5]); + immVertex2f(pos, arrow_coords[6], arrow_coords[7]); + immVertex2f(pos, arrow_coords[2], arrow_coords[3]); + immVertex2f(pos, corner_point[0], corner_point[1]); + break; + default: + break; + } + immEnd(); +} + /* draw stroke defined in buffer (simple ogl lines/points for now, as dotted lines) */ -static void annotation_draw_stroke_buffer(const tGPspoint *points, - int totpoints, +static void annotation_draw_stroke_buffer(bGPdata *gps, short thickness, short dflag, - short sflag, const float ink[4]) { + bGPdata_Runtime runtime = gps->runtime; + const tGPspoint *points = runtime.sbuffer; + int totpoints = runtime.sbuffer_used; + short sflag = runtime.sbuffer_sflag; + int draw_points = 0; /* error checking */ @@ -176,6 +216,26 @@ static void annotation_draw_stroke_buffer(const tGPspoint *points, } immEnd(); + + /* Draw arrow stroke. */ + if (totpoints > 1) { + /* Draw ending arrow stroke. */ + if ((sflag & GP_STROKE_USE_ARROW_END) && + (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) { + float end[2]; + copy_v2_fl2(end, points[1].x, points[1].y); + annotation_draw_stroke_arrow_buffer(pos, end, runtime.arrow_end, runtime.arrow_end_style); + } + /* Draw starting arrow stroke. */ + if ((sflag & GP_STROKE_USE_ARROW_START) && + (runtime.arrow_start_style != GP_STROKE_ARROWSTYLE_NONE)) { + float start[2]; + copy_v2_fl2(start, points[0].x, points[0].y); + annotation_draw_stroke_arrow_buffer( + pos, start, runtime.arrow_start, runtime.arrow_start_style); + } + } + immUnbindProgram(); } @@ -524,131 +584,6 @@ static void annotation_draw_strokes(const bGPDframe *gpf, GPU_program_point_size(false); } -/* Draw selected verts for strokes being edited */ -static void annotation_draw_strokes_edit(bGPDlayer *gpl, - const bGPDframe *gpf, - int offsx, - int offsy, - int winx, - int winy, - short dflag, - float alpha) -{ - /* if alpha 0 do not draw */ - if (alpha == 0.0f) { - return; - } - - const bool no_xray = (dflag & GP_DRAWDATA_NO_XRAY) != 0; - int mask_orig = 0; - - /* set up depth masks... */ - if (dflag & GP_DRAWDATA_ONLY3D) { - if (no_xray) { - glGetIntegerv(GL_DEPTH_WRITEMASK, &mask_orig); - glDepthMask(0); - GPU_depth_test(true); - - /* first arg is normally rv3d->dist, but this isn't - * available here and seems to work quite well without */ - bglPolygonOffset(1.0f, 1.0f); - } - } - - GPU_program_point_size(true); - - /* draw stroke verts */ - LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { - /* check if stroke can be drawn */ - if (annotation_can_draw_stroke(gps, dflag) == false) { - continue; - } - - /* Optimization: only draw points for selected strokes - * We assume that selected points can only occur in - * strokes that are selected too. - */ - if ((gps->flag & GP_STROKE_SELECT) == 0) { - continue; - } - - /* Get size of verts: - * - The selected state needs to be larger than the unselected state so that - * they stand out more. - * - We use the theme setting for size of the unselected verts - */ - float bsize = UI_GetThemeValuef(TH_GP_VERTEX_SIZE); - float vsize; - if ((int)bsize > 8) { - vsize = 10.0f; - bsize = 8.0f; - } - else { - vsize = bsize + 2; - } - - /* Why? */ - UNUSED_VARS(vsize); - - float selectColor[4]; - UI_GetThemeColor3fv(TH_GP_VERTEX_SELECT, selectColor); - selectColor[3] = alpha; - - GPUVertFormat *format = immVertexFormat(); - uint pos; /* specified later */ - uint size = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); - uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - - if (gps->flag & GP_STROKE_3DSPACE) { - pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_3D_POINT_VARYING_SIZE_VARYING_COLOR); - } - else { - pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - immBindBuiltinProgram(GPU_SHADER_2D_POINT_VARYING_SIZE_VARYING_COLOR); - } - - immBegin(GPU_PRIM_POINTS, gps->totpoints); - - /* Draw all the stroke points (selected or not) */ - bGPDspoint *pt = gps->points; - for (int i = 0; i < gps->totpoints; i++, pt++) { - /* size and color first */ - immAttr3fv(color, gpl->color); - immAttr1f(size, bsize); - - /* then position */ - if (gps->flag & GP_STROKE_3DSPACE) { - immVertex3fv(pos, &pt->x); - } - else { - float co[2]; - annotation_calc_2d_stroke_fxy(&pt->x, gps->flag, offsx, offsy, winx, winy, co); - immVertex2fv(pos, co); - } - } - - immEnd(); - immUnbindProgram(); - } - - GPU_program_point_size(false); - - /* clear depth mask */ - if (dflag & GP_DRAWDATA_ONLY3D) { - if (no_xray) { - glDepthMask(mask_orig); - GPU_depth_test(false); - - bglPolygonOffset(0.0, 0.0); -#if 0 - glDisable(GL_POLYGON_OFFSET_LINE); - glPolygonOffset(0, 0); -#endif - } - } -} - /* ----- General Drawing ------ */ /* draw onion-skinning for a layer */ static void annotation_draw_onionskins( @@ -724,7 +659,7 @@ static void annotation_draw_onionskins( /* loop over gpencil data layers, drawing them */ static void annotation_draw_data_layers( - bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, float alpha) + bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { float ink[4]; @@ -767,21 +702,6 @@ static void annotation_draw_data_layers( /* draw the strokes already in active frame */ annotation_draw_strokes(gpf, offsx, offsy, winx, winy, dflag, lthick, ink); - /* Draw verts of selected strokes: - * - when doing OpenGL renders, we don't want to be showing these, as that ends up - * flickering - * - locked layers can't be edited, so there's no point showing these verts - * as they will have no bearings on what gets edited - * - only show when in editmode, since operators shouldn't work otherwise - * (NOTE: doing it this way means that the toggling editmode - * shows visible change immediately). - */ - /* XXX: perhaps we don't want to show these when users are drawing... */ - if ((G.f & G_FLAG_RENDER_VIEWPORT) == 0 && (gpl->flag & GP_LAYER_LOCKED) == 0 && - (gpd->flag & GP_DATA_STROKE_EDITMODE)) { - annotation_draw_strokes_edit(gpl, gpf, offsx, offsy, winx, winy, dflag, alpha); - } - /* Check if may need to draw the active stroke cache, only if this layer is the active layer * that is being edited. (Stroke buffer is currently stored in gp-data) */ @@ -793,67 +713,14 @@ static void annotation_draw_data_layers( * It should also be noted that sbuffer contains temporary point types * i.e. tGPspoints NOT bGPDspoints */ - annotation_draw_stroke_buffer(gpd->runtime.sbuffer, - gpd->runtime.sbuffer_used, - lthick, - dflag, - gpd->runtime.sbuffer_sflag, - ink); + annotation_draw_stroke_buffer(gpd, lthick, dflag, ink); } } } -/* draw a short status message in the top-right corner */ -static void annotation_draw_status_text(const bGPdata *gpd, ARegion *region) -{ - - /* Cannot draw any status text when drawing OpenGL Renders */ - if (G.f & G_FLAG_RENDER_VIEWPORT) { - return; - } - - /* Get bounds of region - Necessary to avoid problems with region overlap */ - const rcti *rect = ED_region_visible_rect(region); - - /* for now, this should only be used to indicate when we are in stroke editmode */ - if (gpd->flag & GP_DATA_STROKE_EDITMODE) { - const char *printable = IFACE_("GPencil Stroke Editing"); - float printable_size[2]; - - int font_id = BLF_default(); - - BLF_width_and_height( - font_id, printable, BLF_DRAW_STR_DUMMY_MAX, &printable_size[0], &printable_size[1]); - - int xco = (rect->xmax - U.widget_unit) - (int)printable_size[0]; - int yco = (rect->ymax - U.widget_unit); - - /* text label */ - UI_FontThemeColor(font_id, TH_TEXT_HI); -#ifdef WITH_INTERNATIONAL - BLF_draw_default(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); -#else - BLF_draw_default_ascii(xco, yco, 0.0f, printable, BLF_DRAW_STR_DUMMY_MAX); -#endif - - /* grease pencil icon... */ - // XXX: is this too intrusive? - GPU_blend_set_func_separate( - GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); - GPU_blend(true); - - xco -= U.widget_unit; - yco -= (int)printable_size[1] / 2; - - UI_icon_draw(xco, yco, ICON_GREASEPENCIL); - - GPU_blend(false); - } -} - /* draw grease-pencil datablock */ static void annotation_draw_data( - bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag, float alpha) + bGPdata *gpd, int offsx, int offsy, int winx, int winy, int cfra, int dflag) { /* turn on smooth lines (i.e. anti-aliasing) */ GPU_line_smooth(true); @@ -864,7 +731,7 @@ static void annotation_draw_data( GPU_blend(true); /* draw! */ - annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha); + annotation_draw_data_layers(gpd, offsx, offsy, winx, winy, cfra, dflag); /* turn off alpha blending, then smooth lines */ GPU_blend(false); // alpha blending @@ -884,7 +751,6 @@ static void annotation_draw_data_all(Scene *scene, const char spacetype) { bGPdata *gpd_source = NULL; - float alpha = 1.0f; if (scene) { if (spacetype == SPACE_VIEW3D) { @@ -897,14 +763,14 @@ static void annotation_draw_data_all(Scene *scene, } if (gpd_source) { - annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag, alpha); + annotation_draw_data(gpd_source, offsx, offsy, winx, winy, cfra, dflag); } } /* scene/clip data has already been drawn, only object/track data is drawn here * if gpd_source == gpd, we don't have any object/track data and we can skip */ if (gpd_source == NULL || (gpd_source && gpd_source != gpd)) { - annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag, alpha); + annotation_draw_data(gpd, offsx, offsy, winx, winy, cfra, dflag); } } @@ -1026,11 +892,6 @@ void ED_annotation_draw_view2d(const bContext *C, bool onlyv2d) annotation_draw_data_all( scene, gpd, 0, 0, region->winx, region->winy, CFRA, dflag, area->spacetype); - - /* draw status text (if in screen/pixel-space) */ - if (!onlyv2d) { - annotation_draw_status_text(gpd, region); - } } /* draw annotations sketches to specified 3d-view assuming that matrices are already set diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c index 8d50e24b7f0..c53b90fbfee 100644 --- a/source/blender/editors/gpencil/annotate_paint.c +++ b/source/blender/editors/gpencil/annotate_paint.c @@ -100,6 +100,9 @@ typedef enum eGPencil_PaintFlags { GP_PAINTFLAG_STROKEADDED = (1 << 1), GP_PAINTFLAG_V3D_ERASER_DEPTH = (1 << 2), GP_PAINTFLAG_SELECTMASK = (1 << 3), + /* Flags used to indicate if stabilization is being used. */ + GP_PAINTFLAG_USE_STABILIZER = (1 << 7), + GP_PAINTFLAG_USE_STABILIZER_TEMP = (1 << 8), } eGPencil_PaintFlags; /* Temporary 'Stroke' Operation data @@ -148,6 +151,11 @@ typedef struct tGPsdata { /** radius of influence for eraser. */ short radius; + /* Stabilizer. */ + float stabilizer_factor; + char stabilizer_radius; + void *stabilizer_cursor; + /** current mouse-position. */ float mval[2]; /** previous recorded mouse-position. */ @@ -278,6 +286,18 @@ static bool gp_stroke_filtermval(tGPsdata *p, const float mval[2], float pmval[2 * - aims to eliminate some jitter-noise from input when trying to draw straight lines freehand */ } + /* If lazy mouse, check minimum distance. */ + else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + if ((dx * dx + dy * dy) > (p->stabilizer_radius * p->stabilizer_radius)) { + return true; + } + else { + /* If the mouse is moving within the radius of the last move, + * don't update the mouse position. This allows sharp turns. */ + copy_v2_v2(p->mval, p->mvalo); + return false; + } + } else if ((dx > MIN_MANHATTEN_PX) && (dy > MIN_MANHATTEN_PX)) { return true; @@ -418,6 +438,85 @@ static void gp_smooth_buffer(tGPsdata *p, float inf, int idx) copy_v2_v2(&ptc->x, c); } +static void gp_stroke_arrow_calc_points_segment(float stroke_points[8], + const float ref_point[2], + const float dir_cw[2], + const float dir_ccw[2], + const float lenght, + const float sign) +{ + stroke_points[0] = ref_point[0] + dir_cw[0] * lenght * sign; + stroke_points[1] = ref_point[1] + dir_cw[1] * lenght * sign; + stroke_points[2] = ref_point[0] + dir_ccw[0] * lenght * sign; + stroke_points[3] = ref_point[1] + dir_ccw[1] * lenght * sign; +} + +static void gp_stroke_arrow_calc_points(tGPspoint *point, + const float stroke_dir[2], + float corner[2], + float stroke_points[8], + const int arrow_style) +{ + const int arrow_lenght = 8; + float norm_dir[2]; + copy_v2_v2(norm_dir, stroke_dir); + normalize_v2(norm_dir); + const float inv_norm_dir_clockwise[2] = {norm_dir[1], -norm_dir[0]}; + const float inv_norm_dir_counterclockwise[2] = {-norm_dir[1], norm_dir[0]}; + + switch (arrow_style) { + case GP_STROKE_ARROWSTYLE_OPEN: + mul_v2_fl(norm_dir, arrow_lenght); + stroke_points[0] = corner[0] + inv_norm_dir_clockwise[0] * arrow_lenght + norm_dir[0]; + stroke_points[1] = corner[1] + inv_norm_dir_clockwise[1] * arrow_lenght + norm_dir[1]; + stroke_points[2] = corner[0] + inv_norm_dir_counterclockwise[0] * arrow_lenght + norm_dir[0]; + stroke_points[3] = corner[1] + inv_norm_dir_counterclockwise[1] * arrow_lenght + norm_dir[1]; + break; + case GP_STROKE_ARROWSTYLE_SEGMENT: + gp_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght, + 1.0f); + break; + case GP_STROKE_ARROWSTYLE_CLOSED: + mul_v2_fl(norm_dir, arrow_lenght); + if (point != NULL) { + add_v2_v2(&point->x, norm_dir); + copy_v2_v2(corner, &point->x); + } + gp_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght, + -1.0f); + stroke_points[4] = corner[0] - norm_dir[0]; + stroke_points[5] = corner[1] - norm_dir[1]; + break; + case GP_STROKE_ARROWSTYLE_SQUARE: + mul_v2_fl(norm_dir, arrow_lenght * 1.5f); + if (point != NULL) { + add_v2_v2(&point->x, norm_dir); + copy_v2_v2(corner, &point->x); + } + gp_stroke_arrow_calc_points_segment(stroke_points, + corner, + inv_norm_dir_clockwise, + inv_norm_dir_counterclockwise, + arrow_lenght * 0.75f, + -1.0f); + stroke_points[4] = stroke_points[0] - norm_dir[0]; + stroke_points[5] = stroke_points[1] - norm_dir[1]; + stroke_points[6] = stroke_points[2] - norm_dir[0]; + stroke_points[7] = stroke_points[3] - norm_dir[1]; + break; + default: + break; + } +} + /* add current stroke-point to buffer (returns whether point was successfully added) */ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime) { @@ -457,6 +556,32 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* now the buffer has 2 points (and shouldn't be allowed to get any larger) */ gpd->runtime.sbuffer_used = 2; + + /* Arrows. */ + if (gpd->runtime.sbuffer_sflag & (GP_STROKE_USE_ARROW_START | GP_STROKE_USE_ARROW_END)) { + /* Store start and end point coords for arrows. */ + float end[2]; + copy_v2_v2(end, &pt->x); + pt = ((tGPspoint *)(gpd->runtime.sbuffer)); + float start[2]; + copy_v2_v2(start, &pt->x); + + /* Arrow end corner. */ + if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) { + pt++; + float e_heading[2] = {start[0] - end[0], start[1] - end[1]}; + /* Calculate points for ending arrow. */ + gp_stroke_arrow_calc_points( + pt, e_heading, end, gpd->runtime.arrow_end, gpd->runtime.arrow_end_style); + } + /* Arrow start corner. */ + if (gpd->runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) { + float s_heading[2] = {end[0] - start[0], end[1] - start[1]}; + /* Calculate points for starting arrow. */ + gp_stroke_arrow_calc_points( + NULL, s_heading, start, gpd->runtime.arrow_start, gpd->runtime.arrow_start_style); + } + } } /* can keep carrying on this way :) */ @@ -481,16 +606,20 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure /* increment counters */ gpd->runtime.sbuffer_used++; - /* smooth while drawing previous points with a reduction factor for previous */ - for (int s = 0; s < 3; s++) { - gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); + + /* Don't smooth if stabilizer is on. */ + if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { + /* smooth while drawing previous points with a reduction factor for previous */ + for (int s = 0; s < 3; s++) { + gp_smooth_buffer(p, 0.5f * ((3.0f - s) / 3.0f), gpd->runtime.sbuffer_used - s); + } } return GP_STROKEADD_NORMAL; } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { /* get pointer to destination point */ - pt = (tGPspoint *)(gpd->runtime.sbuffer); + pt = (tGPspoint *)gpd->runtime.sbuffer; /* store settings */ copy_v2_v2(&pt->x, mval); @@ -552,6 +681,123 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure return GP_STROKEADD_INVALID; } +static void gp_stroke_arrow_init_point_default(bGPDspoint *pt) +{ + pt->pressure = 1.0f; + pt->strength = 1.0f; + pt->time = 1.0f; +} + +static void gp_stroke_arrow_init_conv_point(bGPDspoint *pt, const float point[3]) +{ + copy_v3_v3(&pt->x, point); + gp_stroke_arrow_init_point_default(pt); +} + +static void gp_stroke_arrow_init_point( + tGPsdata *p, tGPspoint *ptc, bGPDspoint *pt, const float co[8], const int co_idx) +{ + /* Note: provided co_idx should be always pair number as it's [x1, y1, x2, y2, x3, y3]. */ + float real_co[2] = {co[co_idx], co[co_idx + 1]}; + copy_v2_v2(&ptc->x, real_co); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gp_stroke_arrow_init_point_default(pt); +} + +static void gp_stroke_arrow_allocate(bGPDstroke *gps, const int totpoints) +{ + /* Copy appropriate settings for stroke. */ + gps->totpoints = totpoints; + /* Allocate enough memory for a continuous array for storage points. */ + gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); +} + +static void gp_arrow_create_open(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float corner_point[3], + const float arrow_points[8]) +{ + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_conv_point(pt, corner_point); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); +} + +static void gp_arrow_create_segm(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float arrow_points[8]) +{ + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); +} + +static void gp_arrow_create_closed(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float arrow_points[8]) +{ + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); +} + +static void gp_arrow_create_square(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + const float corner_point[3], + const float arrow_points[8]) +{ + gp_stroke_arrow_init_conv_point(pt, corner_point); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 0); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 4); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 6); + pt++; + gp_stroke_arrow_init_point(p, ptc, pt, arrow_points, 2); + pt++; + gp_stroke_arrow_init_conv_point(pt, corner_point); +} + +static void gp_arrow_create(tGPsdata *p, + tGPspoint *ptc, + bGPDspoint *pt, + bGPDstroke *arrow_stroke, + const float arrow_points[8], + const int style) +{ + float corner_conv[3]; + copy_v3_v3(corner_conv, &pt->x); + + switch (style) { + case GP_STROKE_ARROWSTYLE_SEGMENT: + gp_arrow_create_segm(p, ptc, pt, arrow_points); + break; + case GP_STROKE_ARROWSTYLE_CLOSED: + gp_arrow_create_closed(p, ptc, pt, arrow_points); + break; + case GP_STROKE_ARROWSTYLE_OPEN: + gp_arrow_create_open(p, ptc, pt, corner_conv, arrow_points); + break; + case GP_STROKE_ARROWSTYLE_SQUARE: + gp_arrow_create_square(p, ptc, pt, corner_conv, arrow_points); + break; + default: + break; + } + /* Link stroke to frame. */ + BLI_addtail(&p->gpf->strokes, arrow_stroke); +} + /* make a new stroke from the buffer data */ static void gp_stroke_newfrombuffer(tGPsdata *p) { @@ -637,17 +883,61 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) } if (totelem == 2) { - /* last point if applicable */ - ptc = ((tGPspoint *)gpd->runtime.sbuffer) + (gpd->runtime.sbuffer_used - 1); + bGPdata_Runtime runtime = gpd->runtime; - /* convert screen-coordinates to appropriate coordinates (and store them) */ + /* Last point if applicable. */ + ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1); + + /* Convert screen-coordinates to appropriate coordinates (and store them). */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure and time */ + /* Copy pressure and time. */ pt->pressure = ptc->pressure; pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = ptc->time; + + /** Create arrow strokes. **/ + /* End arrow stroke. */ + if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_END) && + (runtime.arrow_end_style != GP_STROKE_ARROWSTYLE_NONE)) { + int totarrowpoints = runtime.arrow_end_style; + + /* Setting up arrow stroke. */ + bGPDstroke *e_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false); + gp_stroke_arrow_allocate(e_arrow_gps, totarrowpoints); + + /* Set pointer to first non-initialized point. */ + pt = e_arrow_gps->points + (e_arrow_gps->totpoints - totarrowpoints); + + /* End point. */ + ptc = ((tGPspoint *)runtime.sbuffer) + (runtime.sbuffer_used - 1); + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gp_stroke_arrow_init_point_default(pt); + + /* Fill and convert arrow points to create arrow shape. */ + gp_arrow_create(p, ptc, pt, e_arrow_gps, runtime.arrow_end, runtime.arrow_end_style); + } + /* Start arrow stroke. */ + if ((runtime.sbuffer_sflag & GP_STROKE_USE_ARROW_START) && + (runtime.arrow_start_style != GP_STROKE_ARROWSTYLE_NONE)) { + int totarrowpoints = runtime.arrow_start_style; + + /* Setting up arrow stroke. */ + bGPDstroke *s_arrow_gps = BKE_gpencil_stroke_duplicate(gps, false); + gp_stroke_arrow_allocate(s_arrow_gps, totarrowpoints); + + /* Set pointer to first non-initialized point. */ + pt = s_arrow_gps->points + (s_arrow_gps->totpoints - totarrowpoints); + + /* Start point. */ + ptc = runtime.sbuffer; + gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); + gp_stroke_arrow_init_point_default(pt); + + /* Fill and convert arrow points to create arrow shape. */ + gp_arrow_create(p, ptc, pt, s_arrow_gps, runtime.arrow_start, runtime.arrow_start_style); + } } } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -1456,6 +1746,67 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en p); } } +static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr) +{ + ARegion *region = CTX_wm_region(C); + tGPsdata *p = (tGPsdata *)p_ptr; + bGPdata_Runtime runtime = p->gpd->runtime; + const tGPspoint *points = runtime.sbuffer; + int totpoints = runtime.sbuffer_used; + if (totpoints < 2) { + return; + } + const tGPspoint *pt = &points[totpoints - 1]; + + GPUVertFormat *format = immVertexFormat(); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR); + GPU_line_smooth(true); + GPU_blend(true); + GPU_line_width(1.25f); + const float color[3] = {1.0f, 0.39f, 0.39f}; + + /* default radius and color */ + float darkcolor[3]; + const float radius = 4.0f; + + /* Inner Ring: Color from UI panel */ + immUniformColor4f(color[0], color[1], color[2], 0.8f); + imm_draw_circle_wire_2d(pos, x, y, radius, 40); + + /* Outer Ring: Dark color for contrast on light backgrounds (e.g. gray on white) */ + mul_v3_v3fl(darkcolor, color, 0.40f); + immUniformColor4f(darkcolor[0], darkcolor[1], darkcolor[2], 0.8f); + imm_draw_circle_wire_2d(pos, x, y, radius + 1, 40); + + /* Rope Simple. */ + immUniformColor4f(color[0], color[1], color[2], 0.8f); + immBegin(GPU_PRIM_LINES, 2); + immVertex2f(pos, pt->x + region->winrct.xmin, pt->y + region->winrct.ymin); + immVertex2f(pos, x, y); + immEnd(); + + /* Returns back all GPU settings */ + GPU_blend(false); + GPU_line_smooth(false); + + immUnbindProgram(); +} + +/* Turn *stabilizer* brush cursor in 3D view on/off */ +static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable) +{ + if (p->stabilizer_cursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor); + p->stabilizer_cursor = NULL; + } + else if (enable && !p->stabilizer_cursor) { + /* enable cursor */ + p->stabilizer_cursor = WM_paint_cursor_activate( + CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p); + } +} /* Check if tablet eraser is being used (when processing events) */ static bool gpencil_is_tablet_eraser_active(const wmEvent *event) @@ -1479,6 +1830,9 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op) /* turn off radial brush cursor */ gpencil_draw_toggle_eraser_cursor(C, p, false); } + else if (p->paintmode == GP_PAINTMODE_DRAW) { + gpencil_draw_toggle_stabilizer_cursor(C, p, false); + } /* always store the new eraser size to be used again next time * NOTE: Do this even when not in eraser mode, as eraser may @@ -1566,8 +1920,8 @@ static void gpencil_draw_status_indicators(bContext *C, tGPsdata *p) "ESC/Enter to end (or click outside this area)")); break; default: - /* Do nothing - the others are self explanatory, exit quickly once the mouse is released - * Showing any text would just be annoying as it would flicker. + /* Do nothing - the others are self explanatory, exit quickly once the mouse is + * released Showing any text would just be annoying as it would flicker. */ break; } @@ -1632,6 +1986,16 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph /* Only add current point to buffer if mouse moved * (even though we got an event, it might be just noise). */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { + /* If lazy mouse, interpolate the last and current mouse positions. */ + if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + float now_mouse[2]; + float last_mouse[2]; + copy_v2_v2(now_mouse, p->mval); + copy_v2_v2(last_mouse, p->mvalo); + interp_v2_v2v2(now_mouse, now_mouse, last_mouse, min_ff(p->stabilizer_factor, .995f)); + copy_v2_v2(p->mval, now_mouse); + } + /* try to add point */ short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); @@ -1675,7 +2039,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph /* handle draw event */ static void annotation_draw_apply_event( - wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) + bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y) { tGPsdata *p = op->customdata; PointerRNA itemptr; @@ -1687,8 +2051,23 @@ static void annotation_draw_apply_event( p->mval[0] = (float)event->mval[0] - x; p->mval[1] = (float)event->mval[1] - y; + /* Key to toggle stabilization. */ + if (event->shift > 0 && p->paintmode == GP_PAINTMODE_DRAW) { + /* Using permanent stabilization, shift will deactivate the flag. */ + if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) { + if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + gpencil_draw_toggle_stabilizer_cursor(C, p, false); + p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; + } + } + /* Not using any stabilization flag. Activate temporal one. */ + else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { + p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + } + } /* verify key status for straight lines */ - if ((event->ctrl > 0) || (event->alt > 0)) { + else if ((event->ctrl > 0) || (event->alt > 0)) { if (p->straight[0] == 0) { int dx = abs((int)(p->mval[0] - p->mvalo[0])); int dy = abs((int)(p->mval[1] - p->mvalo[1])); @@ -1709,6 +2088,22 @@ static void annotation_draw_apply_event( } else { p->straight[0] = 0; + /* We were using shift while having permanent stabilization actived, + so activate the temp flag back again. */ + if (p->flags & GP_PAINTFLAG_USE_STABILIZER) { + if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) { + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; + } + } + /* We are using the temporal stabilizer flag atm, + but shift is not pressed as well as the permanent flag is not used, + so we don't need the cursor anymore. */ + else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) { + /* Reset temporal stabilizer flag and remove cursor. */ + p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, false); + } } p->curtime = PIL_check_seconds_timer(); @@ -1896,12 +2291,35 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event /* TODO: set any additional settings that we can take from the events? * TODO? if tablet is erasing, force eraser to be on? */ - /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... */ + /* TODO: move cursor setting stuff to stroke-start so that paintmode can be changed midway... + */ /* if eraser is on, draw radial aid */ if (p->paintmode == GP_PAINTMODE_ERASER) { gpencil_draw_toggle_eraser_cursor(C, p, true); } + else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) { + if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) { + p->gpd->runtime.sbuffer_sflag |= GP_STROKE_USE_ARROW_START; + p->gpd->runtime.arrow_start_style = RNA_enum_get(op->ptr, "arrowstyle_start"); + } + if (RNA_enum_get(op->ptr, "arrowstyle_end") != GP_STROKE_ARROWSTYLE_NONE) { + p->gpd->runtime.sbuffer_sflag |= GP_STROKE_USE_ARROW_END; + p->gpd->runtime.arrow_end_style = RNA_enum_get(op->ptr, "arrowstyle_end"); + } + } + else if (p->paintmode == GP_PAINTMODE_DRAW) { + p->stabilizer_factor = RNA_float_get(op->ptr, "stabilizer_factor"); + p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius"); + if (RNA_boolean_get(op->ptr, "use_stabilizer")) { + p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + } + else if (event->shift > 0) { + p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP; + gpencil_draw_toggle_stabilizer_cursor(C, p, true); + } + } /* set cursor * NOTE: This may change later (i.e. intentionally via brush toggle, * or unintentionally if the user scrolls outside the area)... @@ -1915,7 +2333,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ - annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); op->flag |= OP_IS_MODAL_CURSOR_REGION; } else { @@ -2007,7 +2425,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, 0.5f); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); } else if (dist >= factor) { int slices = 2 + (int)((dist - 1.0) / factor); @@ -2016,7 +2434,7 @@ static void annotation_add_missing_events(bContext *C, interp_v2_v2v2(pt, a, b, n * i); sub_v2_v2v2(pt, b, pt); /* create fake event */ - annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]); + annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]); } } } @@ -2106,7 +2524,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* toggle painting mode upon mouse-button movement - * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox only) + * - LEFTMOUSE = standard drawing (all) / straight line drawing (all) / polyline (toolbox + * only) * - RIGHTMOUSE = polyline (hotkey) / eraser (all) * (Disabling RIGHTMOUSE case here results in bugs like [#32647]) * also making sure we have a valid event value, to not exit too early @@ -2262,7 +2681,8 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* TODO(sergey): Possibly evaluating dependency graph from modal operator? */ - annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); + annotation_draw_apply_event( + C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f); /* finish painting operation if anything went wrong just now */ if (p->status == GP_STATUS_ERROR) { @@ -2370,6 +2790,19 @@ static const EnumPropertyItem prop_gpencil_drawmodes[] = { {0, NULL, 0, NULL, NULL}, }; +static const EnumPropertyItem arrow_types[] = { + {GP_STROKE_ARROWSTYLE_NONE, "NONE", 0, "None", "Don't use any arrow/style in corner"}, + {GP_STROKE_ARROWSTYLE_CLOSED, "ARROW", 0, "Arrow", "Use closed arrow style"}, + {GP_STROKE_ARROWSTYLE_OPEN, "ARROW_OPEN", 0, "Open Arrow", "Use open arrow style"}, + {GP_STROKE_ARROWSTYLE_SEGMENT, + "ARROW_OPEN_INVERTED", + 0, + "Segment", + "Use perpendicular segment style"}, + {GP_STROKE_ARROWSTYLE_SQUARE, "DIAMOND", 0, "Square", "Use square style"}, + {0, NULL, 0, NULL, NULL}, +}; + void GPENCIL_OT_annotate(wmOperatorType *ot) { PropertyRNA *prop; @@ -2393,6 +2826,37 @@ void GPENCIL_OT_annotate(wmOperatorType *ot) ot->prop = RNA_def_enum( ot->srna, "mode", prop_gpencil_drawmodes, 0, "Mode", "Way to interpret mouse movements"); + /* properties */ + prop = RNA_def_enum( + ot->srna, "arrowstyle_start", arrow_types, 0, "Start Arrow Style", "Stroke start style"); + prop = RNA_def_enum( + ot->srna, "arrowstyle_end", arrow_types, 0, "End Arrow Style", "Stroke end style"); + prop = RNA_def_boolean(ot->srna, + "use_stabilizer", + false, + "Stabilize Stroke", + "Helper to draw smooth and clean lines. Press Shift for an invert effect " + "(even if this option is not active)"); + prop = RNA_def_float(ot->srna, + "stabilizer_factor", + 0.75f, + 0.0f, + 1.0f, + "Stabilizer Stroke Factor", + "Higher values gives a smoother stroke", + 0.0f, + 1.0f); + prop = RNA_def_int(ot->srna, + "stabilizer_radius", + 35, + 0, + 200, + "Stabilizer Stroke Radius", + "Minimun distance from last point before stroke continues", + 1, + 100); + RNA_def_property_subtype(prop, PROP_PIXEL); + prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); diff --git a/source/blender/editors/gpencil/gpencil_armature.c b/source/blender/editors/gpencil/gpencil_armature.c index ab8b1a9719b..962a74d9e6f 100644 --- a/source/blender/editors/gpencil/gpencil_armature.c +++ b/source/blender/editors/gpencil/gpencil_armature.c @@ -491,7 +491,7 @@ bool ED_gpencil_add_armature(const bContext *C, ReportList *reports, Object *ob, } /* if no armature modifier, add a new one */ - GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Armature); + GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Armature); if (md == NULL) { md = ED_object_gpencil_modifier_add( reports, bmain, scene, ob, "Armature", eGpencilModifierType_Armature); @@ -590,8 +590,8 @@ static int gpencil_generate_weights_exec(bContext *C, wmOperator *op) } else { /* get armature from modifier */ - GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob_eval, - eGpencilModifierType_Armature); + GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob_eval, + eGpencilModifierType_Armature); if (md == NULL) { BKE_report(op->reports, RPT_ERROR, "The grease pencil object need an Armature modifier"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/gpencil/gpencil_convert.c b/source/blender/editors/gpencil/gpencil_convert.c index e89903adf5f..5441d4e24a6 100644 --- a/source/blender/editors/gpencil/gpencil_convert.c +++ b/source/blender/editors/gpencil/gpencil_convert.c @@ -162,7 +162,7 @@ static void gp_strokepoint_convertcoords(bContext *C, View3D *v3d = CTX_wm_view3d(C); ARegion *region = CTX_wm_region(C); /* TODO(sergey): This function might be called from a loop, but no tagging is happening in it, - * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the + * so it's not that expensive to ensure evaluated depsgraph here. However, ideally all the * parameters are to wrapped into a context style struct and queried from Context once.*/ Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Object *obact = CTX_data_active_object(C); diff --git a/source/blender/editors/gpencil/gpencil_data.c b/source/blender/editors/gpencil/gpencil_data.c index c05162510d7..a7e7246ee82 100644 --- a/source/blender/editors/gpencil/gpencil_data.c +++ b/source/blender/editors/gpencil/gpencil_data.c @@ -55,7 +55,7 @@ #include "BKE_brush.h" #include "BKE_context.h" #include "BKE_deform.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" #include "BKE_lib_id.h" @@ -2619,7 +2619,7 @@ int ED_gpencil_join_objects_exec(bContext *C, wmOperator *op) /* Apply all GP modifiers before */ LISTBASE_FOREACH (GpencilModifierData *, md, &ob_iter->greasepencil_modifiers) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->bakeModifier) { mti->bakeModifier(bmain, depsgraph, md, ob_iter); } @@ -3193,7 +3193,7 @@ void GPENCIL_OT_material_unlock_all(wmOperatorType *ot) /* ***************** Select all strokes using color ************************ */ -static int gpencil_select_material_exec(bContext *C, wmOperator *op) +static int gpencil_material_select_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); Object *ob = CTX_data_active_object(C); @@ -3263,15 +3263,15 @@ static int gpencil_select_material_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void GPENCIL_OT_select_material(wmOperatorType *ot) +void GPENCIL_OT_material_select(wmOperatorType *ot) { /* identifiers */ ot->name = "Select Material"; - ot->idname = "GPENCIL_OT_select_material"; + ot->idname = "GPENCIL_OT_material_select"; ot->description = "Select/Deselect all Grease Pencil strokes using current material"; /* callbacks */ - ot->exec = gpencil_select_material_exec; + ot->exec = gpencil_material_select_exec; ot->poll = gpencil_active_material_poll; /* flags */ @@ -3282,6 +3282,48 @@ void GPENCIL_OT_select_material(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/* ***************** Set active material ************************* */ +static int gpencil_material_set_exec(bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + int slot = RNA_enum_get(op->ptr, "slot"); + + /* Try to get material */ + if ((slot < 1) || (slot > ob->totcol)) { + BKE_reportf( + op->reports, RPT_ERROR, "Cannot change to non-existent material (index = %d)", slot); + return OPERATOR_CANCELLED; + } + + /* Set active material. */ + ob->actcol = slot; + + /* updates */ + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_EDITED, NULL); + WM_event_add_notifier(C, NC_GPENCIL | ND_DATA | NA_SELECTED, NULL); + + return OPERATOR_FINISHED; +} + +void GPENCIL_OT_material_set(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Set Material"; + ot->idname = "GPENCIL_OT_material_set"; + ot->description = "Set active material"; + + /* callbacks */ + ot->exec = gpencil_material_set_exec; + ot->poll = gpencil_active_material_poll; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* Material to use (dynamic enum) */ + ot->prop = RNA_def_enum(ot->srna, "slot", DummyRNA_DEFAULT_items, 0, "Material Slot", ""); + RNA_def_enum_funcs(ot->prop, ED_gpencil_material_enum_itemf); +} + /* ***************** Set selected stroke material the active material ************************ */ static int gpencil_set_active_material_exec(bContext *C, wmOperator *op) @@ -3344,7 +3386,7 @@ bool ED_gpencil_add_lattice_modifier(const bContext *C, } /* if no lattice modifier, add a new one */ - GpencilModifierData *md = BKE_gpencil_modifiers_findByType(ob, eGpencilModifierType_Lattice); + GpencilModifierData *md = BKE_gpencil_modifiers_findby_type(ob, eGpencilModifierType_Lattice); if (md == NULL) { md = ED_object_gpencil_modifier_add( reports, bmain, scene, ob, "Lattice", eGpencilModifierType_Lattice); diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 77e45642939..2d53679b61a 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -90,8 +90,9 @@ #include "gpencil_intern.h" -/* ************************************************ */ -/* Stroke Edit Mode Management */ +/* -------------------------------------------------------------------- */ +/** \name Stroke Edit Mode Management + * \{ */ /* poll callback for all stroke editing operators */ static bool gp_stroke_edit_poll(bContext *C) @@ -138,6 +139,12 @@ static bool gpencil_editmode_toggle_poll(bContext *C) return ED_gpencil_data_get_active(C) != NULL; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Edit Mode Operator + * \{ */ + static int gpencil_editmode_toggle_exec(bContext *C, wmOperator *op) { const int back = RNA_boolean_get(op->ptr, "back"); @@ -223,6 +230,12 @@ void GPENCIL_OT_editmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Select Mode Operator + * \{ */ + /* set select mode */ static bool gpencil_selectmode_toggle_poll(bContext *C) { @@ -298,7 +311,11 @@ void GPENCIL_OT_selectmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* Stroke Paint Mode Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Stroke Paint Mode Operator + * \{ */ static bool gpencil_paintmode_toggle_poll(bContext *C) { @@ -402,7 +419,11 @@ void GPENCIL_OT_paintmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* Stroke Sculpt Mode Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Stroke Sculpt Mode Operator + * \{ */ static bool gpencil_sculptmode_toggle_poll(bContext *C) { @@ -479,6 +500,12 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Weight Paint Mode Operator + * \{ */ + void GPENCIL_OT_sculptmode_toggle(wmOperatorType *ot) { PropertyRNA *prop; @@ -600,7 +627,11 @@ void GPENCIL_OT_weightmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* Vertex Paint Mode Management */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Vertex Paint Mode Operator + * \{ */ static bool gpencil_vertexmode_toggle_poll(bContext *C) { @@ -698,10 +729,11 @@ void GPENCIL_OT_vertexmode_toggle(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* ************************************************ */ -/* Stroke Editing Operators */ +/** \} */ -/* ************ Stroke Hide selection Toggle ************** */ +/* -------------------------------------------------------------------- */ +/** \name Stroke Hide Selection Toggle Operator + * \{ */ static int gpencil_hideselect_toggle_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -740,7 +772,11 @@ void GPENCIL_OT_selection_opacity_toggle(wmOperatorType *ot) ot->flag = OPTYPE_UNDO | OPTYPE_REGISTER; } -/* ************** Duplicate Selected Strokes **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Duplicate Selected Strokes Operator + * \{ */ /* Make copies of selected point segments in a selected stroke */ static void gp_duplicate_points(const bGPDstroke *gps, @@ -917,7 +953,11 @@ void GPENCIL_OT_duplicate(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ************** Extrude Selected Strokes **************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Extrude Selected Strokes Operator + * \{ */ /* helper to copy a point to temp area */ static void copy_move_point(bGPDstroke *gps, @@ -1138,14 +1178,18 @@ void GPENCIL_OT_extrude(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* Copy/Paste Strokes ************************* */ -/* Grease Pencil stroke data copy/paste buffer: +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy/Paste Strokes Utilities + * + * Grease Pencil stroke data copy/paste buffer: * - The copy operation collects all segments of selected strokes, * dumping "ready to be copied" copies of the strokes into the buffer. * - The paste operation makes a copy of those elements, and adds them * to the active layer. This effectively flattens down the strokes * from several different layers into a single layer. - */ + * \{ */ /* list of bGPDstroke instances */ /* NOTE: is exposed within the editors/gpencil module so that other tools can use it too */ @@ -1257,8 +1301,11 @@ GHash *gp_copybuf_validate_colormap(bContext *C) return new_colors; } -/* --------------------- */ -/* Copy selected strokes */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Copy Selected Strokes Operator + * \{ */ static int gp_strokes_copy_exec(bContext *C, wmOperator *op) { @@ -1375,8 +1422,11 @@ void GPENCIL_OT_copy(wmOperatorType *ot) // ot->flag = OPTYPE_REGISTER; } -/* --------------------- */ -/* Paste selected strokes */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Paste Selected Strokes Operator + * \{ */ static bool gp_strokes_paste_poll(bContext *C) { @@ -1547,7 +1597,11 @@ void GPENCIL_OT_paste(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Move To Layer ****************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Move To Layer Operator + * \{ */ static int gp_move_to_layer_exec(bContext *C, wmOperator *op) { @@ -1667,7 +1721,11 @@ void GPENCIL_OT_move_to_layer(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_HIDDEN | PROP_SKIP_SAVE); } -/* ********************* Add Blank Frame *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Add Blank Frame Operator + * \{ */ static int gp_blank_frame_add_exec(bContext *C, wmOperator *op) { @@ -1741,7 +1799,11 @@ void GPENCIL_OT_blank_frame_add(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Delete Active Frame ************************ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Active Frame Operator + * \{ */ static bool gp_actframe_delete_poll(bContext *C) { @@ -1822,7 +1884,12 @@ void GPENCIL_OT_annotation_active_frame_delete(wmOperatorType *ot) ot->exec = gp_actframe_delete_exec; ot->poll = gp_annotation_actframe_delete_poll; } -/* **************** Delete All Active Frames ****************** */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete All Active Frames + * \{ */ static bool gp_actframe_delete_all_poll(bContext *C) { @@ -1883,7 +1950,11 @@ void GPENCIL_OT_active_frames_delete_all(wmOperatorType *ot) ot->poll = gp_actframe_delete_all_poll; } -/* ******************* Delete Operator ************************ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete/Dissolve Utilities + * \{ */ typedef enum eGP_DeleteMode { /* delete selected stroke points */ @@ -1903,8 +1974,6 @@ typedef enum eGP_DissolveMode { GP_DISSOLVE_UNSELECT = 2, } eGP_DissolveMode; -/* ----------------------------------- */ - /* Delete selected strokes */ static int gp_delete_selected_strokes(bContext *C) { @@ -2498,7 +2567,11 @@ int gp_delete_selected_point_wrap(bContext *C) return gp_delete_selected_points(C); } -/* ----------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Operator + * \{ */ static int gp_delete_exec(bContext *C, wmOperator *op) { @@ -2557,6 +2630,12 @@ void GPENCIL_OT_delete(wmOperatorType *ot) "Method used for deleting Grease Pencil data"); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Dissolve Operator + * \{ */ + static int gp_dissolve_exec(bContext *C, wmOperator *op) { eGP_DissolveMode mode = RNA_enum_get(op->ptr, "type"); @@ -2599,7 +2678,11 @@ void GPENCIL_OT_dissolve(wmOperatorType *ot) "Method used for dissolving Stroke points"); } -/* ****************** Snapping - Strokes <-> Cursor ************************ */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snapping Selection to Grid Operator + * \{ */ /* Poll callback for snap operators */ /* NOTE: For now, we only allow these in the 3D view, as other editors do not @@ -2614,8 +2697,6 @@ static bool gp_snap_poll(bContext *C) ((area != NULL) && (area->spacetype == SPACE_VIEW3D)); } -/* --------------------------------- */ - static int gp_snap_to_grid(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -2690,7 +2771,11 @@ void GPENCIL_OT_snap_to_grid(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snapping Selection to Cursor Operator + * \{ */ static int gp_snap_to_cursor(bContext *C, wmOperator *op) { @@ -2782,7 +2867,11 @@ void GPENCIL_OT_snap_to_cursor(wmOperatorType *ot) "Offset the entire stroke instead of selected points only"); } -/* ------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Snapping Cursor to Selection Operator + * \{ */ static int gp_snap_cursor_to_sel(bContext *C, wmOperator *UNUSED(op)) { @@ -2873,7 +2962,11 @@ void GPENCIL_OT_snap_cursor_to_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* Apply layer thickness change to strokes ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Apply Layer Thickness Change to Strokes Operator + * \{ */ static int gp_stroke_apply_thickness_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2920,7 +3013,11 @@ void GPENCIL_OT_stroke_apply_thickness(wmOperatorType *ot) ot->poll = gp_active_layer_poll; } -/* ******************* Close Strokes ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Toggle Cyclic Operator + * \{ */ enum { GP_STROKE_CYCLIC_CLOSE = 1, @@ -3040,7 +3137,11 @@ void GPENCIL_OT_stroke_cyclical_set(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Flat Stroke Caps ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Toggle Flat Caps Operator + * \{ */ enum { GP_STROKE_CAPS_TOGGLE_BOTH = 0, @@ -3136,7 +3237,11 @@ void GPENCIL_OT_stroke_caps_set(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", toggle_type, GP_STROKE_CAPS_TOGGLE_BOTH, "Type", ""); } -/* ******************* Stroke join ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Join Operator + * \{ */ /* Helper: flip stroke */ static void gpencil_flip_stroke(bGPDstroke *gps) @@ -3186,8 +3291,8 @@ static void gpencil_flip_stroke(bGPDstroke *gps) /* Helper: copy point between strokes */ static void gpencil_stroke_copy_point(bGPDstroke *gps, + MDeformVert *dvert, bGPDspoint *point, - int idx, const float delta[3], float pressure, float strength, @@ -3199,6 +3304,13 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, if (gps->dvert != NULL) { gps->dvert = MEM_reallocN(gps->dvert, sizeof(MDeformVert) * (gps->totpoints + 1)); } + else { + /* If destination has weight add weight to origin. */ + if (dvert != NULL) { + gps->dvert = MEM_callocN(sizeof(MDeformVert) * (gps->totpoints + 1), __func__); + } + } + gps->totpoints++; newpoint = &gps->points[gps->totpoints - 1]; @@ -3212,11 +3324,16 @@ static void gpencil_stroke_copy_point(bGPDstroke *gps, copy_v4_v4(newpoint->vert_color, point->vert_color); if (gps->dvert != NULL) { - MDeformVert *dvert = &gps->dvert[idx]; MDeformVert *newdvert = &gps->dvert[gps->totpoints - 1]; - newdvert->totweight = dvert->totweight; - newdvert->dw = MEM_dupallocN(dvert->dw); + if (dvert != NULL) { + newdvert->totweight = dvert->totweight; + newdvert->dw = MEM_dupallocN(dvert->dw); + } + else { + newdvert->totweight = 0; + newdvert->dw = NULL; + } } } @@ -3267,16 +3384,18 @@ static void gpencil_stroke_join_strokes(bGPDstroke *gps_a, /* 1st: add one tail point to start invisible area */ point = gps_a->points[gps_a->totpoints - 1]; deltatime = point.time; - gpencil_stroke_copy_point(gps_a, &point, gps_a->totpoints - 1, delta, 0.0f, 0.0f, 0.0f); + + gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, 0.0f); /* 2nd: add one head point to finish invisible area */ point = gps_b->points[0]; - gpencil_stroke_copy_point(gps_a, &point, 0, delta, 0.0f, 0.0f, deltatime); + gpencil_stroke_copy_point(gps_a, NULL, &point, delta, 0.0f, 0.0f, deltatime); } /* 3rd: add all points */ for (i = 0, pt = gps_b->points; i < gps_b->totpoints && pt; i++, pt++) { - gpencil_stroke_copy_point(gps_a, pt, i, delta, pt->pressure, pt->strength, deltatime); + MDeformVert *dvert = (gps_b->dvert) ? &gps_b->dvert[i] : NULL; + gpencil_stroke_copy_point(gps_a, dvert, pt, delta, pt->pressure, pt->strength, deltatime); } } @@ -3422,7 +3541,11 @@ void GPENCIL_OT_stroke_join(wmOperatorType *ot) "Leave gaps between joined strokes instead of linking them"); } -/* ******************* Stroke flip ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Flip Operator + * \{ */ static int gp_stroke_flip_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -3481,7 +3604,11 @@ void GPENCIL_OT_stroke_flip(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ***************** Reproject Strokes ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Re-project Operator + * \{ */ typedef enum eGP_ReprojectModes { /* Axis */ @@ -3719,7 +3846,6 @@ static int gp_recalc_geometry_exec(bContext *C, wmOperator *UNUSED(op)) void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) { - /* identifiers */ ot->name = "Recalculate internal geometry"; ot->idname = "GPENCIL_OT_recalc_geometry"; @@ -3733,7 +3859,12 @@ void GPENCIL_OT_recalc_geometry(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* Stroke subdivide ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Subdivide Operator + * \{ */ + /* helper to smooth */ static void gp_smooth_stroke(bContext *C, wmOperator *op) { @@ -4114,7 +4245,12 @@ void GPENCIL_OT_stroke_sample(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* ******************* Stroke trim ************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Trim Operator + * \{ */ + static int gp_stroke_trim_exec(bContext *C, wmOperator *UNUSED(op)) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4179,7 +4315,12 @@ void GPENCIL_OT_stroke_trim(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ***************** Separate Strokes ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Separate Operator + * \{ */ + typedef enum eGP_SeparateModes { /* Points */ GP_SEPARATE_POINT = 0, @@ -4397,7 +4538,12 @@ void GPENCIL_OT_stroke_separate(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "mode", separate_type, GP_SEPARATE_POINT, "Mode", ""); } -/* ***************** Split Strokes ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Split Operator + * \{ */ + static int gp_stroke_split_exec(bContext *C, wmOperator *UNUSED(op)) { Object *ob = CTX_data_active_object(C); @@ -4494,6 +4640,12 @@ void GPENCIL_OT_stroke_split(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Smooth Operator + * \{ */ + static int gp_stroke_smooth_exec(bContext *C, wmOperator *op) { bGPdata *gpd = ED_gpencil_data_get_active(C); @@ -4544,11 +4696,17 @@ void GPENCIL_OT_stroke_smooth(wmOperatorType *ot) RNA_def_boolean(ot->srna, "smooth_uv", false, "UV", ""); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Stroke Cutter Operator + * \{ */ + /* smart stroke cutter for trimming stroke ends */ struct GP_SelectLassoUserData { rcti rect; - const int (*mcords)[2]; - int mcords_len; + const int (*mcoords)[2]; + int mcoords_len; }; static bool gpencil_test_lasso(bGPDstroke *gps, @@ -4564,7 +4722,7 @@ static bool gpencil_test_lasso(bGPDstroke *gps, gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); /* test if in lasso */ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) && - BLI_lasso_is_point_inside(data->mcords, data->mcords_len, x0, y0, INT_MAX)); + BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX)); } typedef bool (*GPencilTestFn)(bGPDstroke *gps, @@ -4742,19 +4900,19 @@ static int gpencil_cutter_exec(bContext *C, wmOperator *op) } struct GP_SelectLassoUserData data = {0}; - data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len); + data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len); /* Sanity check. */ - if (data.mcords == NULL) { + if (data.mcoords == NULL) { return OPERATOR_PASS_THROUGH; } /* Compute boundbox of lasso (for faster testing later). */ - BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len); + BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len); gpencil_cutter_lasso_select(C, op, gpencil_test_lasso, &data); - MEM_freeN((void *)data.mcords); + MEM_freeN((void *)data.mcoords); return OPERATOR_FINISHED; } @@ -4800,7 +4958,12 @@ bool ED_object_gpencil_exit(struct Main *bmain, Object *ob) return ok; } -/* ** merge by distance *** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Merge By Distance Operator + * \{ */ + static bool gp_merge_by_distance_poll(bContext *C) { Object *ob = CTX_data_active_object(C); @@ -4869,3 +5032,5 @@ void GPENCIL_OT_stroke_merge_by_distance(wmOperatorType *ot) ot->srna, "use_unselected", 0, "Unselected", "Use whole stroke, not only selected points"); RNA_def_property_flag(prop, PROP_SKIP_SAVE); } + +/** \} */ diff --git a/source/blender/editors/gpencil/gpencil_fill.c b/source/blender/editors/gpencil/gpencil_fill.c index c24f7150cbb..dd7ad8d1767 100644 --- a/source/blender/editors/gpencil/gpencil_fill.c +++ b/source/blender/editors/gpencil/gpencil_fill.c @@ -1152,7 +1152,7 @@ static void gpencil_stroke_from_buffer(tGPDfill *tgpf) pt->time = 0.0f; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, NULL); if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) { MDeformWeight *dw = BKE_defvert_ensure_index(dvert, def_nr); diff --git a/source/blender/editors/gpencil/gpencil_intern.h b/source/blender/editors/gpencil/gpencil_intern.h index c5e5a0b79ef..a98ccb1cba6 100644 --- a/source/blender/editors/gpencil/gpencil_intern.h +++ b/source/blender/editors/gpencil/gpencil_intern.h @@ -68,6 +68,17 @@ struct PropertyRNA; /* Internal Operator-State Data ------------------------ */ +/** Random settings by stroke */ +typedef struct GpRandomSettings { + /** Pressure used for evaluated curves. */ + float pen_press; + + float hsv[3]; + float pressure; + float strength; + float uv; +} GpRandomSettings; + /* Temporary draw data (no draw manager mode) */ typedef struct tGPDdraw { struct RegionView3D *rv3d; /* region to draw */ @@ -230,6 +241,10 @@ typedef struct tGPDprimitive { /** size in pixels for uv calculation */ float totpixlen; + + /** Random settings by stroke */ + GpRandomSettings random_settings; + } tGPDprimitive; /* Modal Operator Drawing Callbacks ------------------------ */ @@ -345,6 +360,10 @@ const struct EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(struct bCon struct PointerRNA *ptr, struct PropertyRNA *prop, bool *r_free); +const struct EnumPropertyItem *ED_gpencil_material_enum_itemf(struct bContext *C, + struct PointerRNA *ptr, + struct PropertyRNA *prop, + bool *r_free); /* ***************************************************** */ /* Operator Defines */ @@ -550,7 +569,8 @@ void GPENCIL_OT_material_reveal(struct wmOperatorType *ot); void GPENCIL_OT_material_lock_all(struct wmOperatorType *ot); void GPENCIL_OT_material_unlock_all(struct wmOperatorType *ot); void GPENCIL_OT_material_lock_unused(struct wmOperatorType *ot); -void GPENCIL_OT_select_material(struct wmOperatorType *ot); +void GPENCIL_OT_material_select(struct wmOperatorType *ot); +void GPENCIL_OT_material_set(struct wmOperatorType *ot); void GPENCIL_OT_set_active_material(struct wmOperatorType *ot); /* convert old 2.7 files to 2.8 */ diff --git a/source/blender/editors/gpencil/gpencil_ops.c b/source/blender/editors/gpencil/gpencil_ops.c index 0171a81f5eb..94c86572fd3 100644 --- a/source/blender/editors/gpencil/gpencil_ops.c +++ b/source/blender/editors/gpencil/gpencil_ops.c @@ -653,7 +653,8 @@ void ED_operatortypes_gpencil(void) WM_operatortype_append(GPENCIL_OT_material_reveal); WM_operatortype_append(GPENCIL_OT_material_lock_all); WM_operatortype_append(GPENCIL_OT_material_unlock_all); - WM_operatortype_append(GPENCIL_OT_select_material); + WM_operatortype_append(GPENCIL_OT_material_select); + WM_operatortype_append(GPENCIL_OT_material_set); /* Editing (Time) --------------- */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 961c4e05a28..cb72553c68b 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -255,6 +255,10 @@ typedef struct tGPsdata { tGPguide guide; ReportList *reports; + + /** Random settings by stroke */ + GpRandomSettings random_settings; + } tGPsdata; /* ------ */ @@ -687,6 +691,78 @@ static void gp_smooth_segment(bGPdata *gpd, const float inf, int from_idx, int t } } +static void gp_apply_randomness(tGPsdata *p, + BrushGpencilSettings *brush_settings, + tGPspoint *pt, + const bool press, + const bool strength, + const bool uv) +{ + bGPdata *gpd = p->gpd; + GpRandomSettings random_settings = p->random_settings; + float value = 0.0f; + /* Apply randomness to pressure. */ + if ((brush_settings->draw_random_press > 0.0f) && (press)) { + if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; + value = 1.0 + rand * 2.0 * brush_settings->draw_random_press; + } + else { + value = 1.0 + random_settings.pressure * brush_settings->draw_random_press; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) { + value *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_pressure, 0, random_settings.pen_press); + } + + pt->pressure *= value; + CLAMP(pt->pressure, 0.1f, 1.0f); + } + + /* Apply randomness to color strength. */ + if ((brush_settings->draw_random_strength) && (strength)) { + if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; + value = 1.0 + rand * brush_settings->draw_random_strength; + } + else { + value = 1.0 + random_settings.strength * brush_settings->draw_random_strength; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) { + value *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_pressure, 0, random_settings.pen_press); + } + + pt->strength *= value; + CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + } + + /* Apply randomness to uv texture rotation. */ + if ((brush_settings->uv_random > 0.0f) && (uv)) { + if ((brush_settings->flag2 & GP_BRUSH_USE_UV_AT_STROKE) == 0) { + float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used)) * 2.0f - + 1.0f; + value = rand * M_PI_2 * brush_settings->uv_random; + } + else { + value = random_settings.uv * M_PI_2 * brush_settings->uv_random; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_UV_RAND_PRESS) { + value *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_uv, 0, random_settings.pen_press); + } + + pt->uv_rot += value; + CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); + } +} + /* add current stroke-point to buffer (returns whether point was successfully added) */ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure, double curtime) { @@ -744,10 +820,6 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure return GP_STROKEADD_INVALID; } - /* Set vertex colors for buffer. */ - ED_gpencil_sbuffer_vertex_color_set( - p->depsgraph, p->ob, p->scene->toolsettings, p->brush, p->material); - /* get pointer to destination point */ pt = ((tGPspoint *)(gpd->runtime.sbuffer) + gpd->runtime.sbuffer_used); @@ -768,6 +840,15 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); } + /* Set vertex colors for buffer. */ + ED_gpencil_sbuffer_vertex_color_set(p->depsgraph, + p->ob, + p->scene->toolsettings, + p->brush, + p->material, + p->random_settings.hsv, + p->random_settings.pen_press); + if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) { /* Apply jitter to position */ if (brush_settings->draw_jitter > 0.0f) { @@ -781,26 +862,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const float mval[2], float pressure const float fac = rand * square_f(exp_factor) * jitpress; gp_brush_jitter(gpd, pt, fac); } - /* apply randomness to pressure */ - if (brush_settings->draw_random_press > 0.0f) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; - CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f); - } - /* apply randomness to uv texture rotation */ - if (brush_settings->uv_random > 0.0f) { - float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used)) * - 2.0f - - 1.0f; - pt->uv_rot += rand * M_PI_2 * brush_settings->uv_random; - CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); - } - /* apply randomness to color strength */ - if (brush_settings->draw_random_strength) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->strength *= 1.0 + rand * brush_settings->draw_random_strength; - CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); - } + + /* Apply other randomness. */ + gp_apply_randomness(p, brush_settings, pt, true, true, true); } /* apply angle of stroke to brush size */ @@ -959,9 +1023,10 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) pt->pressure = ptc->pressure; pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + copy_v4_v4(pt->vert_color, ptc->vert_color); pt->time = ptc->time; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); pt++; @@ -994,7 +1059,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); pt->time = ptc->time; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); if ((ts->gpencil_flags & GP_TOOL_FLAG_CREATE_WEIGHTS) && (have_weight)) { BKE_gpencil_dvert_ensure(gps); @@ -1113,11 +1178,12 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) pt->pressure = ptc->pressure; pt->strength = ptc->strength; CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); + copy_v4_v4(pt->vert_color, ptc->vert_color); pt->time = ptc->time; pt->uv_fac = ptc->uv_fac; pt->uv_rot = ptc->uv_rot; /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + ED_gpencil_point_vertex_color_set(ts, brush, pt, ptc); if (dvert != NULL) { dvert->totweight = 0; @@ -1751,10 +1817,16 @@ static void gp_init_drawing_brush(bContext *C, tGPsdata *p) BKE_brush_gpencil_paint_presets(bmain, ts); changed = true; } - /* be sure curves are initializated */ + /* Be sure curves are initializated. */ BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_sensitivity); BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_strength); BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_jitter); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_pressure); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_strength); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_uv); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_hue); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_saturation); + BKE_curvemapping_initialize(paint->brush->gpencil_settings->curve_rand_value); /* assign to temp tGPsdata */ p->brush = paint->brush; @@ -2700,6 +2772,8 @@ static void gpencil_draw_apply_event(bContext *C, /* handle pressure sensitivity (which is supplied by tablets or otherwise 1.0) */ p->pressure = event->tablet.pressure; + /* By default use pen pressure for random curves but attenuated. */ + p->random_settings.pen_press = pow(p->pressure, 3.0f); /* Hack for pressure sensitive eraser on D+RMB when using a tablet: * The pen has to float over the tablet surface, resulting in @@ -3052,6 +3126,8 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event else { p = op->customdata; } + /* Init random settings. */ + ED_gpencil_init_random_settings(p->brush, event->mval, &p->random_settings); /* TODO: set any additional settings that we can take from the events? * if eraser is on, draw radial aid */ @@ -3175,10 +3251,17 @@ static void gp_brush_angle_segment(tGPsdata *p, tGPspoint *pt_prev, tGPspoint *p static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) { bGPdata *gpd = p->gpd; + BrushGpencilSettings *brush_settings = p->brush->gpencil_settings; + if (gpd->runtime.sbuffer_used < 3) { + tGPspoint *points = (tGPspoint *)gpd->runtime.sbuffer; + /* Apply other randomness to first points. */ + for (int i = 0; i < gpd->runtime.sbuffer_used; i++) { + tGPspoint *pt = &points[i]; + gp_apply_randomness(p, brush_settings, pt, false, false, true); + } return; } - BrushGpencilSettings *brush_settings = p->brush->gpencil_settings; int idx_prev = gpd->runtime.sbuffer_used; /* Add space for new arc points. */ @@ -3233,6 +3316,7 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) corner[0] = midpoint[0] - (cp1[0] - midpoint[0]); corner[1] = midpoint[1] - (cp1[1] - midpoint[1]); + float stepcolor = 1.0f / segments; tGPspoint *pt_step = pt_prev; for (int i = 0; i < segments; i++) { @@ -3243,6 +3327,9 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) /* Set pressure and strength equals to previous. It will be smoothed later. */ pt->pressure = pt_prev->pressure; pt->strength = pt_prev->strength; + /* Interpolate vertex color. */ + interp_v4_v4v4( + pt->vert_color, pt_before->vert_color, pt_prev->vert_color, stepcolor * (i + 1)); /* Apply angle of stroke to brush size to interpolated points but slightly attenuated.. */ if (brush_settings->draw_angle_factor != 0.0f) { @@ -3252,26 +3339,8 @@ static void gpencil_add_arc_points(tGPsdata *p, float mval[2], int segments) pt_step = pt; } - /* Apply randomness to pressure. */ - if (brush_settings->draw_random_press > 0.0f) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; - CLAMP(pt->pressure, GPENCIL_STRENGTH_MIN, 1.0f); - } - /* Apply randomness to color strength. */ - if (brush_settings->draw_random_strength) { - float rand = BLI_rng_get_float(p->rng) * 2.0f - 1.0f; - pt->strength *= 1.0 + rand * brush_settings->draw_random_strength; - CLAMP(pt->strength, GPENCIL_STRENGTH_MIN, 1.0f); - } - /* Apply randomness to uv texture rotation. */ - if (brush_settings->uv_random > 0.0f) { - float rand = BLI_hash_int_01(BLI_hash_int_2d((int)pt->x, gpd->runtime.sbuffer_used + i)) * - 2.0f - - 1.0f; - pt->uv_rot += rand * M_PI_2 * brush_settings->uv_random; - CLAMP(pt->uv_rot, -M_PI_2, M_PI_2); - } + /* Apply other randomness. */ + gp_apply_randomness(p, brush_settings, pt, false, false, true); a += step; } @@ -3323,6 +3392,7 @@ static void gpencil_add_guide_points(const tGPsdata *p, /* Set pressure and strength equals to previous. It will be smoothed later. */ pt->pressure = pt_before->pressure; pt->strength = pt_before->strength; + copy_v4_v4(pt->vert_color, pt_before->vert_color); } } else { @@ -3339,6 +3409,7 @@ static void gpencil_add_guide_points(const tGPsdata *p, /* Set pressure and strength equals to previous. It will be smoothed later. */ pt->pressure = pt_before->pressure; pt->strength = pt_before->strength; + copy_v4_v4(pt->vert_color, pt_before->vert_color); } } } diff --git a/source/blender/editors/gpencil/gpencil_primitive.c b/source/blender/editors/gpencil/gpencil_primitive.c index 11aeeba5a24..1778162c1a3 100644 --- a/source/blender/editors/gpencil/gpencil_primitive.c +++ b/source/blender/editors/gpencil/gpencil_primitive.c @@ -124,8 +124,13 @@ static void gp_session_validatebuffer(tGPDprimitive *p) gpd->runtime.sbuffer_sflag |= GP_STROKE_3DSPACE; /* Set vertex colors for buffer. */ - ED_gpencil_sbuffer_vertex_color_set( - p->depsgraph, p->ob, p->scene->toolsettings, p->brush, p->material); + ED_gpencil_sbuffer_vertex_color_set(p->depsgraph, + p->ob, + p->scene->toolsettings, + p->brush, + p->material, + p->random_settings.hsv, + 1.0f); if (ELEM(p->type, GP_STROKE_BOX, GP_STROKE_CIRCLE)) { gpd->runtime.sbuffer_sflag |= GP_STROKE_CYCLIC; @@ -681,6 +686,8 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) ToolSettings *ts = tgpi->scene->toolsettings; bGPdata *gpd = tgpi->gpd; Brush *brush = tgpi->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + GpRandomSettings random_settings = tgpi->random_settings; bGPDstroke *gps = tgpi->gpf->strokes.first; GP_Sculpt_Settings *gset = &ts->gp_sculpt; int depth_margin = (ts->gpencil_v3d_align & GP_PROJECT_DEPTH_STROKE) ? 4 : 0; @@ -735,11 +742,11 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) { BKE_curvemapping_initialize(ts->gp_sculpt.cur_primitive); } - if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { - BKE_curvemapping_initialize(tgpi->brush->gpencil_settings->curve_jitter); + if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { + BKE_curvemapping_initialize(brush_settings->curve_jitter); } - if (tgpi->brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { - BKE_curvemapping_initialize(tgpi->brush->gpencil_settings->curve_strength); + if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + BKE_curvemapping_initialize(brush_settings->curve_strength); } /* get an array of depths, far depths are blended */ @@ -841,10 +848,9 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) tGPspoint *p2d = &points2D[i]; /* set rnd value for reuse */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) { + if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (p2d->rnd_dirty != true)) { p2d->rnd[0] = BLI_rng_get_float(tgpi->rng); p2d->rnd[1] = BLI_rng_get_float(tgpi->rng); - p2d->rnd[2] = BLI_rng_get_float(tgpi->rng); p2d->rnd_dirty = true; } @@ -858,7 +864,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) /* calc pressure */ float curve_pressure = 1.0; float pressure = 1.0; - float strength = brush->gpencil_settings->draw_strength; + float strength = brush_settings->draw_strength; /* normalize value to evaluate curve */ if (gset->flag & GP_SCULPT_SETT_FLAG_PRIMITIVE_CURVE) { @@ -868,20 +874,18 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) } /* apply jitter to position */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && - (brush->gpencil_settings->draw_jitter > 0.0f)) { + if ((brush_settings->flag & GP_BRUSH_GROUP_RANDOM) && (brush_settings->draw_jitter > 0.0f)) { float jitter; - if (brush->gpencil_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { - jitter = BKE_curvemapping_evaluateF( - brush->gpencil_settings->curve_jitter, 0, curve_pressure); + if (brush_settings->flag & GP_BRUSH_USE_JITTER_PRESSURE) { + jitter = BKE_curvemapping_evaluateF(brush_settings->curve_jitter, 0, curve_pressure); } else { - jitter = brush->gpencil_settings->draw_jitter; + jitter = brush_settings->draw_jitter; } /* exponential value */ - const float exfactor = square_f(brush->gpencil_settings->draw_jitter + 2.0f); + const float exfactor = square_f(brush_settings->draw_jitter + 2.0f); const float fac = p2d->rnd[0] * exfactor * jitter; /* vector */ @@ -906,47 +910,68 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) add_v2_v2(&p2d->x, svec); } - /* apply randomness to pressure */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && - (brush->gpencil_settings->draw_random_press > 0.0f)) { - if (p2d->rnd[0] > 0.5f) { - pressure -= (brush->gpencil_settings->draw_random_press * 2.0f) * p2d->rnd[1]; - } - else { - pressure += (brush->gpencil_settings->draw_random_press * 2.0f) * p2d->rnd[2]; - } - } - /* color strength */ - if (brush->gpencil_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { - float curvef = BKE_curvemapping_evaluateF( - brush->gpencil_settings->curve_strength, 0, curve_pressure); + if (brush_settings->flag & GP_BRUSH_USE_STENGTH_PRESSURE) { + float curvef = BKE_curvemapping_evaluateF(brush_settings->curve_strength, 0, curve_pressure); strength *= curvef; - strength *= brush->gpencil_settings->draw_strength; + strength *= brush_settings->draw_strength; } CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f); - /* apply randomness to color strength */ - if ((brush->gpencil_settings->flag & GP_BRUSH_GROUP_RANDOM) && - (brush->gpencil_settings->draw_random_strength > 0.0f)) { - if (p2d->rnd[2] > 0.5f) { - strength -= strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[0]; + if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) { + /* Apply randomness to pressure. */ + if (brush_settings->draw_random_press > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_PRESS_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f; + pressure *= 1.0 + rand * 2.0 * brush_settings->draw_random_press; + } + else { + pressure *= 1.0 + random_settings.pressure * brush_settings->draw_random_press; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_PRESSURE_RAND_PRESS) { + pressure *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_pressure, 0, pressure); + } + + CLAMP(pressure, 0.1f, 1.0f); } - else { - strength += strength * brush->gpencil_settings->draw_random_strength * p2d->rnd[1]; + + /* Apply randomness to color strength. */ + if (brush_settings->draw_random_strength) { + if ((brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_AT_STROKE) == 0) { + float rand = BLI_rng_get_float(tgpi->rng) * 2.0f - 1.0f; + strength *= 1.0 + rand * brush_settings->draw_random_strength; + } + else { + strength *= 1.0 + random_settings.strength * brush_settings->draw_random_strength; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_STRENGTH_RAND_PRESS) { + strength *= BKE_curvemapping_evaluateF(brush_settings->curve_rand_strength, 0, pressure); + } + + CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f); } - CLAMP(strength, GPENCIL_STRENGTH_MIN, 1.0f); } copy_v2_v2(&tpt->x, &p2d->x); - CLAMP_MIN(pressure, 0.1f); - tpt->pressure = pressure; tpt->strength = strength; tpt->time = p2d->time; + /* Set vertex colors for buffer. */ + ED_gpencil_sbuffer_vertex_color_set(tgpi->depsgraph, + tgpi->ob, + tgpi->scene->toolsettings, + tgpi->brush, + tgpi->material, + tgpi->random_settings.hsv, + strength); + /* point uv */ if (gpd->runtime.sbuffer_used > 0) { tGPspoint *tptb = (tGPspoint *)gpd->runtime.sbuffer + gpd->runtime.sbuffer_used - 1; @@ -994,8 +1019,7 @@ static void gp_primitive_update_strokes(bContext *C, tGPDprimitive *tgpi) pt->time = 0.0f; pt->flag = 0; pt->uv_fac = tpt->uv_fac; - /* Apply the vertex color to point. */ - ED_gpencil_point_vertex_color_set(ts, brush, pt); + copy_v4_v4(pt->vert_color, tpt->vert_color); if (gps->dvert != NULL) { MDeformVert *dvert = &gps->dvert[i]; @@ -1159,6 +1183,7 @@ static void gpencil_primitive_init(bContext *C, wmOperator *op) /* Set Draw brush. */ Brush *brush = BKE_paint_toolslots_brush_get(paint, 0); + BKE_brush_tool_set(brush, paint, 0); BKE_paint_brush_set(paint, brush); tgpi->brush = brush; @@ -1226,6 +1251,9 @@ static int gpencil_primitive_invoke(bContext *C, wmOperator *op, const wmEvent * gpencil_primitive_init(C, op); tgpi = op->customdata; + /* Init random settings. */ + ED_gpencil_init_random_settings(tgpi->brush, event->mval, &tgpi->random_settings); + const bool is_modal = RNA_boolean_get(op->ptr, "wait_for_input"); if (!is_modal) { tgpi->flag = IN_PROGRESS; @@ -1262,6 +1290,7 @@ static void gpencil_primitive_interaction_end(bContext *C, ToolSettings *ts = tgpi->scene->toolsettings; Brush *brush = tgpi->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; const int def_nr = tgpi->ob->actdef - 1; const bool have_weight = (bool)BLI_findlink(&tgpi->ob->defbase, def_nr); @@ -1285,8 +1314,8 @@ static void gpencil_primitive_interaction_end(bContext *C, gps = tgpi->gpf->strokes.first; if (gps) { gps->thickness = brush->size; - gps->hardeness = brush->gpencil_settings->hardeness; - copy_v2_v2(gps->aspect_ratio, brush->gpencil_settings->aspect_ratio); + gps->hardeness = brush_settings->hardeness; + copy_v2_v2(gps->aspect_ratio, brush_settings->aspect_ratio); /* Calc geometry data. */ BKE_gpencil_stroke_geometry_update(gps); @@ -1449,23 +1478,25 @@ static void gpencil_primitive_edit_event_handling( static void gpencil_primitive_strength(tGPDprimitive *tgpi, bool reset) { Brush *brush = tgpi->brush; + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + if (brush) { if (reset) { - brush->gpencil_settings->draw_strength = tgpi->brush_strength; + brush_settings->draw_strength = tgpi->brush_strength; tgpi->brush_strength = 0.0f; } else { if (tgpi->brush_strength == 0.0f) { - tgpi->brush_strength = brush->gpencil_settings->draw_strength; + tgpi->brush_strength = brush_settings->draw_strength; } float move[2]; sub_v2_v2v2(move, tgpi->mval, tgpi->mvalo); float adjust = (move[1] > 0.0f) ? 0.01f : -0.01f; - brush->gpencil_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move)); + brush_settings->draw_strength += adjust * fabsf(len_manhattan_v2(move)); } /* limit low limit because below 0.2f the stroke is invisible */ - CLAMP(brush->gpencil_settings->draw_strength, 0.2f, 1.0f); + CLAMP(brush_settings->draw_strength, 0.2f, 1.0f); } } diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c index e25576f32aa..69d22b52ded 100644 --- a/source/blender/editors/gpencil/gpencil_select.c +++ b/source/blender/editors/gpencil/gpencil_select.c @@ -1327,8 +1327,8 @@ void GPENCIL_OT_select_box(wmOperatorType *ot) struct GP_SelectLassoUserData { rcti rect; - const int (*mcords)[2]; - int mcords_len; + const int (*mcoords)[2]; + int mcoords_len; }; static bool gpencil_test_lasso(bGPDstroke *gps, @@ -1344,25 +1344,25 @@ static bool gpencil_test_lasso(bGPDstroke *gps, gp_point_to_xy(gsc, gps, &pt2, &x0, &y0); /* test if in lasso boundbox + within the lasso noose */ return ((!ELEM(V2D_IS_CLIPPED, x0, y0)) && BLI_rcti_isect_pt(&data->rect, x0, y0) && - BLI_lasso_is_point_inside(data->mcords, data->mcords_len, x0, y0, INT_MAX)); + BLI_lasso_is_point_inside(data->mcoords, data->mcoords_len, x0, y0, INT_MAX)); } static int gpencil_lasso_select_exec(bContext *C, wmOperator *op) { struct GP_SelectLassoUserData data = {0}; - data.mcords = WM_gesture_lasso_path_to_array(C, op, &data.mcords_len); + data.mcoords = WM_gesture_lasso_path_to_array(C, op, &data.mcoords_len); /* Sanity check. */ - if (data.mcords == NULL) { + if (data.mcoords == NULL) { return OPERATOR_PASS_THROUGH; } /* Compute boundbox of lasso (for faster testing later). */ - BLI_lasso_boundbox(&data.rect, data.mcords, data.mcords_len); + BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len); int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data); - MEM_freeN((void *)data.mcords); + MEM_freeN((void *)data.mcoords); return ret; } diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c index 3d571773bc8..03deab15b1e 100644 --- a/source/blender/editors/gpencil/gpencil_utils.c +++ b/source/blender/editors/gpencil/gpencil_utils.c @@ -30,11 +30,14 @@ #include "BLI_blenlib.h" #include "BLI_ghash.h" +#include "BLI_hash.h" #include "BLI_math.h" #include "BLI_rand.h" #include "BLI_utildefines.h" #include "BLT_translation.h" +#include "PIL_time.h" + #include "DNA_brush_types.h" #include "DNA_gpencil_types.h" #include "DNA_meshdata_types.h" @@ -74,6 +77,7 @@ #include "ED_object.h" #include "ED_screen.h" #include "ED_select_utils.h" +#include "ED_transform_snap_object_context.h" #include "ED_view3d.h" #include "GPU_immediate.h" @@ -481,6 +485,40 @@ const EnumPropertyItem *ED_gpencil_layers_with_new_enum_itemf(bContext *C, return item; } +/* Just existing Materials */ +const EnumPropertyItem *ED_gpencil_material_enum_itemf(bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + bool *r_free) +{ + Object *ob = CTX_data_active_object(C); + EnumPropertyItem *item = NULL, item_tmp = {0}; + int totitem = 0; + int i = 0; + + if (ELEM(NULL, C, ob)) { + return DummyRNA_DEFAULT_items; + } + + /* Existing materials */ + for (i = 1; i <= ob->totcol; i++) { + Material *ma = BKE_object_material_get(ob, i); + if (ma) { + item_tmp.identifier = ma->id.name + 2; + item_tmp.name = ma->id.name + 2; + item_tmp.value = i; + item_tmp.icon = ma->preview->icon_id; + + RNA_enum_item_add(&item, &totitem, &item_tmp); + } + } + + RNA_enum_item_end(&item, &totitem); + *r_free = true; + + return item; +} + /* ******************************************************** */ /* Brush Tool Core */ @@ -670,8 +708,8 @@ void gp_apply_parent_point(Depsgraph *depsgraph, Object *obact, bGPDlayer *gpl, /** * Convert a Grease Pencil coordinate (i.e. can be 2D or 3D) to screenspace (2D) * - * \param[out] r_x The screen-space x-coordinate of the point - * \param[out] r_y The screen-space y-coordinate of the point + * \param[out] r_x: The screen-space x-coordinate of the point + * \param[out] r_y: The screen-space y-coordinate of the point * * \warning This assumes that the caller has already checked * whether the stroke in question can be drawn. @@ -2525,26 +2563,170 @@ void ED_gpencil_fill_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDstroke } } -void ED_gpencil_point_vertex_color_set(ToolSettings *ts, Brush *brush, bGPDspoint *pt) +void ED_gpencil_point_vertex_color_set(ToolSettings *ts, + Brush *brush, + bGPDspoint *pt, + tGPspoint *tpt) { if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) { - copy_v3_v3(pt->vert_color, brush->rgb); - pt->vert_color[3] = brush->gpencil_settings->vertex_factor; - srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color); + if (tpt == NULL) { + copy_v3_v3(pt->vert_color, brush->rgb); + pt->vert_color[3] = brush->gpencil_settings->vertex_factor; + srgb_to_linearrgb_v4(pt->vert_color, pt->vert_color); + } + else { + copy_v3_v3(pt->vert_color, tpt->vert_color); + pt->vert_color[3] = brush->gpencil_settings->vertex_factor; + } } else { zero_v4(pt->vert_color); } } -void ED_gpencil_sbuffer_vertex_color_set( - Depsgraph *depsgraph, Object *ob, ToolSettings *ts, Brush *brush, Material *material) +void ED_gpencil_init_random_settings(Brush *brush, + const int mval[2], + GpRandomSettings *random_settings) +{ + int seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128; + /* Use mouse position to get randomness. */ + int ix = mval[0] * seed; + int iy = mval[1] * seed; + int iz = ix + iy * seed; + zero_v3(random_settings->hsv); + + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + /* Random to Hue. */ + if (brush_settings->random_hue > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, iy)) * 2.0f - 1.0f; + random_settings->hsv[0] = rand * brush_settings->random_hue * 0.5f; + } + /* Random to Saturation. */ + if (brush_settings->random_saturation > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, ix)) * 2.0f - 1.0f; + random_settings->hsv[1] = rand * brush_settings->random_saturation; + } + /* Random to Value. */ + if (brush_settings->random_value > 0.0f) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(ix * iz, iy * iz)) * 2.0f - 1.0f; + random_settings->hsv[2] = rand * brush_settings->random_value; + } + + /* Random to pressure. */ + if (brush_settings->draw_random_press > 0.0f) { + random_settings->pressure = BLI_hash_int_01(BLI_hash_int_2d(ix + iz, iy + iz)) * 2.0f - 1.0f; + } + + /* Randomn to color strength. */ + if (brush_settings->draw_random_strength) { + random_settings->strength = BLI_hash_int_01(BLI_hash_int_2d(ix + iy, iy + iz + ix)) * 2.0f - + 1.0f; + } + + /* Random to uv texture rotation. */ + if (brush_settings->uv_random > 0.0f) { + random_settings->uv = BLI_hash_int_01(BLI_hash_int_2d(iy + iz, ix * iz)) * 2.0f - 1.0f; + } +} + +static void gpencil_sbuffer_vertex_color_random( + bGPdata *gpd, Brush *brush, tGPspoint *tpt, float random_color[3], float pen_pressure) +{ + BrushGpencilSettings *brush_settings = brush->gpencil_settings; + if (brush_settings->flag & GP_BRUSH_GROUP_RANDOM) { + int seed = ((uint)(ceil(PIL_check_seconds_timer())) + 1) % 128; + + int ix = (int)(tpt->x * seed); + int iy = (int)(tpt->y * seed); + int iz = ix + iy * seed; + float hsv[3]; + float factor_value[3]; + zero_v3(factor_value); + + /* Apply randomness to Hue. */ + if (brush_settings->random_hue > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_HUE_AT_STROKE) == 0) { + + float rand = BLI_hash_int_01(BLI_hash_int_2d(ix, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f; + factor_value[0] = rand * brush_settings->random_hue * 0.5f; + } + else { + factor_value[0] = random_color[0]; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_HUE_RAND_PRESS) { + factor_value[0] *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_hue, 0, pen_pressure); + } + } + + /* Apply randomness to Saturation. */ + if (brush_settings->random_saturation > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_SAT_AT_STROKE) == 0) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(iy, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f; + factor_value[1] = rand * brush_settings->random_saturation; + } + else { + factor_value[1] = random_color[1]; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_SAT_RAND_PRESS) { + factor_value[1] *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_saturation, 0, pen_pressure); + } + } + + /* Apply randomness to Value. */ + if (brush_settings->random_value > 0.0f) { + if ((brush_settings->flag2 & GP_BRUSH_USE_VAL_AT_STROKE) == 0) { + float rand = BLI_hash_int_01(BLI_hash_int_2d(iz, gpd->runtime.sbuffer_used)) * 2.0f - 1.0f; + factor_value[2] = rand * brush_settings->random_value; + } + else { + factor_value[2] = random_color[2]; + } + + /* Apply random curve. */ + if (brush_settings->flag2 & GP_BRUSH_USE_VAL_RAND_PRESS) { + factor_value[2] *= BKE_curvemapping_evaluateF( + brush_settings->curve_rand_value, 0, pen_pressure); + } + } + + rgb_to_hsv_v(tpt->vert_color, hsv); + add_v3_v3(hsv, factor_value); + /* For Hue need to cover all range, but for Saturation and Value + * is not logic because the effect is too hard, so the value is just clamped. */ + if (hsv[0] < 0.0f) { + hsv[0] += 1.0f; + } + else if (hsv[0] > 1.0f) { + hsv[0] -= 1.0f; + } + + CLAMP3(hsv, 0.0f, 1.0f); + hsv_to_rgb_v(hsv, tpt->vert_color); + } +} + +void ED_gpencil_sbuffer_vertex_color_set(Depsgraph *depsgraph, + Object *ob, + ToolSettings *ts, + Brush *brush, + Material *material, + float random_color[3], + float pen_pressure) { bGPdata *gpd = (bGPdata *)ob->data; Object *ob_eval = (Object *)DEG_get_evaluated_id(depsgraph, &ob->id); bGPdata *gpd_eval = (bGPdata *)ob_eval->data; MaterialGPencilStyle *gp_style = material->gp_style; + int idx = gpd->runtime.sbuffer_used; + tGPspoint *tpt = (tGPspoint *)gpd->runtime.sbuffer + idx; + float vertex_color[4]; copy_v3_v3(vertex_color, brush->rgb); vertex_color[3] = brush->gpencil_settings->vertex_factor; @@ -2559,15 +2741,18 @@ void ED_gpencil_sbuffer_vertex_color_set( } /* Copy stroke vertex color. */ if (GPENCIL_USE_VERTEX_COLOR_STROKE(ts, brush)) { - copy_v4_v4(gpd->runtime.vert_color, vertex_color); + copy_v4_v4(tpt->vert_color, vertex_color); } else { - copy_v4_v4(gpd->runtime.vert_color, gp_style->stroke_rgba); + copy_v4_v4(tpt->vert_color, gp_style->stroke_rgba); } - /* Copy to eval data because paint operators don't tag refresh until end for speedup painting. */ + /* Random Color. */ + gpencil_sbuffer_vertex_color_random(gpd, brush, tpt, random_color, pen_pressure); + + /* Copy to eval data because paint operators don't tag refresh until end for speedup + painting. */ if (gpd_eval != NULL) { - copy_v4_v4(gpd_eval->runtime.vert_color, gpd->runtime.vert_color); copy_v4_v4(gpd_eval->runtime.vert_color_fill, gpd->runtime.vert_color_fill); gpd_eval->runtime.matid = gpd->runtime.matid; } diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h index a9b34e3c735..7d38792f332 100644 --- a/source/blender/editors/include/ED_anim_api.h +++ b/source/blender/editors/include/ED_anim_api.h @@ -229,6 +229,7 @@ typedef enum eAnim_ChannelType { ANIMTYPE_DSHAIR, ANIMTYPE_DSPOINTCLOUD, ANIMTYPE_DSVOLUME, + ANIMTYPE_DSSIMULATION, ANIMTYPE_SHAPEKEY, @@ -356,6 +357,8 @@ typedef enum eAnimFilter_Flags { #define FILTER_HAIR_OBJD(ha) (CHECK_TYPE_INLINE(ha, Hair *), ((ha->flag & HA_DS_EXPAND))) #define FILTER_POINTS_OBJD(pt) (CHECK_TYPE_INLINE(pt, PointCloud *), ((pt->flag & PT_DS_EXPAND))) #define FILTER_VOLUME_OBJD(vo) (CHECK_TYPE_INLINE(vo, Volume *), ((vo->flag & VO_DS_EXPAND))) +#define FILTER_SIMULATION_OBJD(sim) \ + (CHECK_TYPE_INLINE(sim, Simulation *), ((sim->flag & SIM_DS_EXPAND))) /* Variable use expanders */ #define FILTER_NTREE_DATA(ntree) \ (CHECK_TYPE_INLINE(ntree, bNodeTree *), (((ntree)->flag & NTREE_DS_EXPAND))) diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1403ae1f3cc..2dbd979564e 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -40,6 +40,7 @@ struct bGPDspoint; struct bGPDstroke; struct bGPdata; struct tGPspoint; +struct GpRandomSettings; struct ARegion; struct Depsgraph; @@ -48,6 +49,7 @@ struct RegionView3D; struct ReportList; struct Scene; struct ScrArea; +struct SnapObjectContext; struct ToolSettings; struct View3D; struct ViewLayer; @@ -69,14 +71,15 @@ struct wmOperator; * Used as part of the 'stroke cache' used during drawing of new strokes */ typedef struct tGPspoint { - float x, y; /* x and y coordinates of cursor (in relative to area) */ - float pressure; /* pressure of tablet at this point */ - float strength; /* pressure of tablet at this point for alpha factor */ - float time; /* Time relative to stroke start (used when converting to path) */ - float uv_fac; /* factor of uv along the stroke */ - float uv_rot; /* uv rotation for dor mode */ - float rnd[3]; /* rnd value */ - bool rnd_dirty; /* rnd flag */ + float x, y; /* x and y coordinates of cursor (in relative to area) */ + float pressure; /* pressure of tablet at this point */ + float strength; /* pressure of tablet at this point for alpha factor */ + float time; /* Time relative to stroke start (used when converting to path) */ + float uv_fac; /* factor of uv along the stroke */ + float uv_rot; /* uv rotation for dor mode */ + float rnd[3]; /* rnd value */ + bool rnd_dirty; /* rnd flag */ + float vert_color[4]; /* Point vertex color. */ } tGPspoint; /* ----------- Grease Pencil Tools/Context ------------- */ @@ -296,12 +299,18 @@ void ED_gpencil_fill_vertex_color_set(struct ToolSettings *ts, struct bGPDstroke *gps); void ED_gpencil_point_vertex_color_set(struct ToolSettings *ts, struct Brush *brush, - struct bGPDspoint *pt); + struct bGPDspoint *pt, + struct tGPspoint *tpt); void ED_gpencil_sbuffer_vertex_color_set(struct Depsgraph *depsgraph, struct Object *ob, struct ToolSettings *ts, struct Brush *brush, - struct Material *material); + struct Material *material, + float random_color[3], + float pen_pressure); +void ED_gpencil_init_random_settings(struct Brush *brush, + const int mval[2], + struct GpRandomSettings *random_settings); bool ED_gpencil_stroke_check_collision(struct GP_SpaceConversion *gsc, struct bGPDstroke *gps, diff --git a/source/blender/editors/include/ED_image.h b/source/blender/editors/include/ED_image.h index 910cf362a37..a8476e3d1ca 100644 --- a/source/blender/editors/include/ED_image.h +++ b/source/blender/editors/include/ED_image.h @@ -69,7 +69,7 @@ void ED_space_image_get_size(struct SpaceImage *sima, int *r_width, int *r_heigh void ED_space_image_get_size_fl(struct SpaceImage *sima, float r_size[2]); void ED_space_image_get_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy); void ED_space_image_get_zoom(struct SpaceImage *sima, - struct ARegion *region, + const struct ARegion *region, float *r_zoomx, float *r_zoomy); void ED_space_image_get_uv_aspect(struct SpaceImage *sima, float *r_aspx, float *r_aspy); @@ -88,14 +88,18 @@ void ED_image_get_uv_aspect(struct Image *ima, float *r_aspx, float *r_aspy); void ED_image_mouse_pos(struct SpaceImage *sima, - struct ARegion *region, + const struct ARegion *region, const int mval[2], float co[2]); void ED_image_view_center_to_point(struct SpaceImage *sima, float x, float y); -void ED_image_point_pos( - struct SpaceImage *sima, struct ARegion *region, float x, float y, float *r_x, float *r_y); +void ED_image_point_pos(struct SpaceImage *sima, + const struct ARegion *region, + float x, + float y, + float *r_x, + float *r_y); void ED_image_point_pos__reverse(struct SpaceImage *sima, - struct ARegion *region, + const struct ARegion *region, const float co[2], float r_co[2]); bool ED_image_slot_cycle(struct Image *image, int direction); diff --git a/source/blender/editors/include/ED_info.h b/source/blender/editors/include/ED_info.h index 82662a6b118..1146c49bef2 100644 --- a/source/blender/editors/include/ED_info.h +++ b/source/blender/editors/include/ED_info.h @@ -31,9 +31,9 @@ struct Main; /* info_stats.c */ void ED_info_stats_clear(struct ViewLayer *view_layer); -const char *ED_info_stats_string(struct Main *bmain, - struct Scene *scene, - struct ViewLayer *view_layer); +const char *ED_info_footer_string(struct ViewLayer *view_layer); +void ED_info_draw_stats( + Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height); #ifdef __cplusplus } diff --git a/source/blender/editors/include/ED_keyframes_edit.h b/source/blender/editors/include/ED_keyframes_edit.h index 3ae0c254000..28bc0b22790 100644 --- a/source/blender/editors/include/ED_keyframes_edit.h +++ b/source/blender/editors/include/ED_keyframes_edit.h @@ -24,12 +24,12 @@ #ifndef __ED_KEYFRAMES_EDIT_H__ #define __ED_KEYFRAMES_EDIT_H__ +#include "ED_anim_api.h" /* for enum eAnimFilter_Flags */ + #ifdef __cplusplus extern "C" { #endif -#include "ED_anim_api.h" /* for enum eAnimFilter_Flags */ - struct BezTriple; struct FCurve; struct Scene; @@ -106,8 +106,8 @@ typedef enum eEditKeyframes_Mirror { typedef struct KeyframeEdit_LassoData { rctf *rectf_scaled; const rctf *rectf_view; - const int (*mcords)[2]; - int mcords_tot; + const int (*mcoords)[2]; + int mcoords_len; } KeyframeEdit_LassoData; /* use with BEZT_OK_REGION_CIRCLE */ diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 4225ecc6f3d..5635ef2800a 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -24,6 +24,9 @@ #ifndef __ED_KEYFRAMING_H__ #define __ED_KEYFRAMING_H__ +#include "DNA_anim_types.h" +#include "RNA_types.h" + #ifdef __cplusplus extern "C" { #endif @@ -50,9 +53,6 @@ struct PropertyRNA; struct NlaKeyframingContext; -#include "DNA_anim_types.h" -#include "RNA_types.h" - /* ************ Keyframing Management **************** */ /* Get the active settings for keyframing settings from context (specifically the given scene) diff --git a/source/blender/editors/include/ED_node.h b/source/blender/editors/include/ED_node.h index 7a1f64b61d4..1dc98cfee2f 100644 --- a/source/blender/editors/include/ED_node.h +++ b/source/blender/editors/include/ED_node.h @@ -37,6 +37,7 @@ struct Tex; struct View2D; struct bContext; struct bNode; +struct bNodeSocket; struct bNodeSocketType; struct bNodeTree; struct bNodeTree; @@ -79,6 +80,10 @@ void ED_node_draw_snap( struct View2D *v2d, const float cent[2], float size, NodeBorder border, unsigned int pos); /* node_draw.c */ +void ED_node_socket_draw(struct bNodeSocket *sock, + const struct rcti *rect, + const float color[4], + float scale); void ED_node_tree_update(const struct bContext *C); void ED_node_tag_update_id(struct ID *id); void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree, struct bNode *node); @@ -94,6 +99,7 @@ void ED_node_set_tree_type(struct SpaceNode *snode, struct bNodeTreeType *typein bool ED_node_is_compositor(struct SpaceNode *snode); bool ED_node_is_shader(struct SpaceNode *snode); bool ED_node_is_texture(struct SpaceNode *snode); +bool ED_node_is_simulation(struct SpaceNode *snode); void ED_node_shader_default(const struct bContext *C, struct ID *id); void ED_node_composit_default(const struct bContext *C, struct Scene *scene); diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h index 9d25fff477d..32e62a6436c 100644 --- a/source/blender/editors/include/ED_object.h +++ b/source/blender/editors/include/ED_object.h @@ -24,6 +24,9 @@ #ifndef __ED_OBJECT_H__ #define __ED_OBJECT_H__ +#include "BLI_compiler_attrs.h" +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -54,9 +57,6 @@ struct wmOperator; struct wmOperatorType; struct wmWindowManager; -#include "BLI_compiler_attrs.h" -#include "DNA_object_enums.h" - /* object_edit.c */ /* context.object */ struct Object *ED_object_context(struct bContext *C); diff --git a/source/blender/editors/include/ED_outliner.h b/source/blender/editors/include/ED_outliner.h index beed0f98fb5..d3fc5174dd9 100644 --- a/source/blender/editors/include/ED_outliner.h +++ b/source/blender/editors/include/ED_outliner.h @@ -27,9 +27,9 @@ extern "C" { #endif +struct Base; struct ListBase; struct bContext; -struct Base; bool ED_outliner_collections_editor_poll(struct bContext *C); diff --git a/source/blender/editors/include/ED_particle.h b/source/blender/editors/include/ED_particle.h index c8a4dc5b49d..789db5ae56e 100644 --- a/source/blender/editors/include/ED_particle.h +++ b/source/blender/editors/include/ED_particle.h @@ -71,8 +71,8 @@ bool PE_mouse_particles( bool PE_box_select(struct bContext *C, const struct rcti *rect, const int sel_op); bool PE_circle_select(struct bContext *C, const int sel_op, const int mval[2], float rad); int PE_lasso_select(struct bContext *C, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, const int sel_op); bool PE_deselect_all_visible_ex(struct PTCacheEdit *edit); bool PE_deselect_all_visible(struct bContext *C); diff --git a/source/blender/editors/include/ED_screen_types.h b/source/blender/editors/include/ED_screen_types.h index 06c2c3039f5..51f3eea74fa 100644 --- a/source/blender/editors/include/ED_screen_types.h +++ b/source/blender/editors/include/ED_screen_types.h @@ -34,11 +34,11 @@ extern "C" { typedef struct ScreenAnimData { ARegion *region; /* do not read from this, only for comparing if region exists */ short redraws; - short flag; /* flags for playback */ - int sfra; /* frame that playback was started from */ - int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ - double last_duration; /* used for frame dropping */ - bool from_anim_edit; /* playback was invoked from animation editor */ + short flag; /* flags for playback */ + int sfra; /* frame that playback was started from */ + int nextfra; /* next frame to go to (when ANIMPLAY_FLAG_USE_NEXT_FRAME is set) */ + double lagging_frame_count; /* used for frame dropping */ + bool from_anim_edit; /* playback was invoked from animation editor */ } ScreenAnimData; /* for animplayer */ diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index beba4a7199b..27b7511c8a2 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -157,6 +157,8 @@ int BIF_countTransformOrientation(const struct bContext *C); #define P_GPENCIL_EDIT (1 << 13) #define P_CURSOR_EDIT (1 << 14) #define P_CLNOR_INVALIDATE (1 << 15) +/* For properties performed when confirming the transformation. */ +#define P_POST_TRANSFORM (1 << 16) void Transform_Properties(struct wmOperatorType *ot, int flags); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 774cf8c509f..8b7b0430765 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -250,6 +250,8 @@ enum { UI_BUT_TEXT_RIGHT = 1 << 3, /** Prevent the button to show any tooltip. */ UI_BUT_NO_TOOLTIP = 1 << 4, + /** Do not add the usual horizontal padding for text drawing. */ + UI_BUT_NO_TEXT_PADDING = 1 << 5, /* Button align flag, for drawing groups together. * Used in 'uiBlock.flag', take care! */ @@ -500,15 +502,24 @@ typedef void (*uiButHandleRenameFunc)(struct bContext *C, void *arg, char *origs typedef void (*uiButHandleNFunc)(struct bContext *C, void *argN, void *arg2); typedef void (*uiButHandleHoldFunc)(struct bContext *C, struct ARegion *butregion, uiBut *but); typedef int (*uiButCompleteFunc)(struct bContext *C, char *str, void *arg); -typedef struct ARegion *(*uiButSearchCreateFunc)(struct bContext *C, - struct ARegion *butregion, - uiBut *but); -typedef void (*uiButSearchFunc)(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items); -typedef void (*uiButSearchArgFreeFunc)(void *arg); +/* Search types. */ +typedef struct ARegion *(*uiButSearchCreateFn)(struct bContext *C, + struct ARegion *butregion, + uiBut *but); +typedef void (*uiButSearchUpdateFn)(const struct bContext *C, + void *arg, + const char *str, + uiSearchItems *items); +typedef void (*uiButSearchArgFreeFn)(void *arg); +typedef bool (*uiButSearchContextMenuFn)(struct bContext *C, + void *arg, + void *active, + const struct wmEvent *event); +typedef struct ARegion *(*uiButSearchTooltipFn)(struct bContext *C, + struct ARegion *region, + void *arg, + void *active); /* Must return allocated string. */ typedef char *(*uiButToolTipFunc)(struct bContext *C, void *argN, const char *tip); @@ -619,8 +630,7 @@ void UI_popup_block_invoke_ex(struct bContext *C, uiBlockCreateFunc func, void *arg, void (*arg_free)(void *arg), - const char *opname, - int opcontext); + bool can_refresh); void UI_popup_block_ex(struct bContext *C, uiBlockCreateFunc func, uiBlockHandleFunc popup_func, @@ -1570,21 +1580,25 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, /* use inside searchfunc to add items */ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int iconid, int state); -/* bfunc gets search item *poin as arg2, or if NULL the old string */ void UI_but_func_search_set(uiBut *but, - uiButSearchCreateFunc cfunc, - uiButSearchFunc sfunc, + uiButSearchCreateFn search_create_fn, + uiButSearchUpdateFn search_update_fn, void *arg, - uiButSearchArgFreeFunc search_arg_free_func, - uiButHandleFunc bfunc, - const char *search_sep_string, + uiButSearchArgFreeFn search_arg_free_fn, + uiButHandleFunc search_exec_fn, void *active); +void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn); +void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn); +void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string); + /* height in pixels, it's using hardcoded values still */ int UI_searchbox_size_y(void); int UI_searchbox_size_x(void); /* check if a string is in an existing search box */ int UI_search_items_find_index(uiSearchItems *items, const char *name); +void UI_but_node_link_set(uiBut *but, struct bNodeSocket *socket, const float draw_color[4]); + void UI_block_func_handle_set(uiBlock *block, uiBlockHandleFunc func, void *arg); void UI_block_func_butmenu_set(uiBlock *block, uiMenuHandleFunc func, void *arg); void UI_block_func_set(uiBlock *block, uiButHandleFunc func, void *arg1, void *arg2); @@ -1668,6 +1682,7 @@ void UI_panel_end(const struct ScrArea *area, void UI_panels_scale(struct ARegion *region, float new_width); void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y); int UI_panel_size_y(const struct Panel *panel); +bool UI_panel_is_dragging(const struct Panel *panel); bool UI_panel_category_is_visible(const struct ARegion *region); void UI_panel_category_add(struct ARegion *region, const char *name); @@ -1772,6 +1787,10 @@ enum { UI_ITEM_O_DEPRESS = 1 << 10, UI_ITEM_R_COMPACT = 1 << 11, UI_ITEM_R_CHECKBOX_INVERT = 1 << 12, + /** Don't add a real decorator item, just blank space. */ + UI_ITEM_R_FORCE_BLANK_DECORATE = 1 << 13, + /* Even create the property split layout if there's no name to show there. */ + UI_ITEM_R_SPLIT_EMPTY_NAME = 1 << 14, }; #define UI_HEADER_OFFSET ((void)0, 0.4f * UI_UNIT_X) @@ -1782,6 +1801,9 @@ enum { UI_TEMPLATE_OP_PROPS_SHOW_EMPTY = 1 << 1, UI_TEMPLATE_OP_PROPS_COMPACT = 1 << 2, UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED = 1 << 3, + /* Disable property split for the default layout (custom ui callbacks still have full control + * over the layout and can enable it). */ + UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT = 1 << 4, }; /* used for transp checkers */ @@ -1869,7 +1891,9 @@ bool uiLayoutGetPropDecorate(uiLayout *layout); /* layout specifiers */ uiLayout *uiLayoutRow(uiLayout *layout, bool align); +uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading); uiLayout *uiLayoutColumn(uiLayout *layout, bool align); +uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading); uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align); uiLayout *uiLayoutGridFlow(uiLayout *layout, bool row_major, @@ -2044,11 +2068,11 @@ void uiTemplateOperatorSearch(uiLayout *layout); void UI_but_func_menu_search(uiBut *but); void uiTemplateMenuSearch(uiLayout *layout); -eAutoPropButsReturn uiTemplateOperatorPropertyButs(const struct bContext *C, - uiLayout *layout, - struct wmOperator *op, - const eButLabelAlign label_align, - const short flag); +void uiTemplateOperatorPropertyButs(const struct bContext *C, + uiLayout *layout, + struct wmOperator *op, + eButLabelAlign label_align, + short flag); void uiTemplateHeader3D_mode(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); @@ -2088,6 +2112,7 @@ void uiTemplateList(uiLayout *layout, bool sort_reverse, bool sort_lock); void uiTemplateNodeLink(uiLayout *layout, + struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input); @@ -2297,6 +2322,14 @@ void uiItemsFullEnumO_items(uiLayout *layout, const EnumPropertyItem *item_array, int totitem); +typedef struct uiPropertySplitWrapper { + uiLayout *label_column; + uiLayout *property_row; + uiLayout *decorate_column; +} uiPropertySplitWrapper; + +uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout); + void uiItemL(uiLayout *layout, const char *name, int icon); /* label */ void uiItemL_ex( uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert); @@ -2308,6 +2341,9 @@ void uiItemM_ptr(uiLayout *layout, struct MenuType *mt, const char *name, int ic void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon); /* menu contents */ void uiItemMContents(uiLayout *layout, const char *menuname); +/* Decorators */ +void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index); +void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index); /* value */ void uiItemV(uiLayout *layout, const char *name, int icon, int argval); /* separator */ @@ -2375,6 +2411,7 @@ bool UI_context_copy_to_selected_list(struct bContext *C, /* Helpers for Operators */ uiBut *UI_context_active_but_get(const struct bContext *C); +uiBut *UI_context_active_but_get_respect_menu(const struct bContext *C); uiBut *UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index b0995250979..c5c4ca79f14 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -26,10 +26,6 @@ #include "BLI_sys_types.h" -#ifdef __cplusplus -extern "C" { -#endif - /* Define icon enum. */ #define DEF_ICON(name) ICON_##name, #define DEF_ICON_VECTOR(name) ICON_##name, @@ -47,6 +43,10 @@ typedef enum { /* use to denote intentionally unset theme color */ #define TH_UNDEFINED -1 +#ifdef __cplusplus +extern "C" { +#endif + typedef enum ThemeColorID { TH_REDALERT, diff --git a/source/blender/editors/include/UI_view2d.h b/source/blender/editors/include/UI_view2d.h index d4db1b14074..ffc06e94a90 100644 --- a/source/blender/editors/include/UI_view2d.h +++ b/source/blender/editors/include/UI_view2d.h @@ -137,9 +137,9 @@ void UI_view2d_view_orthoSpecial(struct ARegion *region, struct View2D *v2d, con void UI_view2d_view_restore(const struct bContext *C); /* grid drawing */ -void UI_view2d_constant_grid_draw(struct View2D *v2d, float step); +void UI_view2d_constant_grid_draw(const struct View2D *v2d, float step); void UI_view2d_multi_grid_draw( - struct View2D *v2d, int colorid, float step, int level_size, int totlevels); + const struct View2D *v2d, int colorid, float step, int level_size, int totlevels); void UI_view2d_draw_lines_y__values(const struct View2D *v2d); void UI_view2d_draw_lines_x__values(const struct View2D *v2d); @@ -209,14 +209,17 @@ bool UI_view2d_view_to_region_clip( const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); void UI_view2d_view_to_region( - struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); -void UI_view2d_view_to_region_fl( - struct View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) ATTR_NONNULL(); -void UI_view2d_view_to_region_m4(struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL(); -void UI_view2d_view_to_region_rcti(struct View2D *v2d, + const struct View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) ATTR_NONNULL(); +void UI_view2d_view_to_region_fl(const struct View2D *v2d, + float x, + float y, + float *r_region_x, + float *r_region_y) ATTR_NONNULL(); +void UI_view2d_view_to_region_m4(const struct View2D *v2d, float matrix[4][4]) ATTR_NONNULL(); +void UI_view2d_view_to_region_rcti(const struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL(); -bool UI_view2d_view_to_region_rcti_clip(struct View2D *v2d, +bool UI_view2d_view_to_region_rcti_clip(const struct View2D *v2d, const struct rctf *rect_src, struct rcti *rect_dst) ATTR_NONNULL(); @@ -228,9 +231,9 @@ void UI_view2d_scroller_size_get(const struct View2D *v2d, float *r_x, float *r_ void UI_view2d_scale_get(struct View2D *v2d, float *r_x, float *r_y); float UI_view2d_scale_get_x(const struct View2D *v2d); float UI_view2d_scale_get_y(const struct View2D *v2d); -void UI_view2d_scale_get_inverse(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_scale_get_inverse(const struct View2D *v2d, float *r_x, float *r_y); -void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y); +void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y); void UI_view2d_center_set(struct View2D *v2d, float x, float y); void UI_view2d_offset(struct View2D *v2d, float xfac, float yfac); diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index d33023c69a1..c2c27af9770 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -69,6 +69,9 @@ set(SRC interface_regions.c interface_style.c interface_templates.c + interface_template_search_menu.c + interface_template_search_operator.c + interface_undo.c interface_utils.c interface_widgets.c resources.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 9ec660a9714..04c259ab092 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -641,6 +641,26 @@ static int ui_but_calc_float_precision(uiBut *but, double value) /* ************** BLOCK ENDING FUNCTION ************* */ +bool ui_but_rna_equals(const uiBut *a, const uiBut *b) +{ + return ui_but_rna_equals_ex(a, &b->rnapoin, b->rnaprop, b->rnaindex); +} + +bool ui_but_rna_equals_ex(const uiBut *but, + const PointerRNA *ptr, + const PropertyRNA *prop, + int index) +{ + if (but->rnapoin.data != ptr->data) { + return false; + } + if (but->rnaprop != prop || but->rnaindex != index) { + return false; + } + + return true; +} + /* NOTE: if but->poin is allocated memory for every defbut, things fail... */ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) { @@ -649,10 +669,7 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut) if (but->retval != oldbut->retval) { return false; } - if (but->rnapoin.data != oldbut->rnapoin.data) { - return false; - } - if (but->rnaprop != oldbut->rnaprop || but->rnaindex != oldbut->rnaindex) { + if (!ui_but_rna_equals(but, oldbut)) { return false; } if (but->func != oldbut->func) { @@ -790,8 +807,7 @@ static bool ui_but_update_from_old_block(const bContext *C, SWAP(ListBase, but->extra_op_icons, oldbut->extra_op_icons); - SWAP(uiButSearchArgFreeFunc, oldbut->search_arg_free_func, but->search_arg_free_func); - SWAP(void *, oldbut->search_arg, but->search_arg); + SWAP(struct uiButSearchData *, oldbut->search, but->search); /* copy hardmin for list rows to prevent 'sticking' highlight to mouse position * when scrolling without moving mouse (see [#28432]) */ @@ -979,7 +995,9 @@ static void ui_menu_block_set_keyaccels(uiBlock *block) UI_BTYPE_BUT_MENU, UI_BTYPE_MENU, UI_BTYPE_BLOCK, - UI_BTYPE_PULLDOWN) || + UI_BTYPE_PULLDOWN, + /* For PIE-menus. */ + UI_BTYPE_ROW) || (but->flag & UI_HIDDEN)) { /* pass */ } @@ -3208,9 +3226,12 @@ static void ui_but_free(const bContext *C, uiBut *but) MEM_freeN(but->hold_argN); } - if (but->search_arg_free_func) { - but->search_arg_free_func(but->search_arg); - but->search_arg = NULL; + if (but->search != NULL) { + if (but->search->arg_free_fn) { + but->search->arg_free_fn(but->search->arg); + but->search->arg = NULL; + } + MEM_freeN(but->search); } if (but->active) { @@ -6330,40 +6351,51 @@ uiBut *uiDefSearchBut(uiBlock *block, } /** - * \param search_func, bfunc: both get it as \a arg. - * \param arg: user value, - * \param active: when set, button opens with this item visible and selected. - * \param separator_string: when not NULL, this string is used as a separator, - * showing the icon and highlighted text after the last instance of this string. + * \note The item-pointer (referred to below) is a per search item user pointer + * passed to #UI_search_item_add (stored in #uiSearchItems.pointers). + * + * \param search_create_fn: Function to create the menu. + * \param search_update_fn: Function to refresh search content after the search text has changed. + * \param arg: user value. + * \param search_arg_free_fn: When non-null, use this function to free \a arg. + * \param search_exec_fn: Function that executes the action, gets \a arg as the first argument. + * The second argument as the active item-pointer + * \param active: When non-null, this item-pointer item will be visible and selected, + * otherwise the first item will be selected. */ void UI_but_func_search_set(uiBut *but, - uiButSearchCreateFunc search_create_func, - uiButSearchFunc search_func, + uiButSearchCreateFn search_create_fn, + uiButSearchUpdateFn search_update_fn, void *arg, - uiButSearchArgFreeFunc search_arg_free_func, - uiButHandleFunc bfunc, - const char *search_sep_string, + uiButSearchArgFreeFn search_arg_free_fn, + uiButHandleFunc search_exec_fn, void *active) { /* needed since callers don't have access to internal functions * (as an alternative we could expose it) */ - if (search_create_func == NULL) { - search_create_func = ui_searchbox_create_generic; + if (search_create_fn == NULL) { + search_create_fn = ui_searchbox_create_generic; } - if (but->search_arg_free_func != NULL) { - but->search_arg_free_func(but->search_arg); - but->search_arg = NULL; + struct uiButSearchData *search = but->search; + if (search != NULL) { + if (search->arg_free_fn != NULL) { + search->arg_free_fn(but->search->arg); + search->arg = NULL; + } + } + else { + search = MEM_callocN(sizeof(*but->search), __func__); + but->search = search; } - but->search_create_func = search_create_func; - but->search_func = search_func; + search->create_fn = search_create_fn; + search->update_fn = search_update_fn; - but->search_arg = arg; - but->search_arg_free_func = search_arg_free_func; - but->search_sep_string = search_sep_string; + search->arg = arg; + search->arg_free_fn = search_arg_free_fn; - if (bfunc) { + if (search_exec_fn) { #ifdef DEBUG if (but->func) { /* watch this, can be cause of much confusion, see: T47691 */ @@ -6371,7 +6403,7 @@ void UI_but_func_search_set(uiBut *but, __func__); } #endif - UI_but_func_set(but, bfunc, arg, active); + UI_but_func_set(but, search_exec_fn, search->arg, active); } /* search buttons show red-alert if item doesn't exist, not for menus */ @@ -6383,11 +6415,33 @@ void UI_but_func_search_set(uiBut *but, } } +void UI_but_func_search_set_context_menu(uiBut *but, uiButSearchContextMenuFn context_menu_fn) +{ + struct uiButSearchData *search = but->search; + search->context_menu_fn = context_menu_fn; +} + +/** + * \param separator_string: when not NULL, this string is used as a separator, + * showing the icon and highlighted text after the last instance of this string. + */ +void UI_but_func_search_set_sep_string(uiBut *but, const char *search_sep_string) +{ + struct uiButSearchData *search = but->search; + search->sep_string = search_sep_string; +} + +void UI_but_func_search_set_tooltip(uiBut *but, uiButSearchTooltipFn tooltip_fn) +{ + struct uiButSearchData *search = but->search; + search->tooltip_fn = tooltip_fn; +} + /* Callbacks for operator search button. */ -static void operator_enum_search_cb(const struct bContext *C, - void *but, - const char *str, - uiSearchItems *items) +static void operator_enum_search_update_fn(const struct bContext *C, + void *but, + const char *str, + uiSearchItems *items) { wmOperatorType *ot = ((uiBut *)but)->optype; PropertyRNA *prop = ot->prop; @@ -6424,7 +6478,7 @@ static void operator_enum_search_cb(const struct bContext *C, } } -static void operator_enum_call_cb(struct bContext *UNUSED(C), void *but, void *arg2) +static void operator_enum_search_exec_fn(struct bContext *UNUSED(C), void *but, void *arg2) { wmOperatorType *ot = ((uiBut *)but)->optype; PointerRNA *opptr = UI_but_operator_ptr_get(but); /* Will create it if needed! */ @@ -6467,11 +6521,10 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, but = uiDefSearchBut(block, arg, retval, icon, maxlen, x, y, width, height, a1, a2, tip); UI_but_func_search_set(but, ui_searchbox_create_generic, - operator_enum_search_cb, + operator_enum_search_update_fn, but, NULL, - operator_enum_call_cb, - NULL, + operator_enum_search_exec_fn, NULL); but->optype = ot; @@ -6486,6 +6539,13 @@ uiBut *uiDefSearchButO_ptr(uiBlock *block, return but; } +void UI_but_node_link_set(uiBut *but, bNodeSocket *socket, const float draw_color[4]) +{ + but->flag |= UI_BUT_NODE_LINK; + but->custom_data = socket; + rgba_float_to_uchar(but->col, draw_color); +} + /** * push a new event onto event queue to activate the given button * (usually a text-field) upon entering a popup diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 15fc23bc539..8c9768f523d 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -28,12 +28,14 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "BLI_listbase.h" #include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_utildefines.h" #include "BKE_context.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_nla.h" @@ -114,10 +116,40 @@ void ui_but_anim_flag(uiBut *but, float cfra) } } +static uiBut *ui_but_anim_decorate_find_attached_button(uiBut *but_decorate) +{ + uiBut *but_iter = NULL; + + BLI_assert(UI_but_is_decorator(but_decorate)); + BLI_assert(but_decorate->rnasearchpoin.data && but_decorate->rnasearchprop); + + LISTBASE_CIRCULAR_BACKWARD_BEGIN (&but_decorate->block->buttons, but_iter, but_decorate->prev) { + if (but_iter != but_decorate && + ui_but_rna_equals_ex(but_iter, + &but_decorate->rnasearchpoin, + but_decorate->rnasearchprop, + POINTER_AS_INT(but_decorate->custom_data))) { + return but_iter; + } + } + LISTBASE_CIRCULAR_BACKWARD_END(&but_decorate->block->buttons, but_iter, but_decorate->prev); + + return NULL; +} + void ui_but_anim_decorate_update_from_flag(uiBut *but) { - BLI_assert(UI_but_is_decorator(but) && but->prev); - int flag = but->prev->flag; + const uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but); + + if (!but_anim) { + printf("Could not find button with matching property to decorate (%s.%s)\n", + RNA_struct_identifier(but->rnasearchpoin.type), + RNA_property_identifier(but->rnasearchprop)); + return; + } + + int flag = but_anim->flag; + if (flag & UI_BUT_DRIVEN) { but->icon = ICON_DECORATE_DRIVER; } @@ -289,22 +321,26 @@ void ui_but_anim_paste_driver(bContext *C) void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy)) { wmWindowManager *wm = CTX_wm_manager(C); - uiBut *but = arg_but; - but = but->prev; + uiBut *but_decorate = arg_but; + uiBut *but_anim = ui_but_anim_decorate_find_attached_button(but_decorate); + + if (!but_anim) { + return; + } /* FIXME(campbell), swapping active pointer is weak. */ - SWAP(struct uiHandleButtonData *, but->active, but->next->active); + SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active); wm->op_undo_depth++; - if (but->flag & UI_BUT_DRIVEN) { + if (but_anim->flag & UI_BUT_DRIVEN) { /* pass */ /* TODO: report? */ } - else if (but->flag & UI_BUT_ANIMATED_KEY) { + else if (but_anim->flag & UI_BUT_ANIMATED_KEY) { PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_delete_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); } @@ -312,11 +348,11 @@ void ui_but_anim_decorate_cb(bContext *C, void *arg_but, void *UNUSED(arg_dummy) PointerRNA props_ptr; wmOperatorType *ot = WM_operatortype_find("ANIM_OT_keyframe_insert_button", false); WM_operator_properties_create_ptr(&props_ptr, ot); - RNA_boolean_set(&props_ptr, "all", but->rnaindex == -1); + RNA_boolean_set(&props_ptr, "all", but_anim->rnaindex == -1); WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &props_ptr); WM_operator_properties_free(&props_ptr); } - SWAP(struct uiHandleButtonData *, but->active, but->next->active); + SWAP(struct uiHandleButtonData *, but_anim->active, but_decorate->active); wm->op_undo_depth--; } diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c index 5245b724da4..cc370113422 100644 --- a/source/blender/editors/interface/interface_context_menu.c +++ b/source/blender/editors/interface/interface_context_menu.c @@ -962,7 +962,7 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) const PropertyType prop_type = RNA_property_type(but->rnaprop); if (((prop_type == PROP_POINTER) || (prop_type == PROP_STRING && but->type == UI_BTYPE_SEARCH_MENU && - but->search_func == ui_rna_collection_search_cb)) && + but->search->update_fn == ui_rna_collection_search_update_fn)) && ui_jump_to_target_button_poll(C)) { uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump to Target"), diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 9a7e189406c..ebde1d54c07 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -381,6 +381,9 @@ typedef struct uiHandleButtonData { uiSelectContextStore select_others; #endif + /* Text field undo. */ + struct uiUndoStack_Text *undo_stack_text; + /* post activate */ uiButtonActivateType posttype; uiBut *postbut; @@ -417,7 +420,7 @@ typedef struct uiAfterFunc { PropertyRNA *rnaprop; void *search_arg; - uiButSearchArgFreeFunc search_arg_free_func; + uiButSearchArgFreeFn search_arg_free_fn; bContextStore *context; @@ -753,10 +756,12 @@ static void ui_apply_but_func(bContext *C, uiBut *but) after->rnapoin = but->rnapoin; after->rnaprop = but->rnaprop; - after->search_arg_free_func = but->search_arg_free_func; - after->search_arg = but->search_arg; - but->search_arg_free_func = NULL; - but->search_arg = NULL; + if (but->search != NULL) { + after->search_arg_free_fn = but->search->arg_free_fn; + after->search_arg = but->search->arg; + but->search->arg_free_fn = NULL; + but->search->arg = NULL; + } if (but->context) { after->context = CTX_store_copy(but->context); @@ -924,8 +929,8 @@ static void ui_apply_but_funcs_after(bContext *C) MEM_freeN(after.rename_orig); } - if (after.search_arg_free_func) { - after.search_arg_free_func(after.search_arg); + if (after.search_arg_free_fn) { + after.search_arg_free_fn(after.search_arg); } ui_afterfunc_update_preferences_dirty(&after); @@ -2848,6 +2853,23 @@ static bool ui_textedit_delete_selection(uiBut *but, uiHandleButtonData *data) return changed; } +static bool ui_textedit_set_cursor_pos_foreach_glyph(const char *UNUSED(str), + const size_t str_step_ofs, + const rcti *glyph_step_bounds, + const int UNUSED(glyph_advance_x), + const rctf *glyph_bounds, + const int UNUSED(glyph_bearing[2]), + void *user_data) +{ + int *cursor_data = user_data; + float center = glyph_step_bounds->xmin + (BLI_rctf_size_x(glyph_bounds) / 2.0f); + if (cursor_data[0] < center) { + cursor_data[1] = str_step_ofs; + return false; + } + return true; +} + /** * \param x: Screen space cursor location - #wmEvent.x * @@ -2883,8 +2905,7 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con startx += UI_DPI_ICON_SIZE / aspect; } } - /* But this extra .05 makes clicks in between characters feel nicer. */ - startx += ((UI_TEXT_MARGIN_X + 0.05f) * U.widget_unit) / aspect; + startx += (UI_TEXT_MARGIN_X * U.widget_unit) / aspect; /* mouse dragged outside the widget to the left */ if (x < startx) { @@ -2907,48 +2928,24 @@ static void ui_textedit_set_cursor_pos(uiBut *but, uiHandleButtonData *data, con but->pos = but->ofs; } /* mouse inside the widget, mouse coords mapped in widget space */ - else { /* (x >= startx) */ - int pos_i; - - /* keep track of previous distance from the cursor to the char */ - float cdist, cdist_prev = 0.0f; - short pos_prev; - - str_last = &str[strlen(str)]; - - but->pos = pos_prev = ((str_last - str) - but->ofs); - - while (true) { - cdist = startx + BLF_width(fstyle.uifont_id, str + but->ofs, (str_last - str) - but->ofs); - - /* check if position is found */ - if (cdist < x) { - /* check is previous location was in fact closer */ - if ((x - cdist) > (cdist_prev - x)) { - but->pos = pos_prev; - } - break; - } - cdist_prev = cdist; - pos_prev = but->pos; - /* done with tricky distance checks */ - - pos_i = but->pos; - if (but->pos <= 0) { - break; - } - if (BLI_str_cursor_step_prev_utf8(str + but->ofs, but->ofs, &pos_i)) { - but->pos = pos_i; - str_last = &str[but->pos + but->ofs]; - } - else { - break; /* unlikely but possible */ - } - } - but->pos += but->ofs; - if (but->pos < 0) { - but->pos = 0; - } + else { + str_last = &str[but->ofs]; + const int str_last_len = strlen(str_last); + int x_pos = (int)(x - startx); + int glyph_data[2] = { + x_pos, /* horizontal position to test. */ + -1, /* Write the character offset here. */ + }; + BLF_boundbox_foreach_glyph(fstyle.uifont_id, + str + but->ofs, + INT_MAX, + ui_textedit_set_cursor_pos_foreach_glyph, + glyph_data); + /* If value untouched then we are to the right. */ + if (glyph_data[1] == -1) { + glyph_data[1] = str_last_len; + } + but->pos = glyph_data[1] + but->ofs; } if (fstyle.kerning == 1) { @@ -3314,9 +3311,13 @@ static void ui_textedit_begin(bContext *C, uiBut *but, uiHandleButtonData *data) but->selsta = 0; but->selend = len; + /* Initialize undo history tracking. */ + data->undo_stack_text = ui_textedit_undo_stack_create(); + ui_textedit_undo_push(data->undo_stack_text, but->editstr, but->pos); + /* optional searchbox */ if (but->type == UI_BTYPE_SEARCH_MENU) { - data->searchbox = but->search_create_func(C, data->region, but); + data->searchbox = but->search->create_fn(C, data->region, but); ui_searchbox_update(C, data->searchbox, but, true); /* true = reset */ } @@ -3356,6 +3357,9 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) /* ensure menu (popup) too is closed! */ data->escapecancel = true; + + WM_reportf(RPT_ERROR, "Failed to find '%s'", but->editstr); + WM_report_banner_show(); } } @@ -3369,6 +3373,10 @@ static void ui_textedit_end(bContext *C, uiBut *but, uiHandleButtonData *data) WM_cursor_modal_restore(win); + /* Free text undo history text blocks. */ + ui_textedit_undo_stack_destroy(data->undo_stack_text); + data->undo_stack_text = NULL; + #ifdef WITH_INPUT_IME if (win->ime_data) { ui_textedit_ime_end(win, but); @@ -3448,7 +3456,7 @@ static void ui_do_but_textedit( bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) { int retval = WM_UI_HANDLER_CONTINUE; - bool changed = false, inbox = false, update = false; + bool changed = false, inbox = false, update = false, skip_undo_push = false; #ifdef WITH_INPUT_IME wmWindow *win = CTX_wm_window(C); @@ -3468,7 +3476,7 @@ static void ui_do_but_textedit( /* pass */ } else { - ui_searchbox_event(C, data->searchbox, but, event); + ui_searchbox_event(C, data->searchbox, but, data->region, event); } #else ui_searchbox_event(C, data->searchbox, but, event); @@ -3479,6 +3487,16 @@ static void ui_do_but_textedit( case RIGHTMOUSE: case EVT_ESCKEY: if (event->val == KM_PRESS) { + /* Support search context menu. */ + if (event->type == RIGHTMOUSE) { + if (data->searchbox) { + if (ui_searchbox_event(C, data->searchbox, but, data->region, event)) { + /* Only break if the event was handled. */ + break; + } + } + } + #ifdef WITH_INPUT_IME /* skips button handling since it is not wanted */ if (is_ime_composing) { @@ -3587,7 +3605,7 @@ static void ui_do_but_textedit( #ifdef USE_KEYNAV_LIMIT ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event); #endif - ui_searchbox_event(C, data->searchbox, but, event); + ui_searchbox_event(C, data->searchbox, but, data->region, event); break; } if (event->type == WHEELDOWNMOUSE) { @@ -3604,7 +3622,7 @@ static void ui_do_but_textedit( #ifdef USE_KEYNAV_LIMIT ui_mouse_motion_keynav_init(&data->searchbox_keynav_state, event); #endif - ui_searchbox_event(C, data->searchbox, but, event); + ui_searchbox_event(C, data->searchbox, but, data->region, event); break; } if (event->type == WHEELUPMOUSE) { @@ -3670,6 +3688,32 @@ static void ui_do_but_textedit( } retval = WM_UI_HANDLER_BREAK; break; + case EVT_ZKEY: { + /* Ctrl-Z or Ctrl-Shift-Z: Undo/Redo (allowing for OS-Key on Apple). */ + + const bool is_redo = (event->shift != 0); + if ( +#if defined(__APPLE__) + (event->oskey && !IS_EVENT_MOD(event, alt, ctrl)) || +#endif + (event->ctrl && !IS_EVENT_MOD(event, alt, oskey))) { + int undo_pos; + const char *undo_str = ui_textedit_undo( + data->undo_stack_text, is_redo ? 1 : -1, &undo_pos); + if (undo_str != NULL) { + ui_textedit_string_set(but, data, undo_str); + + /* Set the cursor & clear selection. */ + but->pos = undo_pos; + but->selsta = but->pos; + but->selend = but->pos; + changed = true; + } + retval = WM_UI_HANDLER_BREAK; + skip_undo_push = true; + } + break; + } } if ((event->ascii || event->utf8_buf[0]) && (retval == WM_UI_HANDLER_CONTINUE) @@ -3723,6 +3767,11 @@ static void ui_do_but_textedit( #endif if (changed) { + /* The undo stack may be NULL if an event exits editing. */ + if ((skip_undo_push == false) && (data->undo_stack_text != NULL)) { + ui_textedit_undo_push(data->undo_stack_text, data->str, but->pos); + } + /* only do live update when but flag request it (UI_BUT_TEXTEDIT_UPDATE). */ if (update && data->interactive) { ui_apply_but(C, block, but, data, true); @@ -4397,7 +4446,8 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons do_activate = (event->val == KM_RELEASE); } else { - do_activate = (event->val == KM_PRESS); + /* Also use double-clicks to prevent fast clicks to leak to other handlers (T76481). */ + do_activate = ELEM(event->val, KM_PRESS, KM_DBL_CLICK); } } @@ -8213,11 +8263,22 @@ static uiBut *ui_context_rna_button_active(const bContext *C) return ui_context_button_active(CTX_wm_region(C), ui_context_rna_button_active_test); } -uiBut *UI_context_active_but_get(const struct bContext *C) +uiBut *UI_context_active_but_get(const bContext *C) { return ui_context_button_active(CTX_wm_region(C), NULL); } +/* + * Version of #UI_context_active_get() that uses the result of #CTX_wm_menu() + * if set. Does not traverse into parent menus, which may be wanted in some + * cases. + */ +uiBut *UI_context_active_but_get_respect_menu(const bContext *C) +{ + ARegion *ar_menu = CTX_wm_menu(C); + return ui_context_button_active(ar_menu ? ar_menu : CTX_wm_region(C), NULL); +} + uiBut *UI_region_active_but_get(ARegion *region) { return ui_context_button_active(region, NULL); @@ -8814,7 +8875,7 @@ static int ui_handle_button_event(bContext *C, const wmEvent *event, uiBut *but) * This is needed to make sure if a button was active, * it stays active while the mouse is over it. * This avoids adding mousemoves, see: [#33466] */ - if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT)) { + if (ELEM(state_orig, BUTTON_STATE_INIT, BUTTON_STATE_HIGHLIGHT, BUTTON_STATE_WAIT_DRAG)) { if (ui_but_find_mouse_over(region, event) == but) { button_activate_init(C, region, but, BUTTON_ACTIVATE_OVER); } @@ -9339,6 +9400,11 @@ static int ui_handle_menu_button(bContext *C, const wmEvent *event, uiPopupBlock if (event->val == KM_RELEASE) { /* pass, needed so we can exit active menu-items when click-dragging out of them */ } + else if (but->type == UI_BTYPE_SEARCH_MENU) { + /* Pass, needed so search popup can have RMB context menu. + * This may be useful for other interactions which happen in the search popup + * without being directly over the search button. */ + } else if (!ui_block_is_menu(but->block) || ui_block_is_pie_menu(but->block)) { /* pass, skip for dialogs */ } @@ -10772,9 +10838,6 @@ static int ui_popup_handler(bContext *C, const wmEvent *event, void *userdata) if (temp.popup_func) { temp.popup_func(C, temp.popup_arg, temp.retvalue); } - if (temp.optype) { - WM_operator_name_call_ptr(C, temp.optype, temp.opcontext, NULL); - } } else if (temp.cancel_func) { temp.cancel_func(C, temp.popup_arg); @@ -10938,8 +11001,7 @@ void UI_screen_free_active_but(const bContext *C, bScreen *screen) { wmWindow *win = CTX_wm_window(C); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { uiBut *but = ui_region_find_active_but(region); if (but) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 9f9e04eea82..c94a95890c0 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -2320,6 +2320,9 @@ int UI_idcode_icon_get(const int idcode) return ICON_WORLD_DATA; case ID_WS: return ICON_WORKSPACE; + case ID_SIM: + /* TODO: Use correct icon. */ + return ICON_PHYSICS; default: return ICON_NONE; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 3ded62dca7f..3748dbab519 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -41,6 +41,7 @@ struct bContextStore; struct uiHandleButtonData; struct uiLayout; struct uiStyle; +struct uiUndoStack_Text; struct uiWidgetColors; struct wmEvent; struct wmKeyConfig; @@ -147,6 +148,17 @@ enum { /* max amount of items a radial menu (pie menu) can contain */ #define PIE_MAX_ITEMS 8 +struct uiButSearchData { + uiButSearchCreateFn create_fn; + uiButSearchUpdateFn update_fn; + void *arg; + uiButSearchArgFreeFn arg_free_fn; + uiButSearchContextMenuFn context_menu_fn; + uiButSearchTooltipFn tooltip_fn; + + const char *sep_string; +}; + struct uiBut { struct uiBut *next, *prev; int flag, drawflag; @@ -203,11 +215,7 @@ struct uiBut { uiButCompleteFunc autocomplete_func; void *autofunc_arg; - uiButSearchCreateFunc search_create_func; - uiButSearchFunc search_func; - void *search_arg; - uiButSearchArgFreeFunc search_arg_free_func; - const char *search_sep_string; + struct uiButSearchData *search; uiButHandleRenameFunc rename_func; void *rename_arg1; @@ -601,10 +609,8 @@ struct uiPopupBlockHandle { /* for operator popups */ struct wmOperator *popup_op; - struct wmOperatorType *optype; struct ScrArea *ctx_area; struct ARegion *ctx_region; - int opcontext; /* return values */ int butretval; @@ -666,9 +672,10 @@ bool ui_searchbox_inside(struct ARegion *region, int x, int y); int ui_searchbox_find_index(struct ARegion *region, const char *name); void ui_searchbox_update(struct bContext *C, struct ARegion *region, uiBut *but, const bool reset); int ui_searchbox_autocomplete(struct bContext *C, struct ARegion *region, uiBut *but, char *str); -void ui_searchbox_event(struct bContext *C, +bool ui_searchbox_event(struct bContext *C, struct ARegion *region, uiBut *but, + struct ARegion *butregion, const struct wmEvent *event); bool ui_searchbox_apply(uiBut *but, struct ARegion *region); void ui_searchbox_free(struct bContext *C, struct ARegion *region); @@ -709,7 +716,7 @@ uiPopupBlockHandle *ui_popover_panel_create(struct bContext *C, void ui_pie_menu_level_create(uiBlock *block, struct wmOperatorType *ot, const char *propname, - IDProperty *properties, + struct IDProperty *properties, const EnumPropertyItem *items, int totitem, int context, @@ -774,6 +781,16 @@ void ui_draw_but_TRACKPREVIEW(struct ARegion *region, const struct uiWidgetColors *wcol, const rcti *rect); +/* interface_undo.c */ +struct uiUndoStack_Text *ui_textedit_undo_stack_create(void); +void ui_textedit_undo_stack_destroy(struct uiUndoStack_Text *undo_stack); +void ui_textedit_undo_push(struct uiUndoStack_Text *undo_stack, + const char *text, + int cursor_index); +const char *ui_textedit_undo(struct uiUndoStack_Text *undo_stack, + int direction, + int *r_cursor_index); + /* interface_handlers.c */ PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, @@ -800,6 +817,11 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip); void ui_but_clipboard_free(void); +bool ui_but_rna_equals(const uiBut *a, const uiBut *b); +bool ui_but_rna_equals_ex(const uiBut *but, + const PointerRNA *ptr, + const PropertyRNA *prop, + int index); uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new); uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); @@ -869,7 +891,7 @@ void ui_draw_menu_item(const struct uiFontStyle *fstyle, int iconid, int state, bool use_sep, - int *r_name_width); + int *r_xmax); void ui_draw_preview_item( const struct uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state); @@ -1023,9 +1045,10 @@ void UI_OT_eyedropper_driver(struct wmOperatorType *ot); void UI_OT_eyedropper_gpencil_color(struct wmOperatorType *ot); /* interface_util.c */ +bool ui_str_has_word_prefix(const char *haystack, const char *needle, size_t needle_len); /** - * For use with #ui_rna_collection_search_cb. + * For use with #ui_rna_collection_search_update_fn. */ typedef struct uiRNACollectionSearch { PointerRNA target_ptr; @@ -1040,10 +1063,10 @@ typedef struct uiRNACollectionSearch { /* Block has to be stored for freeing butstore (uiBut.block doesn't work with undo). */ uiBlock *butstore_block; } uiRNACollectionSearch; -void ui_rna_collection_search_cb(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items); +void ui_rna_collection_search_update_fn(const struct bContext *C, + void *arg, + const char *str, + uiSearchItems *items); /* interface_ops.c */ bool ui_jump_to_target_button_poll(struct bContext *C); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index cbea32f179a..884e43b4026 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -75,7 +75,7 @@ } \ (void)0 -#define UI_ITEM_PROP_SEP_DIVIDE 0.5f +#define UI_ITEM_PROP_SEP_DIVIDE 0.4f /* uiLayoutRoot */ @@ -135,10 +135,11 @@ enum { UI_ITEM_BOX_ITEM = 1 << 2, /* The item is "inside" a box item */ UI_ITEM_PROP_SEP = 1 << 3, + UI_ITEM_INSIDE_PROP_SEP = 1 << 4, /* Show an icon button next to each property (to set keyframes, show status). * Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */ - UI_ITEM_PROP_DECORATE = 1 << 4, - UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 5, + UI_ITEM_PROP_DECORATE = 1 << 5, + UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 6, }; typedef struct uiButtonItem { @@ -151,8 +152,11 @@ struct uiLayout { uiLayoutRoot *root; bContextStore *context; + uiLayout *parent; ListBase items; + char heading[UI_MAX_NAME_STR]; + /** Sub layout to add child items, if not the layout itself. */ uiLayout *child_items_layout; @@ -1780,6 +1784,7 @@ static void ui_item_rna_size(uiLayout *layout, PropertyType type; PropertySubType subtype; int len, w = 0, h; + bool is_checkbox_only = false; /* arbitrary extended width by type */ type = RNA_property_type(prop); @@ -1791,6 +1796,10 @@ static void ui_item_rna_size(uiLayout *layout, name = "non-empty text"; } else if (type == PROP_BOOLEAN) { + if (icon == ICON_NONE) { + /* Exception for checkboxes, they need a little less space to align nicely. */ + is_checkbox_only = true; + } icon = ICON_DOT; } else if (type == PROP_ENUM) { @@ -1850,6 +1859,9 @@ static void ui_item_rna_size(uiLayout *layout, if (type == PROP_BOOLEAN && name[0]) { w += UI_UNIT_X / 5; } + else if (is_checkbox_only) { + w -= UI_UNIT_X / 4; + } else if (type == PROP_ENUM && !icon_only) { w += UI_UNIT_X / 4; } @@ -1862,6 +1874,57 @@ static void ui_item_rna_size(uiLayout *layout, *r_h = h; } +static bool ui_item_rna_is_expand(PropertyRNA *prop, int index, int item_flag) +{ + const bool is_array = RNA_property_array_check(prop); + const int subtype = RNA_property_subtype(prop); + return is_array && (index == RNA_NO_INDEX) && + ((item_flag & UI_ITEM_R_EXPAND) || + !ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)); +} + +/** + * Find first layout ancestor (or self) with a heading set. + * + * \returns the layout to add the heading to as fallback (i.e. if it can't be placed in a split + * layout). Its #uiLayout.heading member can be cleared to mark the heading as added (so + * it's not added multiple times). Returns a pointer to the heading + */ +static uiLayout *ui_layout_heading_find(uiLayout *cur_layout) +{ + for (uiLayout *parent = cur_layout; parent; parent = parent->parent) { + if (parent->heading[0]) { + return parent; + } + } + + return NULL; +} + +static void ui_layout_heading_label_add(uiLayout *layout, + uiLayout *heading_layout, + bool right_align, + bool respect_prop_split) +{ + const int prev_alignment = layout->alignment; + + if (right_align) { + uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT); + } + + if (respect_prop_split) { + uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE); + } + else { + uiItemL(layout, heading_layout->heading, ICON_NONE); + } + /* After adding the heading label, we have to mark it somehow as added, so it's not added again + * for other items in this layout. For now just clear it. */ + heading_layout->heading[0] = '\0'; + + layout->alignment = prev_alignment; +} + /** * Hack to add further items in a row into the second part of the split layout, so the label part * keeps a fixed size. @@ -1869,7 +1932,14 @@ static void ui_item_rna_size(uiLayout *layout, */ static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split) { + /* Tag item as using property split layout, this is inherited to children so they can get special + * treatment if needed. */ + layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP; + if (layout_parent->item.type == ITEM_LAYOUT_ROW) { + /* Prevent further splits within the row. */ + uiLayoutSetPropSep(layout_parent, false); + layout_parent->child_items_layout = uiLayoutRow(layout_split, true); return layout_parent->child_items_layout; } @@ -1888,13 +1958,18 @@ void uiItemFullR(uiLayout *layout, uiBlock *block = layout->root->block; char namestr[UI_MAX_NAME_STR]; const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0); - - /* By default 'use_prop_sep' uses a separate column for labels. - * This is an exception for check-boxes otherwise only the small checkbox region is clickable. + const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0); + /* Columns can define a heading to insert. If the first item added to a split layout doesn't have + * a label to display in the first column, the heading is inserted there. Otherwise it's inserted + * as a new row before the first item. */ + uiLayout *heading_layout = ui_layout_heading_find(layout); + /* Although checkboxes use the split layout, they are an exception and should only place their + * label in the second column, to not make that almost empty. * * Keep using 'use_prop_sep' instead of disabling it entirely because * we need the ability to have decorators still. */ bool use_prop_sep_split_label = use_prop_sep; + bool use_split_empty_name = (flag & UI_ITEM_R_SPLIT_EMPTY_NAME); #ifdef UI_PROP_DECORATE struct { @@ -2005,6 +2080,9 @@ void uiItemFullR(uiLayout *layout, if (use_prop_sep) { if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { use_prop_sep_split_label = false; + /* For check-boxes we make an exception: We allow showing them in a split row even without + * label. It typically relates to its neighbor items, so no need for an extra label. */ + use_split_empty_name = true; } } #endif @@ -2031,6 +2109,7 @@ void uiItemFullR(uiLayout *layout, /* Split the label / property. */ uiLayout *layout_parent = layout; + if (use_prop_sep) { uiLayout *layout_row = NULL; #ifdef UI_PROP_DECORATE @@ -2041,21 +2120,26 @@ void uiItemFullR(uiLayout *layout, } #endif /* UI_PROP_DECORATE */ - if ((name[0] == '\0') || (use_prop_sep_split_label == false)) { + if ((name[0] == '\0') && !use_split_empty_name) { /* Ensure we get a column when text is not set. */ layout = uiLayoutColumn(layout_row ? layout_row : layout, true); layout->space = 0; + if (heading_layout) { + ui_layout_heading_label_add(layout, heading_layout, false, false); + } } else { - const PropertySubType subtype = RNA_property_subtype(prop); uiLayout *layout_split = uiLayoutSplit( layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true); + bool label_added = false; layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; - if ((index == RNA_NO_INDEX && is_array) && - ((!expand && ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA, PROP_DIRECTION)) == 0)) { + if (!use_prop_sep_split_label) { + /* Pass */ + } + else if (ui_item_rna_is_expand(prop, index, flag)) { char name_with_suffix[UI_MAX_DRAW_STR + 2]; char str[2] = {'\0'}; for (int a = 0; a < len; a++) { @@ -2084,6 +2168,8 @@ void uiItemFullR(uiLayout *layout, ""); but->drawflag |= UI_BUT_TEXT_RIGHT; but->drawflag &= ~UI_BUT_TEXT_LEFT; + + label_added = true; } } else { @@ -2092,13 +2178,17 @@ void uiItemFullR(uiLayout *layout, block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); but->drawflag |= UI_BUT_TEXT_RIGHT; but->drawflag &= ~UI_BUT_TEXT_LEFT; + + label_added = true; } } - if (layout_parent) { - layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); + if (!label_added && heading_layout) { + ui_layout_heading_label_add(layout_sub, heading_layout, true, false); } + layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split); + /* Watch out! We can only write into the new layout now. */ if ((type == PROP_ENUM) && (flag & UI_ITEM_R_EXPAND)) { /* Expanded enums each have their own name. */ @@ -2113,7 +2203,9 @@ void uiItemFullR(uiLayout *layout, } } else { - name = ""; + if (use_prop_sep_split_label) { + name = ""; + } layout = uiLayoutColumn(layout_split, true); } layout->space = 0; @@ -2132,9 +2224,20 @@ void uiItemFullR(uiLayout *layout, #endif /* UI_PROP_DECORATE */ } /* End split. */ + else if (heading_layout) { + /* Could not add heading to split layout, fallback to inserting it to the layout with the + * heading itself. */ + ui_layout_heading_label_add(heading_layout, heading_layout, false, false); + } /* array property */ if (index == RNA_NO_INDEX && is_array) { + if (inside_prop_sep) { + /* Within a split row, add array items to a column so they match the column layout of + * previous items (e.g. transform vector with lock icon for each item). */ + layout = uiLayoutColumn(layout, true); + } + ui_item_array(layout, block, name, @@ -2214,12 +2317,6 @@ void uiItemFullR(uiLayout *layout, if (layout->activate_init) { UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); } - - if (use_prop_sep && (use_prop_sep_split_label == false)) { - /* When the button uses it's own text right align it. */ - but->drawflag |= UI_BUT_TEXT_RIGHT; - but->drawflag &= ~UI_BUT_TEXT_LEFT; - } } /* The resulting button may have the icon set since boolean button drawing @@ -2242,50 +2339,21 @@ void uiItemFullR(uiLayout *layout, #ifdef UI_PROP_DECORATE if (ui_decorate.use_prop_decorate) { - const bool is_anim = RNA_property_animateable(ptr, prop); uiBut *but_decorate = ui_decorate.but ? ui_decorate.but->next : block->buttons.first; + const bool use_blank_decorator = (flag & UI_ITEM_R_FORCE_BLANK_DECORATE); uiLayout *layout_col = uiLayoutColumn(ui_decorate.layout, false); layout_col->space = 0; layout_col->emboss = UI_EMBOSS_NONE; + int i; for (i = 0; i < ui_decorate.len && but_decorate; i++) { + PointerRNA *ptr_dec = use_blank_decorator ? NULL : &but_decorate->rnapoin; + PropertyRNA *prop_dec = use_blank_decorator ? NULL : but_decorate->rnaprop; + /* The icons are set in 'ui_but_anim_flag' */ - if (is_anim) { - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_DOT, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Animate property")); - UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); - but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; - } - else { - /* We may show other information here in future, for now use empty space. */ - but = uiDefIconBut(block, - UI_BTYPE_BUT, - 0, - ICON_BLANK1, - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - ""); - but->flag |= UI_BUT_DISABLED; - } + uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex); + but = block->buttons.last; + /* Order the decorator after the button we decorate, this is used so we can always * do a quick lookup. */ BLI_remlink(&block->buttons, but); @@ -2577,7 +2645,7 @@ static void search_id_collection(StructRNA *ptype, PointerRNA *r_ptr, PropertyRN RNA_STRUCT_END; } -static void ui_rna_collection_search_free_cb(void *ptr) +static void ui_rna_collection_search_arg_free_fn(void *ptr) { uiRNACollectionSearch *coll_search = ptr; UI_butstore_free(coll_search->butstore_block, coll_search->butstore); @@ -2629,10 +2697,9 @@ void ui_but_add_search( UI_but_func_search_set(but, ui_searchbox_create_generic, - ui_rna_collection_search_cb, + ui_rna_collection_search_update_fn, coll_search, - ui_rna_collection_search_free_cb, - NULL, + ui_rna_collection_search_arg_free_fn, NULL, NULL); } @@ -2759,6 +2826,7 @@ static uiBut *ui_item_menu(uiLayout *layout, bool force_menu) { uiBlock *block = layout->root->block; + uiLayout *heading_layout = ui_layout_heading_find(layout); uiBut *but; int w, h; @@ -2788,6 +2856,10 @@ static uiBut *ui_item_menu(uiLayout *layout, } } + if (heading_layout) { + ui_layout_heading_label_add(layout, heading_layout, true, true); + } + if (name[0] && icon) { but = uiDefIconTextMenuBut(block, func, arg, icon, name, 0, 0, w, h, tip); } @@ -2861,6 +2933,91 @@ void uiItemMContents(uiLayout *layout, const char *menuname) UI_menutype_draw(C, mt, layout); } +/** + * Insert a decorator item for a button with the same property as \a prop. + * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a prop. + */ +void uiItemDecoratorR_prop(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index) +{ + uiBlock *block = layout->root->block; + uiBut *but = NULL; + + uiLayout *col; + UI_block_layout_set_current(block, layout); + col = uiLayoutColumn(layout, false); + col->space = 0; + col->emboss = UI_EMBOSS_NONE; + + if (ELEM(NULL, ptr, prop) || !RNA_property_animateable(ptr, prop)) { + but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_BLANK1, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + ""); + but->flag |= UI_BUT_DISABLED; + return; + } + + const bool is_expand = ui_item_rna_is_expand(prop, index, 0); + const bool is_array = RNA_property_array_check(prop); + + /* Loop for the array-case, but only do in case of an expanded array. */ + for (int i = 0; i < (is_expand ? RNA_property_array_length(ptr, prop) : 1); i++) { + but = uiDefIconBut(block, + UI_BTYPE_BUT, + 0, + ICON_DOT, + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + TIP_("Animate property")); + UI_but_func_set(but, ui_but_anim_decorate_cb, but, NULL); + but->flag |= UI_BUT_UNDO | UI_BUT_DRAG_LOCK; + /* Reusing RNA search members, setting actual RNA data has many side-effects. */ + but->rnasearchpoin = *ptr; + but->rnasearchprop = prop; + /* ui_def_but_rna() sets non-array buttons to have a RNA index of 0. */ + but->custom_data = POINTER_FROM_INT((!is_array || is_expand) ? i : index); + } +} + +/** + * Insert a decorator item for a button with the same property as \a prop. + * To force inserting a blank dummy element, NULL can be passed for \a ptr and \a propname. + */ +void uiItemDecoratorR(uiLayout *layout, PointerRNA *ptr, const char *propname, int index) +{ + PropertyRNA *prop = NULL; + + if (ptr && propname) { + /* validate arguments */ + prop = RNA_struct_find_property(ptr, propname); + if (!prop) { + ui_item_disabled(layout, propname); + RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); + return; + } + } + + /* ptr and prop are allowed to be NULL here. */ + uiItemDecoratorR_prop(layout, ptr, prop, index); +} + /* popover */ void uiItemPopoverPanel_ptr( uiLayout *layout, bContext *C, PanelType *pt, const char *name, int icon) @@ -3004,33 +3161,40 @@ void uiItemL(uiLayout *layout, const char *name, int icon) } /** - * Helper to add a label, which handles logic for split property layout if needed. - * - * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where we may - * want to use the logic. For those this helper was added, although it will likely have to be - * extended to support more cases. - * Ideally, #uiItemFullR() could just call this, but it currently has too many special needs. - * - * \return A layout placed in the row after the split layout. Used to place decorator items. + * Normally, we handle the split layout in #uiItemFullR(), but there are other cases where the + * logic is needed. Ideally, #uiItemFullR() could just call this, but it currently has too many + * special needs. + */ +uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout) +{ + uiPropertySplitWrapper split_wrapper = {NULL}; + + uiLayout *layout_row = uiLayoutRow(parent_layout, true); + uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true); + + layout_split->space = 0; + split_wrapper.label_column = uiLayoutColumn(layout_split, true); + split_wrapper.label_column->alignment = UI_LAYOUT_ALIGN_RIGHT; + split_wrapper.property_row = ui_item_prop_split_layout_hack(parent_layout, layout_split); + split_wrapper.decorate_column = uiLayoutColumn(layout_row, true); + + return split_wrapper; +} + +/* + * Helper to add a label and creates a property split layout if needed. */ uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon) { if (layout->item.flag & UI_ITEM_PROP_SEP) { uiBlock *block = uiLayoutGetBlock(layout); - uiLayout *layout_row = uiLayoutRow(layout, true); - uiLayout *layout_split = uiLayoutSplit(layout_row, UI_ITEM_PROP_SEP_DIVIDE, true); - uiLayout *layout_sub = uiLayoutColumn(layout_split, true); - - layout_split->space = layout_sub->space = layout_row->space = 0; - layout_sub->alignment = UI_LAYOUT_ALIGN_RIGHT; + uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout); + /* Further items added to 'layout' will automatically be added to split_wrapper.property_row */ - uiItemL_(layout_sub, text, icon); + uiItemL_(split_wrapper.label_column, text, icon); + UI_block_layout_set_current(block, split_wrapper.property_row); - layout_split = ui_item_prop_split_layout_hack(layout, layout_split); - UI_block_layout_set_current(block, layout_split); - - /* Give caller a new sub-row to place items in. */ - return layout_row; + return split_wrapper.decorate_column; } else { char namestr[UI_MAX_NAME_STR]; @@ -4471,13 +4635,24 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali litem->redalert = layout->redalert; litem->w = layout->w; litem->emboss = layout->emboss; - litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE)); + litem->item.flag = (layout->item.flag & + (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE | UI_ITEM_INSIDE_PROP_SEP)); if (layout->child_items_layout) { BLI_addtail(&layout->child_items_layout->items, litem); + litem->parent = layout->child_items_layout; } else { BLI_addtail(&layout->items, litem); + litem->parent = layout; + } +} + +static void ui_layout_heading_set(uiLayout *layout, const char *heading) +{ + BLI_assert(layout->heading[0] == '\0'); + if (heading) { + STRNCPY(layout->heading, heading); } } @@ -4497,6 +4672,16 @@ uiLayout *uiLayoutRow(uiLayout *layout, bool align) return litem; } +/** + * See #uiLayoutColumnWithHeading(). + */ +uiLayout *uiLayoutRowWithHeading(uiLayout *layout, bool align, const char *heading) +{ + uiLayout *litem = uiLayoutRow(layout, align); + ui_layout_heading_set(litem, heading); + return litem; +} + uiLayout *uiLayoutColumn(uiLayout *layout, bool align) { uiLayout *litem; @@ -4512,6 +4697,19 @@ uiLayout *uiLayoutColumn(uiLayout *layout, bool align) return litem; } +/** + * Variant of #uiLayoutColumn() that sets a heading label for the layout if the first item is + * added through #uiItemFullR(). If split layout is used and the item has no string to add to the + * first split-column, the heading is added there instead. Otherwise the heading inserted with a + * new row. + */ +uiLayout *uiLayoutColumnWithHeading(uiLayout *layout, bool align, const char *heading) +{ + uiLayout *litem = uiLayoutColumn(layout, align); + ui_layout_heading_set(litem, heading); + return litem; +} + uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, bool align) { uiLayoutItemFlow *flow; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 53ea51c9e97..909da434554 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1135,8 +1135,9 @@ static bool jump_to_target_button(bContext *C, bool poll) else if (type == PROP_STRING) { const uiBut *but = UI_context_active_but_get(C); - if (but->type == UI_BTYPE_SEARCH_MENU && but->search_func == ui_rna_collection_search_cb) { - uiRNACollectionSearch *coll_search = but->search_arg; + if (but->type == UI_BTYPE_SEARCH_MENU && but->search && + but->search->update_fn == ui_rna_collection_search_update_fn) { + uiRNACollectionSearch *coll_search = but->search->arg; char str_buf[MAXBONENAME]; char *str_ptr = RNA_property_string_get_alloc(&ptr, prop, str_buf, sizeof(str_buf), NULL); @@ -1678,7 +1679,7 @@ static void UI_OT_button_execute(wmOperatorType *ot) static int button_string_clear_exec(bContext *C, wmOperator *UNUSED(op)) { - uiBut *but = UI_context_active_but_get(C); + uiBut *but = UI_context_active_but_get_respect_menu(C); if (but) { ui_but_active_string_clear_and_exit(C, but); diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 2ad1c25305c..04179721305 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -102,6 +102,7 @@ typedef struct uiHandlePanelData { double starttime; /* dragging */ + bool is_drag_drop; int startx, starty; int startofsx, startofsy; int startsizex, startsizey; @@ -743,7 +744,7 @@ void ui_draw_aligned_panel(uiStyle *style, /* an open panel */ else { /* in some occasions, draw a border */ - if (panel->flag & PNL_SELECT) { + if (panel->flag & PNL_SELECT && !is_subpanel) { if (panel->control & UI_PNL_SOLID) { UI_draw_roundbox_corner_set(UI_CNR_ALL); } @@ -876,6 +877,16 @@ static int get_panel_real_ofsx(Panel *panel) } } +bool UI_panel_is_dragging(const struct Panel *panel) +{ + uiHandlePanelData *data = panel->activedata; + if (!data) { + return false; + } + + return data->is_drag_drop; +} + typedef struct PanelSort { Panel *panel, *orig; } PanelSort; @@ -2458,6 +2469,24 @@ static void ui_handler_remove_panel(bContext *C, void *userdata) panel_activate_state(C, panel, PANEL_STATE_EXIT); } +/** + * Set selection state for a panel and its subpanels. The subpanels need to know they are selected + * too so they can be drawn above their parent when it is dragged. + */ +static void set_panel_selection(Panel *panel, bool value) +{ + if (value) { + panel->flag |= PNL_SELECT; + } + else { + panel->flag &= ~PNL_SELECT; + } + + LISTBASE_FOREACH (Panel *, child, &panel->children) { + set_panel_selection(child, value); + } +} + static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state) { uiHandlePanelData *data = panel->activedata; @@ -2468,6 +2497,8 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS return; } + bool was_drag_drop = (data && data->state == PANEL_STATE_DRAG); + if (state == PANEL_STATE_EXIT || state == PANEL_STATE_ANIMATION) { if (data && data->state != PANEL_STATE_ANIMATION) { /* XXX: @@ -2480,10 +2511,10 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS check_panel_overlap(region, NULL); /* clears */ } - panel->flag &= ~PNL_SELECT; + set_panel_selection(panel, false); } else { - panel->flag |= PNL_SELECT; + set_panel_selection(panel, true); } if (data && data->animtimer) { @@ -2519,6 +2550,12 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS data->startsizex = panel->sizex; data->startsizey = panel->sizey; data->starttime = PIL_check_seconds_timer(); + + /* Remember drag drop state even when animating to the aligned position after dragging. */ + data->is_drag_drop = was_drag_drop; + if (state == PANEL_STATE_DRAG) { + data->is_drag_drop = true; + } } ED_region_tag_redraw(region); diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index 31ef7261eb3..3e34b7f3f8a 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -581,21 +581,18 @@ int UI_popup_menu_invoke(bContext *C, const char *idname, ReportList *reports) /** \name Popup Block API * \{ */ -void UI_popup_block_invoke_ex(bContext *C, - uiBlockCreateFunc func, - void *arg, - void (*arg_free)(void *arg), - const char *opname, - int opcontext) +void UI_popup_block_invoke_ex( + bContext *C, uiBlockCreateFunc func, void *arg, void (*arg_free)(void *arg), bool can_refresh) { wmWindow *window = CTX_wm_window(C); uiPopupBlockHandle *handle; handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, arg_free); handle->popup = true; - handle->can_refresh = true; - handle->optype = (opname) ? WM_operatortype_find(opname, 0) : NULL; - handle->opcontext = opcontext; + + /* It can be useful to disable refresh (even though it will work) + * as this exists text fields which can be disruptive if refresh isn't needed. */ + handle->can_refresh = can_refresh; UI_popup_handlers_add(C, &window->modalhandlers, handle, 0); UI_block_active_only_flagged_buttons(C, handle->region, handle->region->uiblocks.first); @@ -607,7 +604,7 @@ void UI_popup_block_invoke(bContext *C, void *arg, void (*arg_free)(void *arg)) { - UI_popup_block_invoke_ex(C, func, arg, arg_free, NULL, WM_OP_INVOKE_DEFAULT); + UI_popup_block_invoke_ex(C, func, arg, arg_free, true); } void UI_popup_block_ex(bContext *C, diff --git a/source/blender/editors/interface/interface_region_search.c b/source/blender/editors/interface/interface_region_search.c index e2c87891169..0007f6ab9a2 100644 --- a/source/blender/editors/interface/interface_region_search.c +++ b/source/blender/editors/interface/interface_region_search.c @@ -35,6 +35,7 @@ #include "BLI_math.h" +#include "BLI_listbase.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -153,7 +154,8 @@ bool UI_search_item_add(uiSearchItems *items, const char *name, void *poin, int /* Limit flags that can be set so flags such as 'UI_SELECT' aren't accidentally set * which will cause problems, add others as needed. */ - BLI_assert((state & ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT)) == 0); + BLI_assert( + (state & ~(UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)) == 0); if (items->states) { items->states[items->totitem] = state; } @@ -295,10 +297,31 @@ bool ui_searchbox_apply(uiBut *but, ARegion *region) } } -void ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, const wmEvent *event) +static struct ARegion *wm_searchbox_tooltip_init(struct bContext *C, + struct ARegion *region, + int *UNUSED(r_pass), + double *UNUSED(pass_delay), + bool *r_exit_on_event) +{ + *r_exit_on_event = true; + + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->search && but->search->tooltip_fn) { + return but->search->tooltip_fn(C, region, but->search->arg, but->func_arg2); + } + } + } + return NULL; +} + +bool ui_searchbox_event( + bContext *C, ARegion *region, uiBut *but, ARegion *butregion, const wmEvent *event) { uiSearchboxData *data = region->regiondata; int type = event->type, val = event->val; + bool handled = false; + bool tooltip_timer_started = false; if (type == MOUSEPAN) { ui_pan_to_scroll(event, &type, &val); @@ -308,12 +331,36 @@ void ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, const wmEvent case WHEELUPMOUSE: case EVT_UPARROWKEY: ui_searchbox_select(C, region, but, -1); + handled = true; break; case WHEELDOWNMOUSE: case EVT_DOWNARROWKEY: ui_searchbox_select(C, region, but, 1); + handled = true; break; - case MOUSEMOVE: + case RIGHTMOUSE: + if (val) { + if (but->search->context_menu_fn) { + if (data->active != -1) { + /* Check the cursor is over the active element + * (a little confusing if this isn't the case, although it does work). */ + rcti rect; + ui_searchbox_butrect(&rect, data, data->active); + if (BLI_rcti_isect_pt( + &rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) { + + void *active = data->items.pointers[data->active]; + if (but->search->context_menu_fn(C, but->search->arg, active, event)) { + handled = true; + } + } + } + } + } + break; + case MOUSEMOVE: { + bool is_inside = false; + if (BLI_rcti_isect_pt(®ion->winrct, event->x, event->y)) { rcti rect; int a; @@ -322,16 +369,46 @@ void ui_searchbox_event(bContext *C, ARegion *region, uiBut *but, const wmEvent ui_searchbox_butrect(&rect, data, a); if (BLI_rcti_isect_pt( &rect, event->x - region->winrct.xmin, event->y - region->winrct.ymin)) { + is_inside = true; if (data->active != a) { data->active = a; ui_searchbox_select(C, region, but, 0); + handled = true; break; } } } } + + if (U.flag & USER_TOOLTIPS) { + if (is_inside) { + if (data->active != -1) { + ScrArea *area = CTX_wm_area(C); + but->func_arg2 = data->items.pointers[data->active]; + WM_tooltip_timer_init(C, CTX_wm_window(C), area, butregion, wm_searchbox_tooltip_init); + tooltip_timer_started = true; + } + } + } + break; + } } + + if (handled && (tooltip_timer_started == false)) { + wmWindow *win = CTX_wm_window(C); + WM_tooltip_clear(C, win); + } + + return handled; +} + +/** Wrap #uiButSearchUpdateFn callback. */ +static void ui_searchbox_update_fn(bContext *C, uiBut *but, const char *str, uiSearchItems *items) +{ + wmWindow *win = CTX_wm_window(C); + WM_tooltip_clear(C, win); + but->search->update_fn(C, but->search->arg, str, items); } /* region is the search box itself */ @@ -350,9 +427,9 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re data->active = -1; /* handle active */ - if (but->search_func && but->func_arg2) { + if (but->search->update_fn && but->func_arg2) { data->items.active = but->func_arg2; - but->search_func(C, but->search_arg, but->editstr, &data->items); + ui_searchbox_update_fn(C, but, but->editstr, &data->items); data->items.active = NULL; /* found active item, calculate real offset by centering it */ @@ -381,8 +458,8 @@ void ui_searchbox_update(bContext *C, ARegion *region, uiBut *but, const bool re } /* callback */ - if (but->search_func) { - but->search_func(C, but->search_arg, but->editstr, &data->items); + if (but->search->update_fn) { + ui_searchbox_update_fn(C, but, but->editstr, &data->items); } /* handle case where editstr is equal to one of items */ @@ -416,7 +493,7 @@ int ui_searchbox_autocomplete(bContext *C, ARegion *region, uiBut *but, char *st if (str[0]) { data->items.autocpl = UI_autocomplete_begin(str, ui_but_string_get_max_length(but)); - but->search_func(C, but->search_arg, but->editstr, &data->items); + ui_searchbox_update_fn(C, but, but->editstr, &data->items); match = UI_autocomplete_end(data->items.autocpl, str); data->items.autocpl = NULL; @@ -603,7 +680,7 @@ ARegion *ui_searchbox_create_generic(bContext *C, ARegion *butregion, uiBut *but if (but->optype != NULL || (but->drawflag & UI_BUT_HAS_SHORTCUT) != 0) { data->use_sep = true; } - data->sep_string = but->search_sep_string; + data->sep_string = but->search->sep_string; /* compute position */ if (but->block->flag & UI_BLOCK_SEARCH_MENU) { @@ -881,7 +958,7 @@ void ui_but_search_refresh(uiBut *but) items->names[x1] = MEM_callocN(but->hardmax + 1, "search names"); } - but->search_func(but->block->evil_C, but->search_arg, but->drawstr, items); + ui_searchbox_update_fn(but->block->evil_C, but, but->drawstr, items); /* only redalert when we are sure of it, this can miss cases when >10 matches */ if (items->totitem == 0) { diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c new file mode 100644 index 00000000000..0a06f765c0e --- /dev/null +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -0,0 +1,1098 @@ +/* + * 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. + */ + +/** \file + * \ingroup edinterface + * + * Search available menu items via the user interface & key-maps. + * Accessed via the #WM_OT_search_menu operator. + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_action_types.h" +#include "DNA_gpencil_modifier_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_shader_fx_types.h" +#include "DNA_texture_types.h" + +#include "BLI_alloca.h" +#include "BLI_dynstr.h" +#include "BLI_ghash.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" +#include "BLI_math_matrix.h" +#include "BLI_memarena.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_screen.h" + +#include "ED_screen.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "interface_intern.h" + +/* For key-map item access. */ +#include "wm_event_system.h" + +/* -------------------------------------------------------------------- */ +/** \name Menu Search Template Implementation + * \{ */ + +/* Unicode arrow. */ +#define MENU_SEP "\xe2\x96\xb6" + +/** + * Use when #menu_items_from_ui_create is called with `include_all_areas`. + * so we can run the menu item in the area it was extracted from. + */ +struct MenuSearch_Context { + /** + * Index into `Area.ui_type` #EnumPropertyItem or the top-bar when -1. + * Needed to get the display-name to use as a prefix for each menu item. + */ + int space_type_ui_index; + + ScrArea *area; + ARegion *region; +}; + +struct MenuSearch_Parent { + struct MenuSearch_Parent *parent; + MenuType *parent_mt; + const char *drawstr; + + /** Set while writing menu items only. */ + struct MenuSearch_Parent *temp_child; +}; + +struct MenuSearch_Item { + struct MenuSearch_Item *next, *prev; + const char *drawstr; + const char *drawwstr_full; + /** Support a single level sub-menu nesting (for operator buttons that expand). */ + const char *drawstr_submenu; + int icon; + int state; + + struct MenuSearch_Parent *menu_parent; + MenuType *mt; + + enum { + MENU_SEARCH_TYPE_OP = 1, + MENU_SEARCH_TYPE_RNA = 2, + } type; + + union { + /** Operator menu item. */ + struct { + wmOperatorType *type; + PointerRNA *opptr; + short opcontext; + bContextStore *context; + } op; + + /** Property (only for check-box/boolean). */ + struct { + PointerRNA ptr; + PropertyRNA *prop; + int index; + /** Only for enum buttons. */ + int enum_value; + } rna; + }; + + /** Set when we need each menu item to be able to set it's own context. may be NULL. */ + struct MenuSearch_Context *wm_context; +}; + +struct MenuSearch_Data { + /** MenuSearch_Item */ + ListBase items; + /** Use for all small allocations. */ + MemArena *memarena; + + /** Use for context menu, to fake a button to create a context menu. */ + struct { + uiBut but; + uiBlock block; + } context_menu_data; +}; + +static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v) +{ + const struct MenuSearch_Item *menu_item_a = menu_item_a_v; + const struct MenuSearch_Item *menu_item_b = menu_item_b_v; + return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full); +} + +static const char *strdup_memarena(MemArena *memarena, const char *str) +{ + const uint str_size = strlen(str) + 1; + char *str_dst = BLI_memarena_alloc(memarena, str_size); + memcpy(str_dst, str, str_size); + return str_dst; +} + +static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str) +{ + const uint str_size = BLI_dynstr_get_len(dyn_str) + 1; + char *str_dst = BLI_memarena_alloc(memarena, str_size); + BLI_dynstr_get_cstring_ex(dyn_str, str_dst); + return str_dst; +} + +static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *data, + MemArena *memarena, + struct MenuType *mt, + const char *drawstr_submenu, + uiBut *but, + struct MenuSearch_Context *wm_context) +{ + struct MenuSearch_Item *item = NULL; + if (but->optype != NULL) { + item = BLI_memarena_calloc(memarena, sizeof(*item)); + item->type = MENU_SEARCH_TYPE_OP; + + item->op.type = but->optype; + item->op.opcontext = but->opcontext; + item->op.context = but->context; + item->op.opptr = but->opptr; + but->opptr = NULL; + } + else if (but->rnaprop != NULL) { + const int prop_type = RNA_property_type(but->rnaprop); + if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) { + /* Note that these buttons are not prevented, + * but aren't typically used in menus. */ + printf("Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n", + but->drawstr, + mt->idname, + prop_type); + } + else { + item = BLI_memarena_calloc(memarena, sizeof(*item)); + item->type = MENU_SEARCH_TYPE_RNA; + + item->rna.ptr = but->rnapoin; + item->rna.prop = but->rnaprop; + item->rna.index = but->rnaindex; + + if (prop_type == PROP_ENUM) { + item->rna.enum_value = (int)but->hardmax; + } + } + } + + if (item != NULL) { + /* Handle shared settings. */ + item->drawstr = strdup_memarena(memarena, but->drawstr); + item->icon = ui_but_icon(but); + item->state = (but->flag & + (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT | UI_BUT_HAS_SEP_CHAR)); + item->mt = mt; + item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL; + + item->wm_context = wm_context; + + BLI_addtail(&data->items, item); + return true; + } + + return false; +} + +/** + * Populate a fake button from a menu item (use for context menu). + */ +static bool menu_items_to_ui_button(struct MenuSearch_Item *item, uiBut *but) +{ + bool changed = false; + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + but->optype = item->op.type; + but->opcontext = item->op.opcontext; + but->context = item->op.context; + but->opptr = item->op.opptr; + changed = true; + break; + } + case MENU_SEARCH_TYPE_RNA: { + const int prop_type = RNA_property_type(item->rna.prop); + + but->rnapoin = item->rna.ptr; + but->rnaprop = item->rna.prop; + but->rnaindex = item->rna.index; + + if (prop_type == PROP_ENUM) { + but->hardmax = item->rna.enum_value; + } + changed = true; + break; + } + } + + if (changed) { + STRNCPY(but->drawstr, item->drawstr); + char *drawstr_sep = (item->state & UI_BUT_HAS_SEP_CHAR) ? strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + if (drawstr_sep) { + *drawstr_sep = '\0'; + } + + but->icon = item->icon; + but->str = but->strdata; + } + + return changed; +} + +/** + * Populate \a menu_stack with menus from inspecting active key-maps for this context. + */ +static void menu_types_add_from_keymap_items(bContext *C, + wmWindow *win, + ScrArea *area, + ARegion *region, + LinkNode **menuid_stack_p, + GHash *menu_to_kmi, + GSet *menu_tagged) +{ + wmWindowManager *wm = CTX_wm_manager(C); + ListBase *handlers[] = { + region ? ®ion->handlers : NULL, + area ? &area->handlers : NULL, + &win->handlers, + }; + + for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { + if (handlers[handler_index] == NULL) { + continue; + } + LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) { + /* During this loop, UI handlers for nested menus can tag multiple handlers free. */ + if (handler_base->flag & WM_HANDLER_DO_FREE) { + continue; + } + if (handler_base->type != WM_HANDLER_TYPE_KEYMAP) { + continue; + } + + else if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) { + wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; + wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); + if (keymap && WM_keymap_poll(C, keymap)) { + LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { + if (kmi->flag & KMI_INACTIVE) { + continue; + } + if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) { + char menu_idname[MAX_NAME]; + RNA_string_get(kmi->ptr, "name", menu_idname); + MenuType *mt = WM_menutype_find(menu_idname, false); + + if (mt && BLI_gset_add(menu_tagged, mt)) { + /* Unlikely, but possible this will be included twice. */ + BLI_linklist_prepend(menuid_stack_p, mt); + + void **kmi_p; + if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) { + *kmi_p = kmi; + } + } + } + } + } + } + } + } +} + +/** + * Display all operators (last). Developer-only convenience feature. + */ +static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *data) +{ + /* Add to temporary list so we can sort them separately. */ + ListBase operator_items = {NULL, NULL}; + + MemArena *memarena = data->memarena; + GHashIterator iter; + for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); + BLI_ghashIterator_step(&iter)) { + wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + + if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) { + continue; + } + + if (WM_operator_poll((bContext *)C, ot)) { + const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); + + struct MenuSearch_Item *item = NULL; + item = BLI_memarena_calloc(memarena, sizeof(*item)); + item->type = MENU_SEARCH_TYPE_OP; + + item->op.type = ot; + item->op.opcontext = WM_OP_INVOKE_DEFAULT; + item->op.context = NULL; + + char idname_as_py[OP_MAX_TYPENAME]; + char uiname[256]; + WM_operator_py_idname(idname_as_py, ot->idname); + + SNPRINTF(uiname, "%s " MENU_SEP "%s", idname_as_py, ot_ui_name); + + item->drawwstr_full = strdup_memarena(memarena, uiname); + item->drawstr = ot_ui_name; + + item->wm_context = NULL; + + BLI_addtail(&operator_items, item); + } + } + + BLI_listbase_sort(&operator_items, menu_item_sort_by_drawstr_full); + + BLI_movelisttolist(&data->items, &operator_items); +} + +/** + * Create #MenuSearch_Data by inspecting the current context, this uses two methods: + * + * - Look-up pre-defined editor-menus. + * - Look-up key-map items which call menus. + */ +static struct MenuSearch_Data *menu_items_from_ui_create( + bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas) +{ + MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); + /** Map (#MenuType to #MenuSearch_Parent) */ + GHash *menu_parent_map = BLI_ghash_ptr_new(__func__); + GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__); + const uiStyle *style = UI_style_get_dpi(); + + /* Convert into non-ui structure. */ + struct MenuSearch_Data *data = MEM_callocN(sizeof(*data), __func__); + + DynStr *dyn_str = BLI_dynstr_new_memarena(); + + /* Use a stack of menus to handle and discover new menus in passes. */ + LinkNode *menu_stack = NULL; + + /* Tag menu types not to add, either because they have already been added + * or they have been blacklisted. + * Set of #MenuType. */ + GSet *menu_tagged = BLI_gset_ptr_new(__func__); + /** Map (#MenuType -> #wmKeyMapItem). */ + GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__); + + /* Blacklist menus we don't want to show. */ + { + const char *idname_array[] = { + /* While we could include this, it's just showing filenames to load. */ + "TOPBAR_MT_file_open_recent", + }; + for (int i = 0; i < ARRAY_SIZE(idname_array); i++) { + MenuType *mt = WM_menutype_find(idname_array[i], false); + if (mt != NULL) { + BLI_gset_add(menu_tagged, mt); + } + } + } + + /* Collect contexts, one for each 'ui_type'. */ + struct MenuSearch_Context *wm_contexts = NULL; + + const EnumPropertyItem *space_type_ui_items = NULL; + int space_type_ui_items_len = 0; + bool space_type_ui_items_free = false; + + /* Text used as prefix for top-bar menu items. */ + const char *global_menu_prefix = NULL; + + if (include_all_areas) { + /* First create arrays for ui_type. */ + PropertyRNA *prop_ui_type = NULL; + { + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_Area, NULL, &ptr); + prop_ui_type = RNA_struct_find_property(&ptr, "ui_type"); + RNA_property_enum_items(C, + &ptr, + prop_ui_type, + &space_type_ui_items, + &space_type_ui_items_len, + &space_type_ui_items_free); + + wm_contexts = BLI_memarena_calloc(memarena, sizeof(*wm_contexts) * space_type_ui_items_len); + for (int i = 0; i < space_type_ui_items_len; i++) { + wm_contexts[i].space_type_ui_index = -1; + } + } + + bScreen *screen = WM_window_get_active_screen(win); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); + if (region != NULL) { + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_Area, area, &ptr); + const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type); + + int space_type_ui_index = RNA_enum_from_value(space_type_ui_items, space_type_ui); + if (space_type_ui_index == -1) { + continue; + } + + if (wm_contexts[space_type_ui_index].space_type_ui_index != -1) { + ScrArea *area_best = wm_contexts[space_type_ui_index].area; + const uint value_best = (uint)area_best->winx * (uint)area_best->winy; + const uint value_test = (uint)area->winx * (uint)area->winy; + if (value_best > value_test) { + continue; + } + } + + wm_contexts[space_type_ui_index].space_type_ui_index = space_type_ui_index; + wm_contexts[space_type_ui_index].area = area; + wm_contexts[space_type_ui_index].region = region; + } + } + + global_menu_prefix = CTX_IFACE_(RNA_property_translation_context(prop_ui_type), "Top Bar"); + } + + GHashIterator iter; + + for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len; + space_type_ui_index += 1) { + + ScrArea *area = NULL; + ARegion *region = NULL; + struct MenuSearch_Context *wm_context = NULL; + + if (include_all_areas) { + if (space_type_ui_index == -1) { + /* First run without any context, to populate the top-bar without. */ + wm_context = NULL; + area = NULL; + region = NULL; + } + else { + wm_context = &wm_contexts[space_type_ui_index]; + if (wm_context->space_type_ui_index == -1) { + continue; + } + + area = wm_context->area; + region = wm_context->region; + + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + } + else { + area = area_init; + region = region_init; + } + + /* Populate menus from the editors, + * note that we could create a fake header, draw the header and extract the menus + * from the buttons, however this is quite involved and can be avoided as by convention + * each space-type has a single root-menu that headers use. */ + { + const char *idname_array[2] = {NULL}; + int idname_array_len = 0; + + /* Use negative for global (no area) context, populate the top-bar. */ + if (space_type_ui_index == -1) { + idname_array[idname_array_len++] = "TOPBAR_MT_editor_menus"; + } + +#define SPACE_MENU_MAP(space_type, menu_id) \ + case space_type: \ + idname_array[idname_array_len++] = menu_id; \ + break +#define SPACE_MENU_NOP(space_type) \ + case space_type: \ + break + + if (area != NULL) { + SpaceLink *sl = area->spacedata.first; + switch ((eSpace_Type)area->spacetype) { + SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus"); + SPACE_MENU_NOP(SPACE_PROPERTIES); + SPACE_MENU_MAP(SPACE_FILE, "FILEBROWSER_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_ACTION, + (((const SpaceAction *)sl)->mode == SACTCONT_TIMELINE) ? + "TIME_MT_editor_menus" : + "DOPESHEET_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_CLIP, + (((const SpaceClip *)sl)->mode == SC_MODE_TRACKING) ? + "CLIP_MT_tracking_editor_menus" : + "CLIP_MT_masking_editor_menus"); + SPACE_MENU_NOP(SPACE_EMPTY); + SPACE_MENU_NOP(SPACE_SCRIPT); + SPACE_MENU_NOP(SPACE_STATUSBAR); + SPACE_MENU_NOP(SPACE_TOPBAR); + } + } + for (int i = 0; i < idname_array_len; i++) { + MenuType *mt = WM_menutype_find(idname_array[i], false); + if (mt != NULL) { + /* Check if this exists because of 'include_all_areas'. */ + if (BLI_gset_add(menu_tagged, mt)) { + BLI_linklist_prepend(&menu_stack, mt); + } + } + } + } +#undef SPACE_MENU_MAP +#undef SPACE_MENU_NOP + + bool has_keymap_menu_items = false; + + while (menu_stack != NULL) { + MenuType *mt = BLI_linklist_pop(&menu_stack); + if (!WM_menutype_poll(C, mt)) { + continue; + } + + uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); + uiLayout *layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + + UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); + + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); + UI_menutype_draw(C, mt, layout); + + UI_block_end(C, block); + + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + MenuType *mt_from_but = NULL; + /* Support menu titles with dynamic from initial labels + * (used by edit-mesh context menu). */ + if (but->type == UI_BTYPE_LABEL) { + + /* Check if the label is the title. */ + uiBut *but_test = but->prev; + while (but_test && but_test->type == UI_BTYPE_SEPR) { + but_test = but_test->prev; + } + + if (but_test == NULL) { + BLI_ghash_insert( + menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr)); + } + } + else if (menu_items_from_ui_create_item_from_button( + data, memarena, mt, NULL, but, wm_context)) { + /* pass */ + } + else if ((mt_from_but = UI_but_menutype_get(but))) { + + if (BLI_gset_add(menu_tagged, mt_from_but)) { + BLI_linklist_prepend(&menu_stack, mt_from_but); + } + + if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) { + struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena, + sizeof(*menu_parent)); + /* Use brackets for menu key shortcuts, + * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)". + * This is needed so we don't right align sub-menu contents + * we only want to do that for the last menu item, not the path that leads to it. + */ + const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ? + strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + bool drawstr_is_empty = false; + if (drawstr_sep != NULL) { + BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); + /* Detect empty string, fallback to menu name. */ + const char *drawstr = but->drawstr; + int drawstr_len = drawstr_sep - but->drawstr; + if (UNLIKELY(drawstr_len == 0)) { + drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); + drawstr_len = strlen(drawstr); + if (drawstr[0] == '\0') { + drawstr_is_empty = true; + } + } + BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len); + BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1); + menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str); + BLI_dynstr_clear(dyn_str); + } + else { + const char *drawstr = but->drawstr; + if (UNLIKELY(drawstr[0] == '\0')) { + drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); + if (drawstr[0] == '\0') { + drawstr_is_empty = true; + } + } + menu_parent->drawstr = strdup_memarena(memarena, drawstr); + } + menu_parent->parent_mt = mt; + BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent); + + if (drawstr_is_empty) { + printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname); + } + } + } + else if (but->menu_create_func != NULL) { + /* A non 'MenuType' menu button. */ + + /* Only expand one level deep, this is mainly for expanding operator menus. */ + const char *drawstr_submenu = but->drawstr; + + /* +1 to avoid overlap with the current 'block'. */ + uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS); + uiLayout *sub_layout = UI_block_layout( + sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + + UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); + + uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN); + + but->menu_create_func(C, sub_layout, but->poin); + + UI_block_end(C, sub_block); + + LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) { + menu_items_from_ui_create_item_from_button( + data, memarena, mt, drawstr_submenu, sub_but, wm_context); + } + + if (region) { + BLI_remlink(®ion->uiblocks, sub_block); + } + UI_block_free(NULL, sub_block); + } + } + if (region) { + BLI_remlink(®ion->uiblocks, block); + } + UI_block_free(NULL, block); + + /* Add key-map items as a second pass, + * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */ + if ((menu_stack == NULL) && (has_keymap_menu_items == false)) { + has_keymap_menu_items = true; + menu_types_add_from_keymap_items( + C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged); + } + } + } + + LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + item->menu_parent = BLI_ghash_lookup(menu_parent_map, item->mt); + } + + GHASH_ITER (iter, menu_parent_map) { + struct MenuSearch_Parent *menu_parent = BLI_ghashIterator_getValue(&iter); + menu_parent->parent = BLI_ghash_lookup(menu_parent_map, menu_parent->parent_mt); + } + + /* NOTE: currently this builds the full path for each menu item, + * that could be moved into the parent menu. */ + + /* Set names as full paths. */ + LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); + + if (include_all_areas) { + BLI_dynstr_appendf(dyn_str, + "%s: ", + (item->wm_context != NULL) ? + space_type_ui_items[item->wm_context->space_type_ui_index].name : + global_menu_prefix); + } + + if (item->menu_parent != NULL) { + struct MenuSearch_Parent *menu_parent = item->menu_parent; + menu_parent->temp_child = NULL; + while (menu_parent && menu_parent->parent) { + menu_parent->parent->temp_child = menu_parent; + menu_parent = menu_parent->parent; + } + while (menu_parent) { + BLI_dynstr_append(dyn_str, menu_parent->drawstr); + BLI_dynstr_append(dyn_str, " " MENU_SEP " "); + menu_parent = menu_parent->temp_child; + } + } + else { + const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt); + if (drawstr == NULL) { + drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label); + } + BLI_dynstr_append(dyn_str, drawstr); + + wmKeyMapItem *kmi = BLI_ghash_lookup(menu_to_kmi, item->mt); + if (kmi != NULL) { + char kmi_str[128]; + WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); + BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str); + } + + BLI_dynstr_append(dyn_str, " " MENU_SEP " "); + } + + /* Optional nested menu. */ + if (item->drawstr_submenu != NULL) { + BLI_dynstr_append(dyn_str, item->drawstr_submenu); + BLI_dynstr_append(dyn_str, " " MENU_SEP " "); + } + + BLI_dynstr_append(dyn_str, item->drawstr); + + item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str); + BLI_dynstr_clear(dyn_str); + } + BLI_dynstr_free(dyn_str); + + /* Finally sort menu items. + * + * Note: we might want to keep the in-menu order, for now sort all. */ + BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full); + + BLI_ghash_free(menu_parent_map, NULL, NULL); + BLI_ghash_free(menu_display_name_map, NULL, NULL); + + BLI_ghash_free(menu_to_kmi, NULL, NULL); + + BLI_gset_free(menu_tagged, NULL); + + data->memarena = memarena; + + if (include_all_areas) { + CTX_wm_area_set(C, area_init); + CTX_wm_region_set(C, region_init); + + if (space_type_ui_items_free) { + MEM_freeN((void *)space_type_ui_items); + } + } + + /* Include all operators for developers, + * since it can be handy to have a quick way to access any operator, + * including operators being developed which haven't yet been added into the interface. + * + * These are added after all menu items so developers still get normal behavior by default, + * unless searching for something that isn't already in a menu (or scroll down). + * + * Keep this behind a developer only check: + * - Many operators need options to be set to give useful results, see: T74157. + * - User who really prefer to list all operators can use #WM_OT_search_operator. + */ + if (U.flag & USER_DEVELOPER_UI) { + menu_items_from_all_operators(C, data); + } + + return data; +} + +static void menu_search_arg_free_fn(void *data_v) +{ + struct MenuSearch_Data *data = data_v; + LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + if (item->op.opptr != NULL) { + WM_operator_properties_free(item->op.opptr); + MEM_freeN(item->op.opptr); + } + } + case MENU_SEARCH_TYPE_RNA: { + break; + } + } + } + + BLI_memarena_free(data->memarena); + + MEM_freeN(data); +} + +static void menu_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) +{ + struct MenuSearch_Item *item = arg2; + if (item == NULL) { + return; + } + if (item->state & UI_BUT_DISABLED) { + return; + } + + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + switch (item->type) { + case MENU_SEARCH_TYPE_OP: { + CTX_store_set(C, item->op.context); + WM_operator_name_call_ptr(C, item->op.type, item->op.opcontext, item->op.opptr); + CTX_store_set(C, NULL); + break; + } + case MENU_SEARCH_TYPE_RNA: { + PointerRNA *ptr = &item->rna.ptr; + PropertyRNA *prop = item->rna.prop; + int index = item->rna.index; + const int prop_type = RNA_property_type(prop); + bool changed = false; + + if (prop_type == PROP_BOOLEAN) { + const bool is_array = RNA_property_array_check(prop); + if (is_array) { + const bool value = RNA_property_boolean_get_index(ptr, prop, index); + RNA_property_boolean_set_index(ptr, prop, index, !value); + } + else { + const bool value = RNA_property_boolean_get(ptr, prop); + RNA_property_boolean_set(ptr, prop, !value); + } + changed = true; + } + else if (prop_type == PROP_ENUM) { + RNA_property_enum_set(ptr, prop, item->rna.enum_value); + changed = true; + } + + if (changed) { + RNA_property_update(C, ptr, prop); + } + break; + } + } + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } +} + +static void menu_search_update_fn(const bContext *UNUSED(C), + void *arg, + const char *str, + uiSearchItems *items) +{ + struct MenuSearch_Data *data = arg; + const size_t str_len = strlen(str); + const int words_max = (str_len / 2) + 1; + int(*words)[2] = BLI_array_alloca(words, words_max); + + const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); + + for (struct MenuSearch_Item *item = data->items.first; item; item = item->next) { + int index; + + /* match name against all search words */ + for (index = 0; index < words_len; index++) { + if (!ui_str_has_word_prefix(item->drawwstr_full, str + words[index][0], words[index][1])) { + break; + } + } + + if (index == words_len) { + if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state)) { + break; + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Context Menu + * + * This uses a fake button to create a context menu, + * if this ever causes hard to solve bugs we may need to create + * a separate context menu just for the search, however this is fairly involved. + * \{ */ + +static bool ui_search_menu_create_context_menu(struct bContext *C, + void *arg, + void *active, + const struct wmEvent *UNUSED(event)) +{ + struct MenuSearch_Data *data = arg; + struct MenuSearch_Item *item = active; + bool has_menu = false; + + memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + uiBut *but = &data->context_menu_data.but; + uiBlock *block = &data->context_menu_data.block; + + but->block = block; + + if (menu_items_to_ui_button(item, but)) { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + if (ui_popup_context_menu_for_button(C, but)) { + has_menu = true; + } + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } + } + + return has_menu; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Tooltip + * \{ */ + +static struct ARegion *ui_search_menu_create_tooltip(struct bContext *C, + struct ARegion *region, + void *arg, + void *active) +{ + struct MenuSearch_Data *data = arg; + struct MenuSearch_Item *item = active; + + memset(&data->context_menu_data, 0x0, sizeof(data->context_menu_data)); + uiBut *but = &data->context_menu_data.but; + uiBlock *block = &data->context_menu_data.block; + unit_m4(block->winmat); + block->aspect = 1; + + but->block = block; + + /* Place the fake button at the cursor so the tool-tip is places properly. */ + float tip_init[2]; + const wmEvent *event = CTX_wm_window(C)->eventstate; + tip_init[0] = event->x; + tip_init[1] = event->y - (UI_UNIT_Y / 2); + ui_window_to_block_fl(region, block, &tip_init[0], &tip_init[1]); + + but->rect.xmin = tip_init[0]; + but->rect.xmax = tip_init[0]; + but->rect.ymin = tip_init[1]; + but->rect.ymax = tip_init[1]; + + if (menu_items_to_ui_button(item, but)) { + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + + ARegion *region_tip = UI_tooltip_create_from_button(C, region, but, false); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } + return region_tip; + } + + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Menu Search Template Public API + * \{ */ + +void UI_but_func_menu_search(uiBut *but) +{ + bContext *C = but->block->evil_C; + wmWindow *win = CTX_wm_window(C); + ScrArea *area = CTX_wm_area(C); + ARegion *region = CTX_wm_region(C); + /* When run from top-bar scan all areas in the current window. */ + bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR)); + struct MenuSearch_Data *data = menu_items_from_ui_create( + C, win, area, region, include_all_areas); + UI_but_func_search_set(but, + /* Generic callback. */ + ui_searchbox_create_menu, + menu_search_update_fn, + data, + menu_search_arg_free_fn, + menu_search_exec_fn, + NULL); + + UI_but_func_search_set_context_menu(but, ui_search_menu_create_context_menu); + UI_but_func_search_set_tooltip(but, ui_search_menu_create_tooltip); + UI_but_func_search_set_sep_string(but, MENU_SEP); +} + +void uiTemplateMenuSearch(uiLayout *layout) +{ + uiBlock *block; + uiBut *but; + static char search[256] = ""; + + block = uiLayoutGetBlock(layout); + UI_block_layout_set_current(block, layout); + + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); + UI_but_func_menu_search(but); +} + +#undef MENU_SEP + +/** \} */ diff --git a/source/blender/editors/interface/interface_template_search_operator.c b/source/blender/editors/interface/interface_template_search_operator.c new file mode 100644 index 00000000000..cdf87103587 --- /dev/null +++ b/source/blender/editors/interface/interface_template_search_operator.c @@ -0,0 +1,151 @@ +/* + * 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. + */ + +/** \file + * \ingroup edinterface + * + * Search available operators by scanning all and checking their poll function. + * accessed via the #WM_OT_search_operator operator. + */ + +#include <string.h> + +#include "DNA_gpencil_modifier_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_shader_fx_types.h" +#include "DNA_texture_types.h" + +#include "BLI_alloca.h" +#include "BLI_ghash.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_context.h" +#include "BKE_global.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_interface.h" +#include "interface_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Operator Search Template Implementation + * \{ */ + +static void operator_search_exec_fn(bContext *C, void *UNUSED(arg1), void *arg2) +{ + wmOperatorType *ot = arg2; + + if (ot) { + WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL); + } +} + +static void operator_search_update_fn(const bContext *C, + void *UNUSED(arg), + const char *str, + uiSearchItems *items) +{ + GHashIterator iter; + const size_t str_len = strlen(str); + const int words_max = (str_len / 2) + 1; + int(*words)[2] = BLI_array_alloca(words, words_max); + + const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); + + for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); + BLI_ghashIterator_step(&iter)) { + wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); + const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); + int index; + + if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) { + continue; + } + + /* match name against all search words */ + for (index = 0; index < words_len; index++) { + if (!ui_str_has_word_prefix(ot_ui_name, str + words[index][0], words[index][1])) { + break; + } + } + + if (index == words_len) { + if (WM_operator_poll((bContext *)C, ot)) { + char name[256]; + int len = strlen(ot_ui_name); + + /* display name for menu, can hold hotkey */ + BLI_strncpy(name, ot_ui_name, sizeof(name)); + + /* check for hotkey */ + if (len < sizeof(name) - 6) { + if (WM_key_event_operator_string(C, + ot->idname, + WM_OP_EXEC_DEFAULT, + NULL, + true, + &name[len + 1], + sizeof(name) - len - 1)) { + name[len] = UI_SEP_CHAR; + } + } + + if (!UI_search_item_add(items, name, ot, ICON_NONE, 0)) { + break; + } + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Operator Search Template API + * \{ */ + +void UI_but_func_operator_search(uiBut *but) +{ + UI_but_func_search_set(but, + ui_searchbox_create_operator, + operator_search_update_fn, + NULL, + false, + operator_search_exec_fn, + NULL); +} + +void uiTemplateOperatorSearch(uiLayout *layout) +{ + uiBlock *block; + uiBut *but; + static char search[256] = ""; + + block = uiLayoutGetBlock(layout); + UI_block_layout_set_current(block, layout); + + but = uiDefSearchBut( + block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); + UI_but_func_operator_search(but); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index ca9f12a4219..0e67f943ee6 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -37,18 +37,12 @@ #include "DNA_shader_fx_types.h" #include "DNA_texture_types.h" -#include "BLI_alloca.h" -#include "BLI_dynstr.h" #include "BLI_fnmatch.h" -#include "BLI_ghash.h" -#include "BLI_linklist.h" #include "BLI_listbase.h" #include "BLI_math.h" -#include "BLI_memarena.h" #include "BLI_path_util.h" #include "BLI_rect.h" #include "BLI_string.h" -#include "BLI_string_utils.h" #include "BLI_timecode.h" #include "BLI_utildefines.h" @@ -73,7 +67,6 @@ #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_packedFile.h" -#include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_report.h" #include "BKE_scene.h" @@ -103,9 +96,6 @@ #include "PIL_time.h" -/* For key-map item access. */ -#include "wm_event_system.h" - // #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. /* defines for templateID/TemplateSearch */ @@ -213,9 +203,9 @@ static void template_add_button_search_menu(const bContext *C, static uiBlock *template_common_search_menu(const bContext *C, ARegion *region, - uiButSearchFunc search_func, + uiButSearchUpdateFn search_update_fn, void *search_arg, - uiButHandleFunc handle_func, + uiButHandleFunc search_exec_fn, void *active_item, const int preview_rows, const int preview_cols, @@ -289,11 +279,10 @@ static uiBlock *template_common_search_menu(const bContext *C, } UI_but_func_search_set(but, ui_searchbox_create_generic, - search_func, + search_update_fn, search_arg, NULL, - handle_func, - NULL, + search_exec_fn, active_item); UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); @@ -326,7 +315,7 @@ typedef struct TemplateID { } TemplateID; /* Search browse menu, assign */ -static void template_ID_set_property_cb(bContext *C, void *arg_template, void *item) +static void template_ID_set_property_exec_fn(bContext *C, void *arg_template, void *item) { TemplateID *template_ui = (TemplateID *)arg_template; @@ -461,7 +450,8 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) { static TemplateID template_ui; PointerRNA active_item_ptr; - void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb; + void (*id_search_update_fn)( + const bContext *, void *, const char *, uiSearchItems *) = id_search_cb; /* arg_litem is malloced, can be freed by parent button */ template_ui = *((TemplateID *)arg_litem); @@ -471,16 +461,16 @@ static uiBlock *id_search_menu(bContext *C, ARegion *region, void *arg_litem) /* Currently only used for objects. */ if (template_ui.idcode == ID_OB) { if (template_ui.filter == UI_TEMPLATE_ID_FILTER_AVAILABLE) { - id_search_cb_p = id_search_cb_objects_from_scene; + id_search_update_fn = id_search_cb_objects_from_scene; } } } return template_common_search_menu(C, region, - id_search_cb_p, + id_search_update_fn, &template_ui, - template_ID_set_property_cb, + template_ID_set_property_exec_fn, active_item_ptr.data, template_ui.prv_rows, template_ui.prv_cols, @@ -688,6 +678,8 @@ static const char *template_id_browse_tip(const StructRNA *type) return N_("Browse Point Cloud Data to be linked"); case ID_VO: return N_("Browse Volume Data to be linked"); + case ID_SIM: + return N_("Browse Simulation to be linked"); } } return N_("Browse ID data to be linked"); @@ -705,6 +697,8 @@ static const char *template_id_context(StructRNA *type) } return BLT_I18NCONTEXT_DEFAULT; } +#else +# define template_id_context(type) 0 #endif static uiBut *template_id_def_new_but(uiBlock *block, @@ -753,7 +747,8 @@ static uiBut *template_id_def_new_but(uiBlock *block, BLT_I18NCONTEXT_ID_LIGHTPROBE, BLT_I18NCONTEXT_ID_HAIR, BLT_I18NCONTEXT_ID_POINTCLOUD, - BLT_I18NCONTEXT_ID_VOLUME, ); + BLT_I18NCONTEXT_ID_VOLUME, + BLT_I18NCONTEXT_ID_SIMULATION, ); /* Note: BLT_I18N_MSGID_MULTI_CTXT takes a maximum number of parameters, * check the definition to see if a new call must be added when the limit * is exceeded. */ @@ -1187,7 +1182,7 @@ static void template_ID_tabs(bContext *C, 0.0f, 0.0f, ""); - UI_but_funcN_set(&tab->but, template_ID_set_property_cb, MEM_dupallocN(template), id); + UI_but_funcN_set(&tab->but, template_ID_set_property_exec_fn, MEM_dupallocN(template), id); tab->but.custom_data = (void *)id; tab->but.dragpoin = id; tab->menu = mt; @@ -1533,7 +1528,7 @@ typedef struct TemplateSearch { int preview_rows, preview_cols; } TemplateSearch; -static void template_search_handle_cb(bContext *C, void *arg_template, void *item) +static void template_search_exec_fn(bContext *C, void *arg_template, void *item) { TemplateSearch *template_search = arg_template; uiRNACollectionSearch *coll_search = &template_search->search_data; @@ -1557,9 +1552,9 @@ static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_tem return template_common_search_menu(C, region, - ui_rna_collection_search_cb, + ui_rna_collection_search_update_fn, &template_search, - template_search_handle_cb, + template_search_exec_fn, active_ptr.data, template_search.preview_rows, template_search.preview_cols, @@ -1823,14 +1818,14 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) { Object *ob = ob_v; ModifierData *md = md_v; - ModifierData *nmd = modifier_new(md->type); + ModifierData *nmd = BKE_modifier_new(md->type); - modifier_copyData(md, nmd); + BKE_modifier_copydata(md, nmd); nmd->mode &= ~eModifierMode_Virtual; BLI_addhead(&ob->modifiers, nmd); - modifier_unique_name(&ob->modifiers, nmd); + BKE_modifier_unique_name(&ob->modifiers, nmd); ob->partype = PAROBJECT; @@ -1840,20 +1835,26 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) ED_undo_push(C, "Modifier convert to real"); } -static int modifier_can_delete(ModifierData *md) +static bool modifier_can_delete(ModifierData *md) { /* fluid particle modifier can't be deleted here */ if (md->type == eModifierType_ParticleSystem) { short particle_type = ((ParticleSystemModifierData *)md)->psys->part->type; - if (particle_type == PART_FLUID || particle_type == PART_FLUID_FLIP || - particle_type == PART_FLUID_FOAM || particle_type == PART_FLUID_SPRAY || - particle_type == PART_FLUID_BUBBLE || particle_type == PART_FLUID_TRACER || - particle_type == PART_FLUID_SPRAYFOAM || particle_type == PART_FLUID_SPRAYBUBBLE || - particle_type == PART_FLUID_FOAMBUBBLE || particle_type == PART_FLUID_SPRAYFOAMBUBBLE) { - return 0; + if (ELEM(particle_type, + PART_FLUID, + PART_FLUID_FLIP, + PART_FLUID_FOAM, + PART_FLUID_SPRAY, + PART_FLUID_BUBBLE, + PART_FLUID_TRACER, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { + return false; } } - return 1; + return true; } /* Check whether Modifier is a simulation or not, @@ -1888,7 +1889,7 @@ static uiLayout *draw_modifier(uiLayout *layout, int cageIndex, int lastCageIndex) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); PointerRNA ptr; uiBut *but; uiBlock *block; @@ -1982,9 +1983,9 @@ static uiLayout *draw_modifier(uiLayout *layout, } if (ob->type == OB_MESH) { - if (modifier_supportsCage(scene, md) && (index <= lastCageIndex)) { + if (BKE_modifier_supports_cage(scene, md) && (index <= lastCageIndex)) { sub = uiLayoutRow(row, true); - if (index < cageIndex || !modifier_couldBeCage(scene, md)) { + if (index < cageIndex || !BKE_modifier_couldbe_cage(scene, md)) { uiLayoutSetActive(sub, false); } uiItemR(sub, &ptr, "show_on_cage", 0, "", ICON_NONE); @@ -2080,7 +2081,7 @@ static uiLayout *draw_modifier(uiLayout *layout, "apply_as", MODIFIER_APPLY_DATA); - if (modifier_isSameTopology(md) && !modifier_isNonGeometrical(md)) { + if (BKE_modifier_is_same_topology(md) && !BKE_modifier_is_non_geometrical(md)) { uiItemEnumO(row, "OBJECT_OT_modifier_apply", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Apply as Shape Key"), @@ -2147,10 +2148,10 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) UI_block_lock_set(uiLayoutGetBlock(layout), (ob && ID_IS_LINKED(ob)), ERROR_LIBDATA_MESSAGE); /* find modifier and draw it */ - cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0); + cageIndex = BKE_modifiers_get_cage_index(scene, ob, &lastCageIndex, 0); /* XXX virtual modifiers are not accessible for python */ - vmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); + vmd = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); for (i = 0; vmd; i++, vmd = vmd->next) { if (md == vmd) { @@ -2172,7 +2173,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) static uiLayout *gpencil_draw_modifier(uiLayout *layout, Object *ob, GpencilModifierData *md) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); PointerRNA ptr; uiBlock *block; uiLayout *box, *column, *row, *sub; @@ -2315,7 +2316,7 @@ uiLayout *uiTemplateGpencilModifier(uiLayout *layout, bContext *UNUSED(C), Point static uiLayout *gpencil_draw_shaderfx(uiLayout *layout, Object *ob, ShaderFxData *md) { - const ShaderFxTypeInfo *mti = BKE_shaderfxType_getInfo(md->type); + const ShaderFxTypeInfo *mti = BKE_shaderfx_get_info(md->type); PointerRNA ptr; uiBlock *block; uiLayout *box, *column, *row, *sub; @@ -2432,21 +2433,196 @@ uiLayout *uiTemplateShaderFx(uiLayout *layout, bContext *UNUSED(C), PointerRNA * /** \} */ /* -------------------------------------------------------------------- */ -/** \name Operator Redo Buttons Template +/** \name Operator Property Buttons Template * \{ */ -static void template_operator_redo_property_buts_draw( - const bContext *C, wmOperator *op, uiLayout *layout, int layout_flags, bool *r_has_advanced) +typedef struct uiTemplateOperatorPropertyPollParam { + const bContext *C; + wmOperator *op; + short flag; +} uiTemplateOperatorPropertyPollParam; + +#ifdef USE_OP_RESET_BUT +static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), + void *op_pt, + void *UNUSED(arg_dummy2)) +{ + WM_operator_properties_reset((wmOperator *)op_pt); +} +#endif + +static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr), + struct PropertyRNA *prop, + void *user_data) +{ + uiTemplateOperatorPropertyPollParam *params = user_data; + + if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && + (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) { + return false; + } + return params->op->type->poll_property(params->C, params->op, prop); +} + +static eAutoPropButsReturn template_operator_property_buts_draw_single( + const bContext *C, + wmOperator *op, + uiLayout *layout, + const eButLabelAlign label_align, + int layout_flags) +{ + uiBlock *block = uiLayoutGetBlock(layout); + eAutoPropButsReturn return_info = 0; + + if (!op->properties) { + IDPropertyTemplate val = {0}; + op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); + } + + /* poll() on this operator may still fail, + * at the moment there is no nice feedback when this happens just fails silently. */ + if (!WM_operator_repeat_check(C, op)) { + UI_block_lock_set(block, true, "Operator can't' redo"); + return return_info; + } + else { + /* useful for macros where only one of the steps can't be re-done */ + UI_block_lock_clear(block); + } + + if (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { + uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE); + } + + /* menu */ + if (op->type->flag & OPTYPE_PRESET) { + /* XXX, no simple way to get WM_MT_operator_presets.bl_label + * from python! Label remains the same always! */ + PointerRNA op_ptr; + uiLayout *row; + + block->ui_operator = op; + + row = uiLayoutRow(layout, true); + uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE); + + wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); + uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_string_set(&op_ptr, "operator", op->type->idname); + + uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_string_set(&op_ptr, "operator", op->type->idname); + RNA_boolean_set(&op_ptr, "remove_active", true); + } + + if (op->type->ui) { + op->layout = layout; + op->type->ui((bContext *)C, op); + op->layout = NULL; + + /* UI_LAYOUT_OP_SHOW_EMPTY ignored. retun_info is ignored too. We could + * allow ot.ui callback to return this, but not needed right now. */ + } + else { + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags}; + const bool use_prop_split = (layout_flags & UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT) == 0; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + uiLayoutSetPropSep(layout, use_prop_split); + uiLayoutSetPropDecorate(layout, false); + + /* main draw call */ + return_info = uiDefAutoButsRNA( + layout, + &ptr, + op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, + op->type->poll_property ? &user_data : NULL, + op->type->prop, + label_align, + (layout_flags & UI_TEMPLATE_OP_PROPS_COMPACT)); + + if ((return_info & UI_PROP_BUTS_NONE_ADDED) && + (layout_flags & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { + uiItemL(layout, IFACE_("No Properties"), ICON_NONE); + } + } + +#ifdef USE_OP_RESET_BUT + /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled + * but this is not so important if this button is drawn in those cases + * (which isn't all that likely anyway) - campbell */ + if (op->properties->len) { + uiBut *but; + uiLayout *col; /* needed to avoid alignment errors with previous buttons */ + + col = uiLayoutColumn(layout, false); + block = uiLayoutGetBlock(col); + but = uiDefIconTextBut(block, + UI_BTYPE_BUT, + 0, + ICON_FILE_REFRESH, + IFACE_("Reset"), + 0, + 0, + UI_UNIT_X, + UI_UNIT_Y, + NULL, + 0.0, + 0.0, + 0.0, + 0.0, + TIP_("Reset operator defaults")); + UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); + } +#endif + + /* set various special settings for buttons */ + + /* Only do this if we're not refreshing an existing UI. */ + if (block->oldblock == NULL) { + const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; + uiBut *but; + + for (but = block->buttons.first; but; but = but->next) { + /* no undo for buttons for operator redo panels */ + UI_but_flag_disable(but, UI_BUT_UNDO); + + /* only for popups, see [#36109] */ + + /* if button is operator's default property, and a text-field, enable focus for it + * - this is used for allowing operators with popups to rename stuff with fewer clicks + */ + if (is_popup) { + if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { + UI_but_focus_on_enter_event(CTX_wm_window(C), but); + } + } + } + } + + return return_info; +} + +static void template_operator_property_buts_draw_recursive(const bContext *C, + wmOperator *op, + uiLayout *layout, + const eButLabelAlign label_align, + int layout_flags, + bool *r_has_advanced) { if (op->type->flag & OPTYPE_MACRO) { LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) { - template_operator_redo_property_buts_draw(C, macro_op, layout, layout_flags, r_has_advanced); + template_operator_property_buts_draw_recursive( + C, macro_op, layout, label_align, layout_flags, r_has_advanced); } } else { /* Might want to make label_align adjustable somehow. */ - eAutoPropButsReturn return_info = uiTemplateOperatorPropertyButs( - C, layout, op, UI_BUT_LABEL_ALIGN_NONE, layout_flags); + eAutoPropButsReturn return_info = template_operator_property_buts_draw_single( + C, op, layout, label_align, layout_flags); if (return_info & UI_PROP_BUTS_ANY_FAILED_CHECK) { if (r_has_advanced) { *r_has_advanced = true; @@ -2455,6 +2631,61 @@ static void template_operator_redo_property_buts_draw( } } +static bool ui_layout_operator_properties_only_booleans(const bContext *C, + wmWindowManager *wm, + wmOperator *op, + int layout_flags) +{ + if (op->type->flag & OPTYPE_MACRO) { + LISTBASE_FOREACH (wmOperator *, macro_op, &op->macro) { + if (!ui_layout_operator_properties_only_booleans(C, wm, macro_op, layout_flags)) { + return false; + } + } + } + else { + uiTemplateOperatorPropertyPollParam user_data = {.C = C, .op = op, .flag = layout_flags}; + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + RNA_STRUCT_BEGIN (&ptr, prop) { + if (RNA_property_flag(prop) & PROP_HIDDEN) { + continue; + } + if (op->type->poll_property && + !ui_layout_operator_buts_poll_property(&ptr, prop, &user_data)) { + continue; + } + if (RNA_property_type(prop) != PROP_BOOLEAN) { + return false; + } + } + RNA_STRUCT_END; + } + + return true; +} + +/** + * Draw Operator property buttons for redoing execution with different settings. + * This function does not initialize the layout, + * functions can be called on the layout before and after. + */ +void uiTemplateOperatorPropertyButs( + const bContext *C, uiLayout *layout, wmOperator *op, eButLabelAlign label_align, short flag) +{ + wmWindowManager *wm = CTX_wm_manager(C); + + /* If there are only checkbox items, don't use split layout by default. It looks weird if the + * checkboxes only use half the width. */ + if (ui_layout_operator_properties_only_booleans(C, wm, op, flag)) { + flag |= UI_TEMPLATE_OP_PROPS_NO_SPLIT_LAYOUT; + } + + template_operator_property_buts_draw_recursive(C, op, layout, label_align, flag, NULL); +} + void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) { wmOperator *op = WM_operator_last_redo(C); @@ -2487,8 +2718,8 @@ void uiTemplateOperatorRedoProperties(uiLayout *layout, const bContext *C) #endif UI_block_func_handle_set(block, ED_undo_operator_repeat_cb_evt, op); - template_operator_redo_property_buts_draw( - C, op, layout, layout_flags, NULL /* &has_advanced */); + template_operator_property_buts_draw_recursive( + C, op, layout, UI_BUT_LABEL_ALIGN_NONE, layout_flags, NULL /* &has_advanced */); /* Warning! this leaves the handle function for any other users of this block. */ #if 0 @@ -6583,952 +6814,6 @@ void uiTemplateList(uiLayout *layout, /** \} */ /* -------------------------------------------------------------------- */ -/** \name Operator Search Template - * \{ */ - -static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2) -{ - wmOperatorType *ot = arg2; - - if (ot) { - WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, NULL); - } -} - -static bool has_word_prefix(const char *haystack, const char *needle, size_t needle_len) -{ - const char *match = BLI_strncasestr(haystack, needle, needle_len); - if (match) { - if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) { - return true; - } - else { - return has_word_prefix(match + 1, needle, needle_len); - } - } - else { - return false; - } -} - -static void operator_search_cb(const bContext *C, - void *UNUSED(arg), - const char *str, - uiSearchItems *items) -{ - GHashIterator iter; - const size_t str_len = strlen(str); - const int words_max = (str_len / 2) + 1; - int(*words)[2] = BLI_array_alloca(words, words_max); - - const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); - - for (WM_operatortype_iter(&iter); !BLI_ghashIterator_done(&iter); - BLI_ghashIterator_step(&iter)) { - wmOperatorType *ot = BLI_ghashIterator_getValue(&iter); - const char *ot_ui_name = CTX_IFACE_(ot->translation_context, ot->name); - int index; - - if ((ot->flag & OPTYPE_INTERNAL) && (G.debug & G_DEBUG_WM) == 0) { - continue; - } - - /* match name against all search words */ - for (index = 0; index < words_len; index++) { - if (!has_word_prefix(ot_ui_name, str + words[index][0], words[index][1])) { - break; - } - } - - if (index == words_len) { - if (WM_operator_poll((bContext *)C, ot)) { - char name[256]; - int len = strlen(ot_ui_name); - - /* display name for menu, can hold hotkey */ - BLI_strncpy(name, ot_ui_name, sizeof(name)); - - /* check for hotkey */ - if (len < sizeof(name) - 6) { - if (WM_key_event_operator_string(C, - ot->idname, - WM_OP_EXEC_DEFAULT, - NULL, - true, - &name[len + 1], - sizeof(name) - len - 1)) { - name[len] = UI_SEP_CHAR; - } - } - - if (!UI_search_item_add(items, name, ot, ICON_NONE, 0)) { - break; - } - } - } - } -} - -void UI_but_func_operator_search(uiBut *but) -{ - UI_but_func_search_set(but, - ui_searchbox_create_operator, - operator_search_cb, - NULL, - false, - operator_call_cb, - NULL, - NULL); -} - -void uiTemplateOperatorSearch(uiLayout *layout) -{ - uiBlock *block; - uiBut *but; - static char search[256] = ""; - - block = uiLayoutGetBlock(layout); - UI_block_layout_set_current(block, layout); - - but = uiDefSearchBut( - block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); - UI_but_func_operator_search(but); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Menu Search Template - * \{ */ - -/* Unicode arrow. */ -#define MENU_SEP "\xe2\x96\xb6" - -struct MenuSearch_Parent { - struct MenuSearch_Parent *parent; - MenuType *parent_mt; - /* Set while writing menu items only. */ - struct MenuSearch_Parent *temp_child; - const char *drawstr; -}; - -struct MenuSearch_Item { - struct MenuSearch_Item *next, *prev; - const char *drawstr; - const char *drawwstr_full; - /** Support a single level sub-menu nesting (for operator buttons that expand). */ - const char *drawstr_submenu; - int icon; - int state; - - struct MenuSearch_Parent *menu_parent; - MenuType *mt; - - enum { - MENU_SEARCH_TYPE_OP = 1, - MENU_SEARCH_TYPE_RNA = 2, - } type; - - union { - /* Operator menu item. */ - struct { - wmOperatorType *type; - PointerRNA *opptr; - short opcontext; - bContextStore *context; - } op; - - /* Property (only for check-boxe/boolean). */ - struct { - PointerRNA ptr; - PropertyRNA *prop; - int index; - /** Only for enum buttons. */ - int enum_value; - } rna; - }; -}; - -struct MenuSearch_Data { - /** MenuSearch_Item */ - ListBase items; - /** Use for all small allocations. */ - MemArena *memarena; -}; - -static int menu_item_sort_by_drawstr_full(const void *menu_item_a_v, const void *menu_item_b_v) -{ - const struct MenuSearch_Item *menu_item_a = menu_item_a_v; - const struct MenuSearch_Item *menu_item_b = menu_item_b_v; - return strcmp(menu_item_a->drawwstr_full, menu_item_b->drawwstr_full); -} - -static const char *strdup_memarena(MemArena *memarena, const char *str) -{ - const uint str_size = strlen(str) + 1; - char *str_dst = BLI_memarena_alloc(memarena, str_size); - memcpy(str_dst, str, str_size); - return str_dst; -} - -static const char *strdup_memarena_from_dynstr(MemArena *memarena, DynStr *dyn_str) -{ - const uint str_size = BLI_dynstr_get_len(dyn_str) + 1; - char *str_dst = BLI_memarena_alloc(memarena, str_size); - BLI_dynstr_get_cstring_ex(dyn_str, str_dst); - return str_dst; -} - -static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *data, - MemArena *memarena, - struct MenuType *mt, - const char *drawstr_submenu, - uiBut *but) -{ - struct MenuSearch_Item *item = NULL; - if (but->optype != NULL) { - item = BLI_memarena_calloc(memarena, sizeof(*item)); - item->type = MENU_SEARCH_TYPE_OP; - - item->op.type = but->optype; - item->op.opcontext = but->opcontext; - item->op.context = but->context; - item->op.opptr = but->opptr; - but->opptr = NULL; - } - else if (but->rnaprop != NULL) { - const int prop_type = RNA_property_type(but->rnaprop); - if (!ELEM(prop_type, PROP_BOOLEAN, PROP_ENUM)) { - /* Note that these buttons are not prevented, - * but aren't typically used in menus. */ - printf("Button '%s' in menu '%s' is a menu item with unsupported RNA type %d\n", - but->drawstr, - mt->idname, - prop_type); - } - else { - item = BLI_memarena_calloc(memarena, sizeof(*item)); - item->type = MENU_SEARCH_TYPE_RNA; - - item->rna.ptr = but->rnapoin; - item->rna.prop = but->rnaprop; - item->rna.index = but->rnaindex; - - if (prop_type == PROP_ENUM) { - item->rna.enum_value = (int)but->hardmax; - } - } - } - - if (item != NULL) { - /* Handle shared settings. */ - item->drawstr = strdup_memarena(memarena, but->drawstr); - item->icon = ui_but_icon(but); - item->state = (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT)); - item->mt = mt; - item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL; - BLI_addtail(&data->items, item); - return true; - } - - return false; -} - -/** - * Populate \a menu_stack with menus from inspecting active key-maps for this context. - */ -static void menu_types_add_from_keymap_items(bContext *C, - wmWindow *win, - ScrArea *area, - ARegion *region, - LinkNode **menuid_stack_p, - GHash *menu_to_kmi, - GSet *menu_tagged) -{ - wmWindowManager *wm = CTX_wm_manager(C); - ListBase *handlers[] = { - region ? ®ion->handlers : NULL, - area ? &area->handlers : NULL, - &win->handlers, - }; - - for (int handler_index = 0; handler_index < ARRAY_SIZE(handlers); handler_index++) { - if (handlers[handler_index] == NULL) { - continue; - } - LISTBASE_FOREACH (wmEventHandler *, handler_base, handlers[handler_index]) { - /* During this loop, ui handlers for nested menus can tag multiple handlers free. */ - if (handler_base->flag & WM_HANDLER_DO_FREE) { - continue; - } - if (handler_base->type != WM_HANDLER_TYPE_KEYMAP) { - continue; - } - - else if (handler_base->poll == NULL || handler_base->poll(region, win->eventstate)) { - wmEventHandler_Keymap *handler = (wmEventHandler_Keymap *)handler_base; - wmKeyMap *keymap = WM_event_get_keymap_from_handler(wm, handler); - if (keymap && WM_keymap_poll(C, keymap)) { - LISTBASE_FOREACH (wmKeyMapItem *, kmi, &keymap->items) { - if (kmi->flag & KMI_INACTIVE) { - continue; - } - if (STR_ELEM(kmi->idname, "WM_OT_call_menu", "WM_OT_call_menu_pie")) { - char menu_idname[MAX_NAME]; - RNA_string_get(kmi->ptr, "name", menu_idname); - MenuType *mt = WM_menutype_find(menu_idname, false); - - if (mt && BLI_gset_add(menu_tagged, mt)) { - /* Unlikely, but possible this will be included twice. */ - BLI_linklist_prepend(menuid_stack_p, mt); - - void **kmi_p; - if (!BLI_ghash_ensure_p(menu_to_kmi, mt, &kmi_p)) { - *kmi_p = kmi; - } - } - } - } - } - } - } - } -} - -/** - * Create #MenuSearch_Data by inspecting the current context, this uses two methods: - * - * - Look-up pre-defined editor-menus. - * - Look-up key-map items which call menus. - */ -static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, - wmWindow *win, - ScrArea *area, - ARegion *region) -{ - MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); - /** Map (#MenuType to #MenuSearch_Parent) */ - GHash *menu_parent_map = BLI_ghash_ptr_new(__func__); - GHash *menu_display_name_map = BLI_ghash_ptr_new(__func__); - const uiStyle *style = UI_style_get_dpi(); - - /* Convert into non-ui structure. */ - struct MenuSearch_Data *data = MEM_callocN(sizeof(*data), __func__); - - DynStr *dyn_str = BLI_dynstr_new_memarena(); - - /* Use a stack of menus to handle and discover new menus in passes. */ - LinkNode *menu_stack = NULL; - - /* Tag menu types not to add, either because they have already been added - * or they have been blacklisted. - * Set of #MenuType. */ - GSet *menu_tagged = BLI_gset_ptr_new(__func__); - /** Map (#MenuType -> #wmKeyMapItem). */ - GHash *menu_to_kmi = BLI_ghash_ptr_new(__func__); - - /* Blacklist menus we don't want to show. */ - { - const char *idname_array[] = { - /* While we could include this, it's just showing filenames to load. */ - "TOPBAR_MT_file_open_recent", - }; - for (int i = 0; i < ARRAY_SIZE(idname_array); i++) { - MenuType *mt = WM_menutype_find(idname_array[i], false); - if (mt != NULL) { - BLI_gset_add(menu_tagged, mt); - } - } - } - - /* Populate menus from the editors, - * note that we could create a fake header, draw the header and extract the menus - * from the buttons, however this is quite involved and can be avoided as by convention - * each space-type has a single root-menu that headers use. */ - { - const char *idname_array[] = { - "TOPBAR_MT_editor_menus", - /* Optional second menu for the space-type. */ - NULL, - }; - int idname_array_len = 1; - -#define SPACE_MENU_MAP(space_type, menu_id) \ - case space_type: \ - idname_array[idname_array_len++] = menu_id; \ - break -#define SPACE_MENU_NOP(space_type) \ - case space_type: \ - break - - if (area != NULL) { - switch (area->spacetype) { - SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus"); - SPACE_MENU_NOP(SPACE_PROPERTIES); - SPACE_MENU_MAP(SPACE_FILE, "FILE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_ACTION, "DOPESHEET_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_CLIP, - (((const SpaceClip *)area->spacedata.first)->mode == SC_MODE_TRACKING) ? - "CLIP_MT_tracking_editor_menus" : - "CLIP_MT_masking_editor_menus"); - SPACE_MENU_NOP(SPACE_TOPBAR); - SPACE_MENU_NOP(SPACE_STATUSBAR); - default: - printf("Unknown space type '%d'\n", area->spacetype); - } - } - for (int i = 0; i < idname_array_len; i++) { - MenuType *mt = WM_menutype_find(idname_array[i], false); - if (mt != NULL) { - BLI_linklist_prepend(&menu_stack, mt); - BLI_gset_add(menu_tagged, mt); - } - } - } -#undef SPACE_MENU_MAP -#undef SPACE_MENU_NOP - - bool has_keymap_menu_items = false; - - GHashIterator iter; - - while (menu_stack != NULL) { - MenuType *mt = BLI_linklist_pop(&menu_stack); - if (!WM_menutype_poll(C, mt)) { - continue; - } - - uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - - UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); - - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); - UI_menutype_draw(C, mt, layout); - - UI_block_end(C, block); - - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - MenuType *mt_from_but = NULL; - /* Support menu titles with dynamic from initial labels - * (used by edit-mesh context menu). */ - if (but->type == UI_BTYPE_LABEL) { - - /* Check if the label is the title. */ - uiBut *but_test = but->prev; - while (but_test && but_test->type == UI_BTYPE_SEPR) { - but_test = but_test->prev; - } - - if (but_test == NULL) { - BLI_ghash_insert( - menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr)); - } - } - else if (menu_items_from_ui_create_item_from_button(data, memarena, mt, NULL, but)) { - /* pass */ - } - else if ((mt_from_but = UI_but_menutype_get(but))) { - - if (BLI_gset_add(menu_tagged, mt_from_but)) { - BLI_linklist_prepend(&menu_stack, mt_from_but); - } - - if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) { - struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena, - sizeof(*menu_parent)); - /* Use brackets for menu key shortcuts, - * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)". - * This is needed so we don't right align sub-menu contents - * we only want to do that for the last menu item, not the path that leads to it. - */ - const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ? - strrchr(but->drawstr, UI_SEP_CHAR) : - NULL; - bool drawstr_is_empty = false; - if (drawstr_sep != NULL) { - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - /* Detect empty string, fallback to menu name. */ - const char *drawstr = but->drawstr; - int drawstr_len = drawstr_sep - but->drawstr; - if (UNLIKELY(drawstr_len == 0)) { - drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); - drawstr_len = strlen(drawstr); - if (drawstr[0] == '\0') { - drawstr_is_empty = true; - } - } - BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len); - BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1); - menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str); - BLI_dynstr_clear(dyn_str); - } - else { - const char *drawstr = but->drawstr; - if (UNLIKELY(drawstr[0] == '\0')) { - drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); - if (drawstr[0] == '\0') { - drawstr_is_empty = true; - } - } - menu_parent->drawstr = strdup_memarena(memarena, drawstr); - } - menu_parent->parent_mt = mt; - BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent); - - if (drawstr_is_empty) { - printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname); - } - } - } - else if (but->menu_create_func != NULL) { - /* A non 'MenuType' menu button. */ - - /* Only expand one level deep, this is mainly for expanding operator menus. */ - const char *drawstr_submenu = but->drawstr; - - /* +1 to avoid overlap with the current 'block'. */ - uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS); - uiLayout *sub_layout = UI_block_layout( - sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - - UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); - - uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN); - - but->menu_create_func(C, sub_layout, but->poin); - - UI_block_end(C, sub_block); - - LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) { - menu_items_from_ui_create_item_from_button(data, memarena, mt, drawstr_submenu, sub_but); - } - - if (region) { - BLI_remlink(®ion->uiblocks, sub_block); - } - UI_block_free(NULL, sub_block); - } - } - if (region) { - BLI_remlink(®ion->uiblocks, block); - } - UI_block_free(NULL, block); - - /* Add key-map items as a second pass, - * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */ - if ((menu_stack == NULL) && (has_keymap_menu_items == false)) { - has_keymap_menu_items = true; - menu_types_add_from_keymap_items( - C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged); - } - } - - LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { - item->menu_parent = BLI_ghash_lookup(menu_parent_map, item->mt); - } - - GHASH_ITER (iter, menu_parent_map) { - struct MenuSearch_Parent *menu_parent = BLI_ghashIterator_getValue(&iter); - menu_parent->parent = BLI_ghash_lookup(menu_parent_map, menu_parent->parent_mt); - } - - /* NOTE: currently this builds the full path for each menu item, - * that could be moved into the parent menu. */ - - /* Set names as full paths. */ - LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { - if (item->menu_parent != NULL) { - struct MenuSearch_Parent *menu_parent = item->menu_parent; - menu_parent->temp_child = NULL; - while (menu_parent && menu_parent->parent) { - menu_parent->parent->temp_child = menu_parent; - menu_parent = menu_parent->parent; - } - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - while (menu_parent) { - BLI_dynstr_append(dyn_str, menu_parent->drawstr); - BLI_dynstr_append(dyn_str, " " MENU_SEP " "); - menu_parent = menu_parent->temp_child; - } - } - else { - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt); - if (drawstr == NULL) { - drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label); - } - BLI_dynstr_append(dyn_str, drawstr); - - wmKeyMapItem *kmi = BLI_ghash_lookup(menu_to_kmi, item->mt); - if (kmi != NULL) { - char kmi_str[128]; - WM_keymap_item_to_string(kmi, false, kmi_str, sizeof(kmi_str)); - BLI_dynstr_appendf(dyn_str, " (%s)", kmi_str); - } - - BLI_dynstr_append(dyn_str, " " MENU_SEP " "); - } - - /* Optional nested menu. */ - if (item->drawstr_submenu != NULL) { - BLI_dynstr_append(dyn_str, item->drawstr_submenu); - BLI_dynstr_append(dyn_str, " " MENU_SEP " "); - } - - BLI_dynstr_append(dyn_str, item->drawstr); - - item->drawwstr_full = strdup_memarena_from_dynstr(memarena, dyn_str); - BLI_dynstr_clear(dyn_str); - } - BLI_dynstr_free(dyn_str); - - /* Finally sort menu items. - * - * Note: we might want to keep the in-menu order, for now sort all. */ - BLI_listbase_sort(&data->items, menu_item_sort_by_drawstr_full); - - BLI_ghash_free(menu_parent_map, NULL, NULL); - BLI_ghash_free(menu_display_name_map, NULL, NULL); - - BLI_ghash_free(menu_to_kmi, NULL, NULL); - - BLI_gset_free(menu_tagged, NULL); - - data->memarena = memarena; - - return data; -} - -static void menu_items_from_ui_destroy(void *data_v) -{ - struct MenuSearch_Data *data = data_v; - LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { - switch (item->type) { - case MENU_SEARCH_TYPE_OP: { - if (item->op.opptr != NULL) { - WM_operator_properties_free(item->op.opptr); - MEM_freeN(item->op.opptr); - } - } - case MENU_SEARCH_TYPE_RNA: { - break; - } - } - } - - BLI_memarena_free(data->memarena); - - MEM_freeN(data); -} - -static void menu_call_fn(bContext *C, void *UNUSED(arg1), void *arg2) -{ - struct MenuSearch_Item *item = arg2; - if (item == NULL) { - return; - } - if (item->state & UI_BUT_DISABLED) { - return; - } - - switch (item->type) { - case MENU_SEARCH_TYPE_OP: { - CTX_store_set(C, item->op.context); - WM_operator_name_call_ptr(C, item->op.type, item->op.opcontext, item->op.opptr); - CTX_store_set(C, NULL); - break; - } - case MENU_SEARCH_TYPE_RNA: { - PointerRNA *ptr = &item->rna.ptr; - PropertyRNA *prop = item->rna.prop; - int index = item->rna.index; - const int prop_type = RNA_property_type(prop); - bool changed = false; - - if (prop_type == PROP_BOOLEAN) { - const bool is_array = RNA_property_array_check(prop); - if (is_array) { - const bool value = RNA_property_boolean_get_index(ptr, prop, index); - RNA_property_boolean_set_index(ptr, prop, index, !value); - } - else { - const bool value = RNA_property_boolean_get(ptr, prop); - RNA_property_boolean_set(ptr, prop, !value); - } - changed = true; - } - else if (prop_type == PROP_ENUM) { - RNA_property_enum_set(ptr, prop, item->rna.enum_value); - changed = true; - } - - if (changed) { - RNA_property_update(C, ptr, prop); - } - break; - } - } -} - -static void menu_search_cb(const bContext *UNUSED(C), - void *arg, - const char *str, - uiSearchItems *items) -{ - struct MenuSearch_Data *data = arg; - const size_t str_len = strlen(str); - const int words_max = (str_len / 2) + 1; - int(*words)[2] = BLI_array_alloca(words, words_max); - - const int words_len = BLI_string_find_split_words(str, str_len, ' ', words, words_max); - - for (struct MenuSearch_Item *item = data->items.first; item; item = item->next) { - int index; - - /* match name against all search words */ - for (index = 0; index < words_len; index++) { - if (!has_word_prefix(item->drawwstr_full, str + words[index][0], words[index][1])) { - break; - } - } - - if (index == words_len) { - if (!UI_search_item_add(items, item->drawwstr_full, item, item->icon, item->state)) { - break; - } - } - } -} - -void UI_but_func_menu_search(uiBut *but) -{ - bContext *C = but->block->evil_C; - wmWindow *win = CTX_wm_window(C); - ScrArea *area = CTX_wm_area(C); - ARegion *region = CTX_wm_region(C); - struct MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region); - UI_but_func_search_set(but, - ui_searchbox_create_menu, - menu_search_cb, - data, - menu_items_from_ui_destroy, - menu_call_fn, - MENU_SEP, - NULL); -} - -void uiTemplateMenuSearch(uiLayout *layout) -{ - uiBlock *block; - uiBut *but; - static char search[256] = ""; - - block = uiLayoutGetBlock(layout); - UI_block_layout_set_current(block, layout); - - but = uiDefSearchBut( - block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, 0, 0, ""); - UI_but_func_menu_search(but); -} - -#undef MENU_SEP - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Operator Redo Properties Template - * \{ */ - -#ifdef USE_OP_RESET_BUT -static void ui_layout_operator_buts__reset_cb(bContext *UNUSED(C), - void *op_pt, - void *UNUSED(arg_dummy2)) -{ - WM_operator_properties_reset((wmOperator *)op_pt); -} -#endif - -struct uiTemplateOperatorPropertyPollParam { - const bContext *C; - wmOperator *op; - short flag; -}; - -static bool ui_layout_operator_buts_poll_property(struct PointerRNA *UNUSED(ptr), - struct PropertyRNA *prop, - void *user_data) -{ - struct uiTemplateOperatorPropertyPollParam *params = user_data; - if ((params->flag & UI_TEMPLATE_OP_PROPS_HIDE_ADVANCED) && - (RNA_property_tags(prop) & OP_PROP_TAG_ADVANCED)) { - return false; - } - return params->op->type->poll_property(params->C, params->op, prop); -} - -/** - * Draw Operator property buttons for redoing execution with different settings. - * This function does not initialize the layout, - * functions can be called on the layout before and after. - */ -eAutoPropButsReturn uiTemplateOperatorPropertyButs(const bContext *C, - uiLayout *layout, - wmOperator *op, - const eButLabelAlign label_align, - const short flag) -{ - uiBlock *block = uiLayoutGetBlock(layout); - eAutoPropButsReturn return_info = 0; - - if (!op->properties) { - IDPropertyTemplate val = {0}; - op->properties = IDP_New(IDP_GROUP, &val, "wmOperatorProperties"); - } - - /* poll() on this operator may still fail, - * at the moment there is no nice feedback when this happens just fails silently. */ - if (!WM_operator_repeat_check(C, op)) { - UI_block_lock_set(block, true, "Operator can't' redo"); - return return_info; - } - else { - /* useful for macros where only one of the steps can't be re-done */ - UI_block_lock_clear(block); - } - - if (flag & UI_TEMPLATE_OP_PROPS_SHOW_TITLE) { - uiItemL(layout, WM_operatortype_name(op->type, op->ptr), ICON_NONE); - } - - /* menu */ - if (op->type->flag & OPTYPE_PRESET) { - /* XXX, no simple way to get WM_MT_operator_presets.bl_label - * from python! Label remains the same always! */ - PointerRNA op_ptr; - uiLayout *row; - - block->ui_operator = op; - - row = uiLayoutRow(layout, true); - uiItemM(row, "WM_MT_operator_presets", NULL, ICON_NONE); - - wmOperatorType *ot = WM_operatortype_find("WM_OT_operator_preset_add", false); - uiItemFullO_ptr(row, ot, "", ICON_ADD, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_string_set(&op_ptr, "operator", op->type->idname); - - uiItemFullO_ptr(row, ot, "", ICON_REMOVE, NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_string_set(&op_ptr, "operator", op->type->idname); - RNA_boolean_set(&op_ptr, "remove_active", true); - } - - if (op->type->ui) { - op->layout = layout; - op->type->ui((bContext *)C, op); - op->layout = NULL; - - /* UI_LAYOUT_OP_SHOW_EMPTY ignored. return_info is ignored too. We could - * allow ot.ui callback to return this, but not needed right now. */ - } - else { - wmWindowManager *wm = CTX_wm_manager(C); - PointerRNA ptr; - struct uiTemplateOperatorPropertyPollParam user_data = { - .C = C, - .op = op, - .flag = flag, - }; - - RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); - - uiLayoutSetPropSep(layout, true); - uiLayoutSetPropDecorate(layout, false); - - /* main draw call */ - return_info = uiDefAutoButsRNA( - layout, - &ptr, - op->type->poll_property ? ui_layout_operator_buts_poll_property : NULL, - op->type->poll_property ? &user_data : NULL, - op->type->prop, - label_align, - (flag & UI_TEMPLATE_OP_PROPS_COMPACT)); - - if ((return_info & UI_PROP_BUTS_NONE_ADDED) && (flag & UI_TEMPLATE_OP_PROPS_SHOW_EMPTY)) { - uiItemL(layout, IFACE_("No Properties"), ICON_NONE); - } - } - -#ifdef USE_OP_RESET_BUT - /* its possible that reset can do nothing if all have PROP_SKIP_SAVE enabled - * but this is not so important if this button is drawn in those cases - * (which isn't all that likely anyway) - campbell */ - if (op->properties->len) { - uiBut *but; - uiLayout *col; /* needed to avoid alignment errors with previous buttons */ - - col = uiLayoutColumn(layout, false); - block = uiLayoutGetBlock(col); - but = uiDefIconTextBut(block, - UI_BTYPE_BUT, - 0, - ICON_FILE_REFRESH, - IFACE_("Reset"), - 0, - 0, - UI_UNIT_X, - UI_UNIT_Y, - NULL, - 0.0, - 0.0, - 0.0, - 0.0, - TIP_("Reset operator defaults")); - UI_but_func_set(but, ui_layout_operator_buts__reset_cb, op, NULL); - } -#endif - - /* set various special settings for buttons */ - - /* Only do this if we're not refreshing an existing UI. */ - if (block->oldblock == NULL) { - const bool is_popup = (block->flag & UI_BLOCK_KEEP_OPEN) != 0; - uiBut *but; - - for (but = block->buttons.first; but; but = but->next) { - /* no undo for buttons for operator redo panels */ - UI_but_flag_disable(but, UI_BUT_UNDO); - - /* only for popups, see [#36109] */ - - /* if button is operator's default property, and a text-field, enable focus for it - * - this is used for allowing operators with popups to rename stuff with fewer clicks - */ - if (is_popup) { - if ((but->rnaprop == op->type->prop) && (but->type == UI_BTYPE_TEXT)) { - UI_but_focus_on_enter_event(CTX_wm_window(C), but); - } - } - } - } - - return return_info; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Running Jobs Template * \{ */ diff --git a/source/blender/editors/interface/interface_undo.c b/source/blender/editors/interface/interface_undo.c new file mode 100644 index 00000000000..016bc4159db --- /dev/null +++ b/source/blender/editors/interface/interface_undo.c @@ -0,0 +1,139 @@ +/* + * 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. + * + * Copyright (C) 2020 Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup edinterface + * + * Undo stack to use for UI widgets that manage their own editing state. + */ + +#include <string.h> + +#include "BLI_listbase.h" + +#include "DNA_listBase.h" + +#include "MEM_guardedalloc.h" + +#include "interface_intern.h" + +/* -------------------------------------------------------------------- */ +/** \name Text Field Undo Stack + * \{ */ + +typedef struct uiUndoStack_Text_State { + struct uiUndoStack_Text_State *next, *prev; + int cursor_index; + char text[0]; +} uiUndoStack_Text_State; + +typedef struct uiUndoStack_Text { + ListBase states; + uiUndoStack_Text_State *current; +} uiUndoStack_Text; + +static const char *ui_textedit_undo_impl(uiUndoStack_Text *stack, int *r_cursor_index) +{ + /* Don't undo if no data has been pushed yet. */ + if (stack->current == NULL) { + return NULL; + } + + /* Travel backwards in the stack and copy information to the caller. */ + if (stack->current->prev != NULL) { + stack->current = stack->current->prev; + + *r_cursor_index = stack->current->cursor_index; + return stack->current->text; + } + return NULL; +} + +static const char *ui_textedit_redo_impl(uiUndoStack_Text *stack, int *r_cursor_index) +{ + /* Don't redo if no data has been pushed yet. */ + if (stack->current == NULL) { + return NULL; + } + + /* Only redo if new data has not been entered since the last undo. */ + if (stack->current->next) { + stack->current = stack->current->next; + + *r_cursor_index = stack->current->cursor_index; + return stack->current->text; + } + return NULL; +} + +const char *ui_textedit_undo(uiUndoStack_Text *stack, int direction, int *r_cursor_index) +{ + BLI_assert(ELEM(direction, -1, 1)); + if (direction < 0) { + return ui_textedit_undo_impl(stack, r_cursor_index); + } + else { + return ui_textedit_redo_impl(stack, r_cursor_index); + } +} + +/** + * Push the information in the arguments to a new state in the undo stack. + * + * \note Currently the total length of the undo stack is not limited. + */ +void ui_textedit_undo_push(uiUndoStack_Text *stack, const char *text, int cursor_index) +{ + /* Clear all redo actions from the current state. */ + if (stack->current != NULL) { + while (stack->current->next) { + uiUndoStack_Text_State *state = stack->current->next; + BLI_remlink(&stack->states, state); + MEM_freeN(state); + } + } + + /* Create the new state */ + const int text_size = strlen(text) + 1; + stack->current = MEM_mallocN(sizeof(uiUndoStack_Text_State) + text_size, __func__); + stack->current->cursor_index = cursor_index; + memcpy(stack->current->text, text, text_size); + BLI_addtail(&stack->states, stack->current); +} +/** + * Start the undo stack. + * + * \note The current state should be pushed immediately after calling this. + */ +uiUndoStack_Text *ui_textedit_undo_stack_create(void) +{ + uiUndoStack_Text *stack = MEM_mallocN(sizeof(uiUndoStack_Text), __func__); + stack->current = NULL; + BLI_listbase_clear(&stack->states); + + return stack; +} + +void ui_textedit_undo_stack_destroy(uiUndoStack_Text *stack) +{ + BLI_freelistN(&stack->states); + MEM_freeN(stack); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_utils.c b/source/blender/editors/interface/interface_utils.c index 781c8f73b0a..4013e962ce5 100644 --- a/source/blender/editors/interface/interface_utils.c +++ b/source/blender/editors/interface/interface_utils.c @@ -22,6 +22,7 @@ */ #include <assert.h> +#include <ctype.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -51,6 +52,22 @@ #include "interface_intern.h" +bool ui_str_has_word_prefix(const char *haystack, const char *needle, size_t needle_len) +{ + const char *match = BLI_strncasestr(haystack, needle, needle_len); + if (match) { + if ((match == haystack) || (*(match - 1) == ' ') || ispunct(*(match - 1))) { + return true; + } + else { + return ui_str_has_word_prefix(match + 1, needle, needle_len); + } + } + else { + return false; + } +} + /*************************** RNA Utilities ******************************/ uiBut *uiDefAutoButR(uiBlock *block, @@ -294,7 +311,7 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, const bool compact) { eAutoPropButsReturn return_info = UI_PROP_BUTS_NONE_ADDED; - uiLayout *split, *col; + uiLayout *col; const char *name; RNA_STRUCT_BEGIN (ptr, prop) { @@ -325,19 +342,11 @@ eAutoPropButsReturn uiDefAutoButsRNA(uiLayout *layout, } else { BLI_assert(label_align == UI_BUT_LABEL_ALIGN_SPLIT_COLUMN); - split = uiLayoutSplit(layout, 0.5f, false); - - col = uiLayoutColumn(split, false); - uiItemL(col, (is_boolean) ? "" : name, ICON_NONE); - col = uiLayoutColumn(split, false); + col = uiLayoutColumn(layout, true); + /* Let uiItemFullR() create the split layout. */ + uiLayoutSetPropSep(col, true); } - /* May need to add more cases here. - * don't override enum flag names */ - - /* name is shown above, empty name for button below */ - name = (flag & PROP_ENUM_FLAG || is_boolean) ? NULL : ""; - break; } case UI_BUT_LABEL_ALIGN_NONE: @@ -390,10 +399,10 @@ static int sort_search_items_list(const void *a, const void *b) } } -void ui_rna_collection_search_cb(const struct bContext *C, - void *arg, - const char *str, - uiSearchItems *items) +void ui_rna_collection_search_update_fn(const struct bContext *C, + void *arg, + const char *str, + uiSearchItems *items) { uiRNACollectionSearch *data = arg; int i = 0, iconid = 0, flag = RNA_property_flag(data->target_prop); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index ed0f50f4113..4706be205e1 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -41,6 +41,8 @@ #include "BLF_api.h" +#include "ED_node.h" + #include "UI_interface.h" #include "UI_interface_icons.h" @@ -2092,15 +2094,18 @@ static void widget_draw_text_ime_underline(const uiFontStyle *fstyle, #endif /* WITH_INPUT_IME */ static bool widget_draw_text_underline_calc_center_x(const char *UNUSED(str), - const size_t str_ofs, - const rcti *glyph_bounds, - const int glyph_advance_x, + const size_t str_step_ofs, + const rcti *glyph_step_bounds, + const int UNUSED(glyph_advance_x), + const rctf *glyph_bounds, + const int glyph_bearing[2], void *user_data) { /* The index of the character to get, set to the x-position. */ int *ul_data = user_data; - if (ul_data[0] == (int)str_ofs) { - ul_data[1] = glyph_bounds->xmin + (glyph_advance_x / 2); + if (ul_data[0] == (int)str_step_ofs) { + ul_data[1] = glyph_step_bounds->xmin + glyph_bearing[0] + + (BLI_rctf_size_x(glyph_bounds) / 2.0f); /* Early exit. */ return false; } @@ -2418,6 +2423,30 @@ static void widget_draw_extra_icons(const uiWidgetColors *wcol, } } +static void widget_draw_node_link_socket(const uiWidgetColors *wcol, + const rcti *rect, + uiBut *but, + float alpha) +{ + /* Node socket pointer can be passed as custom_data, see UI_but_node_link_set(). */ + if (but->custom_data) { + const float scale = 0.9f / but->block->aspect; + + float col[4]; + rgba_uchar_to_float(col, but->col); + col[3] *= alpha; + + GPU_blend(true); + UI_widgetbase_draw_cache_flush(); + GPU_blend(false); + + ED_node_socket_draw(but->custom_data, rect, col, scale); + } + else { + widget_draw_icon(but, ICON_LAYER_USED, alpha, rect, wcol->text); + } +} + /* draws text and icons for buttons */ static void widget_draw_text_icon(const uiFontStyle *fstyle, const uiWidgetColors *wcol, @@ -2427,15 +2456,27 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, const bool show_menu_icon = ui_but_draw_menu_icon(but); float alpha = (float)wcol->text[3] / 255.0f; char password_str[UI_MAX_DRAW_STR]; + bool no_text_padding = but->drawflag & UI_BUT_NO_TEXT_PADDING; ui_but_text_password_hide(password_str, but, false); /* check for button text label */ if (ELEM(but->type, UI_BTYPE_MENU, UI_BTYPE_POPOVER) && (but->flag & UI_BUT_NODE_LINK)) { rcti temp = *rect; - temp.xmin = rect->xmax - BLI_rcti_size_y(rect) - 1; - widget_draw_icon(but, ICON_LAYER_USED, alpha, &temp, wcol->text); - rect->xmax = temp.xmin; + const int size = BLI_rcti_size_y(rect) + 1; /* Not the icon size! */ + + if (but->drawflag & UI_BUT_ICON_LEFT) { + temp.xmax = rect->xmin + size; + rect->xmin = temp.xmax; + /* Further padding looks off. */ + no_text_padding = true; + } + else { + temp.xmin = rect->xmax - size; + rect->xmax = temp.xmin; + } + + widget_draw_node_link_socket(wcol, &temp, but, alpha); } /* If there's an icon too (made with uiDefIconTextBut) then draw the icon @@ -2520,28 +2561,30 @@ static void widget_draw_text_icon(const uiFontStyle *fstyle, rect->xmin += icon_size + icon_padding; } - int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; - if (but->editstr) { - rect->xmin += text_padding; - } - else if (but->flag & UI_BUT_DRAG_MULTI) { - bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL; - if (text_is_edited) { + if (!no_text_padding) { + int text_padding = (UI_TEXT_MARGIN_X * U.widget_unit) / but->block->aspect; + if (but->editstr) { rect->xmin += text_padding; } - } - else if (but->drawflag & UI_BUT_TEXT_LEFT) { - - /* Reduce the left padding for labels without an icon. */ - if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && - !ui_block_is_menu(but->block)) { - text_padding /= 2; + else if (but->flag & UI_BUT_DRAG_MULTI) { + bool text_is_edited = ui_but_drag_multi_edit_get(but) != NULL; + if (text_is_edited) { + rect->xmin += text_padding; + } } + else if (but->drawflag & UI_BUT_TEXT_LEFT) { - rect->xmin += text_padding; - } - else if (but->drawflag & UI_BUT_TEXT_RIGHT) { - rect->xmax -= text_padding; + /* Reduce the left padding for labels without an icon. */ + if ((but->type == UI_BTYPE_LABEL) && !(but->flag & UI_HAS_ICON) && + !ui_block_is_menu(but->block)) { + text_padding /= 2; + } + + rect->xmin += text_padding; + } + else if (but->drawflag & UI_BUT_TEXT_RIGHT) { + rect->xmax -= text_padding; + } } /* Menu contains sub-menu items with triangle icon on their right. Shortcut @@ -4145,10 +4188,10 @@ static void widget_optionbut(uiWidgetColors *wcol, /* smaller */ delta = 1 + BLI_rcti_size_y(&recttemp) / 8; - recttemp.xmin += delta; - recttemp.ymin += delta; - recttemp.xmax -= delta; - recttemp.ymax -= delta; + BLI_rcti_resize( + &recttemp, BLI_rcti_size_x(&recttemp) - delta * 2, BLI_rcti_size_y(&recttemp) - delta * 2); + /* Keep one edge in place. */ + BLI_rcti_translate(&recttemp, text_before_widget ? delta : -delta, 0); rad = wcol->roundness * BLI_rcti_size_y(&recttemp); round_box_edges(&wtb, UI_CNR_ALL, &recttemp, rad); @@ -4160,13 +4203,13 @@ static void widget_optionbut(uiWidgetColors *wcol, widgetbase_draw(&wtb, wcol); - /* text space */ - const float offset = BLI_rcti_size_y(rect) * 0.7 + delta; + /* Text space - factor is really just eyeballed. */ + const float offset = delta * 0.9; if (text_before_widget) { - rect->xmax -= offset; + rect->xmax = recttemp.xmin - offset; } else { - rect->xmin += offset; + rect->xmin = recttemp.xmax + offset; } } @@ -4723,9 +4766,14 @@ void ui_draw_but(const bContext *C, struct ARegion *region, uiStyle *style, uiBu case UI_BTYPE_CHECKBOX_N: if (!(but->flag & UI_HAS_ICON)) { wt = widget_type(UI_WTYPE_CHECKBOX); + if ((but->drawflag & (UI_BUT_TEXT_LEFT | UI_BUT_TEXT_RIGHT)) == 0) { but->drawflag |= UI_BUT_TEXT_LEFT; } + /* widget_optionbut() carefully sets the text rectangle for fine tuned paddings. If the + * text drawing were to add its own padding, DPI and zoom factor would be applied twice + * in the final padding, so it's difficult to control it. */ + but->drawflag |= UI_BUT_NO_TEXT_PADDING; } else { wt = widget_type(UI_WTYPE_TOGGLE); @@ -5279,15 +5327,23 @@ void ui_draw_tooltip_background(const uiStyle *UNUSED(style), uiBlock *UNUSED(bl wt->draw(&wt->wcol, rect, 0, 0); } -/* helper call to draw a menu item without button */ -/* state: UI_ACTIVE or 0 */ +/** + * Helper call to draw a menu item without a button. + * + * \param state: The state of the button, + * typically #UI_ACTIVE, #UI_BUT_DISABLED, #UI_BUT_INACTIVE. + * \param use_sep: When true, characters after the last #UI_SEP_CHAR are right aligned, + * use for displaying key shortcuts. + * \param r_xmax: The right hand position of the text, this takes into the icon, + * padding and text clipping when there is not enough room to display the full text. + */ void ui_draw_menu_item(const uiFontStyle *fstyle, rcti *rect, const char *name, int iconid, int state, bool use_sep, - int *r_name_width) + int *r_xmax) { uiWidgetType *wt = widget_type(UI_WTYPE_MENU_ITEM); rcti _rect = *rect; @@ -5350,23 +5406,8 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, &xofs, &yofs, &info); - if (r_name_width != NULL) { - *r_name_width = xofs + info.width; - } - } - - /* part text right aligned */ - if (use_sep) { - if (cpoin) { - rect->xmax = _rect.xmax - 5; - UI_fontstyle_draw(fstyle, - rect, - cpoin + 1, - wt->wcol.text, - &(struct uiFontStyleDraw_Params){ - .align = UI_STYLE_TEXT_RIGHT, - }); - *cpoin = UI_SEP_CHAR; + if (r_xmax != NULL) { + *r_xmax = xofs + info.width; } } @@ -5386,6 +5427,24 @@ void ui_draw_menu_item(const uiFontStyle *fstyle, UI_icon_draw_ex(xs, ys, iconid, aspect, 1.0f, 0.0f, wt->wcol.text, false); GPU_blend(false); } + + /* part text right aligned */ + if (use_sep) { + if (cpoin) { + /* Set inactive state for grayed out text. */ + wt->state(wt, state | UI_BUT_INACTIVE, 0); + + rect->xmax = _rect.xmax - 5; + UI_fontstyle_draw(fstyle, + rect, + cpoin + 1, + wt->wcol.text, + &(struct uiFontStyleDraw_Params){ + .align = UI_STYLE_TEXT_RIGHT, + }); + *cpoin = UI_SEP_CHAR; + } + } } void ui_draw_preview_item( diff --git a/source/blender/editors/interface/view2d.c b/source/blender/editors/interface/view2d.c index c07166b9ad2..f8419ba3eba 100644 --- a/source/blender/editors/interface/view2d.c +++ b/source/blender/editors/interface/view2d.c @@ -60,7 +60,7 @@ #include "interface_intern.h" -static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers); +static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize); /* -------------------------------------------------------------------- */ /** \name Internal Utilities @@ -134,7 +134,7 @@ void UI_view2d_mask_from_win(const View2D *v2d, rcti *r_mask) * * \param mask_scroll: Optionally clamp scrollbars by this region. */ -static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scroll) +static void view2d_masks(View2D *v2d, const rcti *mask_scroll) { int scroll; @@ -144,26 +144,24 @@ static void view2d_masks(View2D *v2d, bool check_scrollers, const rcti *mask_scr mask_scroll = &v2d->mask; } - if (check_scrollers) { - /* check size if hiding flag is set: */ - if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { - if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { - v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; - } - else { - v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; - } + /* check size if hiding flag is set: */ + if (v2d->scroll & V2D_SCROLL_HORIZONTAL_HIDE) { + if (!(v2d->scroll & V2D_SCROLL_HORIZONTAL_HANDLES)) { + if (BLI_rctf_size_x(&v2d->tot) > BLI_rctf_size_x(&v2d->cur)) { + v2d->scroll &= ~V2D_SCROLL_HORIZONTAL_FULLR; + } + else { + v2d->scroll |= V2D_SCROLL_HORIZONTAL_FULLR; } } - if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { - if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { - if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { - v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; - } - else { - v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; - } + } + if (v2d->scroll & V2D_SCROLL_VERTICAL_HIDE) { + if (!(v2d->scroll & V2D_SCROLL_VERTICAL_HANDLES)) { + if (BLI_rctf_size_y(&v2d->tot) + 0.01f > BLI_rctf_size_y(&v2d->cur)) { + v2d->scroll &= ~V2D_SCROLL_VERTICAL_FULLR; + } + else { + v2d->scroll |= V2D_SCROLL_VERTICAL_FULLR; } } } @@ -385,8 +383,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) v2d->winx = winx; v2d->winy = winy; - /* set masks (always do), but leave scroller scheck to totrect_set */ - view2d_masks(v2d, 0, NULL); + view2d_masks(v2d, NULL); if (do_init) { /* Visible by default. */ @@ -394,13 +391,12 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) } /* set 'tot' rect before setting cur? */ - /* XXX confusing stuff here still - - * I made this function not check scroller hide - that happens in totrect_set */ + /* XXX confusing stuff here still */ if (tot_changed) { UI_view2d_totRect_set_resize(v2d, winx, winy, !do_init); } else { - ui_view2d_curRect_validate_resize(v2d, !do_init, 0); + ui_view2d_curRect_validate_resize(v2d, !do_init); } } @@ -409,7 +405,7 @@ void UI_view2d_region_reinit(View2D *v2d, short type, int winx, int winy) * 'cur' is not allowed to be: larger than max, smaller than min, or outside of 'tot' */ // XXX pre2.5 -> this used to be called test_view2d() -static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mask_scrollers) +static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize) { float totwidth, totheight, curwidth, curheight, width, height; float winx, winy; @@ -851,12 +847,12 @@ static void ui_view2d_curRect_validate_resize(View2D *v2d, bool resize, bool mas } /* set masks */ - view2d_masks(v2d, mask_scrollers, NULL); + view2d_masks(v2d, NULL); } void UI_view2d_curRect_validate(View2D *v2d) { - ui_view2d_curRect_validate_resize(v2d, 0, 1); + ui_view2d_curRect_validate_resize(v2d, false); } /* ------------------ */ @@ -982,22 +978,10 @@ void UI_view2d_curRect_reset(View2D *v2d) /* Change the size of the maximum viewable area (i.e. 'tot' rect) */ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resize) { - // int scroll = view2d_scroll_mapped(v2d->scroll); - /* don't do anything if either value is 0 */ width = abs(width); height = abs(height); - /* hrumf! */ - /* XXX: there are work arounds for this in the panel and file browse code. */ - /* round to int, because this is called with width + V2D_SCROLL_WIDTH */ - // if (scroll & V2D_SCROLL_HORIZONTAL) { - // width -= (int)V2D_SCROLL_WIDTH; - // } - // if (scroll & V2D_SCROLL_VERTICAL) { - // height -= (int)V2D_SCROLL_HEIGHT; - // } - if (ELEM(0, width, height)) { if (G.debug & G_DEBUG) { printf("Error: View2D totRect set exiting: v2d=%p width=%d height=%d\n", @@ -1047,20 +1031,12 @@ void UI_view2d_totRect_set_resize(View2D *v2d, int width, int height, bool resiz } /* make sure that 'cur' rect is in a valid state as a result of these changes */ - ui_view2d_curRect_validate_resize(v2d, resize, 1); + ui_view2d_curRect_validate_resize(v2d, resize); } void UI_view2d_totRect_set(View2D *v2d, int width, int height) { - int scroll = view2d_scroll_mapped(v2d->scroll); - - UI_view2d_totRect_set_resize(v2d, width, height, 0); - - /* solve bad recursion... if scroller state changed, - * mask is different, so you get different rects */ - if (scroll != view2d_scroll_mapped(v2d->scroll)) { - UI_view2d_totRect_set_resize(v2d, width, height, 0); - } + UI_view2d_totRect_set_resize(v2d, width, height, false); } bool UI_view2d_tab_set(View2D *v2d, int tab) @@ -1258,7 +1234,7 @@ void UI_view2d_view_restore(const bContext *C) * \{ */ /* Draw a constant grid in given 2d-region */ -void UI_view2d_constant_grid_draw(View2D *v2d, float step) +void UI_view2d_constant_grid_draw(const View2D *v2d, float step) { float start_x, start_y; int count_x, count_y; @@ -1330,7 +1306,8 @@ void UI_view2d_constant_grid_draw(View2D *v2d, float step) } /* Draw a multi-level grid in given 2d-region */ -void UI_view2d_multi_grid_draw(View2D *v2d, int colorid, float step, int level_size, int totlevels) +void UI_view2d_multi_grid_draw( + const View2D *v2d, int colorid, float step, int level_size, int totlevels) { /* Exit if there is nothing to draw */ if (totlevels == 0) { @@ -1448,7 +1425,7 @@ View2DScrollers *UI_view2d_scrollers_calc(View2D *v2d, const rcti *mask_custom) scrollers = MEM_callocN(sizeof(View2DScrollers), "View2DScrollers"); /* Always update before drawing (for dynamically sized scrollers). */ - view2d_masks(v2d, false, mask_custom); + view2d_masks(v2d, mask_custom); vert = v2d->vert; hor = v2d->hor; @@ -1801,7 +1778,8 @@ bool UI_view2d_view_to_region_clip( * \param x, y: Coordinates to convert. * \param r_region_x, r_region_y: Resultant coordinates. */ -void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) +void UI_view2d_view_to_region( + const View2D *v2d, float x, float y, int *r_region_x, int *r_region_y) { /* step 1: express given coordinates as proportional values */ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); @@ -1817,7 +1795,7 @@ void UI_view2d_view_to_region(View2D *v2d, float x, float y, int *r_region_x, in } void UI_view2d_view_to_region_fl( - View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) + const View2D *v2d, float x, float y, float *r_region_x, float *r_region_y) { /* express given coordinates as proportional values */ x = (x - v2d->cur.xmin) / BLI_rctf_size_x(&v2d->cur); @@ -1828,7 +1806,7 @@ void UI_view2d_view_to_region_fl( *r_region_y = v2d->mask.ymin + (y * BLI_rcti_size_y(&v2d->mask)); } -void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect_dst) +void UI_view2d_view_to_region_rcti(const View2D *v2d, const rctf *rect_src, rcti *rect_dst) { const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)}; const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)}; @@ -1849,7 +1827,7 @@ void UI_view2d_view_to_region_rcti(View2D *v2d, const rctf *rect_src, rcti *rect clamp_rctf_to_rcti(rect_dst, &rect_tmp); } -void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4]) +void UI_view2d_view_to_region_m4(const View2D *v2d, float matrix[4][4]) { rctf mask; unit_m4(matrix); @@ -1857,7 +1835,7 @@ void UI_view2d_view_to_region_m4(View2D *v2d, float matrix[4][4]) BLI_rctf_transform_calc_m4_pivot_min(&v2d->cur, &mask, matrix); } -bool UI_view2d_view_to_region_rcti_clip(View2D *v2d, const rctf *rect_src, rcti *rect_dst) +bool UI_view2d_view_to_region_rcti_clip(const View2D *v2d, const rctf *rect_src, rcti *rect_dst) { const float cur_size[2] = {BLI_rctf_size_x(&v2d->cur), BLI_rctf_size_y(&v2d->cur)}; const float mask_size[2] = {BLI_rcti_size_x(&v2d->mask), BLI_rcti_size_y(&v2d->mask)}; @@ -1983,7 +1961,7 @@ float UI_view2d_scale_get_y(const View2D *v2d) /** * Same as ``UI_view2d_scale_get() - 1.0f / x, y`` */ -void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y) +void UI_view2d_scale_get_inverse(const View2D *v2d, float *r_x, float *r_y) { if (r_x) { *r_x = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask); @@ -1997,7 +1975,7 @@ void UI_view2d_scale_get_inverse(View2D *v2d, float *r_x, float *r_y) * Simple functions for consistent center offset access. * Used by node editor to shift view center for each individual node tree. */ -void UI_view2d_center_get(struct View2D *v2d, float *r_x, float *r_y) +void UI_view2d_center_get(const struct View2D *v2d, float *r_x, float *r_y) { /* get center */ if (r_x) { diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c index af17303466b..551f7989d53 100644 --- a/source/blender/editors/io/io_alembic.c +++ b/source/blender/editors/io/io_alembic.c @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_alembic.h b/source/blender/editors/io/io_alembic.h index 881712fe630..ecd8c1818f8 100644 --- a/source/blender/editors/io/io_alembic.h +++ b/source/blender/editors/io/io_alembic.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_cache.c b/source/blender/editors/io/io_cache.c index 6c5abf60272..045a293f71b 100644 --- a/source/blender/editors/io/io_cache.c +++ b/source/blender/editors/io/io_cache.c @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_cache.h b/source/blender/editors/io/io_cache.h index 25548dcdbce..c6fc50a236e 100644 --- a/source/blender/editors/io/io_cache.h +++ b/source/blender/editors/io/io_cache.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Blender Foundation. diff --git a/source/blender/editors/io/io_usd.c b/source/blender/editors/io/io_usd.c index bb527ee6a3f..262b15c63e5 100644 --- a/source/blender/editors/io/io_usd.c +++ b/source/blender/editors/io/io_usd.c @@ -10,7 +10,7 @@ * 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, + * 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) 2019 Blender Foundation. diff --git a/source/blender/editors/io/io_usd.h b/source/blender/editors/io/io_usd.h index 4738e1c348d..c794dc744df 100644 --- a/source/blender/editors/io/io_usd.h +++ b/source/blender/editors/io/io_usd.h @@ -10,7 +10,7 @@ * 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, + * 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) 2019 Blender Foundation. diff --git a/source/blender/editors/mask/mask_select.c b/source/blender/editors/mask/mask_select.c index a6dece91eb0..c8cddced99c 100644 --- a/source/blender/editors/mask/mask_select.c +++ b/source/blender/editors/mask/mask_select.c @@ -521,8 +521,8 @@ void MASK_OT_select_box(wmOperatorType *ot) * \{ */ static bool do_lasso_select_mask(bContext *C, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { ScrArea *area = CTX_wm_area(C); @@ -540,7 +540,7 @@ static bool do_lasso_select_mask(bContext *C, } /* get rectangle from operator */ - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ LISTBASE_FOREACH (MaskLayer *, mask_layer, &mask->masklayers) { @@ -573,7 +573,7 @@ static bool do_lasso_select_mask(bContext *C, &screen_co[1]); if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) { + BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) { BKE_mask_point_select_set(point, select); BKE_mask_point_select_set_handle(point, MASK_WHICH_HANDLE_BOTH, select); changed = true; @@ -594,14 +594,14 @@ static bool do_lasso_select_mask(bContext *C, static int clip_lasso_select_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - do_lasso_select_mask(C, mcords, mcords_tot, sel_op); + do_lasso_select_mask(C, mcoords, mcoords_len, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/mesh/editmesh_extrude.c b/source/blender/editors/mesh/editmesh_extrude.c index 23f622ac359..bf6c5a2f829 100644 --- a/source/blender/editors/mesh/editmesh_extrude.c +++ b/source/blender/editors/mesh/editmesh_extrude.c @@ -226,6 +226,7 @@ static bool edbm_extrude_ex(Object *obedit, char htype, const char hflag, const bool use_normal_flip, + const bool use_dissolve_ortho_edges, const bool use_mirror, const bool use_select_history) { @@ -241,6 +242,7 @@ static bool edbm_extrude_ex(Object *obedit, BMO_op_init(bm, &extop, BMO_FLAG_DEFAULTS, "extrude_face_region"); BMO_slot_bool_set(extop.slots_in, "use_normal_flip", use_normal_flip); + BMO_slot_bool_set(extop.slots_in, "use_dissolve_ortho_edges", use_dissolve_ortho_edges); BMO_slot_bool_set(extop.slots_in, "use_select_history", use_select_history); BMO_slot_buffer_from_enabled_hflag(bm, &extop, extop.slots_in, "geom", htype, hflag); @@ -312,7 +314,7 @@ static int edbm_extrude_repeat_exec(bContext *C, wmOperator *op) mul_v3_m3v3(offset_local, tmat, offset); for (int a = 0; a < steps; a++) { - edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, true); + edbm_extrude_ex(obedit, em, BM_ALL_NOLOOP, BM_ELEM_SELECT, false, false, false, true); BMO_op_callf( em->bm, BMO_FLAG_DEFAULTS, "translate vec=%v verts=%hv", offset_local, BM_ELEM_SELECT); } @@ -359,6 +361,7 @@ void MESH_OT_extrude_repeat(wmOperatorType *ot) static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) { const bool use_normal_flip = RNA_boolean_get(op->ptr, "use_normal_flip"); + const bool use_dissolve_ortho_edges = RNA_boolean_get(op->ptr, "use_dissolve_ortho_edges"); const char htype = edbm_extrude_htype_from_em_select(em); enum { NONE = 0, ELEM_FLAG, VERT_ONLY, EDGE_ONLY } nr; bool changed = false; @@ -401,7 +404,14 @@ static bool edbm_extrude_mesh(Object *obedit, BMEditMesh *em, wmOperator *op) case NONE: return false; case ELEM_FLAG: - changed = edbm_extrude_ex(obedit, em, htype, BM_ELEM_SELECT, use_normal_flip, true, true); + changed = edbm_extrude_ex(obedit, + em, + htype, + BM_ELEM_SELECT, + use_normal_flip, + use_dissolve_ortho_edges, + true, + true); break; case VERT_ONLY: changed = edbm_extrude_verts_indiv(em, op, BM_ELEM_SELECT); @@ -465,6 +475,7 @@ void MESH_OT_extrude_region(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -519,6 +530,7 @@ void MESH_OT_extrude_context(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; RNA_def_boolean(ot->srna, "use_normal_flip", false, "Flip Normals", ""); + RNA_def_boolean(ot->srna, "use_dissolve_ortho_edges", false, "Dissolve Orthogonal Edges", ""); Transform_Properties(ot, P_NO_DEFAULTS | P_MIRROR_DUMMY); } @@ -840,7 +852,7 @@ static int edbm_dupli_extrude_cursor_invoke(bContext *C, wmOperator *op, const w } } - edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, true, true); + edbm_extrude_ex(vc.obedit, vc.em, extrude_htype, BM_ELEM_SELECT, false, false, true, true); EDBM_op_callf( vc.em, op, "rotate verts=%hv cent=%v matrix=%m3", BM_ELEM_SELECT, local_center, mat); EDBM_op_callf(vc.em, op, "translate verts=%hv vec=%v", BM_ELEM_SELECT, ofs); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 37bacb4af55..3861676c2cf 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -372,7 +372,8 @@ static int loopcut_init(bContext *C, wmOperator *op, const wmEvent *event) if (is_interactive) { for (uint base_index = 0; base_index < bases_len; base_index++) { Object *ob_iter = bases[base_index]->object; - if (modifiers_isDeformedByLattice(ob_iter) || modifiers_isDeformedByArmature(ob_iter)) { + if (BKE_modifiers_is_deformed_by_lattice(ob_iter) || + BKE_modifiers_is_deformed_by_armature(ob_iter)) { BKE_report( op->reports, RPT_WARNING, "Loop cut does not work well on deformed edit mesh display"); break; diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index c02ef9835a0..eed2cbcce39 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -224,7 +224,7 @@ static int paint_mask_extract_exec(bContext *C, wmOperator *op) if (RNA_boolean_get(op->ptr, "add_solidify")) { ED_object_modifier_add( op->reports, bmain, scene, new_ob, "mask_extract_solidify", eModifierType_Solidify); - SolidifyModifierData *sfmd = (SolidifyModifierData *)modifiers_findByName( + SolidifyModifierData *sfmd = (SolidifyModifierData *)BKE_modifiers_findny_name( new_ob, "mask_extract_solidify"); if (sfmd) { sfmd->offset = -0.05f; diff --git a/source/blender/editors/mesh/editmesh_select_similar.c b/source/blender/editors/mesh/editmesh_select_similar.c index 5106108a16c..365c5b5d264 100644 --- a/source/blender/editors/mesh/editmesh_select_similar.c +++ b/source/blender/editors/mesh/editmesh_select_similar.c @@ -1059,7 +1059,7 @@ static int similar_vert_select_exec(bContext *C, wmOperator *op) if (type == SIMVERT_VGROUP) { /* We store the names of the vertex groups, so we can select - * vertex groups with the same name in different objects. */ + * vertex groups with the same name in different objects. */ const int dvert_tot = BLI_listbase_count(&ob->defbase); for (int i = 0; i < dvert_tot; i++) { if (dvert_selected & (1 << i)) { diff --git a/source/blender/editors/mesh/editmesh_undo.c b/source/blender/editors/mesh/editmesh_undo.c index 48ec41027ff..e4ecfa9c680 100644 --- a/source/blender/editors/mesh/editmesh_undo.c +++ b/source/blender/editors/mesh/editmesh_undo.c @@ -397,9 +397,7 @@ struct UMArrayData { UndoMesh *um; const UndoMesh *um_ref; /* can be NULL */ }; -static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void um_arraystore_compact_cb(TaskPool *__restrict UNUSED(pool), void *taskdata) { struct UMArrayData *um_data = taskdata; um_arraystore_compact_with_info(um_data->um, um_data->um_ref); @@ -541,9 +539,7 @@ static void *undomesh_from_editmesh(UndoMesh *um, BMEditMesh *em, Key *key) # ifdef USE_ARRAY_STORE_THREAD if (um_arraystore.task_pool == NULL) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - um_arraystore.task_pool = BLI_task_pool_create_background( - scheduler, NULL, TASK_PRIORITY_LOW); + um_arraystore.task_pool = BLI_task_pool_create_background(NULL, TASK_PRIORITY_LOW); } struct UMArrayData *um_data = MEM_mallocN(sizeof(*um_data), __func__); diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index 66b2c66f2aa..c52a5956ac4 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -277,6 +277,18 @@ void ED_operatormacros_mesh(void) RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); RNA_boolean_set(otmacro->ptr, "mirror", false); + ot = WM_operatortype_append_macro( + "MESH_OT_extrude_region_dissolve_move_intersect", + "Extrude, Dissolve, Move and Intersect", + "Extrude, dissolves edges whose faces form a flat surface and intersect new edges", + OPTYPE_UNDO | OPTYPE_REGISTER); + otmacro = WM_operatortype_macro_define(ot, "MESH_OT_extrude_region"); + RNA_boolean_set(otmacro->ptr, "use_dissolve_ortho_edges", true); + otmacro = WM_operatortype_macro_define(ot, "TRANSFORM_OT_translate"); + RNA_boolean_set(otmacro->ptr, "use_proportional_edit", false); + RNA_boolean_set(otmacro->ptr, "mirror", false); + RNA_boolean_set(otmacro->ptr, "use_automerge_and_split", true); + ot = WM_operatortype_append_macro("MESH_OT_extrude_context_move", "Extrude Region and Move", "Extrude region together along the average normal", diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt index c2c25e47908..fb273cf49a8 100644 --- a/source/blender/editors/object/CMakeLists.txt +++ b/source/blender/editors/object/CMakeLists.txt @@ -17,8 +17,8 @@ set(INC ../include - ../../blenkernel ../../blenfont + ../../blenkernel ../../blenlib ../../blentranslation ../../bmesh @@ -34,6 +34,7 @@ set(INC ../../shader_fx ../../render/extern/include ../../windowmanager + ../../../../intern/clog ../../../../intern/glew-mx ../../../../intern/guardedalloc ) diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 64abd01983c..4a229ae741f 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -64,7 +64,7 @@ #include "BKE_duplilist.h" #include "BKE_effect.h" #include "BKE_font.h" -#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_curve.h" #include "BKE_hair.h" #include "BKE_key.h" #include "BKE_lattice.h" @@ -1357,6 +1357,7 @@ static int collection_instance_add_exec(bContext *C, wmOperator *op) Object *ob = ED_object_add_type( C, OB_EMPTY, collection->id.name + 2, loc, rot, false, local_view_bits); ob->instance_collection = collection; + ob->empty_drawsize = U.collection_instance_empty_size; ob->transflag |= OB_DUPLICOLLECTION; id_us_plus(&collection->id); diff --git a/source/blender/editors/object/object_bake.c b/source/blender/editors/object/object_bake.c index 2cb0229126d..baa24ab2f4e 100644 --- a/source/blender/editors/object/object_bake.c +++ b/source/blender/editors/object/object_bake.c @@ -156,7 +156,7 @@ static bool multiresbake_check(bContext *C, wmOperator *op) ok = mmd->totlvl > 0; for (md = (ModifierData *)mmd->modifier.next; md && ok; md = md->next) { - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { ok = false; } } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index debad321583..46923b593b1 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -895,7 +895,7 @@ static int bake(Render *re, /* for multires bake, use linear UV subdivision to match low res UVs */ if (pass_type == SCE_PASS_NORMAL && normal_space == R_BAKE_SPACE_TANGENT && !is_selected_to_active) { - mmd_low = (MultiresModifierData *)modifiers_findByType(ob_low, eModifierType_Multires); + mmd_low = (MultiresModifierData *)BKE_modifiers_findby_type(ob_low, eModifierType_Multires); if (mmd_low) { mmd_flags_low = mmd_low->flags; mmd_low->uv_smooth = SUBSURF_UV_SMOOTH_NONE; @@ -945,7 +945,7 @@ static int bake(Render *re, if (md->type == eModifierType_EdgeSplit) { BLI_remlink(&ob_low_eval->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); is_changed = true; } md = md_next; @@ -1096,7 +1096,7 @@ static int bake(Render *re, int mode; BKE_object_eval_reset(ob_low_eval); - md = modifiers_findByType(ob_low_eval, eModifierType_Multires); + md = BKE_modifiers_findby_type(ob_low_eval, eModifierType_Multires); if (md) { mode = md->mode; diff --git a/source/blender/editors/object/object_collection.c b/source/blender/editors/object/object_collection.c index 7554c4efeda..b3155ab3ade 100644 --- a/source/blender/editors/object/object_collection.c +++ b/source/blender/editors/object/object_collection.c @@ -483,7 +483,7 @@ static int collection_link_exec(bContext *C, wmOperator *op) /* Adding object to collection which is used as dupli-collection for self is bad idea. * - * It is also bad idea to add object to collection which is in collection which + * It is also bad idea to add object to collection which is in collection which * contains our current object. */ if (BKE_collection_object_cyclic_check(bmain, ob, collection)) { diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c index 5506895613b..46837e4fdf3 100644 --- a/source/blender/editors/object/object_edit.c +++ b/source/blender/editors/object/object_edit.c @@ -100,6 +100,8 @@ #include "RNA_define.h" #include "RNA_enum_types.h" +#include "CLG_log.h" + /* for menu/popup icons etc etc*/ #include "UI_interface.h" @@ -112,21 +114,17 @@ #include "object_intern.h" // own include +static CLG_LogRef LOG = {"ed.object.edit"}; + /* prototypes */ typedef struct MoveToCollectionData MoveToCollectionData; static void move_to_collection_menus_items(struct uiLayout *layout, struct MoveToCollectionData *menu); static ListBase selected_objects_get(bContext *C); -/* ************* XXX **************** */ -static void error(const char *UNUSED(arg)) -{ -} - -/* port over here */ -static void error_libdata(void) -{ -} +/* -------------------------------------------------------------------- */ +/** \name Internal Utilities + * \{ */ Object *ED_object_context(bContext *C) { @@ -147,7 +145,11 @@ Object *ED_object_active_context(bContext *C) return ob; } -/* ********************** object hiding *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Hide Operator + * \{ */ static bool object_hide_poll(bContext *C) { @@ -401,7 +403,11 @@ void OBJECT_OT_hide_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } -/* ******************* toggle editmode operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Edit-Mode Operator + * \{ */ static bool mesh_needs_keyindex(Main *bmain, const Mesh *me) { @@ -441,7 +447,11 @@ static bool ED_object_editmode_load_ex(Main *bmain, Object *obedit, const bool f } if (me->edit_mesh->bm->totvert > MESH_MAX_VERTS) { - error("Too many vertices"); + /* This used to be warned int the UI, we could warn again although it's quite rare. */ + CLOG_WARN(&LOG, + "Too many vertices for mesh '%s' (%d)", + me->id.name + 2, + me->edit_mesh->bm->totvert); return false; } @@ -600,7 +610,8 @@ bool ED_object_editmode_enter_ex(Main *bmain, Scene *scene, Object *ob, int flag } if (BKE_object_obdata_is_libdata(ob)) { - error_libdata(); + /* Ideally the caller should check this. */ + CLOG_WARN(&LOG, "Unable to enter edit-mode on library data for object '%s'", ob->id.name + 2); return false; } @@ -777,7 +788,11 @@ void OBJECT_OT_editmode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* *************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Pose-Mode Operator + * \{ */ static int posemode_exec(bContext *C, wmOperator *op) { @@ -861,12 +876,16 @@ void OBJECT_OT_posemode_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ******************* force field toggle operator ***************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Force Field Toggle Operator + * \{ */ void ED_object_check_force_modifiers(Main *bmain, Scene *scene, Object *object) { PartDeflect *pd = object->pd; - ModifierData *md = modifiers_findByType(object, eModifierType_Surface); + ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Surface); /* add/remove modifier as needed */ if (!md) { @@ -924,8 +943,11 @@ void OBJECT_OT_forcefield_toggle(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************************************** */ -/* Motion Paths */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Calculate Motion Paths Operator + * \{ */ static eAnimvizCalcRange object_path_convert_range(eObjectPathCalcRange range) { @@ -1019,7 +1041,7 @@ static int object_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEv } /* show popup dialog to allow editing of range... */ - /* FIXME: hardcoded dimensions here are just arbitrary */ + /* FIXME: hard-coded dimensions here are just arbitrary. */ return WM_operator_props_dialog_popup(C, op, 200); } @@ -1088,7 +1110,11 @@ void OBJECT_OT_paths_calculate(wmOperatorType *ot) MAXFRAME / 2.0); } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Motion Paths Operator + * \{ */ static bool object_update_paths_poll(bContext *C) { @@ -1132,7 +1158,11 @@ void OBJECT_OT_paths_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Clear Motion Paths Operator + * \{ */ /* Helper for ED_objects_clear_paths() */ static void object_clear_mpath(Object *ob) @@ -1151,14 +1181,14 @@ static void object_clear_mpath(Object *ob) void ED_objects_clear_paths(bContext *C, bool only_selected) { if (only_selected) { - /* loop over all selected + sedtiable objects in scene */ + /* Loop over all selected + editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { object_clear_mpath(ob); } CTX_DATA_END; } else { - /* loop over all edtiable objects in scene */ + /* Loop over all editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { object_clear_mpath(ob); } @@ -1210,13 +1240,17 @@ void OBJECT_OT_paths_clear(wmOperatorType *ot) RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE); } -/* --------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Update Motion Paths Range from Scene Operator + * \{ */ static int object_update_paths_range_exec(bContext *C, wmOperator *UNUSED(op)) { Scene *scene = CTX_data_scene(C); - /* loop over all edtiable objects in scene */ + /* Loop over all editable objects in scene. */ CTX_DATA_BEGIN (C, Object *, ob, editable_objects) { /* use Preview Range or Full Frame Range - whichever is in use */ ob->avs.path_sf = PSFRA; @@ -1246,63 +1280,99 @@ void OBJECT_OT_paths_range_update(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/********************** Smooth/Flat *********************/ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Shade Smooth/Flat Operator + * \{ */ static int shade_smooth_exec(bContext *C, wmOperator *op) { - ID *data; - Curve *cu; - Nurb *nu; - int clear = (STREQ(op->idname, "OBJECT_OT_shade_flat")); - bool done = false, linked_data = false; + const bool use_smooth = STREQ(op->idname, "OBJECT_OT_shade_smooth"); + bool changed_multi = false; + bool has_linked_data = false; - CTX_DATA_BEGIN (C, Object *, ob, selected_editable_objects) { - data = ob->data; + ListBase ctx_objects = {NULL, NULL}; + CollectionPointerLink ctx_ob_single_active = {NULL}; + + /* For modes that only use an active object, don't handle the whole selection. */ + { + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact && ((obact->mode & OB_MODE_ALL_PAINT))) { + ctx_ob_single_active.ptr.data = obact; + BLI_addtail(&ctx_objects, &ctx_ob_single_active); + } + } + + if (ctx_objects.first != &ctx_ob_single_active) { + CTX_data_selected_editable_objects(C, &ctx_objects); + } + + for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) { + Object *ob = ctx_ob->ptr.data; + ID *data = ob->data; + if (data != NULL) { + data->tag |= LIB_TAG_DOIT; + } + } + + for (CollectionPointerLink *ctx_ob = ctx_objects.first; ctx_ob; ctx_ob = ctx_ob->next) { + /* Always un-tag all object data-blocks irrespective of our ability to operate on them. */ + Object *ob = ctx_ob->ptr.data; + ID *data = ob->data; + if ((data == NULL) || ((data->tag & LIB_TAG_DOIT) == 0)) { + continue; + } + data->tag &= ~LIB_TAG_DOIT; + /* Finished un-tagging, continue with regular logic. */ if (data && ID_IS_LINKED(data)) { - linked_data = true; + has_linked_data = true; continue; } + bool changed = false; if (ob->type == OB_MESH) { - BKE_mesh_smooth_flag_set(ob->data, !clear); - + BKE_mesh_smooth_flag_set(ob->data, use_smooth); BKE_mesh_batch_cache_dirty_tag(ob->data, BKE_MESH_BATCH_DIRTY_ALL); - DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - done = true; + changed = true; } else if (ELEM(ob->type, OB_SURF, OB_CURVE)) { - cu = ob->data; + BKE_curve_smooth_flag_set(ob->data, use_smooth); + changed = true; + } - for (nu = cu->nurb.first; nu; nu = nu->next) { - if (!clear) { - nu->flag |= ME_SMOOTH; - } - else { - nu->flag &= ~ME_SMOOTH; - } - } + if (changed) { + changed_multi = true; DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); - - done = true; } } - CTX_DATA_END; - if (linked_data) { + if (ctx_objects.first != &ctx_ob_single_active) { + BLI_freelistN(&ctx_objects); + } + + if (has_linked_data) { BKE_report(op->reports, RPT_WARNING, "Can't edit linked mesh or curve data"); } - return (done) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + return (changed_multi) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; } static bool shade_poll(bContext *C) { - return (CTX_data_edit_object(C) == NULL); + ViewLayer *view_layer = CTX_data_view_layer(C); + Object *obact = OBACT(view_layer); + if (obact != NULL) { + /* Doesn't handle edit-data, sculpt dynamic-topology, or their undo systems. */ + if (obact->mode & (OB_MODE_EDIT | OB_MODE_SCULPT)) { + return false; + } + } + return true; } void OBJECT_OT_shade_flat(wmOperatorType *ot) @@ -1335,7 +1405,11 @@ void OBJECT_OT_shade_smooth(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Mode Set Operator + * \{ */ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C, PointerRNA *UNUSED(ptr), @@ -1355,7 +1429,8 @@ static const EnumPropertyItem *object_mode_set_itemsf(bContext *C, if (ob) { const bool use_mode_particle_edit = (BLI_listbase_is_empty(&ob->particlesystem) == false) || (ob->soft != NULL) || - (modifiers_findByType(ob, eModifierType_Cloth) != NULL); + (BKE_modifiers_findby_type(ob, eModifierType_Cloth) != + NULL); while (input->identifier) { if ((input->value == OB_MODE_EDIT && OB_TYPE_SUPPORT_EDITMODE(ob->type)) || (input->value == OB_MODE_POSE && (ob->type == OB_ARMATURE)) || @@ -1516,6 +1591,12 @@ void OBJECT_OT_mode_set_with_submode(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Link/Move to Collection Operator + * \{ */ + static ListBase selected_objects_get(bContext *C) { ListBase objects = {NULL}; @@ -1856,3 +1937,5 @@ void OBJECT_OT_link_to_collection(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); ot->prop = prop; } + +/** \} */ diff --git a/source/blender/editors/object/object_gpencil_modifier.c b/source/blender/editors/object/object_gpencil_modifier.c index 5bf5c4bd95a..6d0f53cfa1e 100644 --- a/source/blender/editors/object/object_gpencil_modifier.c +++ b/source/blender/editors/object/object_gpencil_modifier.c @@ -65,7 +65,7 @@ GpencilModifierData *ED_object_gpencil_modifier_add( ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type) { GpencilModifierData *new_md = NULL; - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(type); if (ob->type != OB_GPENCIL) { BKE_reportf(reports, RPT_WARNING, "Modifiers cannot be added to object '%s'", ob->id.name + 2); @@ -73,7 +73,7 @@ GpencilModifierData *ED_object_gpencil_modifier_add( } if (mti->flags & eGpencilModifierTypeFlag_Single) { - if (BKE_gpencil_modifiers_findByType(ob, type)) { + if (BKE_gpencil_modifiers_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return NULL; } @@ -214,7 +214,7 @@ int ED_object_gpencil_modifier_move_down(ReportList *UNUSED(reports), static int gpencil_modifier_apply_obdata( ReportList *reports, Main *bmain, Depsgraph *depsgraph, Object *ob, GpencilModifierData *md) { - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); if (mti->isDisabled && mti->isDisabled(md, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); @@ -281,18 +281,18 @@ int ED_object_gpencil_modifier_apply(Main *bmain, int ED_object_gpencil_modifier_copy(ReportList *reports, Object *ob, GpencilModifierData *md) { GpencilModifierData *nmd; - const GpencilModifierTypeInfo *mti = BKE_gpencil_modifierType_getInfo(md->type); + const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); GpencilModifierType type = md->type; if (mti->flags & eGpencilModifierTypeFlag_Single) { - if (BKE_gpencil_modifiers_findByType(ob, type)) { + if (BKE_gpencil_modifiers_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return 0; } } nmd = BKE_gpencil_modifier_new(md->type); - BKE_gpencil_modifier_copyData(md, nmd); + BKE_gpencil_modifier_copydata(md, nmd); BLI_insertlinkafter(&ob->greasepencil_modifiers, md, nmd); BKE_gpencil_modifier_unique_name(&ob->greasepencil_modifiers, nmd); @@ -335,7 +335,7 @@ static const EnumPropertyItem *gpencil_modifier_add_itemf(bContext *C, for (a = 0; rna_enum_object_greasepencil_modifier_type_items[a].identifier; a++) { md_item = &rna_enum_object_greasepencil_modifier_type_items[a]; if (md_item->identifier[0]) { - mti = BKE_gpencil_modifierType_getInfo(md_item->value); + mti = BKE_gpencil_modifier_get_info(md_item->value); if (mti->flags & eGpencilModifierTypeFlag_NoUserAdd) { continue; @@ -455,7 +455,7 @@ static GpencilModifierData *gpencil_edit_modifier_property_get(wmOperator *op, GpencilModifierData *md; RNA_string_get(op->ptr, "modifier", modifier_name); - md = BKE_gpencil_modifiers_findByName(ob, modifier_name); + md = BKE_gpencil_modifiers_findby_name(ob, modifier_name); if (md && type != 0 && md->type != type) { md = NULL; diff --git a/source/blender/editors/object/object_hook.c b/source/blender/editors/object/object_hook.c index 4414acff115..9d2e5e74352 100644 --- a/source/blender/editors/object/object_hook.c +++ b/source/blender/editors/object/object_hook.c @@ -552,14 +552,14 @@ static int add_hook_object(const bContext *C, } md = obedit->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } - hmd = (HookModifierData *)modifier_new(eModifierType_Hook); + hmd = (HookModifierData *)BKE_modifier_new(eModifierType_Hook); BLI_insertlinkbefore(&obedit->modifiers, md, hmd); BLI_snprintf(hmd->modifier.name, sizeof(hmd->modifier.name), "Hook-%s", ob->id.name + 2); - modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd); + BKE_modifier_unique_name(&obedit->modifiers, (ModifierData *)hmd); hmd->object = ob; hmd->indexar = indexar; @@ -725,7 +725,7 @@ static int object_hook_remove_exec(bContext *C, wmOperator *op) /* remove functionality */ BLI_remlink(&ob->modifiers, (ModifierData *)hmd); - modifier_free((ModifierData *)hmd); + BKE_modifier_free((ModifierData *)hmd); DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index d8ba270073e..d7a7b4ca110 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -169,6 +169,8 @@ void OBJECT_OT_multires_subdivide(struct wmOperatorType *ot); void OBJECT_OT_multires_reshape(struct wmOperatorType *ot); void OBJECT_OT_multires_higher_levels_delete(struct wmOperatorType *ot); void OBJECT_OT_multires_base_apply(struct wmOperatorType *ot); +void OBJECT_OT_multires_unsubdivide(struct wmOperatorType *ot); +void OBJECT_OT_multires_rebuild_subdiv(struct wmOperatorType *ot); void OBJECT_OT_multires_external_save(struct wmOperatorType *ot); void OBJECT_OT_multires_external_pack(struct wmOperatorType *ot); void OBJECT_OT_correctivesmooth_bind(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index a24f3ba2269..5cb4714dabf 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -135,23 +135,24 @@ static void object_force_modifier_bind_simple_options(Depsgraph *depsgraph, Object *object, ModifierData *md) { - ModifierData *md_eval = (ModifierData *)modifier_get_evaluated(depsgraph, object, md); + ModifierData *md_eval = (ModifierData *)BKE_modifier_get_evaluated(depsgraph, object, md); const int mode = md_eval->mode; md_eval->mode |= eModifierMode_Realtime; object_force_modifier_update_for_bind(depsgraph, object); md_eval->mode = mode; } -/** Add a modifier to given object, including relevant extra processing needed by some physics - * types (particles, simulations...). +/** + * Add a modifier to given object, including relevant extra processing needed by some physics types + * (particles, simulations...). * - * \param scene is only used to set current frame in some cases, and may be NULL. + * \param scene: is only used to set current frame in some cases, and may be NULL. */ ModifierData *ED_object_modifier_add( ReportList *reports, Main *bmain, Scene *scene, Object *ob, const char *name, int type) { ModifierData *md = NULL, *new_md = NULL; - const ModifierTypeInfo *mti = modifierType_getInfo(type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(type); /* Check compatibility of modifier [T25291, T50373]. */ if (!BKE_object_support_modifier_type_check(ob, type)) { @@ -160,7 +161,7 @@ ModifierData *ED_object_modifier_add( } if (mti->flags & eModifierTypeFlag_Single) { - if (modifiers_findByType(ob, type)) { + if (BKE_modifiers_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one modifier of this type is allowed"); return NULL; } @@ -174,12 +175,12 @@ ModifierData *ED_object_modifier_add( } else { /* get new modifier data to add */ - new_md = modifier_new(type); + new_md = BKE_modifier_new(type); if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { md = ob->modifiers.first; - while (md && modifierType_getInfo(md->type)->type == eModifierTypeType_OnlyDeform) { + while (md && BKE_modifier_get_info(md->type)->type == eModifierTypeType_OnlyDeform) { md = md->next; } @@ -195,7 +196,7 @@ ModifierData *ED_object_modifier_add( /* make sure modifier data has unique name */ - modifier_unique_name(&ob->modifiers, new_md); + BKE_modifier_unique_name(&ob->modifiers, new_md); /* special cases */ if (type == eModifierType_Softbody) { @@ -382,7 +383,7 @@ static bool object_modifier_remove(Main *bmain, } BLI_remlink(&ob->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); BKE_object_free_derived_caches(ob); return 1; @@ -432,10 +433,10 @@ void ED_object_modifier_clear(Main *bmain, Object *ob) int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md) { if (md->prev) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->type != eModifierTypeType_OnlyDeform) { - const ModifierTypeInfo *nmti = modifierType_getInfo(md->prev->type); + const ModifierTypeInfo *nmti = BKE_modifier_get_info(md->prev->type); if (nmti->flags & eModifierTypeFlag_RequiresOriginalData) { BKE_report(reports, RPT_WARNING, "Cannot move above a modifier requiring original data"); @@ -453,10 +454,10 @@ int ED_object_modifier_move_up(ReportList *reports, Object *ob, ModifierData *md int ED_object_modifier_move_down(ReportList *reports, Object *ob, ModifierData *md) { if (md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (mti->flags & eModifierTypeFlag_RequiresOriginalData) { - const ModifierTypeInfo *nmti = modifierType_getInfo(md->next->type); + const ModifierTypeInfo *nmti = BKE_modifier_get_info(md->next->type); if (nmti->type != eModifierTypeType_OnlyDeform) { BKE_report(reports, RPT_WARNING, "Cannot move beyond a non-deforming modifier"); @@ -619,7 +620,7 @@ static int modifier_apply_shape(Main *bmain, Object *ob, ModifierData *md_eval) { - const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type); if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); @@ -643,7 +644,7 @@ static int modifier_apply_shape(Main *bmain, Key *key = me->key; KeyBlock *kb; - if (!modifier_isSameTopology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) { + if (!BKE_modifier_is_same_topology(md_eval) || mti->type == eModifierTypeType_NonGeometrical) { BKE_report(reports, RPT_ERROR, "Only deforming modifiers can be applied to shapes"); return 0; } @@ -679,7 +680,7 @@ static int modifier_apply_shape(Main *bmain, static int modifier_apply_obdata( ReportList *reports, Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md_eval) { - const ModifierTypeInfo *mti = modifierType_getInfo(md_eval->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md_eval->type); if (mti->isDisabled && mti->isDisabled(scene, md_eval, 0)) { BKE_report(reports, RPT_ERROR, "Modifier is disabled, skipping apply"); @@ -790,7 +791,7 @@ bool ED_object_modifier_apply(Main *bmain, return false; } else if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && - (modifier_isSameTopology(md) == false)) { + (BKE_modifier_is_same_topology(md) == false)) { BKE_report(reports, RPT_ERROR, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); @@ -804,7 +805,7 @@ bool ED_object_modifier_apply(Main *bmain, /* Get evaluated modifier, so object links pointer to evaluated data, * but still use original object it is applied to the original mesh. */ Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); - ModifierData *md_eval = (ob_eval) ? modifiers_findByName(ob_eval, md->name) : md; + ModifierData *md_eval = (ob_eval) ? BKE_modifiers_findny_name(ob_eval, md->name) : md; /* allow apply of a not-realtime modifier, by first re-enabling realtime. */ prev_mode = md_eval->mode; @@ -825,7 +826,7 @@ bool ED_object_modifier_apply(Main *bmain, md_eval->mode = prev_mode; BLI_remlink(&ob->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); BKE_object_free_derived_caches(ob); @@ -836,10 +837,10 @@ int ED_object_modifier_copy(ReportList *UNUSED(reports), Object *ob, ModifierDat { ModifierData *nmd; - nmd = modifier_new(md->type); - modifier_copyData(md, nmd); + nmd = BKE_modifier_new(md->type); + BKE_modifier_copydata(md, nmd); BLI_insertlinkafter(&ob->modifiers, md, nmd); - modifier_unique_name(&ob->modifiers, nmd); + BKE_modifier_unique_name(&ob->modifiers, nmd); return 1; } @@ -885,7 +886,7 @@ static const EnumPropertyItem *modifier_add_itemf(bContext *C, md_item = &rna_enum_object_modifier_type_items[a]; if (md_item->identifier[0]) { - mti = modifierType_getInfo(md_item->value); + mti = BKE_modifier_get_info(md_item->value); if (mti->flags & eModifierTypeFlag_NoUserAdd) { continue; @@ -1019,7 +1020,7 @@ ModifierData *edit_modifier_property_get(wmOperator *op, Object *ob, int type) ModifierData *md; RNA_string_get(op->ptr, "modifier", modifier_name); - md = modifiers_findByName(ob, modifier_name); + md = BKE_modifiers_findny_name(ob, modifier_name); if (md && type != 0 && md->type != type) { md = NULL; @@ -1199,7 +1200,7 @@ static bool modifier_apply_poll(bContext *C) } else if (md != NULL) { if ((ob->mode & OB_MODE_SCULPT) && (find_multires_modifier_before(scene, md)) && - (modifier_isSameTopology(md) == false)) { + (BKE_modifier_is_same_topology(md) == false)) { CTX_wm_operator_poll_msg_set( C, "Constructive modifier cannot be applied to multi-res data in sculpt mode"); return false; @@ -1432,6 +1433,25 @@ void OBJECT_OT_multires_higher_levels_delete(wmOperatorType *ot) /** \name Multires Subdivide Operator * \{ */ +static EnumPropertyItem prop_multires_subdivide_mode_type[] = { + {MULTIRES_SUBDIVIDE_CATMULL_CLARK, + "CATMULL_CLARK", + 0, + "Catmull-Clark", + "Create a new level using Catmull-Clark subdivisions"}, + {MULTIRES_SUBDIVIDE_SIMPLE, + "SIMPLE", + 0, + "Simple", + "Create a new level using simple subdivisions"}, + {MULTIRES_SUBDIVIDE_LINEAR, + "LINEAR", + 0, + "Linear", + "Create a new level using linear interpolation of the sculpted displacement"}, + {0, NULL, 0, NULL, NULL}, +}; + static int multires_subdivide_exec(bContext *C, wmOperator *op) { Object *object = ED_object_active_context(C); @@ -1442,7 +1462,9 @@ static int multires_subdivide_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - multiresModifier_subdivide(object, mmd); + const eMultiresSubdivideModeType subdivide_mode = (eMultiresSubdivideModeType)( + RNA_enum_get(op->ptr, "mode")); + multiresModifier_subdivide(object, mmd, subdivide_mode); ED_object_iter_other( CTX_data_main(C), object, true, ED_object_multires_update_totlevels_cb, &mmd->totlvl); @@ -1481,6 +1503,12 @@ void OBJECT_OT_multires_subdivide(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; edit_modifier_properties(ot); + RNA_def_enum(ot->srna, + "mode", + prop_multires_subdivide_mode_type, + MULTIRES_SUBDIVIDE_CATMULL_CLARK, + "Subdivision Mode", + "How the mesh is going to be subdivided to create a new level"); } /** \} */ @@ -1738,6 +1766,119 @@ void OBJECT_OT_multires_base_apply(wmOperatorType *ot) /** \} */ /* ------------------------------------------------------------------- */ +/** \name Multires Unsubdivide + * \{ */ + +static int multires_unsubdivide_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *object = ED_object_active_context(C); + MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get( + op, object, eModifierType_Multires); + + if (!mmd) { + return OPERATOR_CANCELLED; + } + + int new_levels = multiresModifier_rebuild_subdiv(depsgraph, object, mmd, 1, true); + if (new_levels == 0) { + BKE_report(op->reports, RPT_ERROR, "Not valid subdivisions found to rebuild a lower level"); + return OPERATOR_CANCELLED; + } + + DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object); + + return OPERATOR_FINISHED; +} + +static int multires_unsubdivide_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) { + return multires_unsubdivide_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_multires_unsubdivide(wmOperatorType *ot) +{ + ot->name = "Unsubdivide"; + ot->description = "Rebuild a lower subdivision level of the current base mesh"; + ot->idname = "OBJECT_OT_multires_unsubdivide"; + + ot->poll = multires_poll; + ot->invoke = multires_unsubdivide_invoke; + ot->exec = multires_unsubdivide_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} + +/** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Multires Rebuild Subdivisions + * \{ */ + +static int multires_rebuild_subdiv_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); + Object *object = ED_object_active_context(C); + MultiresModifierData *mmd = (MultiresModifierData *)edit_modifier_property_get( + op, object, eModifierType_Multires); + + if (!mmd) { + return OPERATOR_CANCELLED; + } + + int new_levels = multiresModifier_rebuild_subdiv(depsgraph, object, mmd, INT_MAX, false); + if (new_levels == 0) { + BKE_report(op->reports, RPT_ERROR, "Not valid subdivisions found to rebuild lower levels"); + return OPERATOR_CANCELLED; + } + + BKE_reportf(op->reports, RPT_INFO, "%d new levels rebuilt", new_levels); + + DEG_id_tag_update(&object->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, object); + + return OPERATOR_FINISHED; +} + +static int multires_rebuild_subdiv_invoke(bContext *C, + wmOperator *op, + const wmEvent *UNUSED(event)) +{ + if (edit_modifier_invoke_properties(C, op)) { + return multires_rebuild_subdiv_exec(C, op); + } + else { + return OPERATOR_CANCELLED; + } +} + +void OBJECT_OT_multires_rebuild_subdiv(wmOperatorType *ot) +{ + ot->name = "Rebuild Lower Subdivisions"; + ot->description = + "Rebuilds all possible subdivisions levels to generate a lower resolution base mesh"; + ot->idname = "OBJECT_OT_multires_rebuild_subdiv"; + + ot->poll = multires_poll; + ot->invoke = multires_rebuild_subdiv_invoke; + ot->exec = multires_rebuild_subdiv_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + edit_modifier_properties(ot); +} + +/** \} */ + +/* ------------------------------------------------------------------- */ /** \name Skin Modifier * \{ */ @@ -2071,7 +2212,7 @@ static int skin_armature_create_exec(bContext *C, wmOperator *op) arm_ob = modifier_skin_armature_create(depsgraph, bmain, scene, ob); /* add a modifier to connect the new armature to the mesh */ - arm_md = (ArmatureModifierData *)modifier_new(eModifierType_Armature); + arm_md = (ArmatureModifierData *)BKE_modifier_new(eModifierType_Armature); if (arm_md) { skin_md = edit_modifier_property_get(op, ob, eModifierType_Skin); BLI_insertlinkafter(&ob->modifiers, skin_md, arm_md); @@ -2135,7 +2276,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (!modifier_isEnabled(scene, &csmd->modifier, eModifierMode_Realtime)) { + if (!BKE_modifier_is_enabled(scene, &csmd->modifier, eModifierMode_Realtime)) { BKE_report(op->reports, RPT_ERROR, "Modifier is disabled"); return OPERATOR_CANCELLED; } @@ -2152,7 +2293,7 @@ static int correctivesmooth_bind_exec(bContext *C, wmOperator *op) else { /* Signal to modifier to recalculate. */ CorrectiveSmoothModifierData *csmd_eval = (CorrectiveSmoothModifierData *) - modifier_get_evaluated(depsgraph, ob, &csmd->modifier); + BKE_modifier_get_evaluated(depsgraph, ob, &csmd->modifier); csmd_eval->bind_coords_num = (uint)-1; /* Force modifier to run, it will call binding routine @@ -2231,7 +2372,7 @@ static int meshdeform_bind_exec(bContext *C, wmOperator *op) else { /* Force modifier to run, it will call binding routine * (this has to happen outside of depsgraph evaluation). */ - MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)modifier_get_evaluated( + MeshDeformModifierData *mmd_eval = (MeshDeformModifierData *)BKE_modifier_get_evaluated( depsgraph, ob, &mmd->modifier); mmd_eval->bindfunc = ED_mesh_deform_bind_callback; object_force_modifier_bind_simple_options(depsgraph, ob, &mmd->modifier); @@ -2436,7 +2577,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) } och = BKE_ocean_init_cache(omd->cachepath, - modifier_path_relbase(bmain, ob), + BKE_modifier_path_relbase(bmain, ob), omd->bakestart, omd->bakeend, omd->wave_scale, @@ -2455,7 +2596,7 @@ static int ocean_bake_exec(bContext *C, wmOperator *op) * No drivers or other modifier parameters. */ /* TODO(sergey): This operates on an original data, so no flush is needed. However, baking * usually should happen on an evaluated objects, so this seems to be deeper issue here. */ - BKE_animsys_evaluate_animdata(scene, (ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); + BKE_animsys_evaluate_animdata((ID *)ob, ob->adt, f, ADT_RECALC_ANIM, false); och->time[i] = omd->time; i++; @@ -2559,8 +2700,8 @@ static int laplaciandeform_bind_exec(bContext *C, wmOperator *op) lmd->flag |= MOD_LAPLACIANDEFORM_BIND; } - LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *)modifier_get_evaluated( - depsgraph, ob, &lmd->modifier); + LaplacianDeformModifierData *lmd_eval = (LaplacianDeformModifierData *) + BKE_modifier_get_evaluated(depsgraph, ob, &lmd->modifier); lmd_eval->flag = lmd->flag; /* Force modifier to run, it will call binding routine @@ -2638,7 +2779,7 @@ static int surfacedeform_bind_exec(bContext *C, wmOperator *op) smd->flags |= MOD_SDEF_BIND; } - SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)modifier_get_evaluated( + SurfaceDeformModifierData *smd_eval = (SurfaceDeformModifierData *)BKE_modifier_get_evaluated( depsgraph, ob, &smd->modifier); smd_eval->flags = smd->flags; diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index fef046169a7..819b6c18a44 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -137,6 +137,8 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_multires_reshape); WM_operatortype_append(OBJECT_OT_multires_higher_levels_delete); WM_operatortype_append(OBJECT_OT_multires_base_apply); + WM_operatortype_append(OBJECT_OT_multires_unsubdivide); + WM_operatortype_append(OBJECT_OT_multires_rebuild_subdiv); WM_operatortype_append(OBJECT_OT_multires_external_save); WM_operatortype_append(OBJECT_OT_multires_external_pack); WM_operatortype_append(OBJECT_OT_skin_root_mark); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 759af18ed2b..bfceaef4644 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -557,7 +557,7 @@ static void object_remove_parent_deform_modifiers(Object *ob, const Object *par) /* free modifier if match */ if (free) { BLI_remlink(&ob->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); } } } @@ -803,7 +803,7 @@ bool ED_object_parent_set(ReportList *reports, switch (partype) { case PAR_CURVE: /* curve deform */ - if (modifiers_isDeformedByCurve(ob) != par) { + if (BKE_modifiers_is_deformed_by_curve(ob) != par) { md = ED_object_modifier_add(reports, bmain, scene, ob, NULL, eModifierType_Curve); if (md) { ((CurveModifierData *)md)->object = par; @@ -814,7 +814,7 @@ bool ED_object_parent_set(ReportList *reports, } break; case PAR_LATTICE: /* lattice deform */ - if (modifiers_isDeformedByLattice(ob) != par) { + if (BKE_modifiers_is_deformed_by_lattice(ob) != par) { md = ED_object_modifier_add( reports, bmain, scene, ob, NULL, eModifierType_Lattice); if (md) { @@ -823,7 +823,7 @@ bool ED_object_parent_set(ReportList *reports, } break; default: /* armature deform */ - if (modifiers_isDeformedByArmature(ob) != par) { + if (BKE_modifiers_is_deformed_by_armature(ob) != par) { md = ED_object_modifier_add( reports, bmain, scene, ob, NULL, eModifierType_Armature); if (md) { diff --git a/source/blender/editors/object/object_remesh.c b/source/blender/editors/object/object_remesh.c index 9f9179440a8..22869748b22 100644 --- a/source/blender/editors/object/object_remesh.c +++ b/source/blender/editors/object/object_remesh.c @@ -114,7 +114,7 @@ static bool object_remesh_poll(bContext *C) return false; } - if (modifiers_usesMultires(ob)) { + if (BKE_modifiers_uses_multires(ob)) { CTX_wm_operator_poll_msg_set( C, "The remesher cannot run with a Multires modifier in the modifier stack"); return false; diff --git a/source/blender/editors/object/object_shader_fx.c b/source/blender/editors/object/object_shader_fx.c index cd71ab674ba..30fcdfc88bc 100644 --- a/source/blender/editors/object/object_shader_fx.c +++ b/source/blender/editors/object/object_shader_fx.c @@ -66,7 +66,7 @@ ShaderFxData *ED_object_shaderfx_add( ReportList *reports, Main *bmain, Scene *UNUSED(scene), Object *ob, const char *name, int type) { ShaderFxData *new_fx = NULL; - const ShaderFxTypeInfo *fxi = BKE_shaderfxType_getInfo(type); + const ShaderFxTypeInfo *fxi = BKE_shaderfx_get_info(type); if (ob->type != OB_GPENCIL) { BKE_reportf(reports, RPT_WARNING, "Effect cannot be added to object '%s'", ob->id.name + 2); @@ -74,7 +74,7 @@ ShaderFxData *ED_object_shaderfx_add( } if (fxi->flags & eShaderFxTypeFlag_Single) { - if (BKE_shaderfx_findByType(ob, type)) { + if (BKE_shaderfx_findby_type(ob, type)) { BKE_report(reports, RPT_WARNING, "Only one Effect of this type is allowed"); return NULL; } @@ -236,7 +236,7 @@ static const EnumPropertyItem *shaderfx_add_itemf(bContext *C, for (a = 0; rna_enum_object_shaderfx_type_items[a].identifier; a++) { fx_item = &rna_enum_object_shaderfx_type_items[a]; if (fx_item->identifier[0]) { - mti = BKE_shaderfxType_getInfo(fx_item->value); + mti = BKE_shaderfx_get_info(fx_item->value); if (mti->flags & eShaderFxTypeFlag_NoUserAdd) { continue; @@ -356,7 +356,7 @@ static ShaderFxData *edit_shaderfx_property_get(wmOperator *op, Object *ob, int ShaderFxData *fx; RNA_string_get(op->ptr, "shaderfx", shaderfx_name); - fx = BKE_shaderfx_findByName(ob, shaderfx_name); + fx = BKE_shaderfx_findby_name(ob, shaderfx_name); if (fx && type != 0 && fx->type != type) { fx = NULL; diff --git a/source/blender/editors/object/object_transform.c b/source/blender/editors/object/object_transform.c index 62a8b46e904..132b530455e 100644 --- a/source/blender/editors/object/object_transform.c +++ b/source/blender/editors/object/object_transform.c @@ -1608,6 +1608,7 @@ struct XFormAxisItem { float rot_mat[3][3]; void *obtfm; float xform_dist; + bool is_z_flip; #ifdef USE_RELATIVE_ROTATION /* use when translating multiple */ @@ -1730,11 +1731,16 @@ static void object_apply_location(Object *ob, const float loc[3]) static bool object_orient_to_location(Object *ob, const float rot_orig[3][3], const float axis[3], - const float location[3]) + const float location[3], + const bool z_flip) { float delta[3]; sub_v3_v3v3(delta, ob->obmat[3], location); if (normalize_v3(delta) != 0.0f) { + if (z_flip) { + negate_v3(delta); + } + if (len_squared_v3v3(delta, axis) > FLT_EPSILON) { float delta_rot[3][3]; float final_rot[3][3]; @@ -1841,6 +1847,11 @@ static int object_transform_axis_target_invoke(bContext *C, wmOperator *op, cons for (int i = 0; i < xfd->object_data_len; i++, item++) { item->obtfm = BKE_object_tfm_backup(item->ob); BKE_object_rot_to_mat3(item->ob, item->rot_mat, true); + + /* Detect negative scale matrix. */ + float full_mat3[3][3]; + BKE_object_to_mat3(item->ob, full_mat3); + item->is_z_flip = dot_v3v3(item->rot_mat[2], full_mat3[2]) < 0.0f; } } @@ -1975,7 +1986,7 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const } object_orient_to_location( - item->ob, item->rot_mat, item->rot_mat[2], location_world); + item->ob, item->rot_mat, item->rot_mat[2], location_world, item->is_z_flip); DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); @@ -1989,8 +2000,11 @@ static int object_transform_axis_target_modal(bContext *C, wmOperator *op, const else { struct XFormAxisItem *item = xfd->object_data; for (int i = 0; i < xfd->object_data_len; i++, item++) { - if (object_orient_to_location( - item->ob, item->rot_mat, item->rot_mat[2], location_world)) { + if (object_orient_to_location(item->ob, + item->rot_mat, + item->rot_mat[2], + location_world, + item->is_z_flip)) { DEG_id_tag_update(&item->ob->id, ID_RECALC_TRANSFORM); WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, item->ob); } diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 3ec55d42849..fb79cfb910e 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3945,7 +3945,7 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) { if (bonebase == NULL) { - Object *armobj = modifiers_isDeformedByArmature(ob); + Object *armobj = BKE_modifiers_is_deformed_by_armature(ob); if (armobj != NULL) { bArmature *armature = armobj->data; bonebase = &armature->bonebase; diff --git a/source/blender/editors/physics/dynamicpaint_ops.c b/source/blender/editors/physics/dynamicpaint_ops.c index 37845e8d74e..6922a03b12f 100644 --- a/source/blender/editors/physics/dynamicpaint_ops.c +++ b/source/blender/editors/physics/dynamicpaint_ops.c @@ -72,7 +72,7 @@ static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) DynamicPaintSurface *surface; /* Make sure we're dealing with a canvas */ - pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint); + pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(cObject, eModifierType_DynamicPaint); if (!pmd || !pmd->canvas) { return OPERATOR_CANCELLED; } @@ -117,7 +117,7 @@ static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op)) int id = 0; /* Make sure we're dealing with a canvas */ - pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint); + pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type(obj_ctx, eModifierType_DynamicPaint); if (!pmd || !pmd->canvas) { return OPERATOR_CANCELLED; } @@ -162,7 +162,7 @@ static int type_toggle_exec(bContext *C, wmOperator *op) Object *cObject = ED_object_context(C); Scene *scene = CTX_data_scene(C); - DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType( + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type( cObject, eModifierType_DynamicPaint); int type = RNA_enum_get(op->ptr, "type"); @@ -222,7 +222,7 @@ static int output_toggle_exec(bContext *C, wmOperator *op) { Object *ob = ED_object_context(C); DynamicPaintSurface *surface; - DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType( + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type( ob, eModifierType_DynamicPaint); int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */ @@ -483,7 +483,7 @@ static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op) /* * Get modifier data */ - DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType( + DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)BKE_modifiers_findby_type( object_eval, eModifierType_DynamicPaint); if (pmd == NULL) { BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found"); diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c index 75ae0299318..6cafc51231c 100644 --- a/source/blender/editors/physics/particle_edit.c +++ b/source/blender/editors/physics/particle_edit.c @@ -849,7 +849,6 @@ static void foreach_mouse_hit_key(PEData *data, ForHitKeyMatFunc func, int selec TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, foreach_mouse_hit_key_iter, &settings); } @@ -1229,7 +1228,6 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings); } @@ -1278,7 +1276,6 @@ static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings); } @@ -1353,7 +1350,6 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings); } @@ -2256,7 +2252,7 @@ bool PE_circle_select(bContext *C, const int sel_op, const int mval[2], float ra /************************ lasso select operator ************************/ -int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const int sel_op) +int PE_lasso_select(bContext *C, const int mcoords[][2], const int mcoords_len, const int sel_op) { Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); Scene *scene = CTX_data_scene(C); @@ -2300,7 +2296,8 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const const bool is_inside = ((ED_view3d_project_int_global(region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED) && key_test_depth(&data, co, screen_co)); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2319,7 +2316,8 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, const const bool is_inside = ((ED_view3d_project_int_global(region, co, screen_co, V3D_PROJ_TEST_CLIP_WIN) == V3D_PROJ_RET_OK) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], IS_CLIPPED) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED) && key_test_depth(&data, co, screen_co)); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { @@ -2833,8 +2831,8 @@ static void remove_tagged_keys(Depsgraph *depsgraph, Object *ob, ParticleSystem if (pe_x_mirror(ob)) { /* mirror key tags */ ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *)modifier_get_evaluated( - depsgraph, ob, &psmd->modifier); + ParticleSystemModifierData *psmd_eval = (ParticleSystemModifierData *) + BKE_modifier_get_evaluated(depsgraph, ob, &psmd->modifier); LOOP_POINTS { LOOP_TAGGED_KEYS { @@ -4084,7 +4082,6 @@ typedef struct BrushAddCountIterData { short size; float imat[4][4]; ParticleData *add_pars; - int num_added; } BrushAddCountIterData; typedef struct BrushAddCountIterTLSData { @@ -4113,7 +4110,7 @@ static void brush_add_count_iter(void *__restrict iter_data_v, dmy = size; if (tls->rng == NULL) { tls->rng = BLI_rng_new_srandom(psys->seed + data->mval[0] + data->mval[1] + - tls_v->thread_id); + BLI_task_parallel_thread_id(tls_v)); } /* rejection sampling to get points in circle */ while (dmx * dmx + dmy * dmy > size2) { @@ -4176,12 +4173,19 @@ static void brush_add_count_iter(void *__restrict iter_data_v, } } -static void brush_add_count_iter_finalize(void *__restrict userdata_v, - void *__restrict userdata_chunk_v) +static void brush_add_count_iter_reduce(const void *__restrict UNUSED(userdata), + void *__restrict join_v, + void *__restrict chunk_v) +{ + BrushAddCountIterTLSData *join = (BrushAddCountIterTLSData *)join_v; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v; + join->num_added += tls->num_added; +} + +static void brush_add_count_iter_free(const void *__restrict UNUSED(userdata_v), + void *__restrict chunk_v) { - BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v; - BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v; - iter_data->num_added += tls->num_added; + BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)chunk_v; if (tls->rng != NULL) { BLI_rng_free(tls->rng); } @@ -4245,23 +4249,22 @@ static int brush_add(const bContext *C, PEData *data, short number) iter_data.number = number; iter_data.size = size; iter_data.add_pars = add_pars; - iter_data.num_added = 0; copy_m4_m4(iter_data.imat, imat); BrushAddCountIterTLSData tls = {NULL}; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); - settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC; settings.userdata_chunk = &tls; settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData); - settings.func_finalize = brush_add_count_iter_finalize; + settings.func_reduce = brush_add_count_iter_reduce; + settings.func_free = brush_add_count_iter_free; BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings); /* Convert add_parse to a dense array, where all new particles are in the * beginning of the array. */ - n = iter_data.num_added; + n = tls.num_added; for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) { if (add_pars[current_iter].num == DMCACHE_NOTFOUND) { continue; @@ -5124,7 +5127,8 @@ void PE_create_particle_edit( int totpoint; if (psmd != NULL) { - psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name); + psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name(ob_eval, + psmd->modifier.name); } /* no psmd->dm happens in case particle system modifier is not enabled */ @@ -5251,8 +5255,8 @@ static bool particle_edit_toggle_poll(bContext *C) return 0; } - return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || - modifiers_findByType(ob, eModifierType_Softbody)); + return (ob->particlesystem.first || BKE_modifiers_findby_type(ob, eModifierType_Cloth) || + BKE_modifiers_findby_type(ob, eModifierType_Softbody)); } static void free_all_psys_edit(Object *object) @@ -5297,7 +5301,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) * with possible changes applied when object was outside of the * edit mode. */ Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); - edit->psmd_eval = (ParticleSystemModifierData *)modifiers_findByName( + edit->psmd_eval = (ParticleSystemModifierData *)BKE_modifiers_findny_name( object_eval, edit->psmd->modifier.name); recalc_emitter_field(depsgraph, ob, edit->psys); } diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index f37a20bf43e..e75169a476b 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -1064,7 +1064,7 @@ static void remove_particle_systems_from_object(Object *ob_to) eModifierType_DynamicPaint, eModifierType_Fluid)) { BLI_remlink(&ob_to->modifiers, md); - modifier_free(md); + BKE_modifier_free(md); } } @@ -1138,13 +1138,13 @@ static bool copy_particle_systems_to_object(const bContext *C, psys_unique_name(ob_to, psys, psys->name); /* add a particle system modifier for each system */ - md = modifier_new(eModifierType_ParticleSystem); + md = BKE_modifier_new(eModifierType_ParticleSystem); psmd = (ParticleSystemModifierData *)md; /* push on top of the stack, no use trying to reproduce old stack order */ BLI_addtail(&ob_to->modifiers, md); BLI_snprintf(md->name, sizeof(md->name), "ParticleSystem %i", i); - modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); + BKE_modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd); psmd->psys = psys; diff --git a/source/blender/editors/physics/physics_fluid.c b/source/blender/editors/physics/physics_fluid.c index eb808398254..ceaac201da3 100644 --- a/source/blender/editors/physics/physics_fluid.c +++ b/source/blender/editors/physics/physics_fluid.c @@ -156,7 +156,7 @@ static bool fluid_initjob( FluidDomainSettings *mds; Object *ob = CTX_data_active_object(C); - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { BLI_strncpy(error_msg, N_("Bake failed: no Fluid modifier found"), error_size); return false; @@ -185,13 +185,13 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports) temp_dir[0] = '\0'; bool is_relative = false; - const char *relbase = modifier_path_relbase(job->bmain, job->ob); + const char *relbase = BKE_modifier_path_relbase(job->bmain, job->ob); /* We do not accept empty paths, they can end in random places silently, see T51176. */ if (mds->cache_directory[0] == '\0') { char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); - modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); + BKE_modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); BKE_reportf(reports, RPT_WARNING, "Fluid: Empty cache path, reset to default '%s'", @@ -209,7 +209,7 @@ static bool fluid_validatepaths(FluidJob *job, ReportList *reports) if (!dir_exists) { char cache_name[64]; BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name); - modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); + BKE_modifier_path_init(mds->cache_directory, sizeof(mds->cache_directory), cache_name); BKE_reportf(reports, RPT_ERROR, @@ -361,7 +361,7 @@ static void fluid_bake_endjob(void *customdata) RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start); } else { - if (mds->error != NULL && mds->error[0] != '\0') { + if (mds->error[0] != '\0') { WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error); } else { /* User canceled the bake */ @@ -376,7 +376,7 @@ static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, FluidDomainSettings *mds = job->mmd->domain; char temp_dir[FILE_MAX]; - const char *relbase = modifier_path_relbase_from_global(job->ob); + const char *relbase = BKE_modifier_path_relbase_from_global(job->ob); job->stop = stop; job->do_update = do_update; @@ -473,7 +473,7 @@ static void fluid_free_endjob(void *customdata) RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start); } else { - if (mds->error != NULL && mds->error[0] != '\0') { + if (mds->error[0] != '\0') { WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, mds->error); } else { /* User canceled the free job */ @@ -622,7 +622,7 @@ static int fluid_free_exec(struct bContext *C, struct wmOperator *op) /* * Get modifier data */ - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found"); return OPERATOR_CANCELLED; @@ -684,7 +684,7 @@ static int fluid_pause_exec(struct bContext *C, struct wmOperator *op) /* * Get modifier data */ - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (!mmd) { BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found"); return OPERATOR_CANCELLED; diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f35f92feaec..f2e8209b099 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -144,7 +144,6 @@ typedef struct OGLRender { wmTimer *timer; /* use to check if running modal or not (invoke'd or exec'd)*/ void **movie_ctx_arr; - TaskScheduler *task_scheduler; TaskPool *task_pool; bool pool_ok; bool is_animation; @@ -630,6 +629,7 @@ static int gather_frames_to_render_for_id(LibraryIDLinkCallbackData *cb_data) case ID_HA: /* Hair */ case ID_PT: /* PointCloud */ case ID_VO: /* Volume */ + case ID_SIM: /* Simulation */ break; /* Blacklist: */ @@ -855,22 +855,16 @@ static bool screen_opengl_render_init(bContext *C, wmOperator *op) gather_frames_to_render(C, oglrender); } - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); if (BKE_imtype_is_movie(scene->r.im_format.imtype)) { - task_scheduler = BLI_task_scheduler_create(1); - oglrender->task_scheduler = task_scheduler; - oglrender->task_pool = BLI_task_pool_create_background( - task_scheduler, oglrender, TASK_PRIORITY_LOW); + oglrender->task_pool = BLI_task_pool_create_background_serial(oglrender, TASK_PRIORITY_LOW); } else { - oglrender->task_scheduler = NULL; - oglrender->task_pool = BLI_task_pool_create(task_scheduler, oglrender, TASK_PRIORITY_LOW); + oglrender->task_pool = BLI_task_pool_create(oglrender, TASK_PRIORITY_LOW); } oglrender->pool_ok = true; BLI_spin_init(&oglrender->reports_lock); } else { - oglrender->task_scheduler = NULL; oglrender->task_pool = NULL; } oglrender->num_scheduled_frames = 0; @@ -909,10 +903,6 @@ static void screen_opengl_render_end(bContext *C, OGLRender *oglrender) } BLI_task_pool_work_and_wait(oglrender->task_pool); BLI_task_pool_free(oglrender->task_pool); - /* Depending on various things we might or might not use global scheduler. */ - if (oglrender->task_scheduler != NULL) { - BLI_task_scheduler_free(oglrender->task_scheduler); - } BLI_spin_end(&oglrender->reports_lock); } BLI_mutex_end(&oglrender->task_mutex); @@ -1032,9 +1022,9 @@ typedef struct WriteTaskData { Scene tmp_scene; } WriteTaskData; -static void write_result_func(TaskPool *__restrict pool, void *task_data_v, int UNUSED(thread_id)) +static void write_result_func(TaskPool *__restrict pool, void *task_data_v) { - OGLRender *oglrender = (OGLRender *)BLI_task_pool_userdata(pool); + OGLRender *oglrender = (OGLRender *)BLI_task_pool_user_data(pool); WriteTaskData *task_data = (WriteTaskData *)task_data_v; Scene *scene = &task_data->tmp_scene; RenderResult *rr = task_data->rr; diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 94937ce9db8..8fb96ca0b76 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2517,6 +2517,7 @@ void ED_region_panels_layout_ex(const bContext *C, int margin_x = 0; const bool region_layout_based = region->flag & RGN_FLAG_DYNAMIC_SIZE; const bool is_context_new = (contextnr != -1) ? UI_view2d_tab_set(v2d, contextnr) : false; + bool update_tot_size = true; /* before setting the view */ if (vertical) { @@ -2534,7 +2535,6 @@ void ED_region_panels_layout_ex(const bContext *C, v2d->scroll |= (V2D_SCROLL_BOTTOM); v2d->scroll &= ~(V2D_SCROLL_RIGHT); } - const int scroll = v2d->scroll; /* collect categories */ if (use_category_tabs) { @@ -2586,6 +2586,11 @@ void ED_region_panels_layout_ex(const bContext *C, } } + if (panel && UI_panel_is_dragging(panel)) { + /* Prevent View2d.tot rectangle size changes while dragging panels. */ + update_tot_size = false; + } + ed_panel_draw(C, area, region, ®ion->panels, pt, panel, w, em, vertical); } @@ -2641,17 +2646,9 @@ void ED_region_panels_layout_ex(const bContext *C, y = -y; } - /* this also changes the 'cur' */ - UI_view2d_totRect_set(v2d, x, y); - - if (scroll != v2d->scroll) { - /* Note: this code scales fine, but because of rounding differences, positions of elements - * flip +1 or -1 pixel compared to redoing the entire layout again. - * Leaving in commented code for future tests */ -#if 0 - UI_panels_scale(region, BLI_rctf_size_x(&v2d->cur)); - break; -#endif + if (update_tot_size) { + /* this also changes the 'cur' */ + UI_view2d_totRect_set(v2d, x, y); } if (use_category_tabs) { diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 83edb2c3aca..00afbf452dd 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -413,8 +413,7 @@ static void region_cursor_set(wmWindow *win, bool swin_changed) { bScreen *screen = WM_window_get_active_screen(win); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region == screen->active_region) { region_cursor_set_ex(win, area, region, swin_changed); @@ -467,8 +466,7 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) screen_geom_vertices_scale(win, screen); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { /* set spacetype and region callbacks, calls init() */ /* sets subwindows for regions, adds handlers */ ED_area_initialize(wm, win, area); @@ -691,8 +689,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) ARegion *region; ARegion *region_prev = screen->active_region; - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { if (xy[0] > area_iter->totrct.xmin && xy[0] < area_iter->totrct.xmax) { if (xy[1] > area_iter->totrct.ymin && xy[1] < area_iter->totrct.ymax) { if (ED_area_azones_update(area_iter, xy) == NULL) { @@ -718,8 +715,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) /* Check for redraw headers. */ if (region_prev != screen->active_region) { - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { bool do_draw = false; for (region = area_iter->regionbase.first; region; region = region->next) { diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 31174f88629..5b808206935 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -1741,8 +1741,7 @@ static void area_move_apply_do(const bContext *C, /* only redraw if we actually moved a screen vert, for AREAGRID */ if (doredraw) { bool redraw_all = false; - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { if (area->v1->editflag || area->v2->editflag || area->v3->editflag || area->v4->editflag) { if (ED_area_is_global(area)) { /* Snap to minimum or maximum for global areas. */ @@ -1761,8 +1760,7 @@ static void area_move_apply_do(const bContext *C, } } if (redraw_all) { - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { ED_area_tag_redraw(area); } } @@ -3870,7 +3868,6 @@ static int region_quadview_exec(bContext *C, wmOperator *op) rv3d->viewlock_quad = RV3D_VIEWLOCK_INIT; rv3d->viewlock = 0; - rv3d->rflag &= ~RV3D_CLIPPING; /* FIXME: This fixes missing update to workbench TAA. (see T76216) * However, it would be nice if the tagging should be done in a more conventional way. */ @@ -4393,7 +4390,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv wmWindow *window; ScrArea *area; int sync; - float time; + double time; /* sync, don't sync, or follow scene setting */ if (sad->flag & ANIMPLAY_FLAG_SYNC) { @@ -4416,7 +4413,7 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } else if ((scene->audio.flag & AUDIO_SYNC) && (sad->flag & ANIMPLAY_FLAG_REVERSE) == false && isfinite(time = BKE_sound_sync_scene(scene_eval))) { - double newfra = (double)time * FPS; + double newfra = time * FPS; /* give some space here to avoid jumps */ if (newfra + 0.5 > scene->r.cfra && newfra - 0.5 < scene->r.cfra) { @@ -4440,10 +4437,29 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } else { if (sync) { - /* note: this is very simplistic, - * its has problem that it may skip too many frames. - * however at least this gives a less jittery playback */ - const int step = max_ii(1, floor((wt->duration - sad->last_duration) * FPS)); + /* Try to keep the playback in realtime by dropping frames. */ + + /* How much time (in frames) has passed since the last frame was drawn? */ + double delta_frames = wt->delta * FPS; + + /* Add the remaining fraction from the last time step. */ + delta_frames += sad->lagging_frame_count; + + if (delta_frames < 1.0) { + /* We can render faster than the scene frame rate. However skipping or delaying frames + * here seems to in practice lead to jittery playback so just step forward a minimum of + * one frame. (Even though this can lead to too fast playback, the jitteryness is more + * annoying) + */ + delta_frames = 1.0f; + sad->lagging_frame_count = 0; + } + else { + /* Extract the delta frame fractions that will be skipped when converting to int. */ + sad->lagging_frame_count = delta_frames - (int)delta_frames; + } + + const int step = delta_frames; /* skip frames */ if (sad->flag & ANIMPLAY_FLAG_REVERSE) { @@ -4464,8 +4480,6 @@ static int screen_animation_step(bContext *C, wmOperator *UNUSED(op), const wmEv } } - sad->last_duration = wt->duration; - /* reset 'jumped' flag before checking if we need to jump... */ sad->flag &= ~ANIMPLAY_FLAG_JUMPED; diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c index 536453ad085..191a064a95c 100644 --- a/source/blender/editors/sculpt_paint/paint_cursor.c +++ b/source/blender/editors/sculpt_paint/paint_cursor.c @@ -10,7 +10,7 @@ * 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, + * 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) 2009 by Nicholas Bishop @@ -171,6 +171,8 @@ static void load_tex_task_cb_ex(void *__restrict userdata, bool convert_to_linear = false; struct ColorSpace *colorspace = NULL; + const int thread_id = BLI_task_parallel_thread_id(tls); + if (mtex->tex && mtex->tex->type == TEX_IMAGE && mtex->tex->ima) { ImBuf *tex_ibuf = BKE_image_pool_acquire_ibuf(mtex->tex->ima, &mtex->tex->iuser, pool); /* For consistency, sampling always returns color in linear space. */ @@ -214,8 +216,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata, if (col) { float rgba[4]; - paint_get_tex_pixel_col( - mtex, x, y, rgba, pool, tls->thread_id, convert_to_linear, colorspace); + paint_get_tex_pixel_col(mtex, x, y, rgba, pool, thread_id, convert_to_linear, colorspace); buffer[index * 4] = rgba[0] * 255; buffer[index * 4 + 1] = rgba[1] * 255; @@ -223,7 +224,7 @@ static void load_tex_task_cb_ex(void *__restrict userdata, buffer[index * 4 + 3] = rgba[3] * 255; } else { - float avg = paint_get_tex_pixel(mtex, x, y, pool, tls->thread_id); + float avg = paint_get_tex_pixel(mtex, x, y, pool, thread_id); avg += br->texture_sample_bias; diff --git a/source/blender/editors/sculpt_paint/paint_hide.c b/source/blender/editors/sculpt_paint/paint_hide.c index 69ca86efa9d..e9dcc4a356a 100644 --- a/source/blender/editors/sculpt_paint/paint_hide.c +++ b/source/blender/editors/sculpt_paint/paint_hide.c @@ -10,7 +10,7 @@ * 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, + * 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) 2010 by Nicholas Bishop diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 6af9ec01fc3..3dc6305dcf2 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -5168,9 +5168,7 @@ static void copy_original_alpha_channel(ProjPixel *pixel, bool is_floatbuf) } /* Run this for single and multi-threaded painting. */ -static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), - void *ph_v, - int UNUSED(threadid)) +static void do_projectpaint_thread(TaskPool *__restrict UNUSED(pool), void *ph_v) { /* First unpack args from the struct */ ProjPaintState *ps = ((ProjectHandle *)ph_v)->ps; @@ -5605,7 +5603,6 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po bool touch_any = false; ProjectHandle handles[BLENDER_MAX_THREADS]; - TaskScheduler *scheduler = NULL; TaskPool *task_pool = NULL; int a, i; @@ -5616,8 +5613,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po } if (ps->thread_tot > 1) { - scheduler = BLI_task_scheduler_get(); - task_pool = BLI_task_pool_create_suspended(scheduler, NULL, TASK_PRIORITY_HIGH); + task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH); } image_pool = BKE_image_pool_new(); @@ -5661,7 +5657,7 @@ static bool project_paint_op(void *state, const float lastpos[2], const float po BLI_task_pool_free(task_pool); } else { - do_projectpaint_thread(NULL, &handles[0], 0); + do_projectpaint_thread(NULL, &handles[0]); } BKE_image_pool_free(image_pool); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index fb8cc3a639b..c32e496f4f5 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -10,7 +10,7 @@ * 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, + * 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) 2012 by Nicholas Bishop @@ -168,9 +168,9 @@ static int mask_flood_fill_exec(bContext *C, wmOperator *op) .value = value, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_flood_fill_task_cb, &settings); if (multires) { multires_mark_as_modified(depsgraph, ob, MULTIRES_COORDS_MODIFIED); @@ -343,9 +343,9 @@ bool ED_sculpt_mask_box_select(struct bContext *C, ViewContext *vc, const rcti * .clip_planes_final = clip_planes_final, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_box_select_task_cb, &settings); if (nodes) { MEM_freeN(nodes); @@ -456,10 +456,10 @@ static void mask_gesture_lasso_task_cb(void *__restrict userdata, static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); float clip_planes[4][4], clip_planes_final[4][4]; BoundBox bb; @@ -485,7 +485,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) ob = vc.obact; ED_view3d_ob_project_mat_get(vc.rv3d, ob, data.projviewobjmat); - BLI_lasso_boundbox(&data.rect, mcords, mcords_tot); + BLI_lasso_boundbox(&data.rect, mcoords, mcoords_len); data.width = data.rect.xmax - data.rect.xmin; data.px = BLI_BITMAP_NEW(data.width * (data.rect.ymax - data.rect.ymin), __func__); @@ -493,8 +493,8 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) data.rect.ymin, data.rect.xmax, data.rect.ymax, - mcords, - mcords_tot, + mcoords, + mcoords_len, mask_lasso_px_cb, &data); @@ -532,9 +532,9 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) data.task_data.mode = mode; data.task_data.value = value; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_gesture_lasso_task_cb, &settings); if (nodes) { MEM_freeN(nodes); @@ -551,7 +551,7 @@ static int paint_mask_gesture_lasso_exec(bContext *C, wmOperator *op) SCULPT_undo_push_end(); ED_region_tag_redraw(vc.region); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); MEM_freeN(data.px); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 7887aaaf658..458c24e5194 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -10,7 +10,7 @@ * 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, + * 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) 2009 by Nicholas Bishop diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 60b4a2f8e0c..c84a3b9cbfc 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -166,10 +166,11 @@ float paint_calc_object_space_radius(ViewContext *vc, const float center[3], flo float paint_get_tex_pixel(const MTex *mtex, float u, float v, struct ImagePool *pool, int thread) { - float intensity, rgba[4]; + float intensity; + float rgba_dummy[4]; float co[3] = {u, v, 0.0f}; - externtex(mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba_dummy); return intensity; } @@ -184,11 +185,10 @@ void paint_get_tex_pixel_col(const MTex *mtex, struct ColorSpace *colorspace) { float co[3] = {u, v, 0.0f}; - int hasrgb; float intensity; - hasrgb = externtex( - mtex, co, &intensity, rgba, rgba + 1, rgba + 2, rgba + 3, thread, pool, false, false); + const bool hasrgb = RE_texture_evaluate(mtex, co, thread, pool, false, false, &intensity, rgba); + if (!hasrgb) { rgba[0] = intensity; rgba[1] = intensity; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index d050a39ce68..66e72145835 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -1398,7 +1398,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op) */ { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); if (md != NULL) { /* Can be NULL. */ View3D *v3d = CTX_wm_view3d(C); @@ -2183,9 +2183,9 @@ static void calculate_average_weight(SculptThreadedTaskData *data, struct WPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__); data->custom_data = accum; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (data->sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, data, do_wpaint_brush_calc_average_weight_cb_ex, &settings); uint accum_len = 0; double accum_weight = 0.0; @@ -2231,22 +2231,22 @@ static void wpaint_paint_leaves(bContext *C, data.strength = BKE_brush_weight_get(scene, brush); /* NOTE: current mirroring code cannot be run in parallel */ - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, !(me->editflag & ME_EDIT_MIRROR_X), totnode); switch ((eBrushWeightPaintTool)brush->weightpaint_tool) { case WPAINT_TOOL_AVERAGE: calculate_average_weight(&data, nodes, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); break; case WPAINT_TOOL_SMEAR: - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_smear_task_cb_ex, &settings); break; case WPAINT_TOOL_BLUR: - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_blur_task_cb_ex, &settings); break; case WPAINT_TOOL_DRAW: - BKE_pbvh_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_wpaint_brush_draw_task_cb_ex, &settings); break; } } @@ -3252,9 +3252,9 @@ static void calculate_average_color(SculptThreadedTaskData *data, struct VPaintAverageAccum *accum = MEM_mallocN(sizeof(*accum) * totnode, __func__); data->custom_data = accum; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); - BKE_pbvh_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, data, do_vpaint_brush_calc_average_color_cb_ex, &settings); uint accum_len = 0; uint accum_value[3] = {0}; @@ -3298,21 +3298,21 @@ static void vpaint_paint_leaves(bContext *C, .lcol = (uint *)me->mloopcol, .me = me, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, true, totnode); switch ((eBrushVertexPaintTool)brush->vertexpaint_tool) { case VPAINT_TOOL_AVERAGE: calculate_average_color(&data, nodes, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); break; case VPAINT_TOOL_BLUR: - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_blur_task_cb_ex, &settings); break; case VPAINT_TOOL_SMEAR: - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_smear_task_cb_ex, &settings); break; case VPAINT_TOOL_DRAW: - BKE_pbvh_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_vpaint_brush_draw_task_cb_ex, &settings); break; } } diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c index 103f312975a..08ffd8e620e 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_ops.c @@ -108,7 +108,7 @@ static bool weight_from_bones_poll(bContext *C) { Object *ob = CTX_data_active_object(C); - return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && modifiers_isDeformedByArmature(ob)); + return (ob && (ob->mode & OB_MODE_WEIGHT_PAINT) && BKE_modifiers_is_deformed_by_armature(ob)); } static int weight_from_bones_exec(bContext *C, wmOperator *op) @@ -116,7 +116,7 @@ static int weight_from_bones_exec(bContext *C, wmOperator *op) Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); Scene *scene = CTX_data_scene(C); Object *ob = CTX_data_active_object(C); - Object *armob = modifiers_isDeformedByArmature(ob); + Object *armob = BKE_modifiers_is_deformed_by_armature(ob); Mesh *me = ob->data; int type = RNA_enum_get(op->ptr, "type"); diff --git a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c index 5a3067ef193..a483f63bc06 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c +++ b/source/blender/editors/sculpt_paint/paint_vertex_weight_utils.c @@ -82,7 +82,7 @@ bool ED_wpaint_ensure_data(bContext *C, /* this happens on a Bone select, when no vgroup existed yet */ if (ob->actdef <= 0) { Object *modob; - if ((modob = modifiers_isDeformedByArmature(ob))) { + if ((modob = BKE_modifiers_is_deformed_by_armature(ob))) { Bone *actbone = ((bArmature *)modob->data)->act_bone; if (actbone) { bPoseChannel *pchan = BKE_pose_channel_find_name(modob->pose, actbone->name); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index 69345b70d1c..045fd54b46a 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 by Nicholas Bishop @@ -806,12 +806,12 @@ int SCULPT_nearest_vertex_get( nvtd.nearest_vertex_index = -1; nvtd.nearest_vertex_distance_squared = FLT_MAX; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = nearest_vertex_get_reduce; settings.userdata_chunk = &nvtd; settings.userdata_chunk_size = sizeof(NearestVertexTLSData); - BKE_pbvh_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &task_data, do_nearest_vertex_get_task_cb, &settings); MEM_SAFE_FREE(nodes); @@ -952,11 +952,11 @@ static bool sculpt_has_active_modifiers(Scene *scene, Object *ob) ModifierData *md; VirtualModifierData virtualModifierData; - md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* Exception for shape keys because we can edit those. */ for (; md; md = md->next) { - if (modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + if (BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { return true; } } @@ -1283,9 +1283,9 @@ static void paint_mesh_restore_co(Sculpt *sd, Object *ob) .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP) && !ss->bm, totnode); - BKE_pbvh_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, paint_mesh_restore_co_task_cb, &settings); MEM_SAFE_FREE(nodes); } @@ -1909,12 +1909,12 @@ static void calc_area_center( AreaNormalCenterTLSData anctd = {{{0}}}; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { @@ -1968,12 +1968,12 @@ bool SCULPT_pbvh_calc_area_normal(const Brush *brush, AreaNormalCenterTLSData anctd = {{{0}}}; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, use_threading, totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); /* For area normal. */ for (int i = 0; i < ARRAY_SIZE(anctd.area_nos); i++) { @@ -2009,12 +2009,12 @@ static void calc_area_normal_and_center( AreaNormalCenterTLSData anctd = {{{0}}}; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = calc_area_normal_and_center_reduce; settings.userdata_chunk = &anctd; settings.userdata_chunk_size = sizeof(AreaNormalCenterTLSData); - BKE_pbvh_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, calc_area_normal_and_center_task_cb, &settings); /* For flatten center. */ for (n = 0; n < ARRAY_SIZE(anctd.area_cos); n++) { @@ -2100,7 +2100,7 @@ static float brush_strength(const Sculpt *sd, return alpha * pressure * overlap * feather * 2.0f; case SCULPT_TOOL_CLAY_STRIPS: /* Clay Strips needs less strength to compensate the curve. */ - final_pressure = pressure * pressure * pressure; + final_pressure = powf(pressure, 1.5f); return alpha * flip * final_pressure * overlap * feather * 0.3f; case SCULPT_TOOL_CLAY_THUMB: final_pressure = pressure * pressure; @@ -2618,22 +2618,17 @@ static void do_topology_rake_bmesh_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); PBVHVertexIter vd; BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { - const float fade = bstrength * - SCULPT_brush_strength_factor(ss, - brush, - vd.co, - sqrtf(test.dist), - vd.no, - vd.fno, - *vd.mask, - vd.index, - tls->thread_id) * - ss->cache->pressure; + const float fade = + bstrength * + SCULPT_brush_strength_factor( + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, *vd.mask, vd.index, thread_id) * + ss->cache->pressure; float avg[3], val[3]; @@ -2675,10 +2670,10 @@ static void bmesh_topology_rake( .nodes = nodes, .strength = factor, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_topology_rake_bmesh_task_cb_ex, &settings); } } @@ -2696,12 +2691,13 @@ static void do_mask_brush_draw_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { const float fade = SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); if (bstrength > 0.0f) { (*vd.mask) += fade * bstrength * (1.0f - *vd.mask); @@ -2731,9 +2727,9 @@ static void do_mask_brush_draw(Sculpt *sd, Object *ob, PBVHNode **nodes, int tot .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_mask_brush_draw_task_cb_ex, &settings); } static void do_mask_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) @@ -2768,6 +2764,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2781,7 +2778,7 @@ static void do_draw_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -2818,9 +2815,9 @@ static void do_draw_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .offset = offset, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_draw_brush_task_cb_ex, &settings); } static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, @@ -2843,6 +2840,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2857,7 +2855,7 @@ static void do_draw_sharp_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -2894,9 +2892,9 @@ static void do_draw_sharp_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .offset = offset, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_draw_sharp_brush_task_cb_ex, &settings); } /* -------------------------------------------------------------------- */ @@ -2923,6 +2921,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -2936,7 +2935,7 @@ static void do_topology_slide_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float current_disp[3]; float current_disp_norm[3]; float final_disp[3]; @@ -3037,6 +3036,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3050,7 +3050,7 @@ static void do_topology_relax_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); SCULPT_relax_vertex(ss, &vd, fade * bstrength, false, vd.co); if (vd.mvert) { @@ -3079,15 +3079,15 @@ static void do_slide_relax_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); if (ss->cache->alt_smooth) { for (int i = 0; i < 4; i++) { - BKE_pbvh_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_topology_relax_task_cb_ex, &settings); } } else { - BKE_pbvh_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_topology_slide_task_cb_ex, &settings); } } @@ -3200,6 +3200,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3213,7 +3214,7 @@ static void do_crease_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float val1[3]; float val2[3]; @@ -3288,9 +3289,9 @@ static void do_crease_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .flippedbstrength = flippedbstrength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_crease_brush_task_cb_ex, &settings); } static void do_pinch_brush_task_cb_ex(void *__restrict userdata, @@ -3311,6 +3312,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); float x_object_space[3]; float z_object_space[3]; @@ -3328,7 +3330,7 @@ static void do_pinch_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float disp_center[3]; float x_disp[3]; float z_disp[3]; @@ -3401,9 +3403,9 @@ static void do_pinch_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .stroke_xz = stroke_xz, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_pinch_brush_task_cb_ex, &settings); } static void do_grab_brush_task_cb_ex(void *__restrict userdata, @@ -3427,6 +3429,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3441,7 +3444,7 @@ static void do_grab_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -3473,9 +3476,9 @@ static void do_grab_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_grab_brush_task_cb_ex, &settings); } static void do_elastic_deform_brush_task_cb_ex(void *__restrict userdata, @@ -3582,9 +3585,9 @@ static void do_elastic_deform_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_elastic_deform_brush_task_cb_ex, &settings); } ePaintSymmetryAreas SCULPT_get_vertex_symm_area(const float co[3]) @@ -3744,6 +3747,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3756,7 +3760,7 @@ static void do_nudge_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -3788,9 +3792,9 @@ static void do_nudge_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .cono = cono, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_nudge_brush_task_cb_ex, &settings); } static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, @@ -3817,6 +3821,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3829,7 +3834,7 @@ static void do_snake_hook_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], grab_delta, fade); @@ -3909,9 +3914,9 @@ static void do_snake_hook_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_snake_hook_brush_task_cb_ex, &settings); } static void do_thumb_brush_task_cb_ex(void *__restrict userdata, @@ -3935,6 +3940,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -3949,7 +3955,7 @@ static void do_thumb_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], cono, fade); @@ -3981,9 +3987,9 @@ static void do_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .cono = cono, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_thumb_brush_task_cb_ex, &settings); } static void do_rotate_brush_task_cb_ex(void *__restrict userdata, @@ -4007,6 +4013,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4022,7 +4029,7 @@ static void do_rotate_brush_task_cb_ex(void *__restrict userdata, NULL, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); sub_v3_v3v3(vec, orig_data.co, ss->cache->location); axis_angle_normalized_to_mat3(rot, ss->cache->sculpt_normal_symm, angle * fade); @@ -4054,9 +4061,9 @@ static void do_rotate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .angle = angle, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_rotate_brush_task_cb_ex, &settings); } static void do_layer_brush_task_cb_ex(void *__restrict userdata, @@ -4078,6 +4085,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4092,7 +4100,7 @@ static void do_layer_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); const int vi = vd.index; float *disp_factor; @@ -4169,9 +4177,9 @@ static void do_layer_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_layer_brush_task_cb_ex, &settings); } static void do_inflate_brush_task_cb_ex(void *__restrict userdata, @@ -4191,6 +4199,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4203,7 +4212,7 @@ static void do_inflate_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float val[3]; if (vd.fno) { @@ -4235,9 +4244,9 @@ static void do_inflate_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_inflate_brush_task_cb_ex, &settings); } int SCULPT_plane_trim(const StrokeCache *cache, const Brush *brush, const float val[3]) @@ -4293,6 +4302,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); @@ -4315,7 +4325,7 @@ static void do_flatten_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4359,9 +4369,9 @@ static void do_flatten_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totno .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_flatten_brush_task_cb_ex, &settings); } /* -------------------------------------------------------------------- */ @@ -4447,6 +4457,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); @@ -4467,7 +4478,7 @@ static void do_clay_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4509,13 +4520,13 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) ClaySampleData csd = {{0}}; - PBVHParallelSettings sample_settings; + TaskParallelSettings sample_settings; BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode); sample_settings.func_reduce = calc_clay_surface_reduce; sample_settings.userdata_chunk = &csd; sample_settings.userdata_chunk_size = sizeof(ClaySampleData); - BKE_pbvh_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings); + BLI_task_parallel_range(0, totnode, &sample_data, calc_clay_surface_task_cb, &sample_settings); float d_offset = (csd.plane_dist[0] + csd.plane_dist[1]); d_offset = min_ff(radius, d_offset); @@ -4540,9 +4551,9 @@ static void do_clay_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_clay_brush_task_cb_ex, &settings); } static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, @@ -4566,6 +4577,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, SCULPT_brush_test_init(ss, &test); plane_from_point_normal_v3(test.plane_tool, area_co, area_no_sp); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -4589,7 +4601,7 @@ static void do_clay_strips_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4611,7 +4623,7 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t const bool flip = (ss->cache->bstrength < 0.0f); const float radius = flip ? -ss->cache->radius : ss->cache->radius; const float offset = SCULPT_brush_plane_offset_get(sd, ss); - const float displace = radius * (0.25f + offset); + const float displace = radius * (0.18f + offset); /* The sculpt-plane normal (whatever its set to). */ float area_no_sp[3]; @@ -4673,9 +4685,9 @@ static void do_clay_strips_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int t .mat = mat, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_clay_strips_brush_task_cb_ex, &settings); } static void do_fill_brush_task_cb_ex(void *__restrict userdata, @@ -4697,6 +4709,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); @@ -4720,7 +4733,7 @@ static void do_fill_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4766,9 +4779,9 @@ static void do_fill_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_fill_brush_task_cb_ex, &settings); } static void do_scrape_brush_task_cb_ex(void *__restrict userdata, @@ -4790,6 +4803,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); plane_from_point_normal_v3(test.plane_tool, area_co, area_no); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) @@ -4812,7 +4826,7 @@ static void do_scrape_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -4858,9 +4872,9 @@ static void do_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnod .area_co = area_co, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_scrape_brush_task_cb_ex, &settings); } /* -------------------------------------------------------------------- */ @@ -4888,6 +4902,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); float plane_tilt[4]; float normal_tilt[3]; @@ -4928,7 +4943,7 @@ static void do_clay_thumb_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -5030,9 +5045,9 @@ static void do_clay_thumb_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int to .clay_strength = clay_strength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_clay_thumb_brush_task_cb_ex, &settings); } /** \} */ @@ -5054,6 +5069,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -5066,7 +5082,7 @@ static void do_gravity_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], offset, fade); @@ -5101,9 +5117,9 @@ static void do_gravity(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode, fl .offset = offset, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_gravity_task_cb_ex, &settings); } void SCULPT_vertcos_to_key(Object *ob, KeyBlock *kb, const float (*vertCos)[3]) @@ -5284,7 +5300,7 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe /* Draw Face Sets in draw mode makes a single undo push, in alt-smooth mode deforms the * vertices and uses regular coords undo. */ - /* It also assings the paint_face_set here as it needs to be done regardless of the stroke type + /* It also assigns the paint_face_set here as it needs to be done regardless of the stroke type * and the number of nodes under the brush influence. */ if (brush->sculpt_tool == SCULPT_TOOL_DRAW_FACE_SETS && ss->cache->first_time && ss->cache->mirror_symmetry_pass == 0 && !ss->cache->alt_smooth) { @@ -5310,9 +5326,9 @@ static void do_brush_action(Sculpt *sd, Object *ob, Brush *brush, UnifiedPaintSe .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &task_data, do_brush_action_task_cb, &settings); if (sculpt_brush_needs_normal(ss, brush)) { update_sculpt_normal(sd, ob, nodes, totnode); @@ -5566,9 +5582,9 @@ static void sculpt_combine_proxies(Sculpt *sd, Object *ob) .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, sculpt_combine_proxies_task_cb, &settings); } MEM_SAFE_FREE(nodes); @@ -5654,9 +5670,9 @@ void SCULPT_flush_stroke_deform(Sculpt *sd, Object *ob, bool is_proxy_used) .vertCos = vertCos, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, SCULPT_flush_stroke_deform_task_cb, &settings); if (vertCos) { SCULPT_vertcos_to_key(ob, ss->shapekey_active, vertCos); @@ -6182,7 +6198,7 @@ static float sculpt_brush_dynamic_size_get(Brush *brush, StrokeCache *cache, flo case SCULPT_TOOL_CLAY: return max_ff(initial_size * 0.20f, initial_size * pow3f(cache->pressure)); case SCULPT_TOOL_CLAY_STRIPS: - return max_ff(initial_size * 0.30f, initial_size * pow2f(cache->pressure)); + return max_ff(initial_size * 0.30f, initial_size * powf(cache->pressure, 1.5f)); case SCULPT_TOOL_CLAY_THUMB: { float clay_stabilized_pressure = sculpt_clay_thumb_get_stabilized_pressure(cache); return initial_size * clay_stabilized_pressure; @@ -7523,7 +7539,7 @@ static int ed_object_sculptmode_flush_recalc_flag(Scene *scene, { int flush_recalc = 0; /* Multires in sculpt mode could have different from object mode subdivision level. */ - flush_recalc |= mmd && BKE_multires_sculpt_level_get(mmd) != mmd->lvl; + 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); return flush_recalc; diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c index 3ccf59ba3bb..f0f6478d3a6 100644 --- a/source/blender/editors/sculpt_paint/sculpt_automasking.c +++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c index b1cc6d02bbb..62a7f1925ab 100644 --- a/source/blender/editors/sculpt_paint/sculpt_cloth.c +++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -221,6 +221,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); /* For Pich Perpendicular Deform Type. */ float x_object_space[3]; @@ -269,7 +270,7 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); float brush_disp[3]; float normal[3]; @@ -412,7 +413,7 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, * storing the constraints per node. */ /* Currently all constrains are added to the same global array which can't be accessed from * different threads. */ - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, false, totnode); SculptThreadedTaskData build_constraints_data = { @@ -421,7 +422,7 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd, .brush = brush, .nodes = nodes, }; - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings); } @@ -490,9 +491,9 @@ static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **no .cloth_time_step = CLOTH_SIMULATION_TIME_STEP, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &solve_simulation_data, do_cloth_brush_solve_simulation_task_cb_ex, &settings); } @@ -565,9 +566,9 @@ static void cloth_brush_apply_brush_foces(Sculpt *sd, Object *ob, PBVHNode **nod } } - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &apply_forces_data, do_cloth_brush_apply_forces_task_cb_ex, &settings); } diff --git a/source/blender/editors/sculpt_paint/sculpt_detail.c b/source/blender/editors/sculpt_paint/sculpt_detail.c index a99aa3d1bcf..b7d1cd8c005 100644 --- a/source/blender/editors/sculpt_paint/sculpt_detail.c +++ b/source/blender/editors/sculpt_paint/sculpt_detail.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. diff --git a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c index 0ab3b8cd14e..eefd8529dbf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_dyntopo.c +++ b/source/blender/editors/sculpt_paint/sculpt_dyntopo.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -384,12 +384,12 @@ enum eDynTopoWarnFlag SCULPT_dynamic_topology_check(Scene *scene, Object *ob) { VirtualModifierData virtualModifierData; - ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData); /* Exception for shape keys because we can edit those. */ for (; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) { + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Realtime)) { continue; } diff --git a/source/blender/editors/sculpt_paint/sculpt_face_set.c b/source/blender/editors/sculpt_paint/sculpt_face_set.c index 43ff1ad3ef5..f96f08e3244 100644 --- a/source/blender/editors/sculpt_paint/sculpt_face_set.c +++ b/source/blender/editors/sculpt_paint/sculpt_face_set.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -87,6 +87,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -107,7 +108,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); if (fade > 0.05f && ss->face_sets[vert_map->indices[j]] > 0) { ss->face_sets[vert_map->indices[j]] = abs(ss->cache->paint_face_set); @@ -127,7 +128,7 @@ static void do_draw_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); if (fade > 0.05f) { SCULPT_vertex_face_set_set(ss, vd.index, ss->cache->paint_face_set); @@ -160,6 +161,8 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, bstrength *= 2.0f; } + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -172,7 +175,7 @@ static void do_relax_face_sets_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); SCULPT_relax_vertex(ss, &vd, fade * bstrength, relax_face_sets, vd.co); if (vd.mvert) { @@ -199,15 +202,15 @@ void SCULPT_do_draw_face_sets_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); if (ss->cache->alt_smooth) { for (int i = 0; i < 4; i++) { - BKE_pbvh_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_relax_face_sets_brush_task_cb_ex, &settings); } } else { - BKE_pbvh_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_draw_face_sets_brush_task_cb_ex, &settings); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c index 38bbd083994..d2a683461a7 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mask.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mask.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -246,9 +246,9 @@ static int sculpt_mask_filter_exec(bContext *C, wmOperator *op) .prev_mask = prev_mask, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); if (ELEM(filter_type, MASK_FILTER_GROW, MASK_FILTER_SHRINK)) { MEM_freeN(prev_mask); @@ -275,9 +275,9 @@ void SCULPT_mask_filter_smooth_apply( }; for (int i = 0; i < smooth_iterations; i++) { - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, mask_filter_task_cb, &settings); } } @@ -458,17 +458,17 @@ static int sculpt_dirty_mask_exec(bContext *C, wmOperator *op) .max = -FLT_MAX, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); settings.func_reduce = dirty_mask_compute_range_reduce; settings.userdata_chunk = ⦥ settings.userdata_chunk_size = sizeof(DirtyMaskRangeData); - BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, dirty_mask_compute_range_task_cb, &settings); data.dirty_mask_min = range.min; data.dirty_mask_max = range.max; - BKE_pbvh_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings); + BLI_task_parallel_range(0, totnode, &data, dirty_mask_apply_task_cb, &settings); MEM_SAFE_FREE(nodes); diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c index 94b6e0eb864..7c438e9245b 100644 --- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c +++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -112,10 +112,10 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd) .nodes = ss->filter_cache->nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, filter_cache_init_task_cb, &settings); } @@ -496,13 +496,13 @@ static int sculpt_mesh_filter_modal(bContext *C, wmOperator *op, const wmEvent * .filter_strength = filter_strength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_task_cb, &settings); if (filter_type == MESH_FILTER_SURFACE_SMOOTH) { - BKE_pbvh_parallel_range(0, + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, mesh_filter_surface_smooth_displace_task_cb, diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index bc7a78f491c..9b13f6e6c24 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -10,7 +10,7 @@ * 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, + * 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) 2006 by Nicholas Bishop diff --git a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c index 34ca92acef9..cbb198e14a3 100644 --- a/source/blender/editors/sculpt_paint/sculpt_mask_expand.c +++ b/source/blender/editors/sculpt_paint/sculpt_mask_expand.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -288,10 +288,10 @@ static int sculpt_mask_expand_modal(bContext *C, wmOperator *op, const wmEvent * .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"), }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); ss->filter_cache->mask_update_current_it = mask_expand_update_it; } @@ -458,10 +458,10 @@ static int sculpt_mask_expand_invoke(bContext *C, wmOperator *op, const wmEvent .mask_expand_keep_prev_mask = RNA_boolean_get(op->ptr, "keep_previous_mask"), .mask_expand_create_face_set = RNA_boolean_get(op->ptr, "create_face_set"), }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); + BLI_task_parallel_range(0, ss->filter_cache->totnode, &data, sculpt_expand_task_cb, &settings); const char *status_str = TIP_( "Move the mouse to expand the mask from the active vertex. LMB: confirm mask, ESC/RMB: " diff --git a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c index c74a2ba503a..f3327706102 100644 --- a/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c +++ b/source/blender/editors/sculpt_paint/sculpt_multiplane_scrape.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -79,6 +79,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); /* Apply the brush normal radius to the test before sampling. */ float test_radius = sqrtf(test.radius_squared); @@ -107,7 +108,7 @@ static void calc_multiplane_scrape_surface_task_cb(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); /* Sample the normal and area of the +X and -X axis individually. */ if (local_co[0] > 0.0f) { @@ -163,6 +164,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -208,7 +210,7 @@ static void do_multiplane_scrape_brush_task_cb_ex(void *__restrict userdata, vd.fno, vd.mask ? *vd.mask : 0.0f, vd.index, - tls->thread_id); + thread_id); mul_v3_v3fl(proxy[vd.i], val, fade); @@ -301,13 +303,13 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, MultiplaneScrapeSampleData mssd = {{{0}}}; - PBVHParallelSettings sample_settings; + TaskParallelSettings sample_settings; BKE_pbvh_parallel_range_settings(&sample_settings, (sd->flags & SCULPT_USE_OPENMP), totnode); sample_settings.func_reduce = calc_multiplane_scrape_surface_reduce; sample_settings.userdata_chunk = &mssd; sample_settings.userdata_chunk_size = sizeof(MultiplaneScrapeSampleData); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &sample_data, calc_multiplane_scrape_surface_task_cb, &sample_settings); float sampled_plane_normals[2][3]; @@ -392,9 +394,9 @@ void SCULPT_do_multiplane_scrape_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, normalize_v3(plane_no); plane_from_point_normal_v3(data.multiplane_scrape_planes[0], area_co, plane_no); - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_multiplane_scrape_brush_task_cb_ex, &settings); } void SCULPT_multiplane_scrape_preview_draw(const uint gpuattr, diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c index fde4a9d1d23..c7511dfc80f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_pose.c +++ b/source/blender/editors/sculpt_paint/sculpt_pose.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -263,7 +263,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, }; data.pose_initial_co = pose_target; - PBVHParallelSettings settings; + TaskParallelSettings settings; PoseGrowFactorTLSData gftd; gftd.pos_count = 0; zero_v3(gftd.pos_avg); @@ -279,7 +279,7 @@ static void sculpt_pose_grow_pose_factor(Sculpt *sd, zero_v3(gftd.pos_avg); gftd.pos_count = 0; memcpy(data.prev_mask, pose_factor, SCULPT_vertex_count_get(ss) * sizeof(float)); - BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, pose_brush_grow_factor_task_cb_ex, &settings); if (gftd.pos_count != 0) { mul_v3_fl(gftd.pos_avg, 1.0f / (float)gftd.pos_count); @@ -793,9 +793,9 @@ void SCULPT_pose_brush_init(Sculpt *sd, Object *ob, SculptSession *ss, Brush *br for (int ik = 0; ik < ss->cache->pose_ik_chain->tot_segments; ik++) { data.pose_factor = ss->cache->pose_ik_chain->segments[ik].weights; for (int i = 0; i < br->pose_smooth_iterations; i++) { - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, pose_brush_init_task_cb_ex, &settings); } } @@ -885,9 +885,9 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode) .grab_delta = grab_delta, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_pose_brush_task_cb_ex, &settings); } void SCULPT_pose_ik_chain_free(SculptPoseIKChain *ik_chain) diff --git a/source/blender/editors/sculpt_paint/sculpt_smooth.c b/source/blender/editors/sculpt_paint/sculpt_smooth.c index 3a09d52d418..17451cb40ae 100644 --- a/source/blender/editors/sculpt_paint/sculpt_smooth.c +++ b/source/blender/editors/sculpt_paint/sculpt_smooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -245,6 +245,8 @@ static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -257,7 +259,7 @@ static void do_smooth_brush_mesh_task_cb_ex(void *__restrict userdata, vd.fno, smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), vd.index, - tls->thread_id); + thread_id); if (smooth_mask) { float val = SCULPT_neighbor_mask_average(ss, vd.vert_indices[vd.i]) - *vd.mask; val *= fade * bstrength; @@ -301,6 +303,7 @@ static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata, SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -313,7 +316,7 @@ static void do_smooth_brush_bmesh_task_cb_ex(void *__restrict userdata, vd.fno, smooth_mask ? 0.0f : *vd.mask, vd.index, - tls->thread_id); + thread_id); if (smooth_mask) { float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; val *= fade * bstrength; @@ -358,6 +361,8 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); + BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { if (sculpt_brush_test_sq_fn(&test, vd.co)) { @@ -370,7 +375,7 @@ static void do_smooth_brush_multires_task_cb_ex(void *__restrict userdata, vd.fno, smooth_mask ? 0.0f : (vd.mask ? *vd.mask : 0.0f), vd.index, - tls->thread_id); + thread_id); if (smooth_mask) { float val = SCULPT_neighbor_mask_average(ss, vd.index) - *vd.mask; val *= fade * bstrength; @@ -427,18 +432,18 @@ void SCULPT_smooth(Sculpt *sd, .strength = strength, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); switch (type) { case PBVH_GRIDS: - BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_multires_task_cb_ex, &settings); break; case PBVH_FACES: - BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_mesh_task_cb_ex, &settings); break; case PBVH_BMESH: - BKE_pbvh_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); + BLI_task_parallel_range(0, totnode, &data, do_smooth_brush_bmesh_task_cb_ex, &settings); break; } } @@ -512,6 +517,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); SCULPT_orig_vert_data_init(&orig_data, data->ob, data->nodes[n]); @@ -522,7 +528,7 @@ static void SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex( const float fade = bstrength * SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); float disp[3]; SCULPT_surface_smooth_laplacian_step(ss, @@ -555,6 +561,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( SculptBrushTest test; SculptBrushTestFn sculpt_brush_test_sq_fn = SCULPT_brush_test_init_with_falloff_shape( ss, &test, data->brush->falloff_shape); + const int thread_id = BLI_task_parallel_thread_id(tls); BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE) { @@ -562,7 +569,7 @@ static void SCULPT_do_surface_smooth_brush_displace_task_cb_ex( const float fade = bstrength * SCULPT_brush_strength_factor( - ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, tls->thread_id); + ss, brush, vd.co, sqrtf(test.dist), vd.no, vd.fno, 0.0f, vd.index, thread_id); SCULPT_surface_smooth_displace_step( ss, vd.co, ss->cache->surface_smooth_laplacian_disp, vd.index, beta, fade); } @@ -590,12 +597,12 @@ void SCULPT_do_surface_smooth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, in .nodes = nodes, }; - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); for (int i = 0; i < brush->surface_smooth_iterations; i++) { - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &data, SCULPT_do_surface_smooth_brush_laplacian_task_cb_ex, &settings); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, &data, SCULPT_do_surface_smooth_brush_displace_task_cb_ex, &settings); } } diff --git a/source/blender/editors/sculpt_paint/sculpt_transform.c b/source/blender/editors/sculpt_paint/sculpt_transform.c index c7cbb6672a4..2eb1191b950 100644 --- a/source/blender/editors/sculpt_paint/sculpt_transform.c +++ b/source/blender/editors/sculpt_paint/sculpt_transform.c @@ -10,7 +10,7 @@ * 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, + * 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) 2020 Blender Foundation. @@ -177,10 +177,10 @@ void ED_sculpt_update_modal_transform(struct bContext *C) mul_m4_m4m4(data.transform_mats[i], pivot_mat, data.transform_mats[i]); } - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings( &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, ss->filter_cache->totnode, &data, sculpt_transform_task_cb, &settings); if (ss->deform_modifiers_active || ss->shapekey_active) { diff --git a/source/blender/editors/sculpt_paint/sculpt_undo.c b/source/blender/editors/sculpt_paint/sculpt_undo.c index 1cb9b57e81d..905d0e0a4bf 100644 --- a/source/blender/editors/sculpt_paint/sculpt_undo.c +++ b/source/blender/editors/sculpt_paint/sculpt_undo.c @@ -10,7 +10,7 @@ * 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, + * 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) 2006 by Nicholas Bishop @@ -415,9 +415,9 @@ static void sculpt_undo_bmesh_restore_generic(bContext *C, BKE_pbvh_search_gather(ss->pbvh, NULL, NULL, &nodes, &totnode); - PBVHParallelSettings settings; + TaskParallelSettings settings; BKE_pbvh_parallel_range_settings(&settings, (sd->flags & SCULPT_USE_OPENMP), totnode); - BKE_pbvh_parallel_range( + BLI_task_parallel_range( 0, totnode, nodes, sculpt_undo_bmesh_restore_generic_task_cb, &settings); if (nodes) { diff --git a/source/blender/editors/sculpt_paint/sculpt_uv.c b/source/blender/editors/sculpt_paint/sculpt_uv.c index 0a5814be626..a1094dde749 100644 --- a/source/blender/editors/sculpt_paint/sculpt_uv.c +++ b/source/blender/editors/sculpt_paint/sculpt_uv.c @@ -10,7 +10,7 @@ * 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, + * 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) Blender Foundation, 2002-2009 diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c index a356962946e..b5a0c4a9e22 100644 --- a/source/blender/editors/space_action/action_data.c +++ b/source/blender/editors/space_action/action_data.c @@ -164,13 +164,13 @@ static void actedit_change_action(bContext *C, bAction *act) * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions... * OR * The NLA Editor is active (i.e. Animation Data panel -> new action) - * 2) The associated AnimData block must not be in tweakmode + * 2) The associated AnimData block must not be in tweak-mode. */ static bool action_new_poll(bContext *C) { Scene *scene = CTX_data_scene(C); - /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ + /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, * this operator needs to be run when creating an action from nothing... */ if (ED_operator_action_active(C)) { @@ -300,7 +300,7 @@ void ACTION_OT_new(wmOperatorType *ot) /* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions * 2) There must be an action active - * 3) The associated AnimData block must not be in tweakmode + * 3) The associated AnimData block must not be in tweak-mode */ static bool action_pushdown_poll(bContext *C) { @@ -308,7 +308,7 @@ static bool action_pushdown_poll(bContext *C) SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C); AnimData *adt = ED_actedit_animdata_from_context(C); - /* Check for AnimData, Actions, and that tweakmode is off */ + /* Check for AnimData, Actions, and that tweak-mode is off. */ if (adt && saction->action) { /* NOTE: We check this for the AnimData block in question and not the global flag, * as the global flag may be left dirty by some of the browsing ops here. @@ -330,9 +330,8 @@ static int action_pushdown_exec(bContext *C, wmOperator *op) /* Do the deed... */ if (adt) { - /* Perform the pushdown operation - * - This will deal with all the AnimData-side usercounts - */ + /* Perform the push-down operation + * - This will deal with all the AnimData-side user-counts. */ if (action_has_motion(adt->action) == 0) { /* action may not be suitable... */ BKE_report(op->reports, RPT_WARNING, "Action must have at least one keyframe or F-Modifier"); @@ -389,7 +388,7 @@ static int action_stash_exec(bContext *C, wmOperator *op) if (BKE_nla_action_stash(adt)) { /* The stash operation will remove the user already, * so the flushing step later shouldn't double up - * the usercount fixes. Hence, we must unset this ref + * the user-count fixes. Hence, we must unset this ref * first before setting the new action. */ saction->action = NULL; @@ -435,14 +434,14 @@ void ACTION_OT_stash(wmOperatorType *ot) /* Criteria: * 1) There must be an dopesheet/action editor, and it must be in a mode which uses actions - * 2) The associated AnimData block must not be in tweakmode + * 2) The associated AnimData block must not be in tweak-mode */ static bool action_stash_create_poll(bContext *C) { if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); - /* Check tweakmode is off (as you don't want to be tampering with the action in that case) */ + /* Check tweak-mode is off (as you don't want to be tampering with the action in that case) */ /* NOTE: unlike for pushdown, * this operator needs to be run when creating an action from nothing... */ if (adt) { @@ -498,7 +497,7 @@ static int action_stash_create_exec(bContext *C, wmOperator *op) /* The stash operation will remove the user already, * so the flushing step later shouldn't double up - * the usercount fixes. Hence, we must unset this ref + * the user-count fixes. Hence, we must unset this ref * first before setting the new action. */ saction->action = NULL; @@ -728,8 +727,8 @@ static NlaStrip *action_layer_get_nlastrip(ListBase *strips, float ctime) static void action_layer_switch_strip( AnimData *adt, NlaTrack *old_track, NlaStrip *old_strip, NlaTrack *nlt, NlaStrip *strip) { - /* Exit tweakmode on old strip - * NOTE: We need to manually clear this stuff ourselves, as tweakmode exit doesn't do it + /* Exit tweak-mode on old strip + * NOTE: We need to manually clear this stuff ourselves, as tweak-mode exit doesn't do it */ BKE_nla_tweakmode_exit(adt); @@ -761,11 +760,11 @@ static void action_layer_switch_strip( adt->flag |= ADT_NLA_SOLO_TRACK; nlt->flag |= NLATRACK_SOLO; - // TODO: Needs restpose flushing (when we get reference track) + // TODO: Needs rest-pose flushing (when we get reference track) } } - /* Enter tweakmode again - hopefully we're now "it" */ + /* Enter tweak-mode again - hopefully we're now "it" */ BKE_nla_tweakmode_enter(adt); BLI_assert(adt->actstrip == strip); } @@ -778,7 +777,7 @@ static bool action_layer_next_poll(bContext *C) if (ED_operator_action_active(C)) { AnimData *adt = ED_actedit_animdata_from_context(C); if (adt) { - /* only allow if we're in tweakmode, and there's something above us... */ + /* only allow if we're in tweak-mode, and there's something above us... */ if (adt->flag & ADT_NLA_EDIT_ON) { /* We need to check if there are any tracks above the active one * since the track the action comes from is not stored in AnimData @@ -840,7 +839,7 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) } else { /* No more actions (strips) - Go back to editing the original active action - * NOTE: This will mean exiting tweakmode... + * NOTE: This will mean exiting tweak-mode... */ BKE_nla_tweakmode_exit(adt); @@ -855,13 +854,12 @@ static int action_layer_next_exec(bContext *C, wmOperator *op) /* turn on NLA muting (to keep same effect) */ adt->flag |= ADT_NLA_EVAL_OFF; - // TODO: Needs restpose flushing (when we get reference track) + // TODO: Needs rest-pose flushing (when we get reference track) } } /* Update the action that this editor now uses - * NOTE: The calls above have already handled the usercount/animdata side of things - */ + * NOTE: The calls above have already handled the user-count/anim-data side of things. */ actedit_change_action(C, adt->action); return OPERATOR_FINISHED; } @@ -960,8 +958,7 @@ static int action_layer_prev_exec(bContext *C, wmOperator *op) } /* Update the action that this editor now uses - * NOTE: The calls above have already handled the usercount/animdata side of things - */ + * NOTE: The calls above have already handled the user-count/animdata side of things. */ actedit_change_action(C, adt->action); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c index 927e51a3e04..e90122f2585 100644 --- a/source/blender/editors/space_action/action_edit.c +++ b/source/blender/editors/space_action/action_edit.c @@ -313,8 +313,8 @@ void ACTION_OT_previewrange_set(wmOperatorType *ot) /** * Find the extents of the active channel * - * \param[out] min Bottom y-extent of channel - * \param[out] max Top y-extent of channel + * \param[out] min: Bottom y-extent of channel + * \param[out] max: Top y-extent of channel * \return Success of finding a selected channel */ static bool actkeys_channels_get_selected_extents(bAnimContext *ac, float *min, float *max) @@ -448,7 +448,7 @@ static int actkeys_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) void ACTION_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "ACTION_OT_view_all"; ot->description = "Reset viewable area to show full keyframe range"; diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index 26c29d6cbe7..bbb68f632fb 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -793,8 +793,8 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op) } data_lasso.rectf_view = &rect_fl; - data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot); - if (data_lasso.mcords == NULL) { + data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len); + if (data_lasso.mcoords == NULL) { return OPERATOR_CANCELLED; } @@ -805,13 +805,13 @@ static int actkeys_lassoselect_exec(bContext *C, wmOperator *op) } /* get settings from operator */ - BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot); + BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len); BLI_rctf_rcti_copy(&rect_fl, &rect); /* apply box_select action */ region_select_action_keys(&ac, &rect_fl, BEZT_OK_CHANNEL_LASSO, selectmode, &data_lasso); - MEM_freeN((void *)data_lasso.mcords); + MEM_freeN((void *)data_lasso.mcoords); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 587ba5b0b79..7e6088bc3cc 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -1041,7 +1041,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); CTX_data_pointer_set(result, &ob->id, &RNA_ClothModifier, md); return 1; } @@ -1051,7 +1051,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Softbody); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Softbody); CTX_data_pointer_set(result, &ob->id, &RNA_SoftBodyModifier, md); return 1; } @@ -1062,7 +1062,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid); CTX_data_pointer_set(result, &ob->id, &RNA_FluidModifier, md); return 1; } @@ -1072,7 +1072,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_Collision); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Collision); CTX_data_pointer_set(result, &ob->id, &RNA_CollisionModifier, md); return 1; } @@ -1086,7 +1086,7 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r if (ptr && ptr->data) { Object *ob = ptr->data; - ModifierData *md = modifiers_findByType(ob, eModifierType_DynamicPaint); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint); CTX_data_pointer_set(result, &ob->id, &RNA_DynamicPaintModifier, md); return 1; } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index 00818ac77b5..6b7f86a9143 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -236,10 +236,10 @@ static void buttons_texture_users_from_context(ListBase *users, int a; /* modifiers */ - modifiers_foreachTexLink(ob, buttons_texture_modifier_foreach, users); + BKE_modifiers_foreach_tex_link(ob, buttons_texture_modifier_foreach, users); /* grease pencil modifiers */ - BKE_gpencil_modifiers_foreachTexLink(ob, buttons_texture_modifier_gpencil_foreach, users); + BKE_gpencil_modifiers_foreach_tex_link(ob, buttons_texture_modifier_gpencil_foreach, users); /* particle systems */ if (psys && !limited_mode) { diff --git a/source/blender/editors/space_clip/clip_dopesheet_ops.c b/source/blender/editors/space_clip/clip_dopesheet_ops.c index cd95a00c62a..c3323491085 100644 --- a/source/blender/editors/space_clip/clip_dopesheet_ops.c +++ b/source/blender/editors/space_clip/clip_dopesheet_ops.c @@ -204,7 +204,7 @@ static int dopesheet_view_all_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_dopesheet_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->description = "Reset viewable area to show full keyframe range"; ot->idname = "CLIP_OT_dopesheet_view_all"; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a1652ca0e88..fe7ae7096a0 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -1651,7 +1651,7 @@ static void draw_tracking_tracks(SpaceClip *sc, pos[0] = (pos[0] / (pos[3] * 2.0f) + 0.5f) * width; pos[1] = (pos[1] / (pos[3] * 2.0f) + 0.5f) * height * aspy; - BKE_tracking_distort_v2(tracking, pos, npos); + BKE_tracking_distort_v2(tracking, width, height, pos, npos); if (npos[0] >= 0.0f && npos[1] >= 0.0f && npos[0] <= width && npos[1] <= height * aspy) { vec[0] = (marker->pos[0] + track->offset[0]) * width; @@ -1730,8 +1730,7 @@ static void draw_distortion(SpaceClip *sc, { float x, y; const int n = 10; - int i, j, a; - float pos[2], tpos[2], grid[11][11][2]; + float tpos[2], grid[11][11][2]; MovieTracking *tracking = &clip->tracking; bGPdata *gpd = NULL; float aspy = 1.0f / tracking->camera.pixel_aspect; @@ -1764,7 +1763,7 @@ static void draw_distortion(SpaceClip *sc, float val[4][2], idx[4][2]; float min[2], max[2]; - for (a = 0; a < 4; a++) { + for (int a = 0; a < 4; a++) { if (a < 2) { val[a][a % 2] = FLT_MAX; } @@ -1773,13 +1772,13 @@ static void draw_distortion(SpaceClip *sc, } } - zero_v2(pos); - for (i = 0; i <= n; i++) { - for (j = 0; j <= n; j++) { + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= n; j++) { if (i == 0 || j == 0 || i == n || j == n) { - BKE_tracking_distort_v2(tracking, pos, tpos); + const float pos[2] = {dx * j, dy * i}; + BKE_tracking_distort_v2(tracking, width, height, pos, tpos); - for (a = 0; a < 4; a++) { + for (int a = 0; a < 4; a++) { int ok; if (a < 2) { @@ -1796,59 +1795,49 @@ static void draw_distortion(SpaceClip *sc, } } } - - pos[0] += dx; } - - pos[0] = 0.0f; - pos[1] += dy; } INIT_MINMAX2(min, max); - for (a = 0; a < 4; a++) { - pos[0] = idx[a][0] * dx; - pos[1] = idx[a][1] * dy; + for (int a = 0; a < 4; a++) { + const float pos[2] = {idx[a][0] * dx, idx[a][1] * dy}; - BKE_tracking_undistort_v2(tracking, pos, tpos); + BKE_tracking_undistort_v2(tracking, width, height, pos, tpos); minmax_v2v2_v2(min, max, tpos); } - copy_v2_v2(pos, min); dx = (max[0] - min[0]) / n; dy = (max[1] - min[1]) / n; - for (i = 0; i <= n; i++) { - for (j = 0; j <= n; j++) { - BKE_tracking_distort_v2(tracking, pos, grid[i][j]); + for (int i = 0; i <= n; i++) { + for (int j = 0; j <= n; j++) { + const float pos[2] = {min[0] + dx * j, min[1] + dy * i}; + + BKE_tracking_distort_v2(tracking, width, height, pos, grid[i][j]); grid[i][j][0] /= width; grid[i][j][1] /= height * aspy; - - pos[0] += dx; } - - pos[0] = min[0]; - pos[1] += dy; } immUniformColor3f(1.0f, 0.0f, 0.0f); - for (i = 0; i <= n; i++) { + for (int i = 0; i <= n; i++) { immBegin(GPU_PRIM_LINE_STRIP, n + 1); - for (j = 0; j <= n; j++) { + for (int j = 0; j <= n; j++) { immVertex2fv(position, grid[i][j]); } immEnd(); } - for (j = 0; j <= n; j++) { + for (int j = 0; j <= n; j++) { immBegin(GPU_PRIM_LINE_STRIP, n + 1); - for (i = 0; i <= n; i++) { + for (int i = 0; i <= n; i++) { immVertex2fv(position, grid[i][j]); } @@ -1882,8 +1871,8 @@ static void draw_distortion(SpaceClip *sc, while (stroke) { if (stroke->flag & GP_STROKE_2DSPACE) { if (stroke->totpoints > 1) { - for (i = 0; i < stroke->totpoints - 1; i++) { - float npos[2], dpos[2], len; + for (int i = 0; i < stroke->totpoints - 1; i++) { + float pos[2], npos[2], dpos[2], len; int steps; pos[0] = (stroke->points[i].x + offsx) * width; @@ -1897,8 +1886,8 @@ static void draw_distortion(SpaceClip *sc, /* we want to distort only long straight lines */ if (stroke->totpoints == 2) { - BKE_tracking_undistort_v2(tracking, pos, pos); - BKE_tracking_undistort_v2(tracking, npos, npos); + BKE_tracking_undistort_v2(tracking, width, height, pos, pos); + BKE_tracking_undistort_v2(tracking, width, height, npos, npos); } sub_v2_v2v2(dpos, npos, pos); @@ -1906,8 +1895,8 @@ static void draw_distortion(SpaceClip *sc, immBegin(GPU_PRIM_LINE_STRIP, steps + 1); - for (j = 0; j <= steps; j++) { - BKE_tracking_distort_v2(tracking, pos, tpos); + for (int j = 0; j <= steps; j++) { + BKE_tracking_distort_v2(tracking, width, height, pos, tpos); immVertex2f(position, tpos[0] / width, tpos[1] / (height * aspy)); add_v2_v2(pos, dpos); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index cce01947ab7..5be4b2d5df0 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -546,7 +546,7 @@ void ED_clip_point_undistorted_pos(SpaceClip *sc, const float co[2], float r_co[ r_co[0] *= width; r_co[1] *= height * aspy; - BKE_tracking_undistort_v2(&clip->tracking, r_co, r_co); + BKE_tracking_undistort_v2(&clip->tracking, width, height, r_co, r_co); r_co[0] /= width; r_co[1] /= height * aspy; @@ -580,7 +580,7 @@ void ED_clip_point_stable_pos( float aspy = 1.0f / tracking->camera.pixel_aspect; float tmp[2] = {*xr * width, *yr * height * aspy}; - BKE_tracking_distort_v2(tracking, tmp, tmp); + BKE_tracking_distort_v2(tracking, width, height, tmp, tmp); *xr = tmp[0] / width; *yr = tmp[1] / (height * aspy); @@ -885,9 +885,9 @@ static uchar *prefetch_thread_next_frame(PrefetchQueue *queue, return mem; } -static void prefetch_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid)) +static void prefetch_task_func(TaskPool *__restrict pool, void *task_data) { - PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_userdata(pool); + PrefetchQueue *queue = (PrefetchQueue *)BLI_task_pool_user_data(pool); MovieClip *clip = (MovieClip *)task_data; uchar *mem; size_t size; @@ -942,9 +942,8 @@ static void start_prefetch_threads(MovieClip *clip, float *progress) { PrefetchQueue queue; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; - int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler); + int i, tot_thread = BLI_task_scheduler_num_threads(); /* initialize queue */ BLI_spin_init(&queue.spin); @@ -961,7 +960,7 @@ static void start_prefetch_threads(MovieClip *clip, queue.do_update = do_update; queue.progress = progress; - task_pool = BLI_task_pool_create(task_scheduler, &queue, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&queue, TASK_PRIORITY_LOW); for (i = 0; i < tot_thread; i++) { BLI_task_pool_push(task_pool, prefetch_task_func, clip, false, NULL); } diff --git a/source/blender/editors/space_clip/clip_graph_ops.c b/source/blender/editors/space_clip/clip_graph_ops.c index e974480a233..589831b1c45 100644 --- a/source/blender/editors/space_clip/clip_graph_ops.c +++ b/source/blender/editors/space_clip/clip_graph_ops.c @@ -671,7 +671,7 @@ static int view_all_exec(bContext *C, wmOperator *UNUSED(op)) void CLIP_OT_graph_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->description = "View all curves in editor"; ot->idname = "CLIP_OT_graph_view_all"; diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 3204374b747..984aa0a63ad 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -784,7 +784,7 @@ void CLIP_OT_view_zoom_in(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom In"; + ot->name = "Zoom In"; ot->idname = "CLIP_OT_view_zoom_in"; ot->description = "Zoom in the view"; @@ -841,7 +841,7 @@ void CLIP_OT_view_zoom_out(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom Out"; + ot->name = "Zoom Out"; ot->idname = "CLIP_OT_view_zoom_out"; ot->description = "Zoom out the view"; @@ -975,7 +975,7 @@ void CLIP_OT_view_all(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "CLIP_OT_view_all"; ot->description = "View whole image with markers"; @@ -1367,10 +1367,10 @@ static uchar *proxy_thread_next_frame(ProxyQueue *queue, return mem; } -static void proxy_task_func(TaskPool *__restrict pool, void *task_data, int UNUSED(threadid)) +static void proxy_task_func(TaskPool *__restrict pool, void *task_data) { ProxyThread *data = (ProxyThread *)task_data; - ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_userdata(pool); + ProxyQueue *queue = (ProxyQueue *)BLI_task_pool_user_data(pool); uchar *mem; size_t size; int cfra; @@ -1413,11 +1413,10 @@ static void do_sequence_proxy(void *pjv, ProxyJob *pj = pjv; MovieClip *clip = pj->clip; Scene *scene = pj->scene; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; int sfra = SFRA, efra = EFRA; ProxyThread *handles; - int i, tot_thread = BLI_task_scheduler_num_threads(task_scheduler); + int i, tot_thread = BLI_task_scheduler_num_threads(); int width, height; ProxyQueue queue; @@ -1434,7 +1433,7 @@ static void do_sequence_proxy(void *pjv, queue.do_update = do_update; queue.progress = progress; - task_pool = BLI_task_pool_create(task_scheduler, &queue, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(&queue, TASK_PRIORITY_LOW); handles = MEM_callocN(sizeof(ProxyThread) * tot_thread, "proxy threaded handles"); for (i = 0; i < tot_thread; i++) { ProxyThread *handle = &handles[i]; diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index 4a0df454a78..03f791ad70d 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -166,7 +166,8 @@ static float calculate_reprojection_error_at_marker(MovieClip *clip, reprojected_position[1] = (reprojected_position[1] / (reprojected_position[3] * 2.0f) + 0.5f) * clip_height * aspy; - BKE_tracking_distort_v2(tracking, reprojected_position, reprojected_position); + BKE_tracking_distort_v2( + tracking, clip_width, clip_height, reprojected_position, reprojected_position); marker_position[0] = (marker->pos[0] + track->offset[0]) * clip_width; marker_position[1] = (marker->pos[1] + track->offset[1]) * clip_height * aspy; diff --git a/source/blender/editors/space_clip/tracking_select.c b/source/blender/editors/space_clip/tracking_select.c index c2a4ebdfc63..81cc858c69f 100644 --- a/source/blender/editors/space_clip/tracking_select.c +++ b/source/blender/editors/space_clip/tracking_select.c @@ -598,8 +598,8 @@ void CLIP_OT_select_box(wmOperatorType *ot) /********************** lasso select operator *********************/ static int do_lasso_select_marker(bContext *C, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, bool select) { SpaceClip *sc = CTX_wm_space_clip(C); @@ -616,7 +616,7 @@ static int do_lasso_select_marker(bContext *C, int framenr = ED_space_clip_get_clip_frame_number(sc); /* get rectangle from operator */ - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ track = tracksbase->first; @@ -631,7 +631,8 @@ static int do_lasso_select_marker(bContext *C, ED_clip_point_stable_pos__reverse(sc, region, marker->pos, screen_co); if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { if (select) { BKE_tracking_track_flag_set(track, TRACK_AREA_ALL, SELECT); } @@ -659,7 +660,8 @@ static int do_lasso_select_marker(bContext *C, ED_clip_point_stable_pos__reverse(sc, region, plane_marker->corners[i], screen_co); if (BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { + BLI_lasso_is_point_inside( + mcoords, mcoords_len, screen_co[0], screen_co[1], V2D_IS_CLIPPED)) { if (select) { plane_track->flag |= SELECT; } @@ -685,10 +687,10 @@ static int do_lasso_select_marker(bContext *C, static int clip_lasso_select_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); const bool select = (sel_op != SEL_OP_SUB); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { @@ -696,9 +698,9 @@ static int clip_lasso_select_exec(bContext *C, wmOperator *op) ED_clip_select_all(sc, SEL_DESELECT, NULL); } - do_lasso_select_marker(C, mcords, mcords_tot, select); + do_lasso_select_marker(C, mcoords, mcoords_len, select); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index ac8fa413f07..7f6d0658ec8 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -1264,11 +1264,9 @@ static void filelist_intern_free(FileListIntern *filelist_intern) MEM_SAFE_FREE(filelist_intern->filtered); } -static void filelist_cache_preview_runf(TaskPool *__restrict pool, - void *taskdata, - int UNUSED(threadid)) +static void filelist_cache_preview_runf(TaskPool *__restrict pool, void *taskdata) { - FileListEntryCache *cache = BLI_task_pool_userdata(pool); + FileListEntryCache *cache = BLI_task_pool_user_data(pool); FileListEntryPreviewTaskData *preview_taskdata = taskdata; FileListEntryPreview *preview = preview_taskdata->preview; @@ -1306,9 +1304,7 @@ static void filelist_cache_preview_runf(TaskPool *__restrict pool, // printf("%s: End (%d)...\n", __func__, threadid); } -static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), - void *taskdata, - int UNUSED(threadid)) +static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), void *taskdata) { FileListEntryPreviewTaskData *preview_taskdata = taskdata; FileListEntryPreview *preview = preview_taskdata->preview; @@ -1327,9 +1323,7 @@ static void filelist_cache_preview_freef(TaskPool *__restrict UNUSED(pool), static void filelist_cache_preview_ensure_running(FileListEntryCache *cache) { if (!cache->previews_pool) { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - - cache->previews_pool = BLI_task_pool_create_background(scheduler, cache, TASK_PRIORITY_LOW); + cache->previews_pool = BLI_task_pool_create_background(cache, TASK_PRIORITY_LOW); cache->previews_done = BLI_thread_queue_init(); IMB_thumb_locks_acquire(); diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c index 8c931a0c4a3..6c984860efc 100644 --- a/source/blender/editors/space_graph/graph_buttons.c +++ b/source/blender/editors/space_graph/graph_buttons.c @@ -42,6 +42,7 @@ #include "BKE_context.h" #include "BKE_curve.h" #include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_screen.h" diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c index 08053dba4d9..8ffd2844f1a 100644 --- a/source/blender/editors/space_graph/graph_edit.c +++ b/source/blender/editors/space_graph/graph_edit.c @@ -328,7 +328,7 @@ static int graphkeys_view_selected_exec(bContext *C, wmOperator *op) void GRAPH_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "GRAPH_OT_view_all"; ot->description = "Reset viewable area to show full keyframe range"; diff --git a/source/blender/editors/space_graph/graph_select.c b/source/blender/editors/space_graph/graph_select.c index a2e9ba86dec..ae435b5624a 100644 --- a/source/blender/editors/space_graph/graph_select.c +++ b/source/blender/editors/space_graph/graph_select.c @@ -760,8 +760,8 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op) } data_lasso.rectf_view = &rect_fl; - data_lasso.mcords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcords_tot); - if (data_lasso.mcords == NULL) { + data_lasso.mcoords = WM_gesture_lasso_path_to_array(C, op, &data_lasso.mcoords_len); + if (data_lasso.mcoords == NULL) { return OPERATOR_CANCELLED; } @@ -782,13 +782,13 @@ static int graphkeys_lassoselect_exec(bContext *C, wmOperator *op) } /* get settings from operator */ - BLI_lasso_boundbox(&rect, data_lasso.mcords, data_lasso.mcords_tot); + BLI_lasso_boundbox(&rect, data_lasso.mcoords, data_lasso.mcoords_len); BLI_rctf_rcti_copy(&rect_fl, &rect); /* apply box_select action */ box_select_graphkeys(&ac, &rect_fl, BEZT_OK_REGION_LASSO, selectmode, incl_handles, &data_lasso); - MEM_freeN((void *)data_lasso.mcords); + MEM_freeN((void *)data_lasso.mcoords); /* send notifier that keyframe selection has changed */ WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_SELECTED, NULL); diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index 7f911113b7c..c9f2ec38354 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -264,7 +264,10 @@ void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy) } } -void ED_space_image_get_zoom(SpaceImage *sima, ARegion *region, float *r_zoomx, float *r_zoomy) +void ED_space_image_get_zoom(SpaceImage *sima, + const ARegion *region, + float *r_zoomx, + float *r_zoomy) { int width, height; @@ -314,7 +317,7 @@ void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *r_aspx, float * } /* takes event->mval */ -void ED_image_mouse_pos(SpaceImage *sima, ARegion *region, const int mval[2], float co[2]) +void ED_image_mouse_pos(SpaceImage *sima, const ARegion *region, const int mval[2], float co[2]) { int sx, sy, width, height; float zoomx, zoomy; @@ -341,7 +344,7 @@ void ED_image_view_center_to_point(SpaceImage *sima, float x, float y) } void ED_image_point_pos( - SpaceImage *sima, ARegion *region, float x, float y, float *r_x, float *r_y) + SpaceImage *sima, const ARegion *region, float x, float y, float *r_x, float *r_y) { int sx, sy, width, height; float zoomx, zoomy; @@ -356,7 +359,7 @@ void ED_image_point_pos( } void ED_image_point_pos__reverse(SpaceImage *sima, - ARegion *region, + const ARegion *region, const float co[2], float r_co[2]) { diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index c2054756795..eb97077f77a 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -826,7 +826,7 @@ void IMAGE_OT_view_all(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "IMAGE_OT_view_all"; ot->description = "View the entire image"; @@ -986,7 +986,7 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom In"; + ot->name = "Zoom In"; ot->idname = "IMAGE_OT_view_zoom_in"; ot->description = "Zoom in the image (centered around 2D cursor)"; @@ -1045,7 +1045,7 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot) PropertyRNA *prop; /* identifiers */ - ot->name = "View Zoom Out"; + ot->name = "Zoom Out"; ot->idname = "IMAGE_OT_view_zoom_out"; ot->description = "Zoom out the image (centered around 2D cursor)"; diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 1e1d4373fea..d7d85112497 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -127,6 +127,7 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce simage->zoom = 1.0f; simage->lock = true; simage->flag = SI_SHOW_GPENCIL | SI_USE_ALPHA | SI_COORDFLOATS; + simage->uv_opacity = 1.0f; BKE_imageuser_default(&simage->iuser); simage->iuser.flag = IMA_SHOW_STEREO | IMA_ANIM_ALWAYS; diff --git a/source/blender/editors/space_info/info_stats.c b/source/blender/editors/space_info/info_stats.c index a91a11b2465..f8c0e66873f 100644 --- a/source/blender/editors/space_info/info_stats.c +++ b/source/blender/editors/space_info/info_stats.c @@ -33,6 +33,8 @@ #include "DNA_scene_types.h" #include "DNA_windowmanager_types.h" +#include "BLF_api.h" + #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" @@ -59,9 +61,10 @@ #include "ED_armature.h" #include "ED_info.h" +#include "UI_resources.h" + #include "GPU_extensions.h" -#define MAX_INFO_LEN 512 #define MAX_INFO_NUM_LEN 16 typedef struct SceneStats { @@ -73,8 +76,6 @@ typedef struct SceneStats { uint64_t totlamp, totlampsel; uint64_t tottri; uint64_t totgplayer, totgpframe, totgpstroke, totgppoint; - - char infostr[MAX_INFO_LEN]; } SceneStats; typedef struct SceneStatsFmt { @@ -368,10 +369,16 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer) if (obedit) { /* Edit Mode */ - FOREACH_OBJECT_IN_MODE_BEGIN (view_layer, ((View3D *)NULL), ob->type, ob->mode, ob_iter) { - stats_object_edit(ob_iter, &stats); + FOREACH_OBJECT_BEGIN (view_layer, ob_iter) { + if (ob_iter->base_flag & BASE_VISIBLE_VIEWLAYER) { + if (ob_iter->mode == OB_MODE_EDIT) { + stats_object_edit(ob_iter, &stats); + stats.totobjsel++; + } + stats.totobj++; + } } - FOREACH_OBJECT_IN_MODE_END; + FOREACH_OBJECT_END; } else if (ob && (ob->mode & OB_MODE_POSE)) { /* Pose Mode */ @@ -398,26 +405,98 @@ static void stats_update(Depsgraph *depsgraph, ViewLayer *view_layer) *(view_layer->stats) = stats; } -static void stats_string(ViewLayer *view_layer) +static const char *footer_string(ViewLayer *view_layer) { #define MAX_INFO_MEM_LEN 64 - SceneStats *stats = view_layer->stats; - SceneStatsFmt stats_fmt; - LayerCollection *layer_collection = view_layer->active_collection; - Object *ob = OBACT(view_layer); - Object *obedit = OBEDIT_FROM_OBACT(ob); - eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT; - uintptr_t mem_in_use, mmap_in_use; char memstr[MAX_INFO_MEM_LEN]; char gpumemstr[MAX_INFO_MEM_LEN] = ""; char formatted_mem[15]; - char *s; size_t ofs = 0; - mem_in_use = MEM_get_memory_in_use(); - mmap_in_use = MEM_get_mapped_memory_in_use(); + uintptr_t mem_in_use = MEM_get_memory_in_use(); + uintptr_t mmap_in_use = MEM_get_mapped_memory_in_use(); + + /* get memory statistics */ + BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false); + ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_("Mem: %s"), formatted_mem); + + if (mmap_in_use) { + BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false); + BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem); + } + + if (GPU_mem_stats_supported()) { + int gpu_free_mem, gpu_tot_memory; + + GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); + + BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, false); + ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, TIP_(" | Free GPU Mem: %s"), formatted_mem); + + if (gpu_tot_memory) { + BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, false); + BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_("/%s"), formatted_mem); + } + } + + BLI_snprintf(view_layer->footer_str, + sizeof(view_layer->footer_str), + "%s%s | %s", + memstr, + gpumemstr, + versionstr); + + return view_layer->footer_str; + +#undef MAX_INFO_MEM_LEN +} + +void ED_info_stats_clear(ViewLayer *view_layer) +{ + if (view_layer->stats) { + MEM_freeN(view_layer->stats); + view_layer->stats = NULL; + } +} + +const char *ED_info_footer_string(ViewLayer *view_layer) +{ + return footer_string(view_layer); +} + +static void stats_row(int col1, + const char *key, + int col2, + const char *value1, + const char *value2, + int *y, + int height) +{ + *y -= height; + BLF_draw_default(col1, *y, 0.0f, key, 128); + char values[128]; + BLI_snprintf(values, sizeof(values), (value2) ? "%s / %s" : "%s", value1, value2); + BLF_draw_default(col2, *y, 0.0f, values, sizeof(values)); +} + +void ED_info_draw_stats( + Main *bmain, Scene *scene, ViewLayer *view_layer, int x, int *y, int height) +{ + /* Create stats if they don't already exist. */ + if (!view_layer->stats) { + /* Do not not access dependency graph if interface is marked as locked. */ + wmWindowManager *wm = bmain->wm.first; + if (wm->is_interface_locked) { + return; + } + Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true); + stats_update(depsgraph, view_layer); + } - /* Generate formatted numbers */ + SceneStats *stats = view_layer->stats; + SceneStatsFmt stats_fmt; + + /* Generate formatted numbers. */ #define SCENE_STATS_FMT_INT(_id) BLI_str_format_uint64_grouped(stats_fmt._id, stats->_id) SCENE_STATS_FMT_INT(totvert); @@ -447,151 +526,94 @@ static void stats_string(ViewLayer *view_layer) #undef SCENE_STATS_FMT_INT - /* get memory statistics */ - BLI_str_format_byte_unit(formatted_mem, mem_in_use - mmap_in_use, false); - ofs = BLI_snprintf(memstr, MAX_INFO_MEM_LEN, TIP_(" | Mem: %s"), formatted_mem); - - if (mmap_in_use) { - BLI_str_format_byte_unit(formatted_mem, mmap_in_use, false); - BLI_snprintf(memstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_(" (%s)"), formatted_mem); + Object *ob = OBACT(view_layer); + Object *obedit = OBEDIT_FROM_OBACT(ob); + eObjectMode object_mode = ob ? ob->mode : OB_MODE_OBJECT; + const int font_id = BLF_default(); + + UI_FontThemeColor(font_id, TH_TEXT_HI); + BLF_enable(font_id, BLF_SHADOW); + BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); + BLF_shadow_offset(font_id, 1, -1); + + /* Translated labels for each stat row. */ + enum { + OBJ, + VERTS, + EDGES, + FACES, + TRIS, + BONES, + LAYERS, + FRAMES, + STROKES, + POINTS, + MAX_LABELS_COUNT + }; + char labels[MAX_LABELS_COUNT][64]; + + STRNCPY(labels[OBJ], IFACE_("Objects")); + STRNCPY(labels[VERTS], IFACE_("Vertices")); + STRNCPY(labels[EDGES], IFACE_("Edges")); + STRNCPY(labels[FACES], IFACE_("Faces")); + STRNCPY(labels[TRIS], IFACE_("Triangles")); + STRNCPY(labels[BONES], IFACE_("Bones")); + STRNCPY(labels[LAYERS], IFACE_("Layers")); + STRNCPY(labels[FRAMES], IFACE_("Frames")); + STRNCPY(labels[STROKES], IFACE_("Strokes")); + STRNCPY(labels[POINTS], IFACE_("Points")); + + int longest_label = 0; + int i; + for (i = 0; i < MAX_LABELS_COUNT; ++i) { + longest_label = max_ii(longest_label, BLF_width(font_id, labels[i], sizeof(labels[i]))); } - if (GPU_mem_stats_supported()) { - int gpu_free_mem, gpu_tot_memory; - - GPU_mem_stats_get(&gpu_tot_memory, &gpu_free_mem); - - BLI_str_format_byte_unit(formatted_mem, gpu_free_mem, false); - ofs = BLI_snprintf(gpumemstr, MAX_INFO_MEM_LEN, TIP_(" | Free GPU Mem: %s"), formatted_mem); - - if (gpu_tot_memory) { - BLI_str_format_byte_unit(formatted_mem, gpu_tot_memory, false); - BLI_snprintf(gpumemstr + ofs, MAX_INFO_MEM_LEN - ofs, TIP_("/%s"), formatted_mem); - } - } + int col1 = x; + int col2 = x + longest_label + (0.5f * U.widget_unit); - s = stats->infostr; - ofs = 0; + /* Add some extra margin above this section. */ + *y -= (0.6f * height); if (object_mode == OB_MODE_OBJECT) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - "%s | ", - BKE_collection_ui_name_get(layer_collection->collection)); - } - - if (ob) { - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, "%s | ", ob->id.name + 2); + stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); } if (obedit) { - if (BKE_keyblock_from_object(obedit)) { - ofs += BLI_strncpy_rlen(s + ofs, TIP_("(Key) "), MAX_INFO_LEN - ofs); - } - if (obedit->type == OB_MESH) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s/%s | Edges:%s/%s | Faces:%s/%s | Tris:%s"), - stats_fmt.totvertsel, - stats_fmt.totvert, - stats_fmt.totedgesel, - stats_fmt.totedge, - stats_fmt.totfacesel, - stats_fmt.totface, - stats_fmt.tottri); + stats_row(col1, labels[OBJ], col2, stats_fmt.totobjsel, stats_fmt.totobj, y, height); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); + stats_row(col1, labels[EDGES], col2, stats_fmt.totedgesel, stats_fmt.totedge, y, height); + stats_row(col1, labels[FACES], col2, stats_fmt.totfacesel, stats_fmt.totface, y, height); + stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } else if (obedit->type == OB_ARMATURE) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s/%s | Bones:%s/%s"), - stats_fmt.totvertsel, - stats_fmt.totvert, - stats_fmt.totbonesel, - stats_fmt.totbone); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); + stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height); } else { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s/%s"), - stats_fmt.totvertsel, - stats_fmt.totvert); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvertsel, stats_fmt.totvert, y, height); } - - ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); - ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs); } else if (ob && (object_mode & OB_MODE_POSE)) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Bones:%s/%s %s%s"), - stats_fmt.totbonesel, - stats_fmt.totbone, - memstr, - gpumemstr); + stats_row(col1, labels[BONES], col2, stats_fmt.totbonesel, stats_fmt.totbone, y, height); } else if ((ob) && (ob->type == OB_GPENCIL)) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Layers:%s | Frames:%s | Strokes:%s | Points:%s | Objects:%s/%s"), - stats_fmt.totgplayer, - stats_fmt.totgpframe, - stats_fmt.totgpstroke, - stats_fmt.totgppoint, - stats_fmt.totobjsel, - stats_fmt.totobj); - - ofs += BLI_strncpy_rlen(s + ofs, memstr, MAX_INFO_LEN - ofs); - ofs += BLI_strncpy_rlen(s + ofs, gpumemstr, MAX_INFO_LEN - ofs); + stats_row(col1, labels[LAYERS], col2, stats_fmt.totgplayer, NULL, y, height); + stats_row(col1, labels[FRAMES], col2, stats_fmt.totgpframe, NULL, y, height); + stats_row(col1, labels[STROKES], col2, stats_fmt.totgpstroke, NULL, y, height); + stats_row(col1, labels[POINTS], col2, stats_fmt.totgppoint, NULL, y, height); } else if (stats_is_object_dynamic_topology_sculpt(ob, object_mode)) { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s | Tris:%s%s"), - stats_fmt.totvert, - stats_fmt.tottri, - gpumemstr); + stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height); + stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } else { - ofs += BLI_snprintf(s + ofs, - MAX_INFO_LEN - ofs, - TIP_("Verts:%s | Faces:%s | Tris:%s | Objects:%s/%s%s%s"), - stats_fmt.totvert, - stats_fmt.totface, - stats_fmt.tottri, - stats_fmt.totobjsel, - stats_fmt.totobj, - memstr, - gpumemstr); - } - - ofs += BLI_snprintf(s + ofs, MAX_INFO_LEN - ofs, " | %s", versionstr); -#undef MAX_INFO_MEM_LEN -} - -#undef MAX_INFO_LEN - -void ED_info_stats_clear(ViewLayer *view_layer) -{ - if (view_layer->stats) { - MEM_freeN(view_layer->stats); - view_layer->stats = NULL; + stats_row(col1, labels[VERTS], col2, stats_fmt.totvert, NULL, y, height); + stats_row(col1, labels[EDGES], col2, stats_fmt.totedge, NULL, y, height); + stats_row(col1, labels[FACES], col2, stats_fmt.totface, NULL, y, height); + stats_row(col1, labels[TRIS], col2, stats_fmt.tottri, NULL, y, height); } -} -const char *ED_info_stats_string(Main *bmain, Scene *scene, ViewLayer *view_layer) -{ - /* Looping through dependency graph when interface is locked is not safe. - * The interface is marked as locked when jobs wants to modify the - * dependency graph. */ - wmWindowManager *wm = bmain->wm.first; - if (wm->is_interface_locked) { - return ""; - } - Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, true); - if (!view_layer->stats) { - stats_update(depsgraph, view_layer); - } - stats_string(view_layer); - return view_layer->stats->infostr; + BLF_disable(font_id, BLF_SHADOW); } diff --git a/source/blender/editors/space_nla/nla_buttons.c b/source/blender/editors/space_nla/nla_buttons.c index 218e2be0362..307b6d9bc21 100644 --- a/source/blender/editors/space_nla/nla_buttons.c +++ b/source/blender/editors/space_nla/nla_buttons.c @@ -143,7 +143,8 @@ bool nla_panel_context(const bContext *C, case ANIMTYPE_PALETTE: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* for these channels, we only do AnimData */ if (ale->adt && adt_ptr) { ID *id; @@ -354,7 +355,7 @@ static void nla_panel_properties(const bContext *C, Panel *panel) { PointerRNA strip_ptr; uiLayout *layout = panel->layout; - uiLayout *column; + uiLayout *column, *row; uiBlock *block; short showEvalProps = 1; @@ -401,20 +402,19 @@ static void nla_panel_properties(const bContext *C, Panel *panel) uiItemR(column, &strip_ptr, "blend_in", 0, IFACE_("Blend In"), ICON_NONE); uiItemR(column, &strip_ptr, "blend_out", 0, IFACE_("Out"), ICON_NONE); - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false); - uiItemR(column, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? - - uiItemS(layout); + row = uiLayoutRow(column, true); + uiLayoutSetActive(row, RNA_boolean_get(&strip_ptr, "use_animated_influence") == false); + uiItemR(row, &strip_ptr, "use_auto_blend", 0, NULL, ICON_NONE); // XXX as toggle? /* settings */ - column = uiLayoutColumn(layout, true); - uiLayoutSetActive(column, + column = uiLayoutColumnWithHeading(layout, true, "Playback"); + row = uiLayoutRow(column, true); + uiLayoutSetActive(row, !(RNA_boolean_get(&strip_ptr, "use_animated_influence") || RNA_boolean_get(&strip_ptr, "use_animated_time"))); - uiItemR(column, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); + uiItemR(row, &strip_ptr, "use_reverse", 0, NULL, ICON_NONE); - uiItemR(layout, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE); + uiItemR(column, &strip_ptr, "use_animated_time_cyclic", 0, NULL, ICON_NONE); } } @@ -442,15 +442,12 @@ static void nla_panel_actclip(const bContext *C, Panel *panel) uiItemR(row, &strip_ptr, "action", 0, NULL, ICON_ACTION); /* action extents */ - // XXX custom names were used here (to avoid the prefixes)... probably not necessary in future? column = uiLayoutColumn(layout, true); uiItemR(column, &strip_ptr, "action_frame_start", 0, IFACE_("Frame Start"), ICON_NONE); uiItemR(column, &strip_ptr, "action_frame_end", 0, IFACE_("End"), ICON_NONE); - /* XXX: this layout may actually be too abstract and confusing, - * and may be better using standard column layout. */ - row = uiLayoutRow(layout, false); - uiItemR(row, &strip_ptr, "use_sync_length", 0, IFACE_("Sync Length"), ICON_NONE); + row = uiLayoutRowWithHeading(layout, false, "Sync Length"); + uiItemR(row, &strip_ptr, "use_sync_length", 0, "", ICON_NONE); uiItemO(row, IFACE_("Now"), ICON_FILE_REFRESH, "NLA_OT_action_sync_length"); /* action usage */ diff --git a/source/blender/editors/space_nla/nla_channels.c b/source/blender/editors/space_nla/nla_channels.c index 5adcec8a5d7..d399ea47d7e 100644 --- a/source/blender/editors/space_nla/nla_channels.c +++ b/source/blender/editors/space_nla/nla_channels.c @@ -193,7 +193,8 @@ static int mouse_nla_channels( case ANIMTYPE_PALETTE: case ANIMTYPE_DSHAIR: case ANIMTYPE_DSPOINTCLOUD: - case ANIMTYPE_DSVOLUME: { + case ANIMTYPE_DSVOLUME: + case ANIMTYPE_DSSIMULATION: { /* sanity checking... */ if (ale->adt) { /* select/deselect */ diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c index 5b949911158..f68896e21d6 100644 --- a/source/blender/editors/space_nla/nla_edit.c +++ b/source/blender/editors/space_nla/nla_edit.c @@ -410,8 +410,8 @@ void NLA_OT_previewrange_set(wmOperatorType *ot) /** * Find the extents of the active channel * - * \param[out] min Bottom y-extent of channel - * \param[out] max Top y-extent of channel + * \param[out] min: Bottom y-extent of channel. + * \param[out] max: Top y-extent of channel. * \return Success of finding a selected channel */ static bool nla_channels_get_selected_extents(bAnimContext *ac, float *min, float *max) @@ -526,7 +526,7 @@ static int nlaedit_viewsel_exec(bContext *C, wmOperator *UNUSED(op)) void NLA_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "NLA_OT_view_all"; ot->description = "Reset viewable area to show full strips range"; diff --git a/source/blender/editors/space_node/CMakeLists.txt b/source/blender/editors/space_node/CMakeLists.txt index f8c30f9a688..4e21cdc9d16 100644 --- a/source/blender/editors/space_node/CMakeLists.txt +++ b/source/blender/editors/space_node/CMakeLists.txt @@ -75,6 +75,10 @@ if(WITH_OPENIMAGEDENOISE) add_definitions(-DWITH_OPENIMAGEDENOISE) endif() +if (WITH_NEW_SIMULATION_TYPE) + add_definitions(-DWITH_NEW_SIMULATION_TYPE) +endif() + add_definitions(${GL_DEFINITIONS}) blender_add_lib(bf_editor_space_node "${SRC}" "${INC}" "${INC_SYS}" "${LIB}") diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index e5ca2efb26f..44003a5b9bc 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -69,9 +69,13 @@ #include "NOD_composite.h" #include "NOD_shader.h" +#include "NOD_simulation.h" #include "NOD_texture.h" #include "node_intern.h" /* own include */ +/* Default flags for uiItemR(). Name is kept short since this is used a lot in this file. */ +#define DEFAULT_FLAGS UI_ITEM_R_SPLIT_EMPTY_NAME + /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */ static void node_socket_button_label(bContext *UNUSED(C), @@ -93,7 +97,7 @@ static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *p PointerRNA sockptr; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); - uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); + uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -107,7 +111,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr col = uiLayoutColumn(layout, false); uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); - uiItemR(col, &sockptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(col, &sockptr, "default_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); } static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -118,12 +122,12 @@ static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); - uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE); + uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); if (ELEM(ntree->type, NTREE_COMPOSIT, NTREE_TEXTURE)) { - uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA); + uiItemR(row, ptr, "use_alpha", DEFAULT_FLAGS, "", ICON_IMAGE_RGB_ALPHA); } - uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -145,8 +149,8 @@ static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *pt uiTemplateCurveMapping(layout, ptr, "curve", 's', false, false, false, false); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "frame_start", 0, IFACE_("Sta"), ICON_NONE); - uiItemR(row, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE); + uiItemR(row, ptr, "frame_start", DEFAULT_FLAGS, IFACE_("Sta"), ICON_NONE); + uiItemR(row, ptr, "frame_end", DEFAULT_FLAGS, IFACE_("End"), ICON_NONE); } static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -196,7 +200,7 @@ static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA * PointerRNA sockptr; RNA_pointer_create(ptr->owner_id, &RNA_NodeSocket, output, &sockptr); - uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE); + uiItemR(layout, &sockptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } #if 0 /* not used in 2.5x yet */ @@ -242,33 +246,33 @@ static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA short multi = (node->id && ((Tex *)node->id)->use_nodes && (node->type != CMP_NODE_TEXTURE) && (node->type != TEX_NODE_TEXTURE)); - uiItemR(layout, ptr, "texture", 0, "", ICON_NONE); + uiItemR(layout, ptr, "texture", DEFAULT_FLAGS, "", ICON_NONE); if (multi) { /* Number Drawing not optimal here, better have a list*/ - uiItemR(layout, ptr, "node_output", 0, "", ICON_NONE); + uiItemR(layout, ptr, "node_output", DEFAULT_FLAGS, "", ICON_NONE); } } static void node_shader_buts_clamp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "clamp_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "clamp_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "interpolation_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation_type", DEFAULT_FLAGS, "", ICON_NONE); if (!ELEM(RNA_enum_get(ptr, "interpolation_type"), NODE_MAP_RANGE_SMOOTHSTEP, NODE_MAP_RANGE_SMOOTHERSTEP)) { - uiItemR(layout, ptr, "clamp", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } } static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); - uiItemR(layout, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static int node_resize_area_default(bNode *node, int x, int y) @@ -534,9 +538,9 @@ static int node_resize_area_frame(bNode *node, int x, int y) static void node_buts_frame_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE); - uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE); - uiItemR(layout, ptr, "text", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "label_size", DEFAULT_FLAGS, IFACE_("Label Size"), ICON_NONE); + uiItemR(layout, ptr, "shrink", DEFAULT_FLAGS, IFACE_("Shrink"), ICON_NONE); + uiItemR(layout, ptr, "text", DEFAULT_FLAGS, NULL, ICON_NONE); } #define NODE_REROUTE_SIZE 8.0f @@ -697,7 +701,7 @@ static void node_buts_image_user(uiLayout *layout, col = uiLayoutColumn(layout, false); - uiItemR(col, imaptr, "source", 0, "", ICON_NONE); + uiItemR(col, imaptr, "source", DEFAULT_FLAGS, "", ICON_NONE); source = RNA_enum_get(imaptr, "source"); @@ -716,23 +720,23 @@ static void node_buts_image_user(uiLayout *layout, if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_auto_refresh", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_duration", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_start", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "frame_offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_cyclic", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_auto_refresh", DEFAULT_FLAGS, NULL, ICON_NONE); } if (compositor && RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER && RNA_boolean_get(ptr, "has_layers")) { col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "layer", DEFAULT_FLAGS, NULL, ICON_NONE); } uiLayout *split = uiLayoutSplit(layout, 0.5f, true); PointerRNA colorspace_settings_ptr = RNA_pointer_get(imaptr, "colorspace_settings"); uiItemL(split, IFACE_("Color Space"), ICON_NONE); - uiItemR(split, &colorspace_settings_ptr, "name", 0, "", ICON_NONE); + uiItemR(split, &colorspace_settings_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); /* Avoid losing changes image is painted. */ if (BKE_image_is_dirty(imaptr->data)) { @@ -742,35 +746,35 @@ static void node_buts_image_user(uiLayout *layout, static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "vector_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_vector_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "rotation_type", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "invert", 0, NULL, 0); + uiItemR(layout, ptr, "rotation_type", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "operation", 0, "", ICON_NONE); + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_vect_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "vector_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "convert_from", 0, "", ICON_NONE); - uiItemR(layout, ptr, "convert_to", 0, "", ICON_NONE); + uiItemR(layout, ptr, "vector_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "convert_from", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "convert_to", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE); + uiItemR(layout, ptr, "attribute_name", DEFAULT_FLAGS, IFACE_("Name"), ICON_NONE); } static void node_shader_buts_wireframe(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_pixel_size", 0, NULL, 0); + uiItemR(layout, ptr, "use_pixel_size", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -789,14 +793,14 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA UI_TEMPLATE_ID_FILTER_ALL, false, NULL); - uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); - uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) { - uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE); + uiItemR(layout, ptr, "projection_blend", DEFAULT_FLAGS, "Blend", ICON_NONE); } - uiItemR(layout, ptr, "extension", 0, "", ICON_NONE); + uiItemR(layout, ptr, "extension", DEFAULT_FLAGS, "", ICON_NONE); /* note: image user properties used directly here, unlike compositor image node, * which redefines them in the node struct RNA to get proper updates. @@ -827,8 +831,8 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin false, NULL); - uiItemR(layout, ptr, "interpolation", 0, "", ICON_NONE); - uiItemR(layout, ptr, "projection", 0, "", ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, "", ICON_NONE); node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr, false); } @@ -838,29 +842,29 @@ static void node_shader_buts_tex_environment_ex(uiLayout *layout, bContext *C, P PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user"); uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0, 0); - uiItemR(layout, ptr, "interpolation", 0, IFACE_("Interpolation"), ICON_NONE); - uiItemR(layout, ptr, "projection", 0, IFACE_("Projection"), ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, IFACE_("Interpolation"), ICON_NONE); + uiItemR(layout, ptr, "projection", DEFAULT_FLAGS, IFACE_("Projection"), ICON_NONE); } 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); + uiItemR(layout, ptr, "sky_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "sun_direction", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "turbidity", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NEW) { - uiItemR(layout, ptr, "ground_albedo", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "ground_albedo", DEFAULT_FLAGS, NULL, ICON_NONE); } } static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "gradient_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "turbulence_depth", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -868,48 +872,48 @@ static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); - uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); + uiItemR(col, ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE); - uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE); + uiItemR(col, ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); } static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "wave_type", DEFAULT_FLAGS, "", ICON_NONE); int type = RNA_enum_get(ptr, "wave_type"); if (type == SHD_WAVE_BANDS) { - uiItemR(layout, ptr, "bands_direction", 0, "", ICON_NONE); + uiItemR(layout, ptr, "bands_direction", DEFAULT_FLAGS, "", ICON_NONE); } else { /* SHD_WAVE_RINGS */ - uiItemR(layout, ptr, "rings_direction", 0, "", ICON_NONE); + uiItemR(layout, ptr, "rings_direction", DEFAULT_FLAGS, "", ICON_NONE); } - uiItemR(layout, ptr, "wave_profile", 0, "", ICON_NONE); + uiItemR(layout, ptr, "wave_profile", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "musgrave_dimensions", 0, "", ICON_NONE); - uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "musgrave_dimensions", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "voronoi_dimensions", 0, "", ICON_NONE); - uiItemR(layout, ptr, "feature", 0, "", ICON_NONE); + uiItemR(layout, ptr, "voronoi_dimensions", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "feature", DEFAULT_FLAGS, "", ICON_NONE); int feature = RNA_enum_get(ptr, "feature"); if (!ELEM(feature, SHD_VORONOI_DISTANCE_TO_EDGE, SHD_VORONOI_N_SPHERE_RADIUS) && RNA_enum_get(ptr, "voronoi_dimensions") != 1) { - uiItemR(layout, ptr, "distance", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, "", ICON_NONE); } } static void node_shader_buts_tex_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "noise_dimensions", 0, "", ICON_NONE); + uiItemR(layout, ptr, "noise_dimensions", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_tex_pointdensity(uiLayout *layout, @@ -925,7 +929,7 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, RNA_id_pointer_create(ob ? (ID *)ob->data : NULL, &obdata_ptr); uiItemR(layout, ptr, "point_source", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(layout, ptr, "object", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, ICON_NONE); if (node->id && shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { PointerRNA dataptr; @@ -933,15 +937,15 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, uiItemPointerR(layout, ptr, "particle_system", &dataptr, "particle_systems", NULL, ICON_NONE); } - uiItemR(layout, ptr, "space", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "radius", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "interpolation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "resolution", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "radius", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "interpolation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "resolution", DEFAULT_FLAGS, NULL, ICON_NONE); if (shader_point_density->point_source == SHD_POINTDENSITY_SOURCE_PSYS) { - uiItemR(layout, ptr, "particle_color_source", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "particle_color_source", DEFAULT_FLAGS, NULL, ICON_NONE); } else { - uiItemR(layout, ptr, "vertex_color_source", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "vertex_color_source", DEFAULT_FLAGS, NULL, ICON_NONE); if (shader_point_density->ob_color_source == SHD_POINTDENSITY_COLOR_VERTWEIGHT) { if (ob_ptr.data) { uiItemPointerR( @@ -959,18 +963,18 @@ static void node_shader_buts_tex_pointdensity(uiLayout *layout, static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "object", 0, NULL, 0); - uiItemR(layout, ptr, "from_instancer", 0, NULL, 0); + uiItemR(layout, ptr, "object", DEFAULT_FLAGS, NULL, 0); + uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_bump(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "invert", 0, NULL, 0); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_uvmap(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiItemR(layout, ptr, "from_instancer", 0, NULL, 0); + uiItemR(layout, ptr, "from_instancer", DEFAULT_FLAGS, NULL, 0); if (!RNA_boolean_get(ptr, "from_instancer")) { PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); @@ -996,12 +1000,12 @@ static void node_shader_buts_vertex_color(uiLayout *layout, bContext *C, Pointer static void node_shader_buts_uvalongstroke(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_tips", 0, NULL, 0); + uiItemR(layout, ptr, "use_tips", DEFAULT_FLAGS, NULL, 0); } static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr) { - uiItemR(layout, ptr, "space", 0, "", 0); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", 0); if (RNA_enum_get(ptr, "space") == SHD_SPACE_TANGENT) { PointerRNA obptr = CTX_data_pointer_get(C, "active_object"); @@ -1011,14 +1015,14 @@ static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRN uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else { - uiItemR(layout, ptr, "uv_map", 0, "", 0); + uiItemR(layout, ptr, "uv_map", DEFAULT_FLAGS, "", 0); } } } static void node_shader_buts_displacement(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "space", 0, "", 0); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", 0); } static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1027,7 +1031,7 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * split = uiLayoutSplit(layout, 0.0f, false); - uiItemR(split, ptr, "direction_type", 0, "", 0); + uiItemR(split, ptr, "direction_type", DEFAULT_FLAGS, "", 0); row = uiLayoutRow(split, false); @@ -1039,50 +1043,50 @@ static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA * uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_layers", "", ICON_NONE); } else { - uiItemR(row, ptr, "uv_map", 0, "", 0); + uiItemR(row, ptr, "uv_map", DEFAULT_FLAGS, "", 0); } } else { - uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0); + uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, 0); } } static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_principled(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); - uiItemR(layout, ptr, "subsurface_method", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "subsurface_method", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_anisotropic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distribution", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_subsurface(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "falloff", 0, "", ICON_NONE); + uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_toon(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "component", 0, "", ICON_NONE); + uiItemR(layout, ptr, "component", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "component", 0, "", ICON_NONE); + uiItemR(layout, ptr, "component", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_principled_hair(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "parametrization", 0, "", ICON_NONE); + uiItemR(layout, ptr, "parametrization", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1090,15 +1094,15 @@ static void node_shader_buts_ies(uiLayout *layout, bContext *UNUSED(C), PointerR uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, true); if (RNA_enum_get(ptr, "mode") == NODE_IES_INTERNAL) { - uiItemR(row, ptr, "ies", 0, "", ICON_NONE); + uiItemR(row, ptr, "ies", DEFAULT_FLAGS, "", ICON_NONE); } else { - uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); + uiItemR(row, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE); } } @@ -1107,15 +1111,15 @@ static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), Point uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "mode", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, true); if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL) { - uiItemR(row, ptr, "script", 0, "", ICON_NONE); + uiItemR(row, ptr, "script", DEFAULT_FLAGS, "", ICON_NONE); } else { - uiItemR(row, ptr, "filepath", 0, "", ICON_NONE); + uiItemR(row, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE); } uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update"); @@ -1129,14 +1133,14 @@ static void node_shader_buts_script_ex(uiLayout *layout, bContext *C, PointerRNA #if 0 /* not implemented yet */ if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL) { - uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_auto_update", DEFAULT_FLAGS, NULL, ICON_NONE); } #endif } static void node_buts_output_shader(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "target", 0, "", ICON_NONE); + uiItemR(layout, ptr, "target", DEFAULT_FLAGS, "", ICON_NONE); } static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1145,32 +1149,32 @@ static void node_buts_output_linestyle(uiLayout *layout, bContext *UNUSED(C), Po col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); - uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE); - uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "blend_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "inside", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "only_local", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_shader_buts_white_noise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "noise_dimensions", 0, "", ICON_NONE); + uiItemR(layout, ptr, "noise_dimensions", DEFAULT_FLAGS, "", ICON_NONE); } static void node_shader_buts_output_aov(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "name", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "name", DEFAULT_FLAGS, NULL, ICON_NONE); } /* only once called */ @@ -1355,10 +1359,10 @@ static void node_buts_image_views(uiLayout *layout, if (RNA_boolean_get(ptr, "has_views")) { if (RNA_enum_get(ptr, "view") == 0) { - uiItemR(col, ptr, "view", 0, NULL, ICON_CAMERA_STEREO); + uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_CAMERA_STEREO); } else { - uiItemR(col, ptr, "view", 0, NULL, ICON_SCENE); + uiItemR(col, ptr, "view", DEFAULT_FLAGS, NULL, ICON_SCENE); } } } @@ -1419,7 +1423,7 @@ static void node_composit_buts_viewlayers(uiLayout *layout, bContext *C, Pointer col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, true); - uiItemR(row, ptr, "layer", 0, "", ICON_NONE); + uiItemR(row, ptr, "layer", DEFAULT_FLAGS, "", ICON_NONE); prop = RNA_struct_find_property(ptr, "layer"); if (!(RNA_property_enum_identifier( @@ -1446,56 +1450,56 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point filter = RNA_enum_get(ptr, "filter_type"); reference = RNA_boolean_get(ptr, "use_variable_size"); - uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(col, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); if (filter != R_FILTER_FAST_GAUSS) { - uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE); if (!reference) { - uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_bokeh", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_boolean_get(ptr, "use_relative")) { uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "aspect_correction", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "factor_y", 0, IFACE_("Y"), ICON_NONE); + uiItemR(col, ptr, "factor_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); + uiItemR(col, ptr, "factor_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); } else { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE); + uiItemR(col, ptr, "size_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); + uiItemR(col, ptr, "size_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); } - uiItemR(col, ptr, "use_extended_bounds", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_wrap", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Center:"), ICON_NONE); - uiItemR(col, ptr, "center_x", 0, IFACE_("X"), ICON_NONE); - uiItemR(col, ptr, "center_y", 0, IFACE_("Y"), ICON_NONE); + uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, IFACE_("X"), ICON_NONE); + uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, IFACE_("Y"), ICON_NONE); uiItemS(layout); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); uiItemS(layout); - uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "spin", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "zoom", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_bilateralblur(uiLayout *layout, @@ -1505,9 +1509,9 @@ static void node_composit_buts_bilateralblur(uiLayout *layout, uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sigma_color", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "sigma_space", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -1516,60 +1520,60 @@ static void node_composit_buts_defocus(uiLayout *layout, bContext *C, PointerRNA col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE); - uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE); - uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "bokeh", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_gamma_correction", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == true); - uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_preview", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_zbuffer", DEFAULT_FLAGS, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == false); - uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE); + uiItemR(sub, ptr, "z_scale", DEFAULT_FLAGS, NULL, ICON_NONE); } /* qdn: glare node */ static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "quality", 0, "", ICON_NONE); + uiItemR(layout, ptr, "glare_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "quality", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "glare_type") != 1) { - uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "iterations", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") != 0) { - uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "color_modulation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } } - uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "mix", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") == 2) { - uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "streaks", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "angle_offset", DEFAULT_FLAGS, NULL, ICON_NONE); } if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) { - uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "fade", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); if (RNA_enum_get(ptr, "glare_type") == 0) { - uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_rotate_45", DEFAULT_FLAGS, NULL, ICON_NONE); } } if (RNA_enum_get(ptr, "glare_type") == 1) { - uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -1578,17 +1582,17 @@ static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE); + uiItemR(col, ptr, "tonemap_type", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "tonemap_type") == 0) { - uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "key", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); } else { - uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "intensity", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "adaptation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "correction", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } } @@ -1597,12 +1601,12 @@ static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), P uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_projector", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(col, false); uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == false); - uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_jitter", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_fit", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1610,46 +1614,46 @@ static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE); + uiItemR(col, ptr, "samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "factor", DEFAULT_FLAGS, IFACE_("Blur"), ICON_NONE); col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Speed:"), ICON_NONE); - uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE); - uiItemR(col, ptr, "speed_max", 0, IFACE_("Max"), ICON_NONE); + uiItemR(col, ptr, "speed_min", DEFAULT_FLAGS, IFACE_("Min"), ICON_NONE); + uiItemR(col, ptr, "speed_max", DEFAULT_FLAGS, IFACE_("Max"), ICON_NONE); - uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_curved", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "axis", 0, "", ICON_NONE); + uiItemR(layout, ptr, "axis", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_crop_size", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "relative", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); if (RNA_boolean_get(ptr, "relative")) { - uiItemR(col, ptr, "rel_min_x", 0, IFACE_("Left"), ICON_NONE); - uiItemR(col, ptr, "rel_max_x", 0, IFACE_("Right"), ICON_NONE); - uiItemR(col, ptr, "rel_min_y", 0, IFACE_("Up"), ICON_NONE); - uiItemR(col, ptr, "rel_max_y", 0, IFACE_("Down"), ICON_NONE); + uiItemR(col, ptr, "rel_min_x", DEFAULT_FLAGS, IFACE_("Left"), ICON_NONE); + uiItemR(col, ptr, "rel_max_x", DEFAULT_FLAGS, IFACE_("Right"), ICON_NONE); + uiItemR(col, ptr, "rel_min_y", DEFAULT_FLAGS, IFACE_("Up"), ICON_NONE); + uiItemR(col, ptr, "rel_max_y", DEFAULT_FLAGS, IFACE_("Down"), ICON_NONE); } else { - uiItemR(col, ptr, "min_x", 0, IFACE_("Left"), ICON_NONE); - uiItemR(col, ptr, "max_x", 0, IFACE_("Right"), ICON_NONE); - uiItemR(col, ptr, "min_y", 0, IFACE_("Up"), ICON_NONE); - uiItemR(col, ptr, "max_y", 0, IFACE_("Down"), ICON_NONE); + uiItemR(col, ptr, "min_x", DEFAULT_FLAGS, IFACE_("Left"), ICON_NONE); + uiItemR(col, ptr, "max_x", DEFAULT_FLAGS, IFACE_("Right"), ICON_NONE); + uiItemR(col, ptr, "min_y", DEFAULT_FLAGS, IFACE_("Up"), ICON_NONE); + uiItemR(col, ptr, "max_y", DEFAULT_FLAGS, IFACE_("Down"), ICON_NONE); } } @@ -1659,8 +1663,8 @@ static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C) col = uiLayoutColumn(layout, false); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(col, ptr, "factor", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_double_edge_mask(uiLayout *layout, @@ -1672,9 +1676,9 @@ static void node_composit_buts_double_edge_mask(uiLayout *layout, col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE); - uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE); + uiItemR(col, ptr, "inner_mode", DEFAULT_FLAGS, "", ICON_NONE); uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE); - uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE); + uiItemR(col, ptr, "edge_mode", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1682,7 +1686,7 @@ static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_clamp", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1690,20 +1694,20 @@ static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), uiLayout *sub, *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "size", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "size", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_min", DEFAULT_FLAGS, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min")); - uiItemR(sub, ptr, "min", 0, "", ICON_NONE); + uiItemR(sub, ptr, "min", DEFAULT_FLAGS, "", ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_max", DEFAULT_FLAGS, NULL, ICON_NONE); sub = uiLayoutColumn(col, false); uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max")); - uiItemR(sub, ptr, "max", 0, "", ICON_NONE); + uiItemR(sub, ptr, "max", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1711,8 +1715,8 @@ static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "premul", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1720,27 +1724,27 @@ static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), P uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "use_antialias_z", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "use_antialias_z", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); switch (RNA_enum_get(ptr, "mode")) { case CMP_NODE_DILATEERODE_DISTANCE_THRESH: - uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge", DEFAULT_FLAGS, NULL, ICON_NONE); break; case CMP_NODE_DILATEERODE_DISTANCE_FEATHER: - uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "falloff", DEFAULT_FLAGS, NULL, ICON_NONE); break; } } static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "distance", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1748,8 +1752,8 @@ static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "threshold_neighbor", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold_neighbor", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1757,8 +1761,8 @@ static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_distance_matte(uiLayout *layout, @@ -1771,10 +1775,10 @@ static void node_composit_buts_distance_matte(uiLayout *layout, uiItemL(layout, IFACE_("Color Space:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "falloff", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1783,23 +1787,23 @@ static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C) uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "limit_method") == 0) { uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); } - uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "ratio", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "use_unspill", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_boolean_get(ptr, "use_unspill") == true) { - uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_red", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_green", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "unspill_blue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } } @@ -1808,12 +1812,12 @@ static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "tolerance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "threshold", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, true); /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now */ - uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE); Removed for now*/ } @@ -1822,9 +1826,9 @@ static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C) uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_hue", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "color_value", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_channel_matte(uiLayout *layout, @@ -1835,24 +1839,24 @@ static void node_composit_buts_channel_matte(uiLayout *layout, uiItemL(layout, IFACE_("Color Space:"), ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "color_space", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); uiItemL(col, IFACE_("Key Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "matte_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "limit_method") == 0) { uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, ptr, "limit_channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); } - uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1860,19 +1864,19 @@ static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_max", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(col, ptr, "limit_min", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "index", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_antialiasing", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -1886,7 +1890,7 @@ static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C) else { uiItemL(layout, IFACE_("Base Path:"), ICON_NONE); } - uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE); + uiItemR(layout, ptr, "base_path", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, PointerRNA *ptr) { @@ -1972,7 +1976,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi uiItemL(col, IFACE_("Layer:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE); + uiItemR(row, &active_input_ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", @@ -1987,7 +1991,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi uiItemL(col, IFACE_("File Subpath:"), ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE); + uiItemR(row, &active_input_ptr, "path", DEFAULT_FLAGS, "", ICON_NONE); uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "", @@ -2002,7 +2006,7 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi col = uiLayoutColumn(layout, true); uiItemL(col, IFACE_("Format:"), ICON_NONE); - uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE); + uiItemR(col, &active_input_ptr, "use_node_format", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(layout, false); uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == false); @@ -2017,20 +2021,20 @@ static void node_composit_buts_file_output_ex(uiLayout *layout, bContext *C, Poi static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "space", 0, "", ICON_NONE); + uiItemR(layout, ptr, "space", DEFAULT_FLAGS, "", ICON_NONE); if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) { uiLayout *row; - uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_method", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE); - uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE); + uiItemR(row, ptr, "offset_x", DEFAULT_FLAGS, "X", ICON_NONE); + uiItemR(row, ptr, "offset_y", DEFAULT_FLAGS, "Y", ICON_NONE); } } static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2038,25 +2042,25 @@ static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), Poi uiLayout *col; col = uiLayoutColumn(layout, false); - uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "invert_rgb", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "invert_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE); + uiItemR(layout, ptr, "mapping", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(layout, ptr, "channel", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); } static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *split, *col, *row; - uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "correction_method") == 0) { @@ -2064,17 +2068,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE); } else { @@ -2082,46 +2086,46 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "offset_basis", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "offset_basis", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "power", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE); col = uiLayoutColumn(split, false); uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1); row = uiLayoutRow(col, false); - uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE); } } static void node_composit_buts_colorbalance_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "correction_method", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "correction_method") == 0) { uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1); - uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "lift", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1); - uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "gamma", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1); - uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "gain", DEFAULT_FLAGS, NULL, ICON_NONE); } else { uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1); - uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "offset", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1); - uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "power", DEFAULT_FLAGS, NULL, ICON_NONE); uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1); - uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "slope", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2143,7 +2147,7 @@ static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "mode", 0, "", ICON_NONE); + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2180,19 +2184,19 @@ static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, Pointe return; } - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); - uiItemR(layout, ptr, "invert", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(layout, ptr, "invert", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_translate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_relative", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "wrap_axis", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_relative", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "wrap_axis", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filter_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2206,7 +2210,7 @@ static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, Po return; } - uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE); + uiItemR(layout, ptr, "distortion_type", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_colorcorrection(uiLayout *layout, @@ -2216,9 +2220,9 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "red", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "green", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, "", ICON_NONE); @@ -2230,39 +2234,39 @@ static void node_composit_buts_colorcorrection(uiLayout *layout, row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Master"), ICON_NONE); - uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Highlights"), ICON_NONE); - uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Midtones"), ICON_NONE); - uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); uiItemL(row, IFACE_("Shadows"), ICON_NONE); - uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE); - uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); + uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, "", ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_colorcorrection_ex(uiLayout *layout, @@ -2272,48 +2276,48 @@ static void node_composit_buts_colorcorrection_ex(uiLayout *layout, uiLayout *row; row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "red", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "green", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "red", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "green", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "blue", DEFAULT_FLAGS, NULL, ICON_NONE); row = layout; uiItemL(row, IFACE_("Saturation"), ICON_NONE); - uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_saturation", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Contrast"), ICON_NONE); - uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_contrast", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Gamma"), ICON_NONE); - uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_gamma", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Gain"), ICON_NONE); - uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_gain", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); uiItemL(row, IFACE_("Lift"), ICON_NONE); - uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "master_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "highlights_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "shadows_lift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); row = uiLayoutRow(layout, false); - uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_start", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "midtones_end", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "check", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_switch_view_ex(uiLayout *layout, @@ -2335,32 +2339,32 @@ static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), Po uiLayout *row; row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "x", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "y", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "flaps", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "angle", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "rounding", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "catadioptric", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "shift", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE); - // uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE); // UNUSED - uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "use_extended_bounds", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_variable_size", DEFAULT_FLAGS, NULL, ICON_NONE); + // uiItemR(layout, ptr, "f_stop", DEFAULT_FLAGS, NULL, ICON_NONE); // UNUSED + uiItemR(layout, ptr, "blur_max", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_extended_bounds", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_backdrop_viewer( @@ -2486,36 +2490,36 @@ static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C) { uiLayout *row; row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "x", 0, NULL, ICON_NONE); - uiItemR(row, ptr, "y", 0, NULL, ICON_NONE); + uiItemR(row, ptr, "x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(row, ptr, "y", DEFAULT_FLAGS, NULL, ICON_NONE); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "width", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(row, ptr, "height", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); - uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "rotation", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "mask_type", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_composite(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_viewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_viewer_ex(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { uiLayout *col; - uiItemR(layout, ptr, "use_alpha", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_alpha", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "tile_order", DEFAULT_FLAGS, NULL, ICON_NONE); if (RNA_enum_get(ptr, "tile_order") == 0) { col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE); - uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE); + uiItemR(col, ptr, "center_x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(col, ptr, "center_y", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2524,19 +2528,19 @@ static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *p bNode *node = ptr->data; uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL, UI_TEMPLATE_ID_FILTER_ALL, false, NULL); - uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_feather", DEFAULT_FLAGS, NULL, ICON_NONE); - uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE); + uiItemR(layout, ptr, "size_source", DEFAULT_FLAGS, "", ICON_NONE); if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) { - uiItemR(layout, ptr, "size_x", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "size_y", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "size_x", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "size_y", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE); if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) { - uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2562,18 +2566,18 @@ static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), Poi { /* bNode *node = ptr->data; */ /* UNUSED */ - uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "feather_falloff", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "feather_distance", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_pre", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "screen_balance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "despill_factor", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "despill_balance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge_kernel_radius", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "edge_kernel_tolerance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "clip_black", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "clip_white", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "dilate_distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "feather_falloff", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "feather_distance", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "blur_post", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr) @@ -2605,13 +2609,13 @@ static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRN uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA); } else { - uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA); + uiItemR(layout, ptr, "track_name", DEFAULT_FLAGS, "", ICON_ANIM_DATA); } - uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "position", DEFAULT_FLAGS, NULL, ICON_NONE); if (ELEM(node->custom1, CMP_TRACKPOS_RELATIVE_FRAME, CMP_TRACKPOS_ABSOLUTE_FRAME)) { - uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "frame_relative", DEFAULT_FLAGS, NULL, ICON_NONE); } } } @@ -2650,10 +2654,10 @@ static void node_composit_buts_planetrackdeform(uiLayout *layout, bContext *C, P } } - uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_motion_blur", DEFAULT_FLAGS, NULL, ICON_NONE); if (data->flag & CMP_NODEFLAG_PLANETRACKDEFORM_MOTION_BLUR) { - uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE); - uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_samples", DEFAULT_FLAGS, NULL, ICON_NONE); + uiItemR(layout, ptr, "motion_blur_shutter", DEFAULT_FLAGS, NULL, ICON_NONE); } } @@ -2665,8 +2669,8 @@ static void node_composit_buts_cornerpin(uiLayout *UNUSED(layout), static void node_composit_buts_sunbeams(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "source", UI_ITEM_R_EXPAND, "", ICON_NONE); - uiItemR(layout, ptr, "ray_length", UI_ITEM_R_SLIDER, NULL, ICON_NONE); + uiItemR(layout, ptr, "source", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, "", ICON_NONE); + uiItemR(layout, ptr, "ray_length", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, NULL, ICON_NONE); } static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2679,7 +2683,7 @@ static void node_composit_buts_cryptomatte(uiLayout *layout, bContext *UNUSED(C) uiTemplateCryptoPicker(row, ptr, "add"); uiTemplateCryptoPicker(row, ptr, "remove"); - uiItemR(col, ptr, "matte_id", 0, "", ICON_NONE); + uiItemR(col, ptr, "matte_id", DEFAULT_FLAGS, "", ICON_NONE); } static void node_composit_buts_cryptomatte_ex(uiLayout *layout, @@ -2694,7 +2698,7 @@ static void node_composit_buts_brightcontrast(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "use_premultiply", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_premultiply", DEFAULT_FLAGS, NULL, ICON_NONE); } static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2707,7 +2711,7 @@ static void node_composit_buts_denoise(uiLayout *layout, bContext *UNUSED(C), Po } #endif - uiItemR(layout, ptr, "use_hdr", 0, NULL, ICON_NONE); + uiItemR(layout, ptr, "use_hdr", DEFAULT_FLAGS, NULL, ICON_NONE); } /* only once called */ @@ -2957,12 +2961,12 @@ static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), Poin uiLayout *col; col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "offset", UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); - uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "offset", DEFAULT_FLAGS | UI_ITEM_R_SLIDER, IFACE_("Offset"), ICON_NONE); + uiItemR(col, ptr, "offset_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); col = uiLayoutColumn(layout, true); - uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE); - uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE); + uiItemR(col, ptr, "squash", DEFAULT_FLAGS, IFACE_("Squash"), ICON_NONE); + uiItemR(col, ptr, "squash_frequency", DEFAULT_FLAGS, IFACE_("Frequency"), ICON_NONE); } static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) @@ -2979,68 +2983,73 @@ static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), Pointe switch (tex->type) { case TEX_BLEND: - uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "progression", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "use_flip_axis", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); break; case TEX_MARBLE: row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "marble_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(row, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); break; case TEX_MAGIC: - uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "noise_depth", DEFAULT_FLAGS, NULL, ICON_NONE); break; case TEX_STUCCI: row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "stucci_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); break; case TEX_WOOD: - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); - uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, &tex_ptr, "wood_type", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_basis_2", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING))); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); break; case TEX_CLOUDS: - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(row, &tex_ptr, "cloud_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); row = uiLayoutRow(col, false); - uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE); - uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE); + uiItemR(row, &tex_ptr, "noise_type", DEFAULT_FLAGS | UI_ITEM_R_EXPAND, NULL, ICON_NONE); + uiItemR(col, + &tex_ptr, + "noise_depth", + DEFAULT_FLAGS | UI_ITEM_R_EXPAND, + IFACE_("Depth"), + ICON_NONE); break; case TEX_DISTNOISE: - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); - uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_distortion", DEFAULT_FLAGS, "", ICON_NONE); break; case TEX_MUSGRAVE: - uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE); - uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "musgrave_type", DEFAULT_FLAGS, "", ICON_NONE); + uiItemR(col, &tex_ptr, "noise_basis", DEFAULT_FLAGS, "", ICON_NONE); break; case TEX_VORONOI: - uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "distance_metric", DEFAULT_FLAGS, "", ICON_NONE); if (tex->vn_distm == TEX_MINKOVSKY) { - uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE); + uiItemR(col, &tex_ptr, "minkovsky_exponent", DEFAULT_FLAGS, NULL, ICON_NONE); } - uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE); + uiItemR(col, &tex_ptr, "color_mode", DEFAULT_FLAGS, "", ICON_NONE); break; } } @@ -3070,7 +3079,7 @@ static void node_texture_buts_image_ex(uiLayout *layout, bContext *C, PointerRNA static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) { - uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE); + uiItemR(layout, ptr, "filepath", DEFAULT_FLAGS, "", ICON_NONE); } /* only once called */ @@ -3122,6 +3131,96 @@ static void node_texture_set_butfunc(bNodeType *ntype) } } +/* ****************** BUTTON CALLBACKS FOR SIMULATION NODES ***************** */ + +static void node_simulation_buts_particle_simulation(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "name", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_particle_time_step_event(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_particle_attribute(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_set_particle_attribute(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "mode", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_simulation_set_butfunc(bNodeType *ntype) +{ + switch (ntype->type) { + case SIM_NODE_PARTICLE_SIMULATION: + ntype->draw_buttons = node_simulation_buts_particle_simulation; + break; + case SIM_NODE_PARTICLE_TIME_STEP_EVENT: + ntype->draw_buttons = node_simulation_buts_particle_time_step_event; + break; + case SIM_NODE_PARTICLE_ATTRIBUTE: + ntype->draw_buttons = node_simulation_buts_particle_attribute; + break; + case SIM_NODE_SET_PARTICLE_ATTRIBUTE: + ntype->draw_buttons = node_simulation_buts_set_particle_attribute; + break; + case SIM_NODE_TIME: + ntype->draw_buttons = node_simulation_buts_time; + break; + } +} + +/* ****************** BUTTON CALLBACKS FOR FUNCTION NODES ***************** */ + +static void node_function_buts_boolean_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_function_buts_float_compare(uiLayout *layout, + bContext *UNUSED(C), + PointerRNA *ptr) +{ + uiItemR(layout, ptr, "operation", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_function_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr) +{ + uiItemR(layout, ptr, "data_type", DEFAULT_FLAGS, "", ICON_NONE); +} + +static void node_function_set_butfunc(bNodeType *ntype) +{ + switch (ntype->type) { + case FN_NODE_BOOLEAN_MATH: + ntype->draw_buttons = node_function_buts_boolean_math; + break; + case FN_NODE_FLOAT_COMPARE: + ntype->draw_buttons = node_function_buts_float_compare; + break; + case FN_NODE_SWITCH: + ntype->draw_buttons = node_function_buts_switch; + break; + } +} + /* ****** init draw callbacks for all tree types, only called in usiblender.c, once ************ */ static void node_property_update_default(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr) @@ -3230,6 +3329,8 @@ void ED_node_init_butfuncs(void) node_composit_set_butfunc(ntype); node_shader_set_butfunc(ntype); node_texture_set_butfunc(ntype); + node_simulation_set_butfunc(ntype); + node_function_set_butfunc(ntype); /* define update callbacks for socket properties */ node_template_properties_update(ntype); @@ -3240,6 +3341,7 @@ void ED_node_init_butfuncs(void) ntreeType_Composite->ui_icon = ICON_NODE_COMPOSITING; ntreeType_Shader->ui_icon = ICON_NODE_MATERIAL; ntreeType_Texture->ui_icon = ICON_NODE_TEXTURE; + ntreeType_Simulation->ui_icon = ICON_PHYSICS; /* TODO: Use correct icon. */ } void ED_init_custom_node_type(bNodeType *ntype) @@ -3268,6 +3370,12 @@ static const float std_node_socket_colors[][4] = { {0.0, 0.0, 0.0, 1.0}, /*__SOCK_MESH (deprecated) */ {0.06, 0.52, 0.15, 1.0}, /* SOCK_INT */ {0.39, 0.39, 0.39, 1.0}, /* SOCK_STRING */ + {0.40, 0.10, 0.10, 1.0}, /* SOCK_OBJECT */ + {0.10, 0.40, 0.10, 1.0}, /* SOCK_IMAGE */ + {0.80, 0.80, 0.20, 1.0}, /* SOCK_EMITTERS */ + {0.80, 0.20, 0.80, 1.0}, /* SOCK_EVENTS */ + {0.20, 0.80, 0.80, 1.0}, /* SOCK_FORCES */ + {0.30, 0.30, 0.30, 1.0}, /* SOCK_CONTROL_FLOW */ }; /* common color callbacks for standard types */ @@ -3362,7 +3470,7 @@ static void std_node_socket_draw( case SOCK_FLOAT: case SOCK_INT: case SOCK_BOOLEAN: - uiItemR(layout, ptr, "default_value", 0, text, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); break; case SOCK_VECTOR: if (sock->flag & SOCK_COMPACT) { @@ -3370,11 +3478,11 @@ static void std_node_socket_draw( } else { if (sock->typeinfo->subtype == PROP_DIRECTION) { - uiItemR(layout, ptr, "default_value", 0, "", ICON_NONE); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, "", ICON_NONE); } else { uiLayout *column = uiLayoutColumn(layout, true); - uiItemR(column, ptr, "default_value", 0, text, ICON_NONE); + uiItemR(column, ptr, "default_value", DEFAULT_FLAGS, text, ICON_NONE); } } break; @@ -3382,7 +3490,15 @@ static void std_node_socket_draw( case SOCK_STRING: { uiLayout *row = uiLayoutSplit(layout, 0.5f, false); uiItemL(row, text, 0); - uiItemR(row, ptr, "default_value", 0, "", 0); + uiItemR(row, ptr, "default_value", DEFAULT_FLAGS, "", 0); + break; + } + case SOCK_OBJECT: { + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); + break; + } + case SOCK_IMAGE: { + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0); break; } default: @@ -3400,32 +3516,32 @@ static void std_node_socket_interface_draw(bContext *UNUSED(C), uiLayout *layout switch (type) { case SOCK_FLOAT: { uiLayout *row; - uiItemR(layout, ptr, "default_value", 0, NULL, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0); - uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); + uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0); + uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0); break; } case SOCK_INT: { uiLayout *row; - uiItemR(layout, ptr, "default_value", 0, NULL, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0); - uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); + uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0); + uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0); break; } case SOCK_VECTOR: { uiLayout *row; - uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, 0); + uiItemR(layout, ptr, "default_value", UI_ITEM_R_EXPAND, NULL, DEFAULT_FLAGS); row = uiLayoutRow(layout, true); - uiItemR(row, ptr, "min_value", 0, IFACE_("Min"), 0); - uiItemR(row, ptr, "max_value", 0, IFACE_("Max"), 0); + uiItemR(row, ptr, "min_value", DEFAULT_FLAGS, IFACE_("Min"), 0); + uiItemR(row, ptr, "max_value", DEFAULT_FLAGS, IFACE_("Max"), 0); break; } case SOCK_BOOLEAN: case SOCK_RGBA: case SOCK_STRING: { - uiItemR(layout, ptr, "default_value", 0, NULL, 0); + uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, NULL, 0); break; } } diff --git a/source/blender/editors/space_node/node_buttons.c b/source/blender/editors/space_node/node_buttons.c index 4cf67dddb57..8fc343a9ed4 100644 --- a/source/blender/editors/space_node/node_buttons.c +++ b/source/blender/editors/space_node/node_buttons.c @@ -84,7 +84,7 @@ static void node_sockets_panel(const bContext *C, Panel *panel) split = uiLayoutSplit(layout, 0.35f, false); uiItemL(split, name, ICON_NONE); - uiTemplateNodeLink(split, ntree, node, sock); + uiTemplateNodeLink(split, (bContext *)C, ntree, node, sock); } } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index 0552660b9bf..bd8950c5085 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -94,23 +94,11 @@ void ED_node_tree_update(const bContext *C) static bNodeTree *node_tree_from_ID(ID *id) { if (id) { - short idtype = GS(id->name); - - switch (idtype) { - case ID_NT: - return (bNodeTree *)id; - case ID_MA: - return ((Material *)id)->nodetree; - case ID_LA: - return ((Light *)id)->nodetree; - case ID_WO: - return ((World *)id)->nodetree; - case ID_SCE: - return ((Scene *)id)->nodetree; - case ID_TE: - return ((Tex *)id)->nodetree; - case ID_LS: - return ((FreestyleLineStyle *)id)->nodetree; + if (GS(id->name) == ID_NT) { + return (bNodeTree *)id; + } + else { + return ntreeFromID(id); } } @@ -719,39 +707,19 @@ static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) #define MARKER_SHAPE_CIRCLE 0x2 #define MARKER_SHAPE_INNER_DOT 0x10 -static void node_socket_draw(const bContext *C, - bNodeTree *ntree, - PointerRNA node_ptr, - bNodeSocket *sock, +static void node_socket_draw(const bNodeSocket *sock, + const float color[4], + const float color_outline[4], + float size, + int locx, + int locy, uint pos_id, uint col_id, uint shape_id, uint size_id, - uint outline_col_id, - float size, - bool selected) + uint outline_col_id) { - PointerRNA ptr; - float color[4]; - float outline_color[4]; - uint flags = 0; - - RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); - sock->typeinfo->draw_color((bContext *)C, &ptr, &node_ptr, color); - - bNode *node = node_ptr.data; - if (node->flag & NODE_MUTED) { - color[3] *= 0.25f; - } - - if (selected) { - UI_GetThemeColor4fv(TH_TEXT_HI, outline_color); - outline_color[3] = 0.9f; - } - else { - copy_v4_fl(outline_color, 0.0f); - outline_color[3] = 0.6f; - } + int flags; /* sets shape flags */ switch (sock->display_shape) { @@ -780,8 +748,120 @@ static void node_socket_draw(const bContext *C, immAttr4fv(col_id, color); immAttr1u(shape_id, flags); immAttr1f(size_id, size); - immAttr4fv(outline_col_id, outline_color); - immVertex2f(pos_id, sock->locx, sock->locy); + immAttr4fv(outline_col_id, color_outline); + immVertex2f(pos_id, locx, locy); +} + +static void node_socket_outline_color_get(bool selected, float r_outline_color[4]) +{ + if (selected) { + UI_GetThemeColor4fv(TH_TEXT_HI, r_outline_color); + r_outline_color[3] = 0.9f; + } + else { + copy_v4_fl(r_outline_color, 0.0f); + r_outline_color[3] = 0.6f; + } +} + +/* Usual convention here would be node_socket_get_color(), but that's already used (for setting a + * color property socket). */ +void node_socket_color_get( + bContext *C, bNodeTree *ntree, PointerRNA *node_ptr, bNodeSocket *sock, float r_color[4]) +{ + PointerRNA ptr; + + BLI_assert(RNA_struct_is_a(node_ptr->type, &RNA_Node)); + RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); + + sock->typeinfo->draw_color(C, &ptr, node_ptr, r_color); + + bNode *node = node_ptr->data; + if (node->flag & NODE_MUTED) { + r_color[3] *= 0.25f; + } +} + +static void node_socket_draw_nested(const bContext *C, + bNodeTree *ntree, + PointerRNA *node_ptr, + bNodeSocket *sock, + uint pos_id, + uint col_id, + uint shape_id, + uint size_id, + uint outline_col_id, + float size, + bool selected) +{ + float color[4]; + float outline_color[4]; + + node_socket_color_get((bContext *)C, ntree, node_ptr, sock, color); + node_socket_outline_color_get(selected, outline_color); + + node_socket_draw(sock, + color, + outline_color, + size, + sock->locx, + sock->locy, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id); +} + +/** + * Draw a single node socket at default size. + * \note this is only called from external code, internally #node_socket_draw_nested() is used for + * optimized drawing of multiple/all sockets of a node. + */ +void ED_node_socket_draw(bNodeSocket *sock, const rcti *rect, const float color[4], float scale) +{ + const float size = 2.25f * NODE_SOCKSIZE * scale; + rcti draw_rect = *rect; + float outline_color[4] = {0}; + + node_socket_outline_color_get(sock->flag & SELECT, outline_color); + + BLI_rcti_resize(&draw_rect, size, size); + + GPUVertFormat *format = immVertexFormat(); + uint pos_id = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint col_id = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + uint shape_id = GPU_vertformat_attr_add(format, "flags", GPU_COMP_U32, 1, GPU_FETCH_INT); + uint size_id = GPU_vertformat_attr_add(format, "size", GPU_COMP_F32, 1, GPU_FETCH_FLOAT); + uint outline_col_id = GPU_vertformat_attr_add( + format, "outlineColor", GPU_COMP_F32, 4, GPU_FETCH_FLOAT); + + gpuPushAttr(GPU_BLEND_BIT); + GPU_blend(true); + GPU_program_point_size(true); + + immBindBuiltinProgram(GPU_SHADER_KEYFRAME_DIAMOND); + immUniform1f("outline_scale", 0.7f); + immUniform2f("ViewportSize", -1.0f, -1.0f); + + /* Single point */ + immBegin(GPU_PRIM_POINTS, 1); + node_socket_draw(sock, + color, + outline_color, + BLI_rcti_size_y(&draw_rect), + BLI_rcti_cent_x(&draw_rect), + BLI_rcti_cent_y(&draw_rect), + pos_id, + col_id, + shape_id, + size_id, + outline_col_id); + immEnd(); + + immUnbindProgram(); + GPU_program_point_size(false); + gpuPopAttr(); } /* ************** Socket callbacks *********** */ @@ -974,17 +1054,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } /* socket outputs */ @@ -999,17 +1079,17 @@ void node_draw_sockets(View2D *v2d, continue; } - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); } } @@ -1032,17 +1112,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_input_len == 0) { break; /* stop as soon as last one is drawn */ } @@ -1057,17 +1137,17 @@ void node_draw_sockets(View2D *v2d, continue; } if (select_all || (sock->flag & SELECT)) { - node_socket_draw(C, - ntree, - node_ptr, - sock, - pos_id, - col_id, - shape_id, - size_id, - outline_col_id, - scale, - selected); + node_socket_draw_nested(C, + ntree, + &node_ptr, + sock, + pos_id, + col_id, + shape_id, + size_id, + outline_col_id, + scale, + selected); if (--selected_output_len == 0) { break; /* stop as soon as last one is drawn */ } diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index a82acfc4dbe..bd5ce135f82 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -69,6 +69,7 @@ #include "NOD_composite.h" #include "NOD_shader.h" +#include "NOD_simulation.h" #include "NOD_texture.h" #include "node_intern.h" /* own include */ @@ -438,6 +439,11 @@ bool ED_node_is_texture(struct SpaceNode *snode) return STREQ(snode->tree_idname, ntreeType_Texture->idname); } +bool ED_node_is_simulation(struct SpaceNode *snode) +{ + return STREQ(snode->tree_idname, ntreeType_Simulation->idname); +} + /* assumes nothing being done in ntree yet, sets the default in/out node */ /* called from shading buttons or header */ void ED_node_shader_default(const bContext *C, ID *id) diff --git a/source/blender/editors/space_node/node_group.c b/source/blender/editors/space_node/node_group.c index 3a0ef45a68d..2617384d046 100644 --- a/source/blender/editors/space_node/node_group.c +++ b/source/blender/editors/space_node/node_group.c @@ -69,7 +69,8 @@ static bool node_group_operator_active(bContext *C) */ if (STREQ(snode->tree_idname, "ShaderNodeTree") || STREQ(snode->tree_idname, "CompositorNodeTree") || - STREQ(snode->tree_idname, "TextureNodeTree")) { + STREQ(snode->tree_idname, "TextureNodeTree") || + STREQ(snode->tree_idname, "SimulationNodeTree")) { return true; } } @@ -85,7 +86,8 @@ static bool node_group_operator_editable(bContext *C) * Disabled otherwise to allow pynodes define their own operators * with same keymap. */ - if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode)) { + if (ED_node_is_shader(snode) || ED_node_is_compositor(snode) || ED_node_is_texture(snode) || + ED_node_is_simulation(snode)) { return true; } } @@ -111,6 +113,9 @@ static const char *group_node_idname(bContext *C) else if (ED_node_is_texture(snode)) { return "TextureNodeGroup"; } + else if (ED_node_is_simulation(snode)) { + return "SimulationNodeGroup"; + } return ""; } diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 42439e88c96..04186c3a727 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -38,6 +38,7 @@ struct bContext; struct bNode; struct bNodeLink; struct bNodeSocket; +struct wmGizmoGroupType; struct wmKeyConfig; struct wmWindow; @@ -77,6 +78,11 @@ void node_draw_sockets(struct View2D *v2d, void node_update_default(const struct bContext *C, struct bNodeTree *ntree, struct bNode *node); int node_select_area_default(struct bNode *node, int x, int y); int node_tweak_area_default(struct bNode *node, int x, int y); +void node_socket_color_get(struct bContext *C, + struct bNodeTree *ntree, + struct PointerRNA *node_ptr, + struct bNodeSocket *sock, + float r_color[4]); void node_update_nodetree(const struct bContext *C, struct bNodeTree *ntree); void node_draw_nodetree(const struct bContext *C, struct ARegion *region, @@ -122,7 +128,7 @@ void NODE_OT_find_node(struct wmOperatorType *ot); /* node_view.c */ int space_node_view_flag(struct bContext *C, - SpaceNode *snode, + struct SpaceNode *snode, ARegion *region, const int node_flag, const int smooth_viewtx); @@ -196,7 +202,7 @@ void NODE_OT_detach(struct wmOperatorType *ot); void NODE_OT_link_viewer(struct wmOperatorType *ot); -void NODE_OT_insert_offset(wmOperatorType *ot); +void NODE_OT_insert_offset(struct wmOperatorType *ot); /* node_edit.c */ void snode_notify(struct bContext *C, struct SpaceNode *snode); @@ -207,8 +213,8 @@ void snode_update(struct SpaceNode *snode, struct bNode *node); bool composite_node_active(struct bContext *C); bool 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_has_hidden_sockets(struct bNode *node); +void node_set_hidden_sockets(struct 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, diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 8c2f79109f6..144e3bd3506 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -1657,7 +1657,7 @@ static bool node_link_insert_offset_frame_chain_cb(bNode *fromnode, } /** - * Applies NodeInsertOfsData.offset_x to all childs of \a parent + * Applies #NodeInsertOfsData.offset_x to all children of \a parent. */ static void node_link_insert_offset_frame_chains(const bNodeTree *ntree, const bNode *parent, diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index e96d03f70f4..9eabcc44d80 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -769,7 +769,10 @@ static int node_lasso_select_invoke(bContext *C, wmOperator *op, const wmEvent * return WM_gesture_lasso_invoke(C, op, event); } -static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves, eSelectOp sel_op) +static bool do_lasso_select_node(bContext *C, + const int mcoords[][2], + const int mcoords_len, + eSelectOp sel_op) { SpaceNode *snode = CTX_wm_space_node(C); bNode *node; @@ -786,7 +789,7 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves } /* get rectangle from operator */ - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* do actual selection */ for (node = snode->edittree->nodes.first; node; node = node->next) { @@ -802,7 +805,7 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves if (UI_view2d_view_to_region_clip( ®ion->v2d, cent[0], cent[1], &screen_co[0], &screen_co[1]) && BLI_rcti_isect_pt(&rect, screen_co[0], screen_co[1]) && - BLI_lasso_is_point_inside(mcords, moves, screen_co[0], screen_co[1], INT_MAX)) { + BLI_lasso_is_point_inside(mcoords, mcoords_len, screen_co[0], screen_co[1], INT_MAX)) { nodeSetSelected(node, select); changed = true; } @@ -817,15 +820,15 @@ static bool do_lasso_select_node(bContext *C, const int mcords[][2], short moves static int node_lasso_select_exec(bContext *C, wmOperator *op) { - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - do_lasso_select_node(C, mcords, mcords_tot, sel_op); + do_lasso_select_node(C, mcoords, mcoords_len, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); return OPERATOR_FINISHED; } @@ -1116,10 +1119,10 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot) * \{ */ /* generic search invoke */ -static void node_find_cb(const struct bContext *C, - void *UNUSED(arg), - const char *str, - uiSearchItems *items) +static void node_find_update_fn(const struct bContext *C, + void *UNUSED(arg), + const char *str, + uiSearchItems *items) { SpaceNode *snode = CTX_wm_space_node(C); bNode *node; @@ -1142,7 +1145,7 @@ static void node_find_cb(const struct bContext *C, } } -static void node_find_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2) +static void node_find_exec_fn(struct bContext *C, void *UNUSED(arg1), void *arg2) { SpaceNode *snode = CTX_wm_space_node(C); bNode *active = arg2; @@ -1182,7 +1185,7 @@ static uiBlock *node_find_menu(bContext *C, ARegion *region, void *arg_op) 0, 0, ""); - UI_but_func_search_set(but, NULL, node_find_cb, op->type, NULL, node_find_call_cb, NULL, NULL); + UI_but_func_search_set(but, NULL, node_find_update_fn, op->type, NULL, node_find_exec_fn, NULL); UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); /* fake button, it holds space for search items */ diff --git a/source/blender/editors/space_node/node_templates.c b/source/blender/editors/space_node/node_templates.c index 7d4095326f8..87b1f662b59 100644 --- a/source/blender/editors/space_node/node_templates.c +++ b/source/blender/editors/space_node/node_templates.c @@ -45,6 +45,7 @@ #include "UI_interface.h" #include "ED_node.h" /* own include */ +#include "node_intern.h" #include "ED_undo.h" @@ -662,17 +663,23 @@ static void ui_template_node_link_menu(bContext *C, uiLayout *layout, void *but_ ui_node_menu_column(arg, NODE_CLASS_GROUP, N_("Group")); } -void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSocket *sock) +void uiTemplateNodeLink( + uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, bNodeSocket *sock) { uiBlock *block = uiLayoutGetBlock(layout); NodeLinkArg *arg; uiBut *but; + float socket_col[4]; arg = MEM_callocN(sizeof(NodeLinkArg), "NodeLinkArg"); arg->ntree = ntree; arg->node = node; arg->sock = sock; + PointerRNA node_ptr; + RNA_pointer_create((ID *)ntree, &RNA_Node, node, &node_ptr); + node_socket_color_get(C, ntree, &node_ptr, sock, socket_col); + UI_block_layout_set_current(block, layout); if (sock->link || sock->type == SOCK_SHADER || (sock->flag & SOCK_HIDE_VALUE)) { @@ -687,8 +694,9 @@ void uiTemplateNodeLink(uiLayout *layout, bNodeTree *ntree, bNode *node, bNodeSo } UI_but_type_set_menu_from_pulldown(but); + UI_but_node_link_set(but, sock, socket_col); + UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); - but->flag |= UI_BUT_NODE_LINK; but->poin = (char *)but; but->func_argN = arg; @@ -708,18 +716,14 @@ static void ui_node_draw_node( uiLayout *layout, bContext *C, bNodeTree *ntree, bNode *node, int depth) { bNodeSocket *input; - uiLayout *col, *split; PointerRNA nodeptr; RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); if (node->typeinfo->draw_buttons) { if (node->type != NODE_GROUP) { - split = uiLayoutSplit(layout, 0.5f, false); - col = uiLayoutColumn(split, false); - col = uiLayoutColumn(split, false); - - node->typeinfo->draw_buttons(col, C, &nodeptr); + uiLayoutSetPropSep(layout, true); + node->typeinfo->draw_buttons(layout, C, &nodeptr); } } @@ -733,12 +737,9 @@ static void ui_node_draw_input( { PointerRNA inputptr, nodeptr; uiBlock *block = uiLayoutGetBlock(layout); - uiBut *bt; - uiLayout *split, *row, *col; + uiLayout *row = NULL; bNode *lnode; - char label[UI_MAX_NAME_STR]; - int i, indent = (depth > 1) ? 2 * (depth - 1) : 0; - int dependency_loop; + bool dependency_loop; if (input->flag & SOCK_UNAVAIL) { return; @@ -757,48 +758,43 @@ static void ui_node_draw_input( RNA_pointer_create(&ntree->id, &RNA_NodeSocket, input, &inputptr); RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr); - /* indented label */ - for (i = 0; i < indent; i++) { - label[i] = ' '; - } - label[indent] = '\0'; - BLI_snprintf(label + indent, UI_MAX_NAME_STR - indent, "%s", IFACE_(input->name)); + row = uiLayoutRow(layout, true); + /* Decorations are added manually here. */ + uiLayoutSetPropDecorate(row, false); - /* split in label and value */ - split = uiLayoutSplit(layout, 0.5f, false); + uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(row); + /* Empty decorator item for alignment. */ + bool add_dummy_decorator = false; - row = uiLayoutRow(split, true); + { + uiLayout *sub = uiLayoutRow(split_wrapper.label_column, true); - if (depth > 0) { - UI_block_emboss_set(block, UI_EMBOSS_NONE); + if (depth > 0) { + UI_block_emboss_set(block, UI_EMBOSS_NONE); - if (lnode && - (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) { - int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : - ICON_DISCLOSURE_TRI_DOWN; - uiItemR(row, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); - } - else { - uiItemL(row, "", ICON_BLANK1); - } + if (lnode && + (lnode->inputs.first || (lnode->typeinfo->draw_buttons && lnode->type != NODE_GROUP))) { + int icon = (input->flag & SOCK_COLLAPSED) ? ICON_DISCLOSURE_TRI_RIGHT : + ICON_DISCLOSURE_TRI_DOWN; + uiItemR(sub, &inputptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", icon); + } - bt = block->buttons.last; - bt->rect.xmax = UI_UNIT_X / 2; + UI_block_emboss_set(block, UI_EMBOSS); + } - UI_block_emboss_set(block, UI_EMBOSS); + sub = uiLayoutRow(sub, true); + uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_RIGHT); + uiItemL(sub, IFACE_(input->name), ICON_NONE); } - uiItemL(row, label, ICON_NONE); - bt = block->buttons.last; - bt->drawflag = UI_BUT_TEXT_RIGHT; - if (dependency_loop) { - row = uiLayoutRow(split, false); uiItemL(row, IFACE_("Dependency Loop"), ICON_ERROR); + add_dummy_decorator = true; } else if (lnode) { /* input linked to a node */ - uiTemplateNodeLink(split, ntree, node, input); + uiTemplateNodeLink(row, C, ntree, node, input); + add_dummy_decorator = true; if (depth == 0 || !(input->flag & SOCK_COLLAPSED)) { if (depth == 0) { @@ -809,33 +805,41 @@ static void ui_node_draw_input( } } else { + row = uiLayoutRow(row, true); + + uiTemplateNodeLink(row, C, ntree, node, input); + + if (input->flag & SOCK_HIDE_VALUE) { + add_dummy_decorator = true; + } /* input not linked, show value */ - if (!(input->flag & SOCK_HIDE_VALUE)) { + else { + uiLayout *sub = row; + switch (input->type) { + case SOCK_VECTOR: + if (input->type == SOCK_VECTOR) { + uiItemS(row); + sub = uiLayoutColumn(row, true); + } + ATTR_FALLTHROUGH; case SOCK_FLOAT: case SOCK_INT: case SOCK_BOOLEAN: case SOCK_RGBA: case SOCK_STRING: - row = uiLayoutRow(split, true); - uiItemR(row, &inputptr, "default_value", 0, "", ICON_NONE); - break; - case SOCK_VECTOR: - row = uiLayoutRow(split, false); - col = uiLayoutColumn(row, false); - uiItemR(col, &inputptr, "default_value", 0, "", ICON_NONE); + uiItemR(sub, &inputptr, "default_value", 0, "", ICON_NONE); + uiItemDecoratorR( + split_wrapper.decorate_column, &inputptr, "default_value", RNA_NO_INDEX); break; - default: - row = uiLayoutRow(split, false); - break; + add_dummy_decorator = true; } } - else { - row = uiLayoutRow(split, false); - } + } - uiTemplateNodeLink(row, ntree, node, input); + if (add_dummy_decorator) { + uiItemDecoratorR(split_wrapper.decorate_column, NULL, NULL, 0); } /* clear */ diff --git a/source/blender/editors/space_node/node_view.c b/source/blender/editors/space_node/node_view.c index 5bdca04856b..740d090e641 100644 --- a/source/blender/editors/space_node/node_view.c +++ b/source/blender/editors/space_node/node_view.c @@ -141,7 +141,7 @@ static int node_view_all_exec(bContext *C, wmOperator *op) void NODE_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "NODE_OT_view_all"; ot->description = "Resize view so you can see all nodes"; diff --git a/source/blender/editors/space_node/space_node.c b/source/blender/editors/space_node/space_node.c index 9df04c097bb..f339d11b842 100644 --- a/source/blender/editors/space_node/space_node.c +++ b/source/blender/editors/space_node/space_node.c @@ -936,6 +936,11 @@ static void node_space_subtype_item_extend(bContext *C, EnumPropertyItem **item, bool free; const EnumPropertyItem *item_src = RNA_enum_node_tree_types_itemf_impl(C, &free); for (const EnumPropertyItem *item_iter = item_src; item_iter->identifier; item_iter++) { +#ifndef WITH_NEW_SIMULATION_TYPE + if (STREQ(item_iter->identifier, "SimulationNodeTree")) { + continue; + } +#endif RNA_enum_item_add(item, totitem, item_iter); } if (free) { diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c index c77ee67b859..82ff9e06194 100644 --- a/source/blender/editors/space_outliner/outliner_collections.c +++ b/source/blender/editors/space_outliner/outliner_collections.c @@ -300,19 +300,15 @@ static TreeTraversalAction collection_find_data_to_edit(TreeElement *te, void *c return TRAVERSE_CONTINUE; } -static int collection_delete_exec(bContext *C, wmOperator *op) +void outliner_collection_delete( + bContext *C, Main *bmain, Scene *scene, ReportList *reports, bool hierarchy) { - struct wmMsgBus *mbus = CTX_wm_message_bus(C); - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *basact_prev = BASACT(view_layer); SpaceOutliner *soops = CTX_wm_space_outliner(C); + struct CollectionEditData data = { .scene = scene, .soops = soops, }; - bool hierarchy = RNA_boolean_get(op->ptr, "hierarchy"); data.collections_to_edit = BLI_gset_ptr_new(__func__); @@ -358,7 +354,7 @@ static int collection_delete_exec(bContext *C, wmOperator *op) } else { BKE_reportf( - op->reports, + reports, RPT_WARNING, "Cannot delete linked collection '%s', it is used by other linked scenes/collections", collection->id.name + 2); @@ -367,6 +363,17 @@ static int collection_delete_exec(bContext *C, wmOperator *op) } BLI_gset_free(data.collections_to_edit, NULL); +} + +static int collection_hierarchy_delete_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + const Base *basact_prev = BASACT(view_layer); + + outliner_collection_delete(C, bmain, scene, op->reports, true); DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); DEG_relations_tag_update(bmain); @@ -382,24 +389,19 @@ static int collection_delete_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -void OUTLINER_OT_collection_delete(wmOperatorType *ot) +void OUTLINER_OT_collection_hierarchy_delete(wmOperatorType *ot) { /* identifiers */ - ot->name = "Delete Collection"; - ot->idname = "OUTLINER_OT_collection_delete"; - ot->description = "Delete selected collections"; + ot->name = "Delete Hierarchy"; + ot->idname = "OUTLINER_OT_collection_hierarchy_delete"; + ot->description = "Delete selected collection hierarchies"; /* api callbacks */ - ot->exec = collection_delete_exec; + ot->exec = collection_hierarchy_delete_exec; ot->poll = ED_outliner_collections_editor_poll; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* properties */ - PropertyRNA *prop = RNA_def_boolean( - ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /** \} */ diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index ce83cfc3c97..13cbda5aad7 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -2191,6 +2191,9 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case eModifierType_WeightedNormal: data.icon = ICON_MOD_NORMALEDIT; break; + case eModifierType_Simulation: + data.icon = ICON_PHYSICS; /* TODO: Use correct icon. */ + break; /* Default */ case eModifierType_None: case eModifierType_ShapeKey: @@ -2581,6 +2584,10 @@ TreeElementIcon tree_element_get_icon(TreeStoreElem *tselem, TreeElement *te) case ID_PC: data.icon = ICON_CURVE_BEZCURVE; break; + case ID_SIM: + /* TODO: Use correct icon. */ + data.icon = ICON_PHYSICS; + break; default: break; } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 469a0065e3a..8b4e38a77fd 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -83,9 +83,11 @@ #include "outliner_intern.h" -/* ************************************************************** */ +/** \} */ -/* Highlight --------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Highlight on Cursor Motion Operator + * \{ */ static int outliner_highlight_update(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) { @@ -140,7 +142,11 @@ void OUTLINER_OT_highlight_update(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* Toggle Open/Closed ------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Open/Closed Operator + * \{ */ /* Open or close a tree element, optionally toggling all children recursively */ void outliner_item_openclose(TreeElement *te, bool open, bool toggle_all) @@ -262,8 +268,10 @@ void OUTLINER_OT_item_openclose(wmOperatorType *ot) RNA_def_boolean(ot->srna, "all", false, "All", "Close or open all items"); } +/** \} */ + /* -------------------------------------------------------------------- */ -/** \name Object Mode Enter/Exit +/** \name Object Mode Enter/Exit Utilities * \{ */ static void item_object_mode_enter_exit(bContext *C, ReportList *reports, Object *ob, bool enter) @@ -317,7 +325,9 @@ void item_object_mode_exit_cb(bContext *C, /** \} */ -/* Rename --------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Rename Operator + * \{ */ static void do_item_rename(ARegion *region, TreeElement *te, @@ -449,7 +459,11 @@ void OUTLINER_OT_item_rename(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* ID delete --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Delete Operator + * \{ */ static void id_delete(bContext *C, ReportList *reports, TreeElement *te, TreeStoreElem *tselem) { @@ -563,7 +577,11 @@ void OUTLINER_OT_id_delete(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* ID remap --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Remap Operator + * \{ */ static int outliner_id_remap_exec(bContext *C, wmOperator *op) { @@ -736,7 +754,11 @@ void id_remap_cb(bContext *C, WM_operator_properties_free(&op_props); } -/* ID copy/Paste ------------------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Copy Operator + * \{ */ static int outliner_id_copy_tag(SpaceOutliner *soops, ListBase *tree) { @@ -801,6 +823,12 @@ void OUTLINER_OT_id_copy(wmOperatorType *ot) ot->flag = 0; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID Paste Operator + * \{ */ + static int outliner_id_paste_exec(bContext *C, wmOperator *op) { char str[FILE_MAX]; @@ -835,7 +863,11 @@ void OUTLINER_OT_id_paste(wmOperatorType *ot) ot->flag = 0; } -/* Library relocate/reload --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Library Relocate Operator + * \{ */ static int lib_relocate( bContext *C, TreeElement *te, TreeStoreElem *tselem, wmOperatorType *ot, const bool reload) @@ -979,6 +1011,12 @@ static int outliner_lib_reload_invoke(bContext *C, wmOperator *op, const wmEvent return OPERATOR_CANCELLED; } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Library Reload Operator + * \{ */ + void OUTLINER_OT_lib_reload(wmOperatorType *ot) { ot->name = "Reload Library"; @@ -1002,13 +1040,11 @@ void lib_reload_cb(bContext *C, lib_relocate(C, te, tselem, ot, true); } -/* ************************************************************** */ -/* Setting Toggling Operators */ - -/* =============================================== */ -/* Toggling Utilities (Exported) */ +/** \} */ -/* Apply Settings ------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Apply Settings Utilities + * \{ */ static int outliner_count_levels(ListBase *lb, const int curlevel) { @@ -1090,7 +1126,11 @@ bool outliner_flag_flip(ListBase *lb, short flag) return changed; } -/* Restriction Columns ------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Restriction Column Utility + * \{ */ /* same check needed for both object operation and restrict column button func * return 0 when in edit mode (cannot restrict view or select) @@ -1116,10 +1156,11 @@ int common_restrict_check(bContext *C, Object *ob) return 1; } -/* =============================================== */ -/* Outliner setting toggles */ +/** \} */ -/* Toggle Expanded (Outliner) ---------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name Toggle Expanded (Outliner) Operator + * \{ */ static int outliner_toggle_expanded_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -1152,7 +1193,11 @@ void OUTLINER_OT_expanded_toggle(wmOperatorType *ot) /* no undo or registry, UI option */ } -/* Toggle Selected (Outliner) ---------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Toggle Selected (Outliner) Operator + * \{ */ static int outliner_select_all_exec(bContext *C, wmOperator *op) { @@ -1202,10 +1247,11 @@ void OUTLINER_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } -/* ************************************************************** */ -/* Hotkey Only Operators */ +/** \} */ -/* Show Active --------------------------------------------------- */ +/* -------------------------------------------------------------------- */ +/** \name View Show Active (Outliner) Operator + * \{ */ static void outliner_set_coordinates_element_recursive(SpaceOutliner *soops, TreeElement *te, @@ -1355,7 +1401,11 @@ void OUTLINER_OT_show_active(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* View Panning --------------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name View Panning (Outliner) Operator + * \{ */ static int outliner_scroll_page_exec(bContext *C, wmOperator *op) { @@ -1393,10 +1443,14 @@ void OUTLINER_OT_scroll_page(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* Search ------------------------------------------------------- */ -// TODO: probably obsolete now with filtering? +/** \} */ + +#if 0 // TODO: probably obsolete now with filtering? + +/* -------------------------------------------------------------------- */ +/** \name Search + * \{ */ -#if 0 /* find next element that has this name */ static TreeElement *outliner_find_name( @@ -1509,9 +1563,14 @@ static void outliner_find_panel( BKE_reportf(reports, RPT_WARNING, "Not found: %s", name); } } -#endif -/* Show One Level ----------------------------------------------- */ +/** \} */ + +#endif /* if 0 */ + +/* -------------------------------------------------------------------- */ +/** \name Show One Level Operator + * \{ */ /* helper function for Show/Hide one level operator */ static void outliner_openclose_level(ListBase *lb, int curlevel, int level, int open) @@ -1584,7 +1643,11 @@ void OUTLINER_OT_show_one_level(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_SKIP_SAVE); } -/* Show Hierarchy ----------------------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Show Hierarchy Operator + * \{ */ /* Helper function for tree_element_shwo_hierarchy() - * recursively checks whether subtrees have any objects. */ @@ -1676,11 +1739,15 @@ void OUTLINER_OT_show_hierarchy(wmOperatorType *ot) /* no undo or registry, UI option */ } -/* ************************************************************** */ -/* ANIMATO OPERATIONS */ -/* KeyingSet and Driver Creation - Helper functions */ +/** \} */ -/* specialized poll callback for these operators to work in Datablocks view only */ +/* -------------------------------------------------------------------- */ +/** \name Animation Internal Utilities + * \{ */ + +/** + * Specialized poll callback for these operators to work in data-blocks view only. + */ static bool ed_operator_outliner_datablocks_active(bContext *C) { ScrArea *area = CTX_wm_area(C); @@ -1842,19 +1909,23 @@ static void tree_element_to_path(TreeElement *te, BLI_freelistN(&hierarchy); } -/* =============================================== */ -/* Driver Operations */ +/** \} */ -/* These operators are only available in databrowser mode for now, as - * they depend on having RNA paths and/or hierarchies available. +/* -------------------------------------------------------------------- */ +/** \name Driver Internal Utilities + * \{ */ + +/** + * Driver Operations + * + * These operators are only available in data-browser mode for now, + * as they depend on having RNA paths and/or hierarchies available. */ enum { DRIVERS_EDITMODE_ADD = 0, DRIVERS_EDITMODE_REMOVE, } /*eDrivers_EditModes*/; -/* Utilities ---------------------------------- */ - /* Recursively iterate over tree, finding and working on selected items */ static void do_outliner_drivers_editop(SpaceOutliner *soops, ListBase *tree, @@ -1930,7 +2001,11 @@ static void do_outliner_drivers_editop(SpaceOutliner *soops, } } -/* Add Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Add Operator + * \{ */ static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op) { @@ -1965,7 +2040,11 @@ void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* Remove Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Driver Remove Operator + * \{ */ static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op) { @@ -2000,10 +2079,16 @@ void OUTLINER_OT_drivers_delete_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* =============================================== */ -/* Keying Set Operations */ +/** \} */ -/* These operators are only available in databrowser mode for now, as +/* -------------------------------------------------------------------- */ +/** \name Keying-Set Internal Utilities + * \{ */ + +/** + * Keying-Set Operations + * + * These operators are only available in data-browser mode for now, as * they depend on having RNA paths and/or hierarchies available. */ enum { @@ -2011,8 +2096,6 @@ enum { KEYINGSET_EDITMODE_REMOVE, } /*eKeyingSet_EditModes*/; -/* Utilities ---------------------------------- */ - /* find the 'active' KeyingSet, and add if not found (if adding is allowed) */ // TODO: should this be an API func? static KeyingSet *verify_active_keyingset(Scene *scene, short add) @@ -2104,7 +2187,11 @@ static void do_outliner_keyingset_editop(SpaceOutliner *soops, } } -/* Add Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keying-Set Add Operator + * \{ */ static int outliner_keyingset_additems_exec(bContext *C, wmOperator *op) { @@ -2145,7 +2232,11 @@ void OUTLINER_OT_keyingset_add_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* Remove Operator ---------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Keying-Set Remove Operator + * \{ */ static int outliner_keyingset_removeitems_exec(bContext *C, wmOperator *UNUSED(op)) { @@ -2182,8 +2273,11 @@ void OUTLINER_OT_keyingset_remove_selected(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ************************************************************** */ -/* ORPHANED DATABLOCKS */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Purge Orphan Data-Blocks Operator + * \{ */ static bool ed_operator_outliner_id_orphans_active(bContext *C) { @@ -2195,7 +2289,7 @@ static bool ed_operator_outliner_id_orphans_active(bContext *C) return true; } -/* Purge Orphans Operator --------------------------------------- */ +/** \} */ static void outliner_orphans_purge_tag(ID *id, int *num_tagged) { @@ -2313,3 +2407,5 @@ void OUTLINER_OT_orphans_purge(wmOperatorType *ot) PropertyRNA *prop = RNA_def_int(ot->srna, "num_deleted", 0, 0, INT_MAX, "", "", 0, INT_MAX); RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN); } + +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index 90092817acc..f2b64bc2a4b 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -108,7 +108,8 @@ typedef struct TreeElementIcon { ID_LP, \ ID_HA, \ ID_PT, \ - ID_VO) || /* Only in 'blendfile' mode ... :/ */ \ + ID_VO, \ + ID_SIM) || /* Only in 'blendfile' mode ... :/ */ \ ELEM(GS((_id)->name), \ ID_SCR, \ ID_WM, \ @@ -430,6 +431,7 @@ void OUTLINER_OT_animdata_operation(struct wmOperatorType *ot); void OUTLINER_OT_action_set(struct wmOperatorType *ot); void OUTLINER_OT_constraint_operation(struct wmOperatorType *ot); void OUTLINER_OT_modifier_operation(struct wmOperatorType *ot); +void OUTLINER_OT_delete(struct wmOperatorType *ot); /* ---------------------------------------------------------------- */ @@ -441,11 +443,16 @@ void outliner_keymap(struct wmKeyConfig *keyconf); bool outliner_is_collection_tree_element(const TreeElement *te); struct Collection *outliner_collection_from_tree_element(const TreeElement *te); +void outliner_collection_delete(struct bContext *C, + struct Main *bmain, + struct Scene *scene, + struct ReportList *reports, + bool hierarchy); void OUTLINER_OT_collection_new(struct wmOperatorType *ot); void OUTLINER_OT_collection_duplicate_linked(struct wmOperatorType *ot); void OUTLINER_OT_collection_duplicate(struct wmOperatorType *ot); -void OUTLINER_OT_collection_delete(struct wmOperatorType *ot); +void OUTLINER_OT_collection_hierarchy_delete(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot); void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot); void OUTLINER_OT_collection_link(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c index 9d7efc7fe46..af7d97b6950 100644 --- a/source/blender/editors/space_outliner/outliner_ops.c +++ b/source/blender/editors/space_outliner/outliner_ops.c @@ -66,6 +66,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_action_set); WM_operatortype_append(OUTLINER_OT_constraint_operation); WM_operatortype_append(OUTLINER_OT_modifier_operation); + WM_operatortype_append(OUTLINER_OT_delete); WM_operatortype_append(OUTLINER_OT_show_one_level); WM_operatortype_append(OUTLINER_OT_show_active); @@ -93,7 +94,7 @@ void outliner_operatortypes(void) WM_operatortype_append(OUTLINER_OT_collection_new); WM_operatortype_append(OUTLINER_OT_collection_duplicate_linked); WM_operatortype_append(OUTLINER_OT_collection_duplicate); - WM_operatortype_append(OUTLINER_OT_collection_delete); + WM_operatortype_append(OUTLINER_OT_collection_hierarchy_delete); WM_operatortype_append(OUTLINER_OT_collection_objects_select); WM_operatortype_append(OUTLINER_OT_collection_objects_deselect); WM_operatortype_append(OUTLINER_OT_collection_link); diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index 1c9998d256b..0ccf982fd29 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -39,6 +39,7 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_volume_types.h" #include "DNA_world_types.h" @@ -88,9 +89,9 @@ #include "outliner_intern.h" -/* ****************************************************** */ - -/* ************ SELECTION OPERATIONS ********* */ +/* -------------------------------------------------------------------- */ +/** \name ID/Library/Data Set/Un-link Utilities + * \{ */ static void set_operation_types(SpaceOutliner *soops, ListBase *lb, @@ -160,6 +161,7 @@ static void set_operation_types(SpaceOutliner *soops, case ID_HA: case ID_PT: case ID_VO: + case ID_SIM: is_standard_id = true; break; case ID_WM: @@ -412,7 +414,12 @@ static void outliner_do_libdata_operation(bContext *C, } } -/* ******************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Scene Menu Operator + * \{ */ + typedef enum eOutliner_PropSceneOps { OL_SCENE_OP_DELETE = 1, } eOutliner_PropSceneOps; @@ -500,7 +507,12 @@ void OUTLINER_OT_scene_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_scene_op_types, 0, "Scene Operation", ""); } -/* ******************************************** */ + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Search Utilities + * \{ */ /** * Stores the parent and a child element of a merged icon-row icon for @@ -541,10 +553,10 @@ static void merged_element_search_cb_recursive( } /* Get a list of elements that match the search string */ -static void merged_element_search_cb(const bContext *UNUSED(C), - void *data, - const char *str, - uiSearchItems *items) +static void merged_element_search_update_fn(const bContext *UNUSED(C), + void *data, + const char *str, + uiSearchItems *items) { MergedSearchData *search_data = (MergedSearchData *)data; TreeElement *parent = search_data->parent_element; @@ -556,7 +568,7 @@ static void merged_element_search_cb(const bContext *UNUSED(C), } /* Activate an element from the merged element search menu */ -static void merged_element_search_call_cb(struct bContext *C, void *UNUSED(arg1), void *element) +static void merged_element_search_exec_fn(struct bContext *C, void *UNUSED(arg1), void *element) { SpaceOutliner *soops = CTX_wm_space_outliner(C); TreeElement *te = (TreeElement *)element; @@ -588,7 +600,7 @@ static uiBlock *merged_element_search_menu(bContext *C, ARegion *region, void *d but = uiDefSearchBut( block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, menu_width, UI_UNIT_Y, 0, 0, ""); UI_but_func_search_set( - but, NULL, merged_element_search_cb, data, NULL, merged_element_search_call_cb, NULL, NULL); + but, NULL, merged_element_search_update_fn, data, NULL, merged_element_search_exec_fn, NULL); UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT); /* Fake button to hold space for search items */ @@ -641,6 +653,12 @@ static void object_select_cb(bContext *C, } } +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Callbacks (Selection, Users & Library) Utilities + * \{ */ + static void object_select_hierarchy_cb(bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), @@ -671,13 +689,10 @@ static void object_deselect_cb(bContext *C, } } -static void object_delete_cb(bContext *C, - ReportList *reports, - Scene *scene, - TreeElement *UNUSED(te), - TreeStoreElem *UNUSED(tsep), - TreeStoreElem *tselem, - void *UNUSED(user_data)) +static void outliner_object_delete(bContext *C, + ReportList *reports, + Scene *scene, + TreeStoreElem *tselem) { Object *ob = (Object *)tselem->id; if (ob) { @@ -883,7 +898,11 @@ void outliner_do_object_operation(bContext *C, outliner_do_object_operation_ex(C, reports, scene_act, soops, lb, operation_cb, NULL, true); } -/* ******************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Internal Tagging Utilities + * \{ */ static void clear_animdata_cb(int UNUSED(event), TreeElement *UNUSED(te), @@ -935,7 +954,11 @@ static void refreshdrivers_animdata_cb(int UNUSED(event), } } -/* --------------------------------- */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Operation Utilities + * \{ */ typedef enum eOutliner_PropDataOps { OL_DOP_SELECT = 1, @@ -1308,13 +1331,16 @@ static void object_batch_delete_hierarchy_cb(bContext *C, } } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Object Menu Operator + * \{ */ enum { OL_OP_SELECT = 1, OL_OP_DESELECT, OL_OP_SELECT_HIERARCHY, - OL_OP_DELETE, OL_OP_DELETE_HIERARCHY, OL_OP_REMAP, OL_OP_LOCALIZED, /* disabled, see below */ @@ -1330,7 +1356,6 @@ static const EnumPropertyItem prop_object_op_types[] = { {OL_OP_SELECT, "SELECT", ICON_RESTRICT_SELECT_OFF, "Select", ""}, {OL_OP_DESELECT, "DESELECT", 0, "Deselect", ""}, {OL_OP_SELECT_HIERARCHY, "SELECT_HIERARCHY", 0, "Select Hierarchy", ""}, - {OL_OP_DELETE, "DELETE", ICON_X, "Delete", ""}, {OL_OP_DELETE_HIERARCHY, "DELETE_HIERARCHY", 0, "Delete Hierarchy", ""}, {OL_OP_REMAP, "REMAP", @@ -1386,29 +1411,6 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) str = "Deselect Objects"; selection_changed = true; } - else if (event == OL_OP_DELETE) { - ViewLayer *view_layer = CTX_data_view_layer(C); - const Base *basact_prev = BASACT(view_layer); - - outliner_do_object_operation(C, op->reports, scene, soops, &soops->tree, object_delete_cb); - - /* XXX: tree management normally happens from draw_outliner(), but when - * you're clicking to fast on Delete object from context menu in - * outliner several mouse events can be handled in one cycle without - * handling notifiers/redraw which leads to deleting the same object twice. - * cleanup tree here to prevent such cases. */ - outliner_cleanup_tree(soops); - - DEG_relations_tag_update(bmain); - str = "Delete Objects"; - DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); - if (basact_prev != BASACT(view_layer)) { - WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); - } - selection_changed = true; - } else if (event == OL_OP_DELETE_HIERARCHY) { ViewLayer *view_layer = CTX_data_view_layer(C); const Base *basact_prev = BASACT(view_layer); @@ -1433,7 +1435,7 @@ static int outliner_object_operation_exec(bContext *C, wmOperator *op) BKE_id_multi_tagged_delete(bmain); } - /* XXX: See OL_OP_DELETE comment above. */ + /* XXX: See outliner_delete_exec comment below. */ outliner_cleanup_tree(soops); DEG_relations_tag_update(bmain); @@ -1500,7 +1502,85 @@ void OUTLINER_OT_object_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_object_op_types, 0, "Object Operation", ""); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Delete Object/Collection Operator + * \{ */ + +static void outliner_objects_delete( + bContext *C, Scene *scene, SpaceOutliner *soops, ReportList *reports, ListBase *lb) +{ + LISTBASE_FOREACH (TreeElement *, te, lb) { + TreeStoreElem *tselem = TREESTORE(te); + + if (tselem->flag & TSE_SELECTED) { + if (tselem->type == 0 && te->idcode == ID_OB) { + outliner_object_delete(C, reports, scene, tselem); + } + } + + if (TSELEM_OPEN(tselem, soops)) { + outliner_objects_delete(C, scene, soops, reports, &te->subtree); + } + } +} + +static int outliner_delete_exec(bContext *C, wmOperator *op) +{ + Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); + SpaceOutliner *soops = CTX_wm_space_outliner(C); + struct wmMsgBus *mbus = CTX_wm_message_bus(C); + + ViewLayer *view_layer = CTX_data_view_layer(C); + const Base *basact_prev = BASACT(view_layer); + + outliner_collection_delete(C, bmain, scene, op->reports, false); + outliner_objects_delete(C, scene, soops, op->reports, &soops->tree); + + /* Tree management normally happens from draw_outliner(), but when + * you're clicking too fast on Delete object from context menu in + * outliner several mouse events can be handled in one cycle without + * handling notifiers/redraw which leads to deleting the same object twice. + * cleanup tree here to prevent such cases. */ + outliner_cleanup_tree(soops); + + DEG_id_tag_update(&scene->id, ID_RECALC_COPY_ON_WRITE); + DEG_relations_tag_update(bmain); + + if (basact_prev != BASACT(view_layer)) { + WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); + WM_msg_publish_rna_prop(mbus, &scene->id, view_layer, LayerObjects, active); + } + + DEG_id_tag_update(&scene->id, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene); + ED_outliner_select_sync_from_object_tag(C); + + return OPERATOR_FINISHED; +} + +void OUTLINER_OT_delete(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Delete"; + ot->idname = "OUTLINER_OT_delete"; + ot->description = "Delete selected objects and collections"; + + /* callbacks */ + ot->exec = outliner_delete_exec; + ot->poll = ED_operator_outliner_active; + + /* flags */ + ot->flag |= OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name ID-Data Menu Operator + * \{ */ typedef enum eOutlinerIdOpTypes { OUTLINER_IDOP_INVALID = 0, @@ -1800,7 +1880,11 @@ void OUTLINER_OT_id_operation(wmOperatorType *ot) RNA_def_enum_funcs(ot->prop, outliner_id_operation_itemf); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Library Menu Operator + * \{ */ typedef enum eOutlinerLibOpTypes { OL_LIB_INVALID = 0, @@ -1901,7 +1985,11 @@ void OUTLINER_OT_lib_operation(wmOperatorType *ot) ot->srna, "type", outliner_lib_op_type_items, 0, "Library Operation", ""); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Outliner Set Active Action Operator + * \{ */ static void outliner_do_id_set_operation( SpaceOutliner *soops, @@ -1927,8 +2015,6 @@ static void outliner_do_id_set_operation( } } -/* ------------------------------------------ */ - static void actionset_id_cb(TreeElement *UNUSED(te), TreeStoreElem *tselem, TreeStoreElem *tsep, @@ -2026,7 +2112,11 @@ void OUTLINER_OT_action_set(wmOperatorType *ot) ot->prop = prop; } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Animation Menu Operator + * \{ */ typedef enum eOutliner_AnimDataOps { OUTLINER_ANIMOP_INVALID = 0, @@ -2142,7 +2232,11 @@ void OUTLINER_OT_animdata_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_animdata_op_types, 0, "Animation Operation", ""); } -/* **************************************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Constraint Menu Operator + * \{ */ static const EnumPropertyItem prop_constraint_op_types[] = { {OL_CONSTRAINTOP_ENABLE, "ENABLE", ICON_HIDE_OFF, "Enable", ""}, @@ -2188,7 +2282,11 @@ void OUTLINER_OT_constraint_operation(wmOperatorType *ot) ot->srna, "type", prop_constraint_op_types, 0, "Constraint Operation", ""); } -/* ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Modifier Menu Operator + * \{ */ static const EnumPropertyItem prop_modifier_op_types[] = { {OL_MODIFIER_OP_TOGVIS, "TOGVIS", ICON_RESTRICT_VIEW_OFF, "Toggle viewport use", ""}, @@ -2233,7 +2331,11 @@ void OUTLINER_OT_modifier_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_modifier_op_types, 0, "Modifier Operation", ""); } -/* ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Data Menu Operator + * \{ */ // XXX: select linked is for RNA structs only static const EnumPropertyItem prop_data_op_types[] = { @@ -2326,7 +2428,11 @@ void OUTLINER_OT_data_operation(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_data_op_types, 0, "Data Operation", ""); } -/* ******************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Context Menu Operator + * \{ */ static int outliner_operator_menu(bContext *C, const char *opname) { @@ -2491,4 +2597,4 @@ void OUTLINER_OT_operation(wmOperatorType *ot) ot->poll = ED_operator_outliner_active; } -/* ****************************************************** */ +/** \} */ diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c index b226d291188..7bb62b0d1e2 100644 --- a/source/blender/editors/space_outliner/outliner_tree.c +++ b/source/blender/editors/space_outliner/outliner_tree.c @@ -46,6 +46,7 @@ #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_speaker_types.h" #include "DNA_volume_types.h" #include "DNA_world_types.h" @@ -58,7 +59,7 @@ #include "BLT_translation.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_idtype.h" #include "BKE_layer.h" #include "BKE_lib_id.h" @@ -773,6 +774,13 @@ static void outliner_add_id_contents(SpaceOutliner *soops, outliner_add_element(soops, &te->subtree, volume, te, TSE_ANIM_DATA, 0); break; } + case ID_SIM: { + Simulation *simulation = (Simulation *)id; + if (outliner_animdata_test(simulation->adt)) { + outliner_add_element(soops, &te->subtree, simulation, te, TSE_ANIM_DATA, 0); + } + break; + } default: break; } diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c index edbd52f4d53..d935f7dbb40 100644 --- a/source/blender/editors/space_sequencer/sequencer_edit.c +++ b/source/blender/editors/space_sequencer/sequencer_edit.c @@ -2930,7 +2930,7 @@ static int sequencer_view_all_exec(bContext *C, wmOperator *op) void SEQUENCER_OT_view_all(wmOperatorType *ot) { /* Identifiers. */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "SEQUENCER_OT_view_all"; ot->description = "View all the strips in the sequencer"; @@ -3017,7 +3017,7 @@ static int sequencer_view_all_preview_exec(bContext *C, wmOperator *UNUSED(op)) void SEQUENCER_OT_view_all_preview(wmOperatorType *ot) { /* Identifiers. */ - ot->name = "View All"; + ot->name = "Frame All"; ot->idname = "SEQUENCER_OT_view_all_preview"; ot->description = "Zoom preview to fit in the area"; diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index b06bc7ad8b7..243a6e193eb 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -447,7 +447,6 @@ static void draw_histogram_bar(ImBuf *ibuf, int x, float val, int col) typedef struct MakeHistogramViewData { const ImBuf *ibuf; - uint32_t (*bins)[HIS_STEPS]; } MakeHistogramViewData; static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata, @@ -469,17 +468,16 @@ static void make_histogram_view_from_ibuf_byte_fn(void *__restrict userdata, } } -static void make_histogram_view_from_ibuf_finalize(void *__restrict userdata, - void *__restrict userdata_chunk) +static void make_histogram_view_from_ibuf_reduce(const void *__restrict UNUSED(userdata), + void *__restrict chunk_join, + void *__restrict chunk) { - MakeHistogramViewData *data = userdata; - uint32_t(*bins)[HIS_STEPS] = data->bins; - - uint32_t(*cur_bins)[HIS_STEPS] = userdata_chunk; + uint32_t(*join_bins)[HIS_STEPS] = chunk_join; + uint32_t(*bins)[HIS_STEPS] = chunk; for (int j = 3; j--;) { for (int i = 0; i < HIS_STEPS; i++) { - bins[j][i] += cur_bins[j][i]; + join_bins[j][i] += bins[j][i]; } } } @@ -496,14 +494,13 @@ static ImBuf *make_histogram_view_from_ibuf_byte(ImBuf *ibuf) MakeHistogramViewData data = { .ibuf = ibuf, - .bins = bins, }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; settings.userdata_chunk_size = sizeof(bins); - settings.func_finalize = make_histogram_view_from_ibuf_finalize; + settings.func_reduce = make_histogram_view_from_ibuf_reduce; BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_byte_fn, &settings); nr = nb = ng = 0; @@ -582,14 +579,13 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) MakeHistogramViewData data = { .ibuf = ibuf, - .bins = bins, }; TaskParallelSettings settings; BLI_parallel_range_settings_defaults(&settings); settings.use_threading = (ibuf->y >= 256); settings.userdata_chunk = bins; settings.userdata_chunk_size = sizeof(bins); - settings.func_finalize = make_histogram_view_from_ibuf_finalize; + settings.func_reduce = make_histogram_view_from_ibuf_reduce; BLI_task_parallel_range(0, ibuf->y, &data, make_histogram_view_from_ibuf_float_fn, &settings); nr = nb = ng = 0; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index e58559f4f6b..fac378ae104 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -63,6 +63,7 @@ #include "ED_armature.h" #include "ED_gpencil.h" +#include "ED_info.h" #include "ED_keyframing.h" #include "ED_screen.h" #include "ED_screen_types.h" @@ -101,6 +102,8 @@ #define M_GOLDEN_RATIO_CONJUGATE 0.618033988749895f +#define VIEW3D_OVERLAY_LINEHEIGHT (0.9f * U.widget_unit) + /* -------------------------------------------------------------------- */ /** \name General Functions * \{ */ @@ -1341,7 +1344,7 @@ static void draw_viewport_name(ARegion *region, View3D *v3d, int xoffset, int *y UI_FontThemeColor(BLF_default(), TH_TEXT_HI); - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; BLF_draw_default(xoffset, *yoffset, 0.0f, name, sizeof(tmpstr)); @@ -1473,7 +1476,7 @@ static void draw_selected_name( BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; BLF_draw_default(xoffset, *yoffset, 0.0f, info, sizeof(info)); BLF_disable(font_id, BLF_SHADOW); @@ -1494,7 +1497,7 @@ static void draw_grid_unit_name( BLI_snprintf(numstr, sizeof(numstr), "%s x %.4g", grid_unit, v3d->grid); } - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; BLF_enable(font_id, BLF_SHADOW); BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); @@ -1515,6 +1518,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) View3D *v3d = CTX_wm_view3d(C); Scene *scene = CTX_data_scene(C); wmWindowManager *wm = CTX_wm_manager(C); + Main *bmain = CTX_data_main(C); + ViewLayer *view_layer = CTX_data_view_layer(C); #ifdef WITH_INPUT_NDOF if ((U.ndof_flag & NDOF_SHOW_GUIDE) && ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) && @@ -1550,8 +1555,8 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) } } - int xoffset = rect->xmin + U.widget_unit; - int yoffset = rect->ymax; + int xoffset = rect->xmin + (0.5f * U.widget_unit); + int yoffset = rect->ymax - (0.1f * U.widget_unit); if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_no_scrub(wm)) { @@ -1562,7 +1567,6 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) } if (U.uiflag & USER_DRAWVIEWINFO) { - ViewLayer *view_layer = CTX_data_view_layer(C); Object *ob = OBACT(view_layer); draw_selected_name(scene, view_layer, ob, xoffset, &yoffset); } @@ -1571,10 +1575,12 @@ void view3d_draw_region_info(const bContext *C, ARegion *region) /* draw below the viewport name */ draw_grid_unit_name(scene, rv3d, v3d, xoffset, &yoffset); } + + DRW_draw_region_engine_info(xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); } - if ((v3d->overlay.flag & V3D_OVERLAY_HIDE_TEXT) == 0) { - DRW_draw_region_engine_info(xoffset, yoffset); + if ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0 && (v3d->overlay.flag & V3D_OVERLAY_STATS)) { + ED_info_draw_stats(bmain, scene, view_layer, xoffset, &yoffset, VIEW3D_OVERLAY_LINEHEIGHT); } BLF_batch_draw_end(); @@ -2493,7 +2499,7 @@ void ED_scene_draw_fps(const Scene *scene, int xoffset, int *yoffset) BLF_shadow(font_id, 5, (const float[4]){0.0f, 0.0f, 0.0f, 1.0f}); BLF_shadow_offset(font_id, 1, -1); - *yoffset -= U.widget_unit; + *yoffset -= VIEW3D_OVERLAY_LINEHEIGHT; #ifdef WITH_INTERNATIONAL BLF_draw_default(xoffset, *yoffset, 0.0f, printable, sizeof(printable)); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 0a30336aed8..5cdf6ce28cb 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -2980,7 +2980,7 @@ static int view3d_all_exec(bContext *C, wmOperator *op) void VIEW3D_OT_view_all(wmOperatorType *ot) { /* identifiers */ - ot->name = "View All"; + ot->name = "Frame All"; ot->description = "View all objects in scene"; ot->idname = "VIEW3D_OT_view_all"; @@ -5372,6 +5372,7 @@ void VIEW3D_OT_toggle_xray(wmOperatorType *ot) /* identifiers */ ot->name = "Toggle X-Ray"; ot->idname = "VIEW3D_OT_toggle_xray"; + ot->description = "Transparent scene display. Allow selecting through items"; /* api callbacks */ ot->exec = toggle_xray_exec; diff --git a/source/blender/editors/space_view3d/view3d_iterators.c b/source/blender/editors/space_view3d/view3d_iterators.c index d8e1c8c1c72..08e68c9174e 100644 --- a/source/blender/editors/space_view3d/view3d_iterators.c +++ b/source/blender/editors/space_view3d/view3d_iterators.c @@ -388,7 +388,7 @@ void mesh_foreachScreenFace( BM_mesh_elem_table_ensure(vc->em->bm, BM_FACE); - if (modifiers_usesSubsurfFacedots(vc->scene, vc->obedit)) { + if (BKE_modifiers_uses_subsurf_facedots(vc->scene, vc->obedit)) { BKE_mesh_foreach_mapped_subdiv_face_center( me, mesh_foreachScreenFace__mapFunc, &data, MESH_FOREACH_NOP); } diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 67c61b4ecac..2ce2edb98fe 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -408,8 +408,8 @@ typedef struct LassoSelectUserData { const rcti *rect; const rctf *rect_fl; rctf _rect_fl; - const int (*mcords)[2]; - int moves; + const int (*mcoords)[2]; + int mcoords_len; eSelectOp sel_op; /* runtime */ @@ -421,8 +421,8 @@ typedef struct LassoSelectUserData { static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, ViewContext *vc, const rcti *rect, - const int (*mcords)[2], - const int moves, + const int (*mcoords)[2], + const int mcoords_len, const eSelectOp sel_op) { r_data->vc = vc; @@ -431,8 +431,8 @@ static void view3d_userdata_lassoselect_init(LassoSelectUserData *r_data, r_data->rect_fl = &r_data->_rect_fl; BLI_rctf_rcti_copy(&r_data->_rect_fl, rect); - r_data->mcords = mcords; - r_data->moves = moves; + r_data->mcoords = mcoords; + r_data->mcoords_len = mcoords_len; r_data->sel_op = sel_op; /* runtime */ @@ -527,7 +527,8 @@ static void do_lasso_select_pose__do_tag(void *userData, if (screen_co_a[0] != IS_CLIPPED) { points_proj_tot++; if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { is_point_done = true; } } @@ -536,22 +537,28 @@ static void do_lasso_select_pose__do_tag(void *userData, if (screen_co_b[0] != IS_CLIPPED) { points_proj_tot++; if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { is_point_done = true; } } /* if one of points selected, we skip the bone itself */ - if ((is_point_done == true) || - ((is_point_done == false) && (points_proj_tot == 2) && - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX))) { + if ((is_point_done == true) || ((is_point_done == false) && (points_proj_tot == 2) && + BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + INT_MAX))) { pchan->bone->flag |= BONE_DONE; } data->is_changed |= is_point_done; } } -static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2], short moves) +static void do_lasso_tag_pose(ViewContext *vc, + Object *ob, + const int mcoords[][2], + const int mcoords_len) { ViewContext vc_tmp; LassoSelectUserData data; @@ -564,9 +571,9 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2] vc_tmp = *vc; vc_tmp.obact = ob; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, 0); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, 0); ED_view3d_init_mats_rv3d(vc_tmp.obact, vc->rv3d); @@ -574,8 +581,8 @@ static void do_lasso_tag_pose(ViewContext *vc, Object *ob, const int mcords[][2] } static bool do_lasso_select_objects(ViewContext *vc, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { View3D *v3d = vc->v3d; @@ -591,7 +598,7 @@ static bool do_lasso_select_objects(ViewContext *vc, const bool is_select = base->flag & BASE_SELECTED; const bool is_inside = ((ED_view3d_project_base(vc->region, base) == V3D_PROJ_RET_OK) && BLI_lasso_is_point_inside( - mcords, moves, base->sx, base->sy, IS_CLIPPED)); + mcoords, mcoords_len, base->sx, base->sy, IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { ED_object_base_select(base, sel_op_result ? BA_SELECT : BA_DESELECT); @@ -685,8 +692,8 @@ static bool do_pose_tag_select_op_exec(Base **bases, const uint bases_len, const } static bool do_lasso_select_pose(ViewContext *vc, - const int mcords[][2], - const short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { uint bases_len; @@ -695,7 +702,7 @@ static bool do_lasso_select_pose(ViewContext *vc, for (int i = 0; i < bases_len; i++) { Base *base_iter = bases[i]; Object *ob_iter = base_iter->object; - do_lasso_tag_pose(vc, ob_iter, mcords, moves); + do_lasso_tag_pose(vc, ob_iter, mcoords, mcoords_len); } const bool changed_multi = do_pose_tag_select_op_exec(bases, bases_len, sel_op); @@ -715,9 +722,10 @@ static void do_lasso_select_mesh__doSelectVert(void *userData, { LassoSelectUserData *data = userData; const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT); - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_vert_select_set(data->vc->em->bm, eve, sel_op_result); @@ -746,8 +754,10 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data, const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); const bool is_inside = (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED)); + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), IS_CLIPPED) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_edge_select_set(data->vc->em->bm, eed, sel_op_result); @@ -770,8 +780,8 @@ static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data, } const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT); - const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords, - data->moves, + const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED)); @@ -789,9 +799,10 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, { LassoSelectUserData *data = userData; const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT); - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { BM_face_select_set(data->vc->em->bm, efa, sel_op_result); @@ -801,8 +812,8 @@ static void do_lasso_select_mesh__doSelectFace(void *userData, static bool do_lasso_select_mesh(ViewContext *vc, wmGenericUserData *wm_userdata, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; @@ -812,9 +823,9 @@ static bool do_lasso_select_mesh(ViewContext *vc, /* set editmesh */ vc->em = BKE_editmesh_from_object(vc->obedit); - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { if (vc->em->bm->totvertsel) { @@ -836,7 +847,7 @@ static bool do_lasso_select_mesh(ViewContext *vc, editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, ts->selectmode); esel = wm_userdata->data; esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); } } @@ -897,7 +908,7 @@ static void do_lasso_select_curve__doSelect(void *userData, LassoSelectUserData *data = userData; const bool is_inside = BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED); + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED); if (bp) { const bool is_select = bp->f1 & SELECT; const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); @@ -930,16 +941,16 @@ static void do_lasso_select_curve__doSelect(void *userData, } static bool do_lasso_select_curve(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { Curve *curve = (Curve *)vc->obedit->data; @@ -958,9 +969,10 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const { LassoSelectUserData *data = userData; const bool is_select = bp->f1 & SELECT; - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(bp->f1, sel_op_result, SELECT); @@ -968,16 +980,16 @@ static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, const } } static bool do_lasso_select_lattice(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_lattice_flags_set(vc->obedit, 0); @@ -1002,7 +1014,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData, if (screen_co_a[0] != IS_CLIPPED) { if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_a)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_a), INT_MAX)) { is_inside_flag |= BONESEL_ROOT; } } @@ -1012,7 +1025,8 @@ static void do_lasso_select_armature__doSelectBone(void *userData, if (screen_co_b[0] != IS_CLIPPED) { if (BLI_rcti_isect_pt(data->rect, UNPACK2(screen_co_b)) && - BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), INT_MAX)) { + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, UNPACK2(screen_co_b), INT_MAX)) { is_inside_flag |= BONESEL_TIP; } } @@ -1022,8 +1036,11 @@ static void do_lasso_select_armature__doSelectBone(void *userData, if (is_ignore_flag == 0) { if (is_inside_flag == (BONE_ROOTSEL | BONE_TIPSEL) || - BLI_lasso_is_edge_inside( - data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), INT_MAX)) { + BLI_lasso_is_edge_inside(data->mcoords, + data->mcoords_len, + UNPACK2(screen_co_a), + UNPACK2(screen_co_b), + INT_MAX)) { is_inside_flag |= BONESEL_BONE; } } @@ -1033,16 +1050,16 @@ static void do_lasso_select_armature__doSelectBone(void *userData, } static bool do_lasso_select_armature(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; rcti rect; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= ED_armature_edit_deselect_all_visible(vc->obedit); @@ -1071,9 +1088,10 @@ static void do_lasso_select_mball__doSelectElem(void *userData, { LassoSelectUserData *data = userData; const bool is_select = ml->flag & SELECT; - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], INT_MAX)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], INT_MAX)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(ml->flag, sel_op_result, SELECT); @@ -1081,8 +1099,8 @@ static void do_lasso_select_mball__doSelectElem(void *userData, } } static bool do_lasso_select_meta(ViewContext *vc, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { LassoSelectUserData data; @@ -1090,9 +1108,9 @@ static bool do_lasso_select_meta(ViewContext *vc, MetaBall *mb = (MetaBall *)vc->obedit->data; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); if (SEL_OP_USE_PRE_DESELECT(sel_op)) { data.is_changed |= BKE_mball_deselect_all(mb); @@ -1113,9 +1131,10 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, { LassoSelectUserData *data = userData; const bool is_select = mv->flag & SELECT; - const bool is_inside = (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && - BLI_lasso_is_point_inside( - data->mcords, data->moves, screen_co[0], screen_co[1], IS_CLIPPED)); + const bool is_inside = + (BLI_rctf_isect_pt_v(data->rect_fl, screen_co) && + BLI_lasso_is_point_inside( + data->mcoords, data->mcoords_len, screen_co[0], screen_co[1], IS_CLIPPED)); const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT); @@ -1124,8 +1143,8 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData, } static bool do_lasso_select_paintvert(ViewContext *vc, wmGenericUserData *wm_userdata, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { const bool use_zbuf = !XRAY_ENABLED(vc->v3d); @@ -1143,7 +1162,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, changed |= paintvert_deselect_all_visible(ob, SEL_DESELECT, false); } - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); struct EditSelectBuf_Cache *esel = wm_userdata->data; if (use_zbuf) { @@ -1151,7 +1170,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_VERTEX); esel = wm_userdata->data; esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); } } @@ -1163,7 +1182,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc, else { LassoSelectUserData data; - view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, sel_op); + view3d_userdata_lassoselect_init(&data, vc, &rect, mcoords, mcoords_len, sel_op); ED_view3d_init_mats_rv3d(vc->obact, vc->rv3d); @@ -1185,8 +1204,8 @@ static bool do_lasso_select_paintvert(ViewContext *vc, } static bool do_lasso_select_paintface(ViewContext *vc, wmGenericUserData *wm_userdata, - const int mcords[][2], - short moves, + const int mcoords[][2], + const int mcoords_len, const eSelectOp sel_op) { Object *ob = vc->obact; @@ -1203,14 +1222,14 @@ static bool do_lasso_select_paintface(ViewContext *vc, changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false); } - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); struct EditSelectBuf_Cache *esel = wm_userdata->data; if (esel == NULL) { editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc, SCE_SELECT_FACE); esel = wm_userdata->data; esel->select_bitmap = DRW_select_buffer_bitmap_from_poly( - vc->depsgraph, vc->region, vc->v3d, mcords, moves, &rect, NULL); + vc->depsgraph, vc->region, vc->v3d, mcoords, mcoords_len, &rect, NULL); } if (esel->select_bitmap) { @@ -1224,7 +1243,7 @@ static bool do_lasso_select_paintface(ViewContext *vc, } #if 0 -static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp sel_op) +static void do_lasso_select_node(int mcoords[][2], const int mcoords_len, const eSelectOp sel_op) { SpaceNode *snode = area->spacedata.first; @@ -1234,7 +1253,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s float node_centf[2]; bool changed = false; - BLI_lasso_boundbox(&rect, mcords, moves); + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); /* store selection in temp test flag */ for (node = snode->edittree->nodes.first; node; node = node->next) { @@ -1244,7 +1263,7 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent); const bool is_select = node->flag & SELECT; const bool is_inside = (BLI_rcti_isect_pt_v(&rect, node_cent) && - BLI_lasso_is_point_inside(mcords, moves, node_cent[0], node_cent[1])); + BLI_lasso_is_point_inside(mcoords, mcoords_len, node_cent[0], node_cent[1])); const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside); if (sel_op_result != -1) { SET_FLAG_FROM_TEST(node->flag, sel_op_result, SELECT); @@ -1257,8 +1276,11 @@ static void do_lasso_select_node(int mcords[][2], short moves, const eSelectOp s } #endif -static bool view3d_lasso_select( - bContext *C, ViewContext *vc, const int mcords[][2], short moves, const eSelectOp sel_op) +static bool view3d_lasso_select(bContext *C, + ViewContext *vc, + const int mcoords[][2], + const int mcoords_len, + const eSelectOp sel_op) { Object *ob = CTX_data_active_object(C); bool changed_multi = false; @@ -1268,26 +1290,26 @@ static bool view3d_lasso_select( if (vc->obedit == NULL) { /* Object Mode */ if (BKE_paint_select_face_test(ob)) { - changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcoords, mcoords_len, sel_op); } else if (BKE_paint_select_vert_test(ob)) { - changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op); + changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcoords, mcoords_len, sel_op); } else if (ob && (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) { /* pass */ } else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { - changed_multi |= PE_lasso_select(C, mcords, moves, sel_op); + changed_multi |= PE_lasso_select(C, mcoords, mcoords_len, sel_op); } else if (ob && (ob->mode & OB_MODE_POSE)) { - changed_multi |= do_lasso_select_pose(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_pose(vc, mcoords, mcoords_len, sel_op); if (changed_multi) { ED_outliner_select_sync_from_pose_bone_tag(C); } } else { - changed_multi |= do_lasso_select_objects(vc, mcords, moves, sel_op); + changed_multi |= do_lasso_select_objects(vc, mcoords, mcoords_len, sel_op); if (changed_multi) { ED_outliner_select_sync_from_object_tag(C); } @@ -1300,23 +1322,23 @@ static bool view3d_lasso_select( switch (vc->obedit->type) { case OB_MESH: - changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op); + changed = do_lasso_select_mesh(vc, wm_userdata, mcoords, mcoords_len, sel_op); break; case OB_CURVE: case OB_SURF: - changed = do_lasso_select_curve(vc, mcords, moves, sel_op); + changed = do_lasso_select_curve(vc, mcoords, mcoords_len, sel_op); break; case OB_LATTICE: - changed = do_lasso_select_lattice(vc, mcords, moves, sel_op); + changed = do_lasso_select_lattice(vc, mcoords, mcoords_len, sel_op); break; case OB_ARMATURE: - changed = do_lasso_select_armature(vc, mcords, moves, sel_op); + changed = do_lasso_select_armature(vc, mcoords, mcoords_len, sel_op); if (changed) { ED_outliner_select_sync_from_edit_bone_tag(C); } break; case OB_MBALL: - changed = do_lasso_select_meta(vc, mcords, moves, sel_op); + changed = do_lasso_select_meta(vc, mcoords, mcoords_len, sel_op); break; default: BLI_assert(!"lasso select on incorrect object type"); @@ -1342,10 +1364,10 @@ static bool view3d_lasso_select( static int view3d_lasso_select_exec(bContext *C, wmOperator *op) { ViewContext vc; - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); - if (mcords) { + if (mcoords) { Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); view3d_operator_needs_opengl(C); BKE_object_update_select_id(CTX_data_main(C)); @@ -1354,9 +1376,9 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op) ED_view3d_viewcontext_init(C, &vc, depsgraph); eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - bool changed_multi = view3d_lasso_select(C, &vc, mcords, mcords_tot, sel_op); + bool changed_multi = view3d_lasso_select(C, &vc, mcoords, mcoords_len, sel_op); - MEM_freeN((void *)mcords); + MEM_freeN((void *)mcoords); if (changed_multi) { return OPERATOR_FINISHED; @@ -1982,7 +2004,7 @@ static bool ed_object_select_pick(bContext *C, /* setup view context for argument to callbacks */ ED_view3d_viewcontext_init(C, &vc, depsgraph); - ARegion *region = CTX_wm_region(C); + const ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); View3D *v3d = CTX_wm_view3d(C); diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index b90f7aa870e..fe77ca05a04 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -1062,7 +1062,7 @@ int view3d_opengl_select(ViewContext *vc, * the number of items is nearly always 1, maybe 2..3 in rare cases. */ LinkNode *ob_pose_list = NULL; VirtualModifierData virtualModifierData; - const ModifierData *md = modifiers_getVirtualModifierList(obact, &virtualModifierData); + const ModifierData *md = BKE_modifiers_get_virtual_modifierlist(obact, &virtualModifierData); for (; md; md = md->next) { if (md->type == eModifierType_Armature) { ArmatureModifierData *amd = (ArmatureModifierData *)md; diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index d376c71d867..8e3ad55bae1 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -778,9 +778,10 @@ wmKeyMap *transform_modal_keymap(wmKeyConfig *keyconf) return keymap; } -static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cmode, bool is_plane) +static void transform_event_xyz_constraint(TransInfo *t, short key_type, bool is_plane) { if (!(t->flag & T_NO_CONSTRAINT)) { + char cmode = constraintModeToChar(t); int constraint_axis, constraint_plane; const bool edit_2d = (t->flag & T_2D_EDIT) != 0; const char *msg1 = "", *msg2 = "", *msg3 = ""; @@ -824,34 +825,22 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm } } else if (!edit_2d) { - if (cmode != axis) { - /* First press, constraint to an axis. */ - t->orientation.index = 0; - const short *orientation_ptr = t->orientation.types[t->orientation.index]; - const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; - if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); - } - else { - setUserConstraint(t, orientation, constraint_plane, msg3); - } - } - else { + if (t->orientation.index == 0 || ELEM(cmode, '\0', axis)) { /* Successive presses on existing axis, cycle orientation modes. */ t->orientation.index = (t->orientation.index + 1) % ARRAY_SIZE(t->orientation.types); + initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]); + } - if (t->orientation.index == 0) { - stopConstraint(t); + if (t->orientation.index == 0) { + stopConstraint(t); + } + else { + const short orientation = t->orientation.types[t->orientation.index]; + if (is_plane == false) { + setUserConstraint(t, orientation, constraint_axis, msg2); } else { - const short *orientation_ptr = t->orientation.types[t->orientation.index]; - const short orientation = orientation_ptr ? *orientation_ptr : V3D_ORIENT_GLOBAL; - if (is_plane == false) { - setUserConstraint(t, orientation, constraint_axis, msg2); - } - else { - setUserConstraint(t, orientation, constraint_plane, msg3); - } + setUserConstraint(t, orientation, constraint_plane, msg3); } } } @@ -861,7 +850,6 @@ static void transform_event_xyz_constraint(TransInfo *t, short key_type, char cm int transformEvent(TransInfo *t, const wmEvent *event) { - char cmode = constraintModeToChar(t); bool handled = false; const int modifiers_prev = t->modifiers; const int mode_prev = t->mode; @@ -1047,42 +1035,42 @@ int transformEvent(TransInfo *t, const wmEvent *event) break; case TFM_MODAL_AXIS_X: if (!(t->flag & T_NO_CONSTRAINT)) { - transform_event_xyz_constraint(t, EVT_XKEY, cmode, false); + transform_event_xyz_constraint(t, EVT_XKEY, false); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_AXIS_Y: if ((t->flag & T_NO_CONSTRAINT) == 0) { - transform_event_xyz_constraint(t, EVT_YKEY, cmode, false); + transform_event_xyz_constraint(t, EVT_YKEY, false); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_AXIS_Z: if ((t->flag & (T_NO_CONSTRAINT)) == 0) { - transform_event_xyz_constraint(t, EVT_ZKEY, cmode, false); + transform_event_xyz_constraint(t, EVT_ZKEY, false); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_PLANE_X: if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_XKEY, cmode, true); + transform_event_xyz_constraint(t, EVT_XKEY, true); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_PLANE_Y: if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_YKEY, cmode, true); + transform_event_xyz_constraint(t, EVT_YKEY, true); t->redraw |= TREDRAW_HARD; handled = true; } break; case TFM_MODAL_PLANE_Z: if ((t->flag & (T_NO_CONSTRAINT | T_2D_EDIT)) == 0) { - transform_event_xyz_constraint(t, EVT_ZKEY, cmode, true); + transform_event_xyz_constraint(t, EVT_ZKEY, true); t->redraw |= TREDRAW_HARD; handled = true; } @@ -1228,17 +1216,7 @@ int transformEvent(TransInfo *t, const wmEvent *event) stopConstraint(t); } else { - if (event->shift) { - /* bit hackish... but it prevents mmb select to print the - * orientation from menu */ - float mati[3][3]; - strcpy(t->spacename, "global"); - unit_m3(mati); - initSelectConstraint(t, mati); - } - else { - initSelectConstraint(t, t->spacemtx); - } + initSelectConstraint(t, event->shift); postSelectConstraint(t); } } @@ -1699,18 +1677,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) ts->prop_mode = t->prop_mode; } } - - if (t->spacetype == SPACE_VIEW3D) { - if ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && - !RNA_property_is_set(op->ptr, prop) && - (t->orientation.user != V3D_ORIENT_CUSTOM_MATRIX)) { - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; - orient_slot->type = t->orientation.user; - BLI_assert(((orient_slot->index_custom == -1) && (t->orientation.custom == NULL)) || - (BKE_scene_transform_orientation_get_index(t->scene, t->orientation.custom) == - orient_slot->index_custom)); - } - } } if (t->flag & T_MODAL) { @@ -1737,34 +1703,6 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) RNA_property_boolean_set(op->ptr, prop, (t->flag & T_NO_MIRROR) == 0); } - /* Orientation used for redo. */ - const bool use_orient_axis = (t->orient_matrix_is_set && - (RNA_struct_find_property(op->ptr, "orient_axis") != NULL)); - short orientation; - if (t->con.mode & CON_APPLY) { - orientation = t->con.orientation; - if (orientation == V3D_ORIENT_CUSTOM) { - const int orientation_index_custom = BKE_scene_transform_orientation_get_index( - t->scene, t->orientation.custom); - /* Maybe we need a t->con.custom_orientation? - * Seems like it would always match t->orientation.custom. */ - orientation = V3D_ORIENT_CUSTOM + orientation_index_custom; - BLI_assert(orientation >= V3D_ORIENT_CUSTOM); - } - } - else if ((t->orientation.user == V3D_ORIENT_CUSTOM_MATRIX) && - (prop = RNA_struct_find_property(op->ptr, "orient_matrix_type"))) { - orientation = RNA_property_enum_get(op->ptr, prop); - } - else if (use_orient_axis) { - /* We're not using an orientation, use the fallback. */ - orientation = t->orientation.unset; - } - else { - orientation = V3D_ORIENT_GLOBAL; - unit_m3(t->spacemtx); - } - if ((prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { if (t->flag & T_MODAL) { if (t->con.mode & CON_APPLY) { @@ -1784,56 +1722,40 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op) } } - if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix"))) { - if (t->flag & T_MODAL) { - if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { - if (t->flag & T_MODAL) { - RNA_enum_set(op->ptr, "orient_matrix_type", orientation); - } - } - if (t->con.mode & CON_APPLY) { - RNA_float_set_array(op->ptr, "orient_matrix", &t->con.mtx[0][0]); - } - else if (use_orient_axis) { - RNA_float_set_array(op->ptr, "orient_matrix", &t->orient_matrix[0][0]); - } - else { - RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); - } - } - } - if ((prop = RNA_struct_find_property(op->ptr, "orient_type"))) { - /* constraint orientation can be global, even if user selects something else - * so use the orientation in the constraint if set */ + short orient_set, orient_cur; + orient_set = RNA_property_is_set(op->ptr, prop) ? RNA_property_enum_get(op->ptr, prop) : -1; + orient_cur = t->orientation.types[t->orientation.index]; - /* Use 'orient_matrix' instead. */ - if (t->flag & T_MODAL) { - if (orientation != V3D_ORIENT_CUSTOM_MATRIX) { - RNA_property_enum_set(op->ptr, prop, orientation); - } + if (!ELEM(orient_cur, orient_set, V3D_ORIENT_CUSTOM_MATRIX)) { + RNA_property_enum_set(op->ptr, prop, orient_cur); + orient_set = orient_cur; + } + + if (((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) && + !RNA_property_is_set(op->ptr, prop))) { + /* Set the first time to register on redo. */ + RNA_property_enum_set(op->ptr, prop, orient_set); + RNA_float_set_array(op->ptr, "orient_matrix", &t->spacemtx[0][0]); } } if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { bool constraint_axis[3] = {false, false, false}; - if (t->flag & T_MODAL) { - /* Only set if needed, so we can hide in the UI when nothing is set. - * See 'transform_poll_property'. */ - if (t->con.mode & CON_APPLY) { - if (t->con.mode & CON_AXIS0) { - constraint_axis[0] = true; - } - if (t->con.mode & CON_AXIS1) { - constraint_axis[1] = true; - } - if (t->con.mode & CON_AXIS2) { - constraint_axis[2] = true; - } + if (t->con.mode & CON_APPLY) { + if (t->con.mode & CON_AXIS0) { + constraint_axis[0] = true; } - if (ELEM(true, UNPACK3(constraint_axis))) { - RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + if (t->con.mode & CON_AXIS1) { + constraint_axis[1] = true; } + if (t->con.mode & CON_AXIS2) { + constraint_axis[2] = true; + } + RNA_property_boolean_set_array(op->ptr, prop, constraint_axis); + } + else { + RNA_property_unset(op->ptr, prop); } } @@ -1959,7 +1881,13 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve unit_m3(t->spacemtx); initTransInfo(C, t, op, event); - initTransformOrientation(C, t); + + /* Use the custom orientation when it is set. */ + short orientation = t->orientation.types[0] == V3D_ORIENT_CUSTOM_MATRIX ? + V3D_ORIENT_CUSTOM_MATRIX : + t->orientation.types[t->orientation.index]; + + initTransformOrientation(C, t, orientation); if (t->spacetype == SPACE_VIEW3D) { t->draw_handle_apply = ED_region_draw_cb_activate( @@ -2084,33 +2012,6 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve calculatePropRatio(t); calculateCenter(t); - /* Overwrite initial values if operator supplied a non-null vector. - * - * Run before init functions so 'values_modal_offset' can be applied on mouse input. - */ - BLI_assert(is_zero_v4(t->values_modal_offset)); - if ((prop = RNA_struct_find_property(op->ptr, "value")) && RNA_property_is_set(op->ptr, prop)) { - float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ - - if (RNA_property_array_check(prop)) { - RNA_float_get_array(op->ptr, "value", values); - } - else { - values[0] = RNA_float_get(op->ptr, "value"); - } - - copy_v4_v4(t->values, values); - - if (t->flag & T_MODAL) { - copy_v4_v4(t->values_modal_offset, values); - t->redraw = TREDRAW_HARD; - } - else { - copy_v4_v4(t->values, values); - t->flag |= T_INPUT_IS_VALUES_FINAL; - } - } - if (event) { /* Initialize accurate transform to settings requested by keymap. */ bool use_accurate = false; @@ -2141,38 +2042,8 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve } /* Constraint init from operator */ - if ((t->flag & T_MODAL) || - /* For mirror operator the constraint axes are effectively the values. */ - (RNA_struct_find_property(op->ptr, "value") == NULL)) { - if ((prop = RNA_struct_find_property(op->ptr, "constraint_axis")) && - RNA_property_is_set(op->ptr, prop)) { - bool constraint_axis[3]; - - RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); - - if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { - t->con.mode |= CON_APPLY; - - if (constraint_axis[0]) { - t->con.mode |= CON_AXIS0; - } - if (constraint_axis[1]) { - t->con.mode |= CON_AXIS1; - } - if (constraint_axis[2]) { - t->con.mode |= CON_AXIS2; - } - - setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); - } - } - } - else { - /* So we can adjust in non global orientation. */ - if (t->orientation.user != V3D_ORIENT_GLOBAL) { - t->con.mode |= CON_APPLY | CON_AXIS0 | CON_AXIS1 | CON_AXIS2; - setUserConstraint(t, t->orientation.user, t->con.mode, "%s"); - } + if (t->con.mode & CON_APPLY) { + setUserConstraint(t, t->orientation.types[t->orientation.index], t->con.mode, "%s"); } /* Don't write into the values when non-modal because they are already set from operator redo diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index 701e068d3fa..503e7bd4691 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -531,17 +531,12 @@ typedef struct TransInfo { bool is_launch_event_tweak; struct { - /** Orientation type when when we're not constrained. - * nearly always global except for rotate which defaults to screen-space orientation. */ - short unset; - /** Orientation to use when a key is pressed. */ - short user; - /* Used when user is global. */ - short user_alt; short index; - short *types[2]; - /* this gets used when custom_orientation is V3D_ORIENT_CUSTOM */ + short types[3]; + /* this gets used when orientation.type[x] is V3D_ORIENT_CUSTOM */ struct TransformOrientation *custom; + /* this gets used when orientation.type[0] is V3D_ORIENT_CUSTOM_MATRIX */ + float custom_matrix[3][3]; } orientation; /** backup from view3d, to restore on end. */ short gizmo_flag; @@ -566,15 +561,6 @@ typedef struct TransInfo { /** Secondary axis, shear uses this. */ int orient_axis_ortho; - /** Often this matrix has similar usage to #TransInfo.spacemtx however this - * is used to define extra axes to operate on, not necessarily a space. - * - * For example, by default rotation operates on the view (`orient_matrix[2]`), - * even when the current space isn't set to the view. */ - float orient_matrix[3][3]; - /** Don't overwrite when set by operator redo defines the orientation axis. */ - bool orient_matrix_is_set; - /** remove elements if operator is canceled. */ bool remove_on_cancel; @@ -677,6 +663,10 @@ enum { T_MODAL_CURSOR_SET = 1 << 26, T_CLNOR_REBUILD = 1 << 27, + + /* Special Aftertrans. */ + T_AUTOMERGE = 1 << 28, + T_AUTOSPLIT = 1 << 29, }; /** #TransInfo.modifiers */ @@ -922,7 +912,7 @@ void transform_data_ext_rotate(TransData *td, float mat[3][3], bool use_drot); /*********************** Transform Orientations ******************************/ -void initTransformOrientation(struct bContext *C, TransInfo *t); +void initTransformOrientation(struct bContext *C, TransInfo *t, short orientation); /* Those two fill in mat and return non-zero on success */ bool createSpaceNormal(float mat[3][3], const float normal[3]); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index cdff9fdf750..b07eb6edf5a 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -713,7 +713,10 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte break; case V3D_ORIENT_VIEW: BLI_snprintf(text, sizeof(text), ftext, TIP_("view")); - setConstraint(t, t->spacemtx, mode, text); + float mtx[3][3]; + copy_m3_m3(mtx, t->spacemtx); + negate_v3(mtx[2]); + setConstraint(t, mtx, mode, text); break; case V3D_ORIENT_CURSOR: BLI_snprintf(text, sizeof(text), ftext, TIP_("cursor")); @@ -727,7 +730,9 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char fte BLI_snprintf(text, sizeof(text), ftext, TIP_("custom matrix")); setConstraint(t, t->spacemtx, mode, text); break; - case V3D_ORIENT_CUSTOM: { + case V3D_ORIENT_CUSTOM: + default: { + BLI_assert(orientation >= V3D_ORIENT_CUSTOM); char orientation_str[128]; BLI_snprintf(orientation_str, sizeof(orientation_str), @@ -984,17 +989,22 @@ void getConstraintMatrix(TransInfo *t) /*------------------------- MMB Select -------------------------------*/ -void initSelectConstraint(TransInfo *t, float mtx[3][3]) +void initSelectConstraint(TransInfo *t, bool force_global) { - copy_m3_m3(t->con.mtx, mtx); - t->con.mode |= CON_APPLY; - t->con.mode |= CON_SELECT; + short orientation; + if (force_global) { + orientation = V3D_ORIENT_GLOBAL; + } + else { + if (t->orientation.index == 0) { + t->orientation.index = 1; + initTransformOrientation(t->context, t, t->orientation.types[t->orientation.index]); + } + orientation = t->orientation.types[t->orientation.index]; + } + setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, ""); setNearestAxis(t); - t->con.drawExtra = NULL; - t->con.applyVec = applyAxisConstraintVec; - t->con.applySize = applyAxisConstraintSize; - t->con.applyRot = applyAxisConstraintRot; } void selectConstraint(TransInfo *t) diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h index 8938ca93ad8..c98234c83da 100644 --- a/source/blender/editors/transform/transform_constraints.h +++ b/source/blender/editors/transform/transform_constraints.h @@ -36,7 +36,7 @@ void drawPropCircle(const struct bContext *C, TransInfo *t); void startConstraint(TransInfo *t); void stopConstraint(TransInfo *t); void getConstraintMatrix(TransInfo *t); -void initSelectConstraint(TransInfo *t, float mtx[3][3]); +void initSelectConstraint(TransInfo *t, bool force_global); void selectConstraint(TransInfo *t); void postSelectConstraint(TransInfo *t); void setNearestAxis(TransInfo *t); diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c index 6744f7b6262..b2d87272203 100644 --- a/source/blender/editors/transform/transform_convert.c +++ b/source/blender/editors/transform/transform_convert.c @@ -447,12 +447,12 @@ static void bone_children_clear_transflag(int mode, short around, ListBase *lb) } } -/* sets transform flags in the bones - * returns total number of bones with BONE_TRANSFORM */ -int count_set_pose_transflags(Object *ob, - const int mode, - const short around, - bool has_translate_rotate[2]) +/* Sets transform flags in the bones. + * Returns total number of bones with `BONE_TRANSFORM`. */ +int transform_convert_pose_transflags_update(Object *ob, + const int mode, + const short around, + bool has_translate_rotate[2]) { bArmature *arm = ob->data; bPoseChannel *pchan; @@ -1846,8 +1846,8 @@ static void special_aftertrans_update__node(bContext *C, TransInfo *t) static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) { - /* so automerge supports mirror */ - if ((t->scene->toolsettings->automerge) && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) { + bool use_automerge = (t->flag & (T_AUTOMERGE | T_AUTOSPLIT)) != 0; + if (use_automerge && ((t->flag & T_EDIT) && t->obedit_type == OB_MESH)) { FOREACH_TRANS_DATA_CONTAINER (t, tc) { BMEditMesh *em = BKE_editmesh_from_object(tc->obedit); @@ -1873,14 +1873,12 @@ static void special_aftertrans_update__mesh(bContext *UNUSED(C), TransInfo *t) hflag = BM_ELEM_SELECT; } - if (t->scene->toolsettings->automerge & AUTO_MERGE) { - if (t->scene->toolsettings->automerge & AUTO_MERGE_AND_SPLIT) { - EDBM_automerge_and_split( - tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); - } - else { - EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); - } + if (t->flag & T_AUTOSPLIT) { + EDBM_automerge_and_split( + tc->obedit, true, true, true, hflag, t->scene->toolsettings->doublimit); + } + else { + EDBM_automerge(tc->obedit, true, hflag, t->scene->toolsettings->doublimit); } /* Special case, this is needed or faces won't re-select. @@ -2288,7 +2286,7 @@ void special_aftertrans_update(bContext *C, TransInfo *t) /* set BONE_TRANSFORM flags for autokey, gizmo draw might have changed them */ if (!canceled && (t->mode != TFM_DUMMY)) { - count_set_pose_transflags(ob, t->mode, t->around, NULL); + transform_convert_pose_transflags_update(ob, t->mode, t->around, NULL); } /* if target-less IK grabbing, we calculate the pchan transforms and clear flag */ @@ -2743,7 +2741,7 @@ void createTransData(bContext *C, TransInfo *t) /* important that ob_armature can be set even when its not selected [#23412] * lines below just check is also visible */ has_transform_context = false; - Object *ob_armature = modifiers_isDeformedByArmature(ob); + Object *ob_armature = BKE_modifiers_is_deformed_by_armature(ob); if (ob_armature && ob_armature->mode & OB_MODE_POSE) { Base *base_arm = BKE_view_layer_base_find(t->view_layer, ob_armature); if (base_arm) { diff --git a/source/blender/editors/transform/transform_convert.h b/source/blender/editors/transform/transform_convert.h index f975d320e62..fccaeb994e9 100644 --- a/source/blender/editors/transform/transform_convert.h +++ b/source/blender/editors/transform/transform_convert.h @@ -37,10 +37,10 @@ struct bKinematicConstraint; struct bPoseChannel; /* transform_convert.c */ -int count_set_pose_transflags(Object *ob, - const int mode, - const short around, - bool has_translate_rotate[2]); +int transform_convert_pose_transflags_update(Object *ob, + const int mode, + const short around, + bool has_translate_rotate[2]); void transform_autoik_update(TransInfo *t, short mode); void autokeyframe_object(struct bContext *C, struct Scene *scene, diff --git a/source/blender/editors/transform/transform_convert_armature.c b/source/blender/editors/transform/transform_convert_armature.c index 779257ef671..35bb7e3f0d8 100644 --- a/source/blender/editors/transform/transform_convert_armature.c +++ b/source/blender/editors/transform/transform_convert_armature.c @@ -609,9 +609,9 @@ void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object * /* TODO(germano): Realitve Mirror support */ } data->flag |= CONSTRAINT_IK_AUTO; - /* Add a temporary auto IK constraint here, as we will only temporarly active this targetless - * bone during transform. (Targetless IK constraints are treated as if they are disabled - * unless they are transformed) */ + /* Add a temporary auto IK constraint here, as we will only temporarily active this + * target-less bone during transform. (Target-less IK constraints are treated as if they are + * disabled unless they are transformed) */ add_temporary_ik_constraint(pchan, data); Main *bmain = CTX_data_main(t->context); update_deg_with_temporary_ik(bmain, ob); @@ -669,7 +669,9 @@ void createTransPose(TransInfo *t) const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0); /* set flags and count total */ - tc->data_len = count_set_pose_transflags(ob, t->mode, t->around, has_translate_rotate); + tc->data_len = transform_convert_pose_transflags_update( + ob, t->mode, t->around, has_translate_rotate); + if (tc->data_len == 0) { continue; } diff --git a/source/blender/editors/transform/transform_convert_mesh.c b/source/blender/editors/transform/transform_convert_mesh.c index 7528f791130..24dda8c8464 100644 --- a/source/blender/editors/transform/transform_convert_mesh.c +++ b/source/blender/editors/transform/transform_convert_mesh.c @@ -781,9 +781,9 @@ void createTransEditVerts(TransInfo *t) } /* detect CrazySpace [tm] */ - if (modifiers_getCageIndex(t->scene, tc->obedit, NULL, 1) != -1) { + if (BKE_modifiers_get_cage_index(t->scene, tc->obedit, NULL, 1) != -1) { int totleft = -1; - if (modifiers_isCorrectableDeformed(t->scene, tc->obedit)) { + if (BKE_modifiers_is_correctable_deformed(t->scene, tc->obedit)) { BKE_scene_graph_evaluated_ensure(t->depsgraph, CTX_data_main(t->context)); /* Use evaluated state because we need b-bone cache. */ diff --git a/source/blender/editors/transform/transform_convert_object.c b/source/blender/editors/transform/transform_convert_object.c index 9b76db7f265..8deba0f7ad0 100644 --- a/source/blender/editors/transform/transform_convert_object.c +++ b/source/blender/editors/transform/transform_convert_object.c @@ -197,7 +197,7 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) /* NOTE: This is not really following copy-on-write design and we should not * be re-evaluating the evaluated object. But as the comment above mentioned * this is part of a hack. - * More proper solution would be to make a shallow copy of the object and + * More proper solution would be to make a shallow copy of the object and * evaluate that, and access matrix of that evaluated copy of the object. * Might be more tricky than it sounds, if some logic later on accesses the * object matrix via td->ob->obmat. */ diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index 05318a5c1d3..4472facf183 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -1187,7 +1187,6 @@ void recalcData(TransInfo *t) flushTransPaintCurve(t); } else if (t->options & CTX_GPENCIL_STROKES) { - /* set recalc triangle cache flag */ recalcData_gpencil_strokes(t); } else if (t->options & CTX_SCULPT) { @@ -1431,11 +1430,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve unit_m3(t->mat); - unit_m3(t->orient_matrix); - negate_m3(t->orient_matrix); - /* Leave 't->orient_matrix_is_set' to false, - * so we overwrite it when we have a useful value. */ - /* Default to rotate on the Z axis. */ t->orient_axis = 2; t->orient_axis_ortho = 1; @@ -1513,22 +1507,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->around = V3D_AROUND_CURSOR; } - TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; - t->orientation.unset = V3D_ORIENT_GLOBAL; - t->orientation.user = orient_slot->type; - t->orientation.custom = BKE_scene_transform_orientation_find(t->scene, - orient_slot->index_custom); - - t->orientation.index = 0; - ARRAY_SET_ITEMS(t->orientation.types, &t->orientation.user, NULL); - - /* Make second orientation local if both are global. */ - if (t->orientation.user == V3D_ORIENT_GLOBAL) { - t->orientation.user_alt = V3D_ORIENT_LOCAL; - t->orientation.types[0] = &t->orientation.user_alt; - SWAP(short *, t->orientation.types[0], t->orientation.types[1]); - } - /* exceptional case */ if (t->around == V3D_AROUND_LOCAL_ORIGINS) { if (ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL)) { @@ -1617,48 +1595,138 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->around = V3D_AROUND_CENTER_BOUNDS; } - if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { - t->orient_axis = RNA_property_enum_get(op->ptr, prop); - } - if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { - t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); - } + BLI_assert(is_zero_v4(t->values_modal_offset)); + bool t_values_set_is_array = false; + if (op && (prop = RNA_struct_find_property(op->ptr, "value")) && + RNA_property_is_set(op->ptr, prop)) { + float values[4] = {0}; /* in case value isn't length 4, avoid uninitialized memory */ + if (RNA_property_array_check(prop)) { + RNA_float_get_array(op->ptr, "value", values); + t_values_set_is_array = true; + } + else { + values[0] = RNA_float_get(op->ptr, "value"); + } - if (op && - ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) && - RNA_property_is_set(op->ptr, prop)) && - ((t->flag & T_MODAL) || - /* When using redo, don't use the custom constraint matrix - * if the user selects a different orientation. */ - (RNA_enum_get(op->ptr, "orient_type") == RNA_enum_get(op->ptr, "orient_matrix_type")))) { - RNA_property_float_get_array(op->ptr, prop, &t->orient_matrix[0][0]); - copy_m3_m3(t->spacemtx, t->orient_matrix); - /* Some transform modes use this to operate on an axis. */ - t->orient_matrix_is_set = true; - t->orientation.user = V3D_ORIENT_CUSTOM_MATRIX; - t->orientation.custom = 0; + copy_v4_v4(t->values, values); if (t->flag & T_MODAL) { - RNA_enum_set(op->ptr, "orient_matrix_type", RNA_enum_get(op->ptr, "orient_type")); + /* Run before init functions so 'values_modal_offset' can be applied on mouse input. */ + copy_v4_v4(t->values_modal_offset, values); + } + else { + copy_v4_v4(t->values, values); + t->flag |= T_INPUT_IS_VALUES_FINAL; } } - else if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && - RNA_property_is_set(op->ptr, prop))) { - short orientation = RNA_property_enum_get(op->ptr, prop); + + if (op && (prop = RNA_struct_find_property(op->ptr, "constraint_axis"))) { + bool constraint_axis[3] = {false, false, false}; + if (RNA_property_is_set(op->ptr, prop)) { + RNA_property_boolean_get_array(op->ptr, prop, constraint_axis); + } + + if (t_values_set_is_array && t->flag & T_INPUT_IS_VALUES_FINAL) { + /* For operators whose `t->values` is array, set contrain so that the + * orientation is more intuitive in the Redo Panel. */ + for (int i = 3; i--;) { + constraint_axis[i] |= t->values[i] != 0.0f; + } + } + + if (constraint_axis[0] || constraint_axis[1] || constraint_axis[2]) { + t->con.mode |= CON_APPLY; + + if (constraint_axis[0]) { + t->con.mode |= CON_AXIS0; + } + if (constraint_axis[1]) { + t->con.mode |= CON_AXIS1; + } + if (constraint_axis[2]) { + t->con.mode |= CON_AXIS2; + } + } + } + + { + TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT]; TransformOrientation *custom_orientation = NULL; + short orient_type_set = -1; + short orient_type_matrix_set = -1; + short orient_type_scene = orient_slot->type; + if (orient_type_scene == V3D_ORIENT_CUSTOM) { + const int index_custom = orient_slot->index_custom; + custom_orientation = BKE_scene_transform_orientation_find(t->scene, index_custom); + orient_type_scene += index_custom; + } - if (orientation >= V3D_ORIENT_CUSTOM) { - if (orientation >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) { - orientation = V3D_ORIENT_GLOBAL; + short orient_type_default = V3D_ORIENT_GLOBAL; + short orient_type_constraint[2]; + + if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis"))) { + t->orient_axis = RNA_property_enum_get(op->ptr, prop); + + /* For transfor modes that require "orient_axis" use + * `V3D_ORIENT_VIEW` as default. */ + orient_type_default = V3D_ORIENT_VIEW; + } + if (op && (prop = RNA_struct_find_property(op->ptr, "orient_axis_ortho"))) { + t->orient_axis_ortho = RNA_property_enum_get(op->ptr, prop); + } + + if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_type")) && + RNA_property_is_set(op->ptr, prop))) { + orient_type_set = RNA_property_enum_get(op->ptr, prop); + if (orient_type_set >= V3D_ORIENT_CUSTOM) { + if (orient_type_set >= V3D_ORIENT_CUSTOM + BIF_countTransformOrientation(C)) { + orient_type_set = V3D_ORIENT_GLOBAL; + } + else { + custom_orientation = BKE_scene_transform_orientation_find( + t->scene, orient_type_default - V3D_ORIENT_CUSTOM); + } + } + + /* Change the default orientation to be used when redoing. */ + orient_type_default = orient_type_set; + orient_type_constraint[0] = orient_type_set; + orient_type_constraint[1] = orient_type_scene; + } + else { + orient_type_constraint[0] = orient_type_scene; + orient_type_constraint[1] = orient_type_scene != V3D_ORIENT_GLOBAL ? V3D_ORIENT_GLOBAL : + V3D_ORIENT_LOCAL; + } + + if (op && ((prop = RNA_struct_find_property(op->ptr, "orient_matrix")) && + RNA_property_is_set(op->ptr, prop))) { + RNA_property_float_get_array(op->ptr, prop, &t->orientation.custom_matrix[0][0]); + + if ((prop = RNA_struct_find_property(op->ptr, "orient_matrix_type")) && + RNA_property_is_set(op->ptr, prop)) { + orient_type_matrix_set = RNA_property_enum_get(op->ptr, prop); + } + else if (orient_type_set != -1) { + orient_type_matrix_set = orient_type_set; } else { - custom_orientation = BKE_scene_transform_orientation_find(t->scene, - orientation - V3D_ORIENT_CUSTOM); - orientation = V3D_ORIENT_CUSTOM; + orient_type_matrix_set = orient_type_set = V3D_ORIENT_GLOBAL; + } + + if (orient_type_matrix_set == orient_type_set) { + /* Constraints are forced to use the custom matrix when redoing. */ + orient_type_default = V3D_ORIENT_CUSTOM_MATRIX; } } - t->orientation.user = orientation; + t->orientation.types[0] = orient_type_default; + t->orientation.types[1] = orient_type_constraint[0]; + t->orientation.types[2] = orient_type_constraint[1]; t->orientation.custom = custom_orientation; + + if (t->con.mode & CON_APPLY) { + t->orientation.index = 1; + } } if (op && ((prop = RNA_struct_find_property(op->ptr, "release_confirm")) && @@ -1763,6 +1831,24 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve t->options |= CTX_NO_PET; } + if (t->obedit_type == OB_MESH) { + if (op && (prop = RNA_struct_find_property(op->ptr, "use_automerge_and_split")) && + RNA_property_is_set(op->ptr, prop)) { + if (RNA_property_boolean_get(op->ptr, prop)) { + t->flag |= T_AUTOMERGE | T_AUTOSPLIT; + } + } + else { + char automerge = t->scene->toolsettings->automerge; + if (automerge & AUTO_MERGE) { + t->flag |= T_AUTOMERGE; + if (automerge & AUTO_MERGE_AND_SPLIT) { + t->flag |= T_AUTOSPLIT; + } + } + } + } + // Mirror is not supported with PET, turn it off. #if 0 if (t->flag & T_PROP_EDIT) { diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c index aa298b04d1a..7a9be86624e 100644 --- a/source/blender/editors/transform/transform_gizmo_3d.c +++ b/source/blender/editors/transform/transform_gizmo_3d.c @@ -713,7 +713,9 @@ void ED_transform_calc_orientation_from_type_ex(const bContext *C, ok = true; break; } - case V3D_ORIENT_CUSTOM: { + case V3D_ORIENT_CUSTOM: + default: { + BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM); TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find( scene, orientation_index_custom); if (applyTransformOrientation(custom_orientation, r_mat, NULL)) { @@ -1033,7 +1035,7 @@ int ED_transform_calc_gizmo_stats(const bContext *C, /* mislead counting bones... bah. We don't know the gizmo mode, could be mixed */ const int mode = TFM_ROTATION; - const int totsel_iter = count_set_pose_transflags( + const int totsel_iter = transform_convert_pose_transflags_update( ob_iter, mode, V3D_AROUND_CENTER_BOUNDS, NULL); if (totsel_iter) { @@ -1402,7 +1404,7 @@ void drawDial3d(const TransInfo *t) } else { axis_idx = MAN_AXIS_ROT_C; - negate_v3_v3(mat_basis[2], t->orient_matrix[t->orient_axis]); + negate_v3_v3(mat_basis[2], t->spacemtx[t->orient_axis]); scale *= 1.2f; line_with -= 1.0f; } diff --git a/source/blender/editors/transform/transform_mode.c b/source/blender/editors/transform/transform_mode.c index a2b3a891031..4c14c3aebd7 100644 --- a/source/blender/editors/transform/transform_mode.c +++ b/source/blender/editors/transform/transform_mode.c @@ -529,7 +529,7 @@ void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) void postInputRotation(TransInfo *t, float values[3]) { float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, values); } diff --git a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c index 18149a09f20..fde0d5b187e 100644 --- a/source/blender/editors/transform/transform_mode_edge_rotate_normal.c +++ b/source/blender/editors/transform/transform_mode_edge_rotate_normal.c @@ -81,7 +81,7 @@ static void applyNormalRotation(TransInfo *t, const int UNUSED(mval[2])) char str[UI_MAX_DRAW_STR]; float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, NULL); diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c index 6c2b3dc77d2..f52bfda0d14 100644 --- a/source/blender/editors/transform/transform_mode_rotate.c +++ b/source/blender/editors/transform/transform_mode_rotate.c @@ -146,7 +146,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2])) snapGridIncrement(t, &final); float axis_final[3]; - copy_v3_v3(axis_final, t->orient_matrix[t->orient_axis]); + copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { t->con.applyRot(t, NULL, NULL, axis_final, NULL); diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c index ba79f5f3c7b..da34bf50ba3 100644 --- a/source/blender/editors/transform/transform_mode_shear.c +++ b/source/blender/editors/transform/transform_mode_shear.c @@ -53,17 +53,17 @@ static void initShear_mouseInputMode(TransInfo *t) { float dir[3]; bool dir_flip = false; - copy_v3_v3(dir, t->orient_matrix[t->orient_axis_ortho]); + copy_v3_v3(dir, t->spacemtx[t->orient_axis_ortho]); /* Needed for axis aligned view gizmo. */ - if (t->orientation.user == V3D_ORIENT_VIEW) { + if (t->orientation.types[t->orientation.index] == V3D_ORIENT_VIEW) { if (t->orient_axis_ortho == 0) { - if (t->center2d[1] > t->mouse.imval[1]) { + if (t->center2d[1] < t->mouse.imval[1]) { dir_flip = !dir_flip; } } else if (t->orient_axis_ortho == 1) { - if (t->center2d[0] > t->mouse.imval[0]) { + if (t->center2d[0] < t->mouse.imval[0]) { dir_flip = !dir_flip; } } @@ -154,8 +154,8 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2])) unit_m3(smat); smat[1][0] = value; - copy_v3_v3(axismat_inv[0], t->orient_matrix[t->orient_axis_ortho]); - copy_v3_v3(axismat_inv[2], t->orient_matrix[t->orient_axis]); + copy_v3_v3(axismat_inv[0], t->spacemtx[t->orient_axis_ortho]); + copy_v3_v3(axismat_inv[2], t->spacemtx[t->orient_axis]); cross_v3_v3v3(axismat_inv[1], axismat_inv[0], axismat_inv[2]); invert_m3_m3(axismat, axismat_inv); diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 36f42992573..d643244e6ca 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -716,6 +716,15 @@ void Transform_Properties(struct wmOperatorType *ot, int flags) prop = RNA_def_boolean(ot->srna, "use_accurate", 0, "Accurate", "Use accurate transformation"); RNA_def_property_flag(prop, PROP_HIDDEN); } + + if (flags & P_POST_TRANSFORM) { + prop = RNA_def_boolean(ot->srna, + "use_automerge_and_split", + 0, + "Auto Merge & Split", + "Forces the use of Auto Merge & Split"); + RNA_def_property_flag(prop, PROP_HIDDEN); + } } static void TRANSFORM_OT_translate(struct wmOperatorType *ot) @@ -741,7 +750,7 @@ static void TRANSFORM_OT_translate(struct wmOperatorType *ot) Transform_Properties(ot, P_ORIENT_MATRIX | P_CONSTRAINT | P_PROPORTIONAL | P_MIRROR | P_ALIGN_SNAP | - P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT); + P_OPTIONS | P_GPENCIL_EDIT | P_CURSOR_EDIT | P_POST_TRANSFORM); } static void TRANSFORM_OT_resize(struct wmOperatorType *ot) diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 76823adfd20..81c63278366 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -407,14 +407,19 @@ bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3] return true; } -static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) +/* Updates all `BONE_TRANSFORM` flags. + * Returns total number of bones with `BONE_TRANSFORM`. + * Note: `transform_convert_pose_transflags_update` has a similar logic. */ +static int armature_bone_transflags_update_recursive(bArmature *arm, + ListBase *lb, + const bool do_it) { Bone *bone; bool do_next; int total = 0; for (bone = lb->first; bone; bone = bone->next) { - bone->flag &= ~(BONE_TRANSFORM | BONE_TRANSFORM_MIRROR); + bone->flag &= ~BONE_TRANSFORM; do_next = do_it; if (do_it) { if (bone->layer & arm->layer) { @@ -427,18 +432,18 @@ static int count_bone_select(bArmature *arm, ListBase *lb, const bool do_it) } } } - total += count_bone_select(arm, &bone->childbase, do_next); + total += armature_bone_transflags_update_recursive(arm, &bone->childbase, do_next); } return total; } -void initTransformOrientation(bContext *C, TransInfo *t) +void initTransformOrientation(bContext *C, TransInfo *t, short orientation) { Object *ob = CTX_data_active_object(C); Object *obedit = CTX_data_active_object(C); - switch (t->orientation.user) { + switch (orientation) { case V3D_ORIENT_GLOBAL: unit_m3(t->spacemtx); BLI_strncpy(t->spacename, TIP_("global"), sizeof(t->spacename)); @@ -471,32 +476,33 @@ void initTransformOrientation(bContext *C, TransInfo *t) break; - case V3D_ORIENT_VIEW: + case V3D_ORIENT_VIEW: { + float mat[3][3]; if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) { - RegionView3D *rv3d = t->region->regiondata; - float mat[3][3]; - BLI_strncpy(t->spacename, TIP_("view"), sizeof(t->spacename)); - copy_m3_m4(mat, rv3d->viewinv); + copy_m3_m4(mat, t->viewinv); normalize_m3(mat); - copy_m3_m3(t->spacemtx, mat); } else { - unit_m3(t->spacemtx); + unit_m3(mat); } + negate_v3(mat[2]); + copy_m3_m3(t->spacemtx, mat); break; + } case V3D_ORIENT_CURSOR: { BLI_strncpy(t->spacename, TIP_("cursor"), sizeof(t->spacename)); BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, t->spacemtx); break; } case V3D_ORIENT_CUSTOM_MATRIX: - /* Already set. */ BLI_strncpy(t->spacename, TIP_("custom"), sizeof(t->spacename)); + copy_m3_m3(t->spacemtx, t->orientation.custom_matrix); break; case V3D_ORIENT_CUSTOM: + default: + BLI_assert(orientation >= V3D_ORIENT_CUSTOM); BLI_strncpy(t->spacename, t->orientation.custom->name, sizeof(t->spacename)); - if (applyTransformOrientation(t->orientation.custom, t->spacemtx, t->spacename)) { /* pass */ } @@ -505,20 +511,6 @@ void initTransformOrientation(bContext *C, TransInfo *t) } break; } - - if (t->orient_matrix_is_set == false) { - t->orient_matrix_is_set = true; - if (t->flag & T_MODAL) { - /* Rotate for example defaults to operating on the view plane. */ - t->orientation.unset = V3D_ORIENT_VIEW; - copy_m3_m4(t->orient_matrix, t->viewinv); - normalize_m3(t->orient_matrix); - negate_m3(t->orient_matrix); - } - else { - copy_m3_m3(t->orient_matrix, t->spacemtx); - } - } } /** @@ -1072,10 +1064,9 @@ int getTransformOrientation_ex(const bContext *C, ok = true; } else { - int totsel; - - totsel = count_bone_select(arm, &arm->bonebase, true); - if (totsel) { + int transformed_len; + transformed_len = armature_bone_transflags_update_recursive(arm, &arm->bonebase, true); + if (transformed_len) { /* use channels to get stats */ for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { if (pchan->bone && pchan->bone->flag & BONE_TRANSFORM) { diff --git a/source/blender/editors/uvedit/CMakeLists.txt b/source/blender/editors/uvedit/CMakeLists.txt index d2ba9ab9591..b40b82c50fb 100644 --- a/source/blender/editors/uvedit/CMakeLists.txt +++ b/source/blender/editors/uvedit/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC uvedit_draw.c uvedit_ops.c uvedit_parametrizer.c + uvedit_select.c uvedit_smart_stitch.c uvedit_unwrap_ops.c diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c index 6ea1bbbcc10..959ca1eeef1 100644 --- a/source/blender/editors/uvedit/uvedit_draw.c +++ b/source/blender/editors/uvedit/uvedit_draw.c @@ -306,6 +306,7 @@ static void draw_uvs(SpaceImage *sima, Object *ob_eval = batch->ob_eval; const ToolSettings *ts = scene->toolsettings; float col1[4], col2[4], col3[4], transparent[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + const float overlay_alpha = sima->uv_opacity; if (sima->flag & SI_DRAWSHADOW) { bool is_cage_like_final_meshes = false; @@ -346,7 +347,11 @@ static void draw_uvs(SpaceImage *sima, UI_GetThemeColor4fv(TH_FACE, col1); UI_GetThemeColor4fv(TH_FACE_SELECT, col2); UI_GetThemeColor4fv(TH_EDITMESH_ACTIVE, col3); - col3[3] *= 0.2; /* Simulate dithering */ + + col1[3] *= overlay_alpha; + col2[3] *= overlay_alpha; + col3[3] *= overlay_alpha; + GPU_batch_uniform_4fv(batch->faces, "faceColor", col1); GPU_batch_uniform_4fv(batch->faces, "selectColor", col2); GPU_batch_uniform_4fv(batch->faces, "activeColor", col3); @@ -372,9 +377,16 @@ static void draw_uvs(SpaceImage *sima, GPU_line_smooth(true); GPU_blend(true); } + else if (overlay_alpha < 1.0f) { + GPU_blend(true); + } + switch (sima->dt_uv) { case SI_UVDT_DASH: { - float dash_colors[2][4] = {{0.56f, 0.56f, 0.56f, 1.0f}, {0.07f, 0.07f, 0.07f, 1.0f}}; + float dash_colors[2][4] = { + {0.56f, 0.56f, 0.56f, overlay_alpha}, + {0.07f, 0.07f, 0.07f, overlay_alpha}, + }; float viewport_size[4]; GPU_viewport_size_get_f(viewport_size); @@ -398,7 +410,8 @@ static void draw_uvs(SpaceImage *sima, * instead of modifying the provoking vert. */ glProvokingVertex(GL_FIRST_VERTEX_CONVENTION); - UI_GetThemeColor4fv(TH_EDGE_SELECT, col2); + UI_GetThemeColor3fv(TH_EDGE_SELECT, col2); + col2[3] = overlay_alpha; GPU_batch_program_set_builtin( batch->edges, (interpedges) ? GPU_SHADER_2D_UV_EDGES_SMOOTH : GPU_SHADER_2D_UV_EDGES); @@ -406,18 +419,19 @@ static void draw_uvs(SpaceImage *sima, if (sima->dt_uv == SI_UVDT_OUTLINE) { /* Black Outline. */ GPU_line_width(3.0f); - GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, 1.0f); - GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, 1.0f); + GPU_batch_uniform_4f(batch->edges, "edgeColor", 0.0f, 0.0f, 0.0f, overlay_alpha); + GPU_batch_uniform_4f(batch->edges, "selectColor", 0.0f, 0.0f, 0.0f, overlay_alpha); GPU_batch_draw(batch->edges); - UI_GetThemeColor4fv(TH_WIRE_EDIT, col1); + UI_GetThemeColor3fv(TH_WIRE_EDIT, col1); } else if (sima->dt_uv == SI_UVDT_WHITE) { - copy_v4_fl4(col1, 1.0f, 1.0f, 1.0f, 1.0f); + copy_v3_fl3(col1, 1.0f, 1.0f, 1.0f); } else { - copy_v4_fl4(col1, 0.0f, 0.0f, 0.0f, 1.0f); + copy_v3_fl3(col1, 0.0f, 0.0f, 0.0f); } + col1[3] = overlay_alpha; /* Inner Line. Use depth test to insure selection is drawn on top. */ GPU_depth_test(true); @@ -435,6 +449,9 @@ static void draw_uvs(SpaceImage *sima, GPU_line_smooth(false); GPU_blend(false); } + else if (overlay_alpha < 1.0f) { + GPU_blend(false); + } } if (batch->verts || batch->facedots) { UI_GetThemeColor4fv(TH_VERTEX_SELECT, col2); diff --git a/source/blender/editors/uvedit/uvedit_intern.h b/source/blender/editors/uvedit/uvedit_intern.h index 7bc6b048585..ffab5bd094f 100644 --- a/source/blender/editors/uvedit/uvedit_intern.h +++ b/source/blender/editors/uvedit/uvedit_intern.h @@ -99,6 +99,7 @@ bool uv_find_nearest_face_multi(struct Scene *scene, void uvedit_live_unwrap_update(struct SpaceImage *sima, struct Scene *scene, struct Object *obedit); +void uvedit_pixel_to_float(struct SpaceImage *sima, float pixeldist, float r_dist[2]); /* operators */ @@ -113,4 +114,31 @@ void UV_OT_sphere_project(struct wmOperatorType *ot); void UV_OT_unwrap(struct wmOperatorType *ot); void UV_OT_stitch(struct wmOperatorType *ot); +/* uvedit_select.c */ + +bool uvedit_select_is_any_selected(struct Scene *scene, struct Image *ima, struct Object *obedit); +bool uvedit_select_is_any_selected_multi(struct Scene *scene, + struct Image *ima, + struct Object **objects, + const uint objects_len); +const float *uvedit_first_selected_uv_from_vertex(struct Scene *scene, + struct Object *obedit, + struct Image *ima, + struct BMVert *eve, + const int cd_loop_uv_offset); + +void UV_OT_select_all(struct wmOperatorType *ot); +void UV_OT_select(struct wmOperatorType *ot); +void UV_OT_select_loop(struct wmOperatorType *ot); +void UV_OT_select_linked(struct wmOperatorType *ot); +void UV_OT_select_linked_pick(struct wmOperatorType *ot); +void UV_OT_select_split(struct wmOperatorType *ot); +void UV_OT_select_pinned(struct wmOperatorType *ot); +void UV_OT_select_box(struct wmOperatorType *ot); +void UV_OT_select_lasso(struct wmOperatorType *ot); +void UV_OT_select_circle(struct wmOperatorType *ot); +void UV_OT_select_more(struct wmOperatorType *ot); +void UV_OT_select_less(struct wmOperatorType *ot); +void UV_OT_select_overlap(struct wmOperatorType *ot); + #endif /* __UVEDIT_INTERN_H__ */ diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c index e169222380e..a99e05cb52b 100644 --- a/source/blender/editors/uvedit/uvedit_ops.c +++ b/source/blender/editors/uvedit/uvedit_ops.c @@ -36,15 +36,9 @@ #include "DNA_scene_types.h" #include "DNA_space_types.h" -#include "BLI_alloca.h" #include "BLI_array.h" -#include "BLI_blenlib.h" -#include "BLI_hash.h" -#include "BLI_kdopbvh.h" #include "BLI_kdtree.h" -#include "BLI_lasso_2d.h" #include "BLI_math.h" -#include "BLI_polyfill_2d.h" #include "BLI_utildefines.h" #include "BLT_translation.h" @@ -52,31 +46,22 @@ #include "BKE_context.h" #include "BKE_customdata.h" #include "BKE_editmesh.h" -#include "BKE_image.h" #include "BKE_layer.h" #include "BKE_main.h" #include "BKE_material.h" -#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_node.h" -#include "BKE_report.h" -#include "BKE_scene.h" #include "DEG_depsgraph.h" -#include "DEG_depsgraph_query.h" #include "ED_image.h" #include "ED_mesh.h" #include "ED_node.h" -#include "ED_object.h" #include "ED_screen.h" -#include "ED_select_utils.h" -#include "ED_transform.h" #include "ED_uvedit.h" #include "RNA_access.h" #include "RNA_define.h" -#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_message.h" @@ -88,26 +73,6 @@ #include "uvedit_intern.h" -static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit); -static bool uv_select_is_any_selected_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len); -static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action); -static void uv_select_all_perform_multi( - Scene *scene, Image *ima, Object **objects, const uint objects_len, int action); -static void uv_select_flush_from_tag_face(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select); -static void uv_select_flush_from_tag_loop(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select); -static void uv_select_tag_update_for_object(Depsgraph *depsgraph, - const ToolSettings *ts, - Object *obedit); - /* -------------------------------------------------------------------- */ /** \name State Testing * \{ */ @@ -225,7 +190,7 @@ void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *i /** \name Space Conversion * \{ */ -static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist) +void uvedit_pixel_to_float(SpaceImage *sima, float pixeldist, float r_dist[2]) { int width, height; @@ -237,351 +202,8 @@ static void uvedit_pixel_to_float(SpaceImage *sima, float *dist, float pixeldist height = IMG_SIZE_FALLBACK; } - dist[0] = pixeldist / width; - dist[1] = pixeldist / height; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Visibility and Selection Utilities - * \{ */ - -static void uvedit_vertex_select_tagged(BMEditMesh *em, - Scene *scene, - bool select, - int cd_loop_uv_offset) -{ - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } -} - -bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0); - } - else { - return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); - } -} -bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa) -{ - return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa); -} - -bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa) -{ - if (ts->uv_flag & UV_SHOW_SAME_IMAGE) { - Image *face_image; - ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL); - return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false; - } - else { - return uvedit_face_visible_nolocal_ex(ts, efa); - } -} -bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa) -{ - return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa); -} - -bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (BM_elem_flag_test(efa, BM_ELEM_SELECT)); - } - else { - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (!(luv->flag & MLOOPUV_VERTSEL)) { - return false; - } - } - - return true; - } -} -bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_uv_offset) -{ - return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset); -} - -bool uvedit_face_select_set(const struct Scene *scene, - struct BMEditMesh *em, - struct BMFace *efa, - const bool select, - const bool do_history, - const int cd_loop_uv_offset) -{ - if (select) { - return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset); - } - else { - return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); - } -} - -bool uvedit_face_select_enable(const Scene *scene, - BMEditMesh *em, - BMFace *efa, - const bool do_history, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - BM_face_select_set(em->bm, efa, true); - if (do_history) { - BM_select_history_store(em->bm, (BMElem *)efa); - } - } - else { - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; - } - - return true; - } - - return false; -} - -bool uvedit_face_select_disable(const Scene *scene, - BMEditMesh *em, - BMFace *efa, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - BM_face_select_set(em->bm, efa, false); - } - else { - BMLoop *l; - MLoopUV *luv; - BMIter liter; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag &= ~MLOOPUV_VERTSEL; - } - - return true; - } - - return false; -} - -bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - return BM_elem_flag_test(l->f, BM_ELEM_SELECT); - } - else if (ts->selectmode == SCE_SELECT_EDGE) { - return BM_elem_flag_test(l->e, BM_ELEM_SELECT); - } - else { - return BM_elem_flag_test(l->v, BM_ELEM_SELECT) && - BM_elem_flag_test(l->next->v, BM_ELEM_SELECT); - } - } - else { - MLoopUV *luv1, *luv2; - - luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL); - } -} -bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) -{ - return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); -} - -void uvedit_edge_select_set(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool select, - const bool do_history, - const int cd_loop_uv_offset) - -{ - if (select) { - uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset); - } - else { - uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset); - } -} - -void uvedit_edge_select_enable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool do_history, - const int cd_loop_uv_offset) - -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, true); - } - else if (ts->selectmode & SCE_SELECT_EDGE) { - BM_edge_select_set(em->bm, l->e, true); - } - else { - BM_vert_select_set(em->bm, l->e->v1, true); - BM_vert_select_set(em->bm, l->e->v2, true); - } - - if (do_history) { - BM_select_history_store(em->bm, (BMElem *)l->e); - } - } - else { - MLoopUV *luv1, *luv2; - - luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - luv1->flag |= MLOOPUV_VERTSEL; - luv2->flag |= MLOOPUV_VERTSEL; - } -} - -void uvedit_edge_select_disable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const int cd_loop_uv_offset) - -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, false); - } - else if (ts->selectmode & SCE_SELECT_EDGE) { - BM_edge_select_set(em->bm, l->e, false); - } - else { - BM_vert_select_set(em->bm, l->e->v1, false); - BM_vert_select_set(em->bm, l->e->v2, false); - } - } - else { - MLoopUV *luv1, *luv2; - - luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - luv1->flag &= ~MLOOPUV_VERTSEL; - luv2->flag &= ~MLOOPUV_VERTSEL; - } -} - -bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT); - } - else { - return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT); - } - } - else { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - return (luv->flag & MLOOPUV_VERTSEL) != 0; - } -} -bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) -{ - return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); -} - -void uvedit_uv_select_set(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool select, - const bool do_history, - const int cd_loop_uv_offset) -{ - if (select) { - uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset); - } - else { - uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset); - } -} - -void uvedit_uv_select_enable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const bool do_history, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, true); - } - else { - BM_vert_select_set(em->bm, l->v, true); - } - - if (do_history) { - BM_select_history_remove(em->bm, (BMElem *)l->v); - } - } - else { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag |= MLOOPUV_VERTSEL; - } -} - -void uvedit_uv_select_disable(BMEditMesh *em, - const Scene *scene, - BMLoop *l, - const int cd_loop_uv_offset) -{ - const ToolSettings *ts = scene->toolsettings; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode & SCE_SELECT_FACE) { - BM_face_select_set(em->bm, l->f, false); - } - else { - BM_vert_select_set(em->bm, l->v, false); - } - } - else { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag &= ~MLOOPUV_VERTSEL; - } + r_dist[0] = pixeldist / width; + r_dist[1] = pixeldist / height; } /** \} */ @@ -770,7 +392,8 @@ bool ED_uvedit_center_from_pivot_ex(SpaceImage *sima, uint objects_len = 0; Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( view_layer, ((View3D *)NULL), &objects_len); - *r_has_select = uv_select_is_any_selected_multi(scene, sima->image, objects, objects_len); + *r_has_select = uvedit_select_is_any_selected_multi( + scene, sima->image, objects, objects_len); MEM_freeN(objects); } break; @@ -799,877 +422,6 @@ bool ED_uvedit_center_from_pivot( /** \} */ /* -------------------------------------------------------------------- */ -/** \name Find Nearest Elements - * \{ */ - -bool uv_find_nearest_edge( - Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv, *luv_next; - int i; - bool found = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - - const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); - - if (dist_test_sq < hit->dist_sq) { - hit->efa = efa; - - hit->l = l; - hit->luv = luv; - hit->luv_next = luv_next; - hit->lindex = i; - - hit->dist_sq = dist_test_sq; - found = true; - } - } - } - return found; -} - -bool uv_find_nearest_edge_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float co[2], - UvNearestHit *hit_final) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) { - hit_final->ob = obedit; - found = true; - } - } - return found; -} - -bool uv_find_nearest_face( - Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - bool found = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* this will fill in hit.vert1 and hit.vert2 */ - float dist_sq_init = hit_final->dist_sq; - UvNearestHit hit = *hit_final; - if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { - hit.dist_sq = dist_sq_init; - hit.l = NULL; - hit.luv = hit.luv_next = NULL; - - BMIter iter; - BMFace *efa; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); - - const float dist_test_sq = len_squared_v2v2(co, cent); - - if (dist_test_sq < hit.dist_sq) { - hit.efa = efa; - hit.dist_sq = dist_test_sq; - found = true; - } - } - } - if (found) { - *hit_final = hit; - } - return found; -} - -bool uv_find_nearest_face_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float co[2], - UvNearestHit *hit_final) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) { - hit_final->ob = obedit; - found = true; - } - } - return found; -} - -static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset) -{ - const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv; - const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv; - const float *uv_next = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset))->uv; - - return ((line_point_side_v2(uv_prev, uv_curr, co) > 0.0f) && - (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f)); -} - -bool uv_find_nearest_vert(Scene *scene, - Image *ima, - Object *obedit, - float const co[2], - const float penalty_dist, - UvNearestHit *hit_final) -{ - bool found = false; - - /* this will fill in hit.vert1 and hit.vert2 */ - float dist_sq_init = hit_final->dist_sq; - UvNearestHit hit = *hit_final; - if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { - hit.dist_sq = dist_sq_init; - - hit.l = NULL; - hit.luv = hit.luv_next = NULL; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMIter iter; - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BMIter liter; - BMLoop *l; - int i; - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - float dist_test_sq; - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist; - dist_test_sq = square_f(dist_test_sq); - } - else { - dist_test_sq = len_squared_v2v2(co, luv->uv); - } - - if (dist_test_sq <= hit.dist_sq) { - if (dist_test_sq == hit.dist_sq) { - if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { - continue; - } - } - - hit.dist_sq = dist_test_sq; - - hit.l = l; - hit.luv = luv; - hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); - hit.efa = efa; - hit.lindex = i; - found = true; - } - } - } - } - - if (found) { - *hit_final = hit; - } - - return found; -} - -bool uv_find_nearest_vert_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - float const co[2], - const float penalty_dist, - UvNearestHit *hit_final) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) { - hit_final->ob = obedit; - found = true; - } - } - return found; -} - -bool ED_uvedit_nearest_uv(const Scene *scene, - Object *obedit, - Image *ima, - const float co[2], - float *dist_sq, - float r_uv[2]) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMIter iter; - BMFace *efa; - const float *uv_best = NULL; - float dist_best = *dist_sq; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - BMLoop *l_iter, *l_first; - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - do { - const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv; - const float dist_test = len_squared_v2v2(co, uv); - if (dist_best > dist_test) { - dist_best = dist_test; - uv_best = uv; - } - } while ((l_iter = l_iter->next) != l_first); - } - - if (uv_best != NULL) { - copy_v2_v2(r_uv, uv_best); - *dist_sq = dist_best; - return true; - } - else { - return false; - } -} - -bool ED_uvedit_nearest_uv_multi(const Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float co[2], - float *dist_sq, - float r_uv[2]) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) { - found = true; - } - } - return found; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Loop Select - * \{ */ - -static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first) -{ - UvMapVert *iterv; - int count = 0; - - for (iterv = first; iterv; iterv = iterv->next) { - if (iterv->separate && iterv != first) { - break; - } - - count++; - } - - if (count < 5) { - first->flag = 1; - } -} - -static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l) -{ - UvMapVert *iterv, *first; - first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); - - for (iterv = first; iterv; iterv = iterv->next) { - if (iterv->separate) { - first = iterv; - } - if (iterv->poly_index == BM_elem_index_get(efa)) { - return first; - } - } - - return NULL; -} - -static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, - UvMapVert *first1, - UvMapVert *first2, - int *totface) -{ - UvMapVert *iterv1, *iterv2; - BMFace *efa; - int tot = 0; - - /* count number of faces this edge has */ - for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { - if (iterv1->separate && iterv1 != first1) { - break; - } - - for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { - if (iterv2->separate && iterv2 != first2) { - break; - } - - if (iterv1->poly_index == iterv2->poly_index) { - /* if face already tagged, don't do this edge */ - efa = BM_face_at_index(em->bm, iterv1->poly_index); - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - return false; - } - - tot++; - break; - } - } - } - - if (*totface == 0) { /* start edge */ - *totface = tot; - } - else if (tot != *totface) { /* check for same number of faces as start edge */ - return false; - } - - /* tag the faces */ - for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { - if (iterv1->separate && iterv1 != first1) { - break; - } - - for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { - if (iterv2->separate && iterv2 != first2) { - break; - } - - if (iterv1->poly_index == iterv2->poly_index) { - efa = BM_face_at_index(em->bm, iterv1->poly_index); - BM_elem_flag_enable(efa, BM_ELEM_TAG); - break; - } - } - } - - return true; -} - -static int uv_select_edgeloop(Scene *scene, - Image *ima, - Object *obedit, - UvNearestHit *hit, - const float limit[2], - const bool extend) -{ - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMIter iter, liter; - BMLoop *l; - UvVertMap *vmap; - UvMapVert *iterv_curr; - UvMapVert *iterv_next; - int starttotf; - bool looking, select; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* setup */ - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, limit, false, false); - - BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); - - if (!extend) { - uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); - } - - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - - /* set flags for first face and verts */ - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); - iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); - uv_select_edgeloop_vertex_loop_flag(iterv_curr); - uv_select_edgeloop_vertex_loop_flag(iterv_next); - - starttotf = 0; - uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf); - - /* sorry, first edge isn't even ok */ - looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0); - - /* iterate */ - while (looking) { - looking = false; - - /* find correct valence edges which are not tagged yet, but connect to tagged one */ - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && - uvedit_face_visible_test(scene, obedit, ima, efa)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - /* check face not hidden and not tagged */ - if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) { - continue; - } - if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) { - continue; - } - - /* check if vertex is tagged and has right valence */ - if (iterv_curr->flag || iterv_next->flag) { - if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) { - looking = true; - BM_elem_flag_enable(efa, BM_ELEM_TAG); - - uv_select_edgeloop_vertex_loop_flag(iterv_curr); - uv_select_edgeloop_vertex_loop_flag(iterv_next); - break; - } - } - } - } - } - } - - /* do the actual select/deselect */ - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); - iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); - iterv_curr->flag = 1; - iterv_next->flag = 1; - - if (extend) { - select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset)); - } - else { - select = true; - } - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l); - - if (iterv_curr->flag) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - - /* cleanup */ - BM_uv_vert_map_free(vmap); - - return (select) ? 1 : -1; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Linked - * \{ */ - -static void uv_select_linked_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len, - const float limit[2], - UvNearestHit *hit_final, - bool extend, - bool deselect, - bool toggle, - bool select_faces) -{ - /* loop over objects, or just use hit_final->ob */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - if (hit_final && ob_index != 0) { - break; - } - Object *obedit = hit_final ? hit_final->ob : objects[ob_index]; - - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - UvVertMap *vmap; - UvMapVert *vlist, *iterv, *startv; - int i, stacksize = 0, *stack; - uint a; - char *flag; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ - - /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320 - * this made *every* projection split the island into front/back islands. - * Keep 'use_winding' to false, see: T50970. - * - * Better solve this by having a delimit option for select-linked operator, - * keeping island-select working as is. */ - vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); - - if (vmap == NULL) { - continue; - } - - stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack"); - flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag"); - - if (hit_final == NULL) { - /* Use existing selection */ - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - if (select_faces) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - } - } - else { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - - break; - } - } - } - } - } - } - else { - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (efa == hit_final->efa) { - stack[stacksize] = a; - stacksize++; - flag[a] = 1; - break; - } - } - } - - while (stacksize > 0) { - - stacksize--; - a = stack[stacksize]; - - efa = BM_face_at_index(em->bm, a); - - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { - - /* make_uv_vert_map_EM sets verts tmp.l to the indices */ - vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); - - startv = vlist; - - for (iterv = vlist; iterv; iterv = iterv->next) { - if (iterv->separate) { - startv = iterv; - } - if (iterv->poly_index == a) { - break; - } - } - - for (iterv = startv; iterv; iterv = iterv->next) { - if ((startv != iterv) && (iterv->separate)) { - break; - } - else if (!flag[iterv->poly_index]) { - flag[iterv->poly_index] = 1; - stack[stacksize] = iterv->poly_index; - stacksize++; - } - } - } - } - - /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */ - if ((toggle == true) && (extend == false) && (deselect == false)) { - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - bool found_selected = false; - if (!flag[a]) { - continue; - } - - if (select_faces) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { - found_selected = true; - } - } - else { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { - found_selected = true; - } - } - - if (found_selected) { - deselect = true; - break; - } - } - } - } - -#define SET_SELECTION(value) \ - if (select_faces) { \ - BM_face_select_set(em->bm, efa, value); \ - } \ - else { \ - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \ - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \ - luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \ - } \ - } \ - (void)0 - - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { - if (!flag[a]) { - if (!extend && !deselect && !toggle) { - SET_SELECTION(false); - } - continue; - } - - if (!deselect) { - SET_SELECTION(true); - } - else { - SET_SELECTION(false); - } - } - -#undef SET_SELECTION - - MEM_freeN(stack); - MEM_freeN(flag); - BM_uv_vert_map_free(vmap); - } -} - -/* WATCH IT: this returns first selected UV, - * not ideal in many cases since there could be multiple */ -static float *uv_sel_co_from_eve( - Scene *scene, Object *obedit, Image *ima, BMEditMesh *em, BMVert *eve) -{ - BMIter liter; - BMLoop *l; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { - if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { - continue; - } - - if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - return luv->uv; - } - } - - return NULL; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select More/Less Operator - * \{ */ - -static int uv_select_more_less(bContext *C, const bool select) -{ - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - SpaceImage *sima = CTX_wm_space_image(C); - - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - const ToolSettings *ts = scene->toolsettings; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (select) { - EDBM_select_more(em, true); - } - else { - EDBM_select_less(em, true); - } - - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - continue; - } - - if (is_uv_face_selectmode) { - - /* clear tags */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - - /* mark loops to be selected */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - -#define IS_SEL 1 -#define IS_UNSEL 2 - - int sel_state = 0; - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (luv->flag & MLOOPUV_VERTSEL) { - sel_state |= IS_SEL; - } - else { - sel_state |= IS_UNSEL; - } - - /* if we have a mixed selection, tag to grow it */ - if (sel_state == (IS_SEL | IS_UNSEL)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - break; - } - } - -#undef IS_SEL -#undef IS_UNSEL - } - } - } - else { - - /* clear tags */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - BM_elem_flag_disable(l, BM_ELEM_TAG); - } - } - - /* mark loops to be selected */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (((luv->flag & MLOOPUV_VERTSEL) != 0) == select) { - BM_elem_flag_enable(l->next, BM_ELEM_TAG); - BM_elem_flag_enable(l->prev, BM_ELEM_TAG); - changed = true; - } - } - } - } - } - - if (changed) { - if (is_uv_face_selectmode) { - /* Select tagged faces. */ - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - else { - /* Select tagged loops. */ - uv_select_flush_from_tag_loop(sima, scene, obedit, select); - } - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - } - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static int uv_select_more_exec(bContext *C, wmOperator *UNUSED(op)) -{ - return uv_select_more_less(C, true); -} - -static void UV_OT_select_more(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select More"; - ot->description = "Select more UV vertices connected to initial selection"; - ot->idname = "UV_OT_select_more"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_more_exec; - ot->poll = ED_operator_uvedit_space_image; -} - -static int uv_select_less_exec(bContext *C, wmOperator *UNUSED(op)) -{ - return uv_select_more_less(C, false); -} - -static void UV_OT_select_less(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Less"; - ot->description = "Deselect UV vertices at the boundary of each selection region"; - ot->idname = "UV_OT_select_less"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_less_exec; - ot->poll = ED_operator_uvedit_space_image; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Weld Align Operator * \{ */ @@ -1866,9 +618,10 @@ static void uv_weld_align(bContext *C, eUVWeldAlign tool) if (BLI_array_len(eve_line) > 2) { /* we know the returns from these must be valid */ - const float *uv_start = uv_sel_co_from_eve(scene, obedit, ima, em, eve_line[0]); - const float *uv_end = uv_sel_co_from_eve( - scene, obedit, ima, em, eve_line[BLI_array_len(eve_line) - 1]); + const float *uv_start = uvedit_first_selected_uv_from_vertex( + scene, obedit, ima, eve_line[0], cd_loop_uv_offset); + const float *uv_end = uvedit_first_selected_uv_from_vertex( + scene, obedit, ima, eve_line[BLI_array_len(eve_line) - 1], cd_loop_uv_offset); /* For UV_STRAIGHTEN_X & UV_STRAIGHTEN_Y modes */ float a = 0.0f; eUVWeldAlign tool_local = tool; @@ -2316,1665 +1069,6 @@ static void UV_OT_weld(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name (De)Select All Operator - * \{ */ - -static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) -{ - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel); - } - else { - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (luv->flag & MLOOPUV_VERTSEL) { - return true; - } - } - } - } - return false; -} - -static bool uv_select_is_any_selected_multi(Scene *scene, - Image *ima, - Object **objects, - const uint objects_len) -{ - bool found = false; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - if (uv_select_is_any_selected(scene, ima, obedit)) { - found = true; - break; - } - } - return found; -} - -static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action) -{ - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if (action == SEL_TOGGLE) { - action = uv_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT; - } - - if (ts->uv_flag & UV_SYNC_SELECTION) { - switch (action) { - case SEL_TOGGLE: - EDBM_select_toggle_all(em); - break; - case SEL_SELECT: - EDBM_flag_enable_all(em, BM_ELEM_SELECT); - break; - case SEL_DESELECT: - EDBM_flag_disable_all(em, BM_ELEM_SELECT); - break; - case SEL_INVERT: - EDBM_select_swap(em); - EDBM_selectmode_flush(em); - break; - } - } - else { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - switch (action) { - case SEL_SELECT: - luv->flag |= MLOOPUV_VERTSEL; - break; - case SEL_DESELECT: - luv->flag &= ~MLOOPUV_VERTSEL; - break; - case SEL_INVERT: - luv->flag ^= MLOOPUV_VERTSEL; - break; - } - } - } - } -} - -static void uv_select_all_perform_multi( - Scene *scene, Image *ima, Object **objects, const uint objects_len, int action) -{ - if (action == SEL_TOGGLE) { - action = uv_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT : - SEL_SELECT; - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - uv_select_all_perform(scene, ima, obedit, action); - } -} - -static int uv_select_all_exec(bContext *C, wmOperator *op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - - int action = RNA_enum_get(op->ptr, "action"); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - uv_select_all_perform_multi(scene, ima, objects, objects_len, action); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static void UV_OT_select_all(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "(De)select All"; - ot->description = "Change selection of all UV vertices"; - ot->idname = "UV_OT_select_all"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_all_exec; - ot->poll = ED_operator_uvedit; - - WM_operator_properties_select_all(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Mouse Select Operator - * \{ */ - -static bool uv_sticky_select( - float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen) -{ - int i; - - /* this function test if some vertex needs to selected - * in addition to the existing ones due to sticky select */ - if (sticky == SI_STICKY_DISABLE) { - return false; - } - - for (i = 0; i < hitlen; i++) { - if (hitv[i] == v) { - if (sticky == SI_STICKY_LOC) { - if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) { - return true; - } - } - else if (sticky == SI_STICKY_VERTEX) { - return true; - } - } - } - - return false; -} - -static int uv_mouse_select_multi(bContext *C, - Object **objects, - uint objects_len, - const float co[2], - const bool extend, - const bool deselect_all, - const bool loop) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - UvNearestHit hit = UV_NEAREST_HIT_INIT; - int i, selectmode, sticky, sync, *hitv = NULL; - bool select = true; - bool found_item = false; - /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ - int flush = 0; - int hitlen = 0; - float limit[2], **hituv = NULL; - - /* notice 'limit' is the same no matter the zoom level, since this is like - * remove doubles and could annoying if it joined points when zoomed out. - * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and - * shift-selecting can consider an adjacent point close enough to add to - * the selection rather than de-selecting the closest. */ - - float penalty_dist; - { - float penalty[2]; - uvedit_pixel_to_float(sima, limit, 0.05f); - uvedit_pixel_to_float(sima, penalty, 5.0f / (sima ? sima->zoom : 1.0f)); - penalty_dist = len_v2(penalty); - } - - /* retrieve operation mode */ - if (ts->uv_flag & UV_SYNC_SELECTION) { - sync = 1; - - if (ts->selectmode & SCE_SELECT_FACE) { - selectmode = UV_SELECT_FACE; - } - else if (ts->selectmode & SCE_SELECT_EDGE) { - selectmode = UV_SELECT_EDGE; - } - else { - selectmode = UV_SELECT_VERTEX; - } - - sticky = SI_STICKY_DISABLE; - } - else { - sync = 0; - selectmode = ts->uv_selectmode; - sticky = (sima) ? sima->sticky : 1; - } - - /* find nearest element */ - if (loop) { - /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); - } - else if (selectmode == UV_SELECT_VERTEX) { - /* find vertex */ - found_item = uv_find_nearest_vert_multi( - scene, ima, objects, objects_len, co, penalty_dist, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - - if (found_item) { - /* mark 1 vertex as being hit */ - hitv = BLI_array_alloca(hitv, hit.efa->len); - hituv = BLI_array_alloca(hituv, hit.efa->len); - copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); - - hitv[hit.lindex] = BM_elem_index_get(hit.l->v); - hituv[hit.lindex] = hit.luv->uv; - - hitlen = hit.efa->len; - } - } - else if (selectmode == UV_SELECT_EDGE) { - /* find edge */ - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - - if (found_item) { - /* mark 2 edge vertices as being hit */ - hitv = BLI_array_alloca(hitv, hit.efa->len); - hituv = BLI_array_alloca(hituv, hit.efa->len); - copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); - - hitv[hit.lindex] = BM_elem_index_get(hit.l->v); - hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v); - hituv[hit.lindex] = hit.luv->uv; - hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv; - - hitlen = hit.efa->len; - } - } - else if (selectmode == UV_SELECT_FACE) { - /* find face */ - found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - - if (found_item) { - BMEditMesh *em = BKE_editmesh_from_object(hit.ob); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* make active */ - BM_mesh_active_face_set(em->bm, hit.efa); - - /* mark all face vertices as being hit */ - - hitv = BLI_array_alloca(hitv, hit.efa->len); - hituv = BLI_array_alloca(hituv, hit.efa->len); - BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - hituv[i] = luv->uv; - hitv[i] = BM_elem_index_get(l->v); - } - - hitlen = hit.efa->len; - } - } - else if (selectmode == UV_SELECT_ISLAND) { - found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); - found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); - } - - if (!found_item) { - if (deselect_all) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; - } - return OPERATOR_CANCELLED; - } - - Object *obedit = hit.ob; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* do selection */ - if (loop) { - if (!extend) { - /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend); - } - else if (selectmode == UV_SELECT_ISLAND) { - if (!extend) { - /* TODO(MULTI_EDIT): We only need to de-select non-active */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - /* Current behavior of 'extend' - * is actually toggling, so pass extend flag as 'toggle' here */ - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, false, false, extend, false); - } - else if (extend) { - if (selectmode == UV_SELECT_VERTEX) { - /* (de)select uv vertex */ - select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset); - uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_EDGE) { - /* (de)select edge */ - select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset)); - uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_FACE) { - /* (de)select face */ - select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset)); - uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset); - flush = -1; - } - - /* de-selecting an edge may deselect a face too - validate */ - if (sync) { - if (select == false) { - BM_select_history_validate(em->bm); - } - } - - /* (de)select sticky uv nodes */ - if (sticky != SI_STICKY_DISABLE) { - - BM_mesh_elem_index_ensure(em->bm, BM_VERT); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uv_sticky_select( - limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - - flush = select ? 1 : -1; - } - } - else { - /* deselect all */ - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - - if (selectmode == UV_SELECT_VERTEX) { - /* select vertex */ - uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_EDGE) { - /* select edge */ - uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); - flush = 1; - } - else if (selectmode == UV_SELECT_FACE) { - /* select face */ - uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset); - } - - /* select sticky uvs */ - if (sticky != SI_STICKY_DISABLE) { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (sticky == SI_STICKY_DISABLE) { - continue; - } - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (uv_sticky_select( - limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { - uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); - } - - flush = 1; - } - } - } - } - - if (sync) { - /* flush for mesh selection */ - - /* before bmesh */ -#if 0 - if (ts->selectmode != SCE_SELECT_FACE) { - if (flush == 1) { - EDBM_select_flush(em); - } - else if (flush == -1) { - EDBM_deselect_flush(em); - } - } -#else - if (flush != 0) { - if (loop) { - /* push vertex -> edge selection */ - if (select) { - EDBM_select_flush(em); - } - else { - EDBM_deselect_flush(em); - } - } - else { - EDBM_selectmode_flush(em); - } - } -#endif - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obiter = objects[ob_index]; - uv_select_tag_update_for_object(depsgraph, ts, obiter); - } - - return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; -} -static int uv_mouse_select( - bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop) -{ - ViewLayer *view_layer = CTX_data_view_layer(C); - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop); - MEM_freeN(objects); - return ret; -} - -static int uv_select_exec(bContext *C, wmOperator *op) -{ - float co[2]; - - RNA_float_get_array(op->ptr, "location", co); - const bool extend = RNA_boolean_get(op->ptr, "extend"); - const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); - const bool loop = false; - - return uv_mouse_select(C, co, extend, deselect_all, loop); -} - -static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - ARegion *region = CTX_wm_region(C); - float co[2]; - - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); - RNA_float_set_array(op->ptr, "location", co); - - return uv_select_exec(C, op); -} - -static void UV_OT_select(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select"; - ot->description = "Select UV vertices"; - ot->idname = "UV_OT_select"; - ot->flag = OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_exec; - ot->invoke = uv_select_invoke; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* properties */ - PropertyRNA *prop; - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - prop = RNA_def_boolean(ot->srna, - "deselect_all", - false, - "Deselect On Nothing", - "Deselect all when nothing under the cursor"); - RNA_def_property_flag(prop, PROP_SKIP_SAVE); - - RNA_def_float_vector( - ot->srna, - "location", - 2, - NULL, - -FLT_MAX, - FLT_MAX, - "Location", - "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", - -100.0f, - 100.0f); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Loop Select Operator - * \{ */ - -static int uv_select_loop_exec(bContext *C, wmOperator *op) -{ - float co[2]; - - RNA_float_get_array(op->ptr, "location", co); - const bool extend = RNA_boolean_get(op->ptr, "extend"); - const bool deselect_all = false; - const bool loop = true; - - return uv_mouse_select(C, co, extend, deselect_all, loop); -} - -static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - ARegion *region = CTX_wm_region(C); - float co[2]; - - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); - RNA_float_set_array(op->ptr, "location", co); - - return uv_select_loop_exec(C, op); -} - -static void UV_OT_select_loop(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Loop Select"; - ot->description = "Select a loop of connected UV vertices"; - ot->idname = "UV_OT_select_loop"; - ot->flag = OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_loop_exec; - ot->invoke = uv_select_loop_invoke; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* properties */ - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - RNA_def_float_vector( - ot->srna, - "location", - 2, - NULL, - -FLT_MAX, - FLT_MAX, - "Location", - "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", - -100.0f, - 100.0f); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Linked Operator - * \{ */ - -static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick) -{ - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - float limit[2]; - bool extend = true; - bool deselect = false; - bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE); - - UvNearestHit hit = UV_NEAREST_HIT_INIT; - - if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { - BKE_report(op->reports, - RPT_ERROR, - "Select linked only works in face select mode when sync selection is enabled"); - return OPERATOR_CANCELLED; - } - - if (pick) { - extend = RNA_boolean_get(op->ptr, "extend"); - deselect = RNA_boolean_get(op->ptr, "deselect"); - } - uvedit_pixel_to_float(sima, limit, 0.05f); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - if (pick) { - float co[2]; - - if (event) { - /* invoke */ - ARegion *region = CTX_wm_region(C); - - UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); - RNA_float_set_array(op->ptr, "location", co); - } - else { - /* exec */ - RNA_float_get_array(op->ptr, "location", co); - } - - if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) { - MEM_freeN(objects); - return OPERATOR_CANCELLED; - } - } - - if (!extend) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - uv_select_linked_multi(scene, - ima, - objects, - objects_len, - limit, - pick ? &hit : NULL, - extend, - deselect, - false, - select_faces); - - /* weak!, but works */ - Object **objects_free = objects; - if (pick) { - objects = &hit.ob; - objects_len = 1; - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); - WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); - } - - MEM_SAFE_FREE(objects_free); - - return OPERATOR_FINISHED; -} - -static int uv_select_linked_exec(bContext *C, wmOperator *op) -{ - return uv_select_linked_internal(C, op, NULL, false); -} - -static void UV_OT_select_linked(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Linked"; - ot->description = "Select all UV vertices linked to the active UV map"; - ot->idname = "UV_OT_select_linked"; - - /* api callbacks */ - ot->exec = uv_select_linked_exec; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Linked (Cursor Pick) Operator - * \{ */ - -static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) -{ - return uv_select_linked_internal(C, op, event, true); -} - -static int uv_select_linked_pick_exec(bContext *C, wmOperator *op) -{ - return uv_select_linked_internal(C, op, NULL, true); -} - -static void UV_OT_select_linked_pick(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Linked Pick"; - ot->description = "Select all UV vertices linked under the mouse"; - ot->idname = "UV_OT_select_linked_pick"; - - /* flags */ - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->invoke = uv_select_linked_pick_invoke; - ot->exec = uv_select_linked_pick_exec; - ot->poll = ED_operator_uvedit; /* requires space image */ - - /* properties */ - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); - RNA_def_boolean(ot->srna, - "deselect", - 0, - "Deselect", - "Deselect linked UV vertices rather than selecting them"); - RNA_def_float_vector( - ot->srna, - "location", - 2, - NULL, - -FLT_MAX, - FLT_MAX, - "Location", - "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", - -100.0f, - 100.0f); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Split Operator - * \{ */ - -/** - * \note This is based on similar use case to #MESH_OT_split(), which has a similar effect - * but in this case they are not joined to begin with (only having the behavior of being joined) - * so its best to call this #uv_select_split() instead of just split(), but assigned to the same - * key as #MESH_OT_split - Campbell. - */ -static int uv_select_split_exec(bContext *C, wmOperator *op) -{ - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const ToolSettings *ts = scene->toolsettings; - Image *ima = CTX_data_edit_image(C); - - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - if (ts->uv_flag & UV_SYNC_SELECTION) { - BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); - return OPERATOR_CANCELLED; - } - - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMesh *bm = BKE_editmesh_from_object(obedit)->bm; - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - bool is_sel = false; - bool is_unsel = false; - - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - /* are we all selected? */ - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_VERTSEL) { - is_sel = true; - } - else { - is_unsel = true; - } - - /* we have mixed selection, bail out */ - if (is_sel && is_unsel) { - break; - } - } - - if (is_sel && is_unsel) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - luv->flag &= ~MLOOPUV_VERTSEL; - } - - changed = true; - } - } - - if (changed) { - changed_multi = true; - WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL); - } - } - MEM_freeN(objects); - - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; -} - -static void UV_OT_select_split(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Split"; - ot->description = "Select only entirely selected faces"; - ot->idname = "UV_OT_select_split"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_split_exec; - ot->poll = ED_operator_uvedit; /* requires space image */ -} - -static void uv_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const short select) -{ - /* bmesh API handles flushing but not on de-select */ - if (ts->uv_flag & UV_SYNC_SELECTION) { - if (ts->selectmode != SCE_SELECT_FACE) { - if (select == false) { - EDBM_deselect_flush(em); - } - else { - EDBM_select_flush(em); - } - } - - if (select == false) { - BM_select_history_validate(em->bm); - } - } -} - -static void uv_select_tag_update_for_object(Depsgraph *depsgraph, - const ToolSettings *ts, - Object *obedit) -{ - if (ts->uv_flag & UV_SYNC_SELECTION) { - DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); - WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); - } - else { - Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); - BKE_mesh_batch_cache_dirty_tag(obedit_eval->data, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT); - /* Only for region redraw. */ - WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); - } -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select/Tag Flushing Utils - * - * Utility functions to flush the uv-selection from tags. - * \{ */ - -/** - * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face - */ -static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, - BMEditMesh *em, - UvVertMap *vmap, - const uint efa_index, - BMLoop *l, - const bool select, - const int cd_loop_uv_offset) -{ - UvMapVert *start_vlist = NULL, *vlist_iter; - BMFace *efa_vlist; - - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - - vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); - - while (vlist_iter) { - if (vlist_iter->separate) { - start_vlist = vlist_iter; - } - - if (efa_index == vlist_iter->poly_index) { - break; - } - - vlist_iter = vlist_iter->next; - } - - vlist_iter = start_vlist; - while (vlist_iter) { - - if (vlist_iter != start_vlist && vlist_iter->separate) { - break; - } - - if (efa_index != vlist_iter->poly_index) { - BMLoop *l_other; - efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index); - /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */ - - l_other = BM_iter_at_index( - em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index); - - uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset); - } - vlist_iter = vlist_iter->next; - } -} - -/** - * Flush the selection from face tags based on sticky and selection modes. - * - * needed because settings the selection a face is done in a number of places but it also - * needs to respect the sticky modes for the UV verts, so dealing with the sticky modes - * is best done in a separate function. - * - * \note This function is very similar to #uv_select_flush_from_tag_loop, - * be sure to update both upon changing. - */ -static void uv_select_flush_from_tag_face(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select) -{ - /* Selecting UV Faces with some modes requires us to change - * the selection in other faces (depending on the sticky mode). - * - * This only needs to be done when the Mesh is not used for - * selection (so for sticky modes, vertex or location based). */ - - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { - /* Tag all verts as untouched, then touch the ones that have a face center - * in the loop and select all MLoopUV's that use a touched vert. */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } - } - } - - /* now select tagged verts */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - } - else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { - struct UvVertMap *vmap; - float limit[2]; - uint efa_index; - - uvedit_pixel_to_float(sima, limit, 0.05); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, limit, false, false); - if (vmap == NULL) { - return; - } - - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - uv_select_flush_from_tag_sticky_loc_internal( - scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); - } - } - } - BM_uv_vert_map_free(vmap); - } - else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { - uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset); - } - } - } -} - -/** - * Flush the selection from loop tags based on sticky and selection modes. - * - * needed because settings the selection a face is done in a number of places but it also needs - * to respect the sticky modes for the UV verts, so dealing with the sticky modes is best done - * in a separate function. - * - * \note This function is very similar to #uv_select_flush_from_tag_loop, - * be sure to update both upon changing. - */ -static void uv_select_flush_from_tag_loop(SpaceImage *sima, - Scene *scene, - Object *obedit, - const bool select) -{ - /* Selecting UV Loops with some modes requires us to change - * the selection in other faces (depending on the sticky mode). - * - * This only needs to be done when the Mesh is not used for - * selection (so for sticky modes, vertex or location based). */ - - const ToolSettings *ts = scene->toolsettings; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { - /* Tag all verts as untouched, then touch the ones that have a face center - * in the loop and select all MLoopUV's that use a touched vert. */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } - } - } - - /* now select tagged verts */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - } - else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { - struct UvVertMap *vmap; - float limit[2]; - uint efa_index; - - uvedit_pixel_to_float(sima, limit, 0.05); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - vmap = BM_uv_vert_map_create(em->bm, limit, false, false); - if (vmap == NULL) { - return; - } - - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { - /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - uv_select_flush_from_tag_sticky_loc_internal( - scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); - } - } - } - BM_uv_vert_map_free(vmap); - } - else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if (BM_elem_flag_test(l, BM_ELEM_TAG)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - } - } - } - } -} - -/** \} */ - -#define UV_SELECT_ISLAND_LIMIT \ - float limit[2]; \ - uvedit_pixel_to_float(sima, limit, 0.05f) - -/* -------------------------------------------------------------------- */ -/** \name Box Select Operator - * \{ */ - -static int uv_box_select_exec(bContext *C, wmOperator *op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - ARegion *region = CTX_wm_region(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - rctf rectf; - bool pinned; - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); - - /* get rectangle from operator */ - WM_operator_properties_border_to_rctf(op, &rectf); - UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); - - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - const bool select = (sel_op != SEL_OP_SUB); - const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - - pinned = RNA_boolean_get(op->ptr, "pinned"); - - UV_SELECT_ISLAND_LIMIT; - - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - /* don't indent to avoid diff noise! */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* do actual selection */ - if (use_face_center && !pinned) { - /* handle face selection mode */ - float cent[2]; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - /* assume not touched */ - BM_elem_flag_disable(efa, BM_ELEM_TAG); - - if (uvedit_face_visible_test(scene, obedit, ima, efa)) { - uv_poly_center(efa, cent, cd_loop_uv_offset); - if (BLI_rctf_isect_pt_v(&rectf, cent)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } - } - - /* (de)selects all tagged faces and deals with sticky modes */ - if (changed) { - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - } - else { - /* other selection modes */ - changed = true; - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - bool has_selected = false; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { - if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { - /* UV_SYNC_SELECTION - can't do pinned selection */ - if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - has_selected = true; - } - } - else if (pinned) { - if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - } - } - } - } - if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { - UvNearestHit hit = { - .ob = obedit, - .efa = efa, - }; - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); - } - } - - if (sima->sticky == SI_STICKY_VERTEX) { - uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); - } - } - - if (changed || use_pre_deselect) { - changed_multi = true; - - uv_select_sync_flush(ts, em, select); - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - - MEM_freeN(objects); - - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; -} - -static void UV_OT_select_box(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Box Select"; - ot->description = "Select UV vertices using box selection"; - ot->idname = "UV_OT_select_box"; - - /* api callbacks */ - ot->invoke = WM_gesture_box_invoke; - ot->exec = uv_box_select_exec; - ot->modal = WM_gesture_box_modal; - ot->poll = ED_operator_uvedit_space_image; /* requires space image */ - ot->cancel = WM_gesture_box_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only"); - - WM_operator_properties_gesture_box(ot); - WM_operator_properties_select_operation_simple(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Circle Select Operator - * \{ */ - -static int uv_inside_circle(const float uv[2], const float offset[2], const float ellipse[2]) -{ - /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ - float x, y; - x = (uv[0] - offset[0]) * ellipse[0]; - y = (uv[1] - offset[1]) * ellipse[1]; - return ((x * x + y * y) < 1.0f); -} - -static int uv_circle_select_exec(bContext *C, wmOperator *op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - const ToolSettings *ts = scene->toolsettings; - ARegion *region = CTX_wm_region(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - int x, y, radius, width, height; - float zoomx, zoomy, offset[2], ellipse[2]; - - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); - - /* get operator properties */ - x = RNA_int_get(op->ptr, "x"); - y = RNA_int_get(op->ptr, "y"); - radius = RNA_int_get(op->ptr, "radius"); - - /* compute ellipse size and location, not a circle since we deal - * with non square image. ellipse is normalized, r = 1.0. */ - ED_space_image_get_size(sima, &width, &height); - ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); - - ellipse[0] = width * zoomx / radius; - ellipse[1] = height * zoomy / radius; - - UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); - - UV_SELECT_ISLAND_LIMIT; - - bool changed_multi = false; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), - WM_gesture_is_modal_first(op->customdata)); - const bool select = (sel_op != SEL_OP_SUB); - const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - - if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - bool changed = false; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* do selection */ - if (use_face_center) { - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - /* assume not touched */ - if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { - float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); - if (uv_inside_circle(cent, offset, ellipse)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } - } - - /* (de)selects all tagged faces and deals with sticky modes */ - if (changed) { - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - } - else { - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - bool has_selected = false; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (uv_inside_circle(luv->uv, offset, ellipse)) { - changed = true; - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - has_selected = true; - } - } - } - if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { - UvNearestHit hit = { - .ob = obedit, - .efa = efa, - }; - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); - } - } - - if (sima->sticky == SI_STICKY_VERTEX) { - uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); - } - } - - if (changed || use_pre_deselect) { - changed_multi = true; - - uv_select_sync_flush(ts, em, select); - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - MEM_freeN(objects); - - return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; -} - -static void UV_OT_select_circle(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Circle Select"; - ot->description = "Select UV vertices using circle selection"; - ot->idname = "UV_OT_select_circle"; - - /* api callbacks */ - ot->invoke = WM_gesture_circle_invoke; - ot->modal = WM_gesture_circle_modal; - ot->exec = uv_circle_select_exec; - ot->poll = ED_operator_uvedit_space_image; /* requires space image */ - ot->cancel = WM_gesture_circle_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_gesture_circle(ot); - WM_operator_properties_select_operation_simple(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Lasso Select Operator - * \{ */ - -static bool do_lasso_select_mesh_uv(bContext *C, - const int mcords[][2], - short moves, - const eSelectOp sel_op) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - SpaceImage *sima = CTX_wm_space_image(C); - Image *ima = CTX_data_edit_image(C); - ARegion *region = CTX_wm_region(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? - (ts->selectmode == SCE_SELECT_FACE) : - (ts->uv_selectmode == UV_SELECT_FACE)); - const bool select = (sel_op != SEL_OP_SUB); - const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); - - BMIter iter, liter; - - BMFace *efa; - BMLoop *l; - int screen_uv[2]; - bool changed_multi = false; - rcti rect; - - UV_SELECT_ISLAND_LIMIT; - - BLI_lasso_boundbox(&rect, mcords, moves); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - if (use_pre_deselect) { - uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); - } - - /* don't indent to avoid diff noise! */ - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - - bool changed = false; - - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - if (use_face_center) { /* Face Center Sel */ - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - BM_elem_flag_disable(efa, BM_ELEM_TAG); - /* assume not touched */ - if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { - float cent[2]; - uv_poly_center(efa, cent, cd_loop_uv_offset); - - if (UI_view2d_view_to_region_clip( - ®ion->v2d, cent[0], cent[1], &screen_uv[0], &screen_uv[1]) && - BLI_rcti_isect_pt_v(&rect, screen_uv) && - BLI_lasso_is_point_inside( - mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { - BM_elem_flag_enable(efa, BM_ELEM_TAG); - changed = true; - } - } - } - - /* (de)selects all tagged faces and deals with sticky modes */ - if (changed) { - uv_select_flush_from_tag_face(sima, scene, obedit, select); - } - } - else { /* Vert Sel */ - BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - bool has_selected = false; - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - if (UI_view2d_view_to_region_clip( - ®ion->v2d, luv->uv[0], luv->uv[1], &screen_uv[0], &screen_uv[1]) && - BLI_rcti_isect_pt_v(&rect, screen_uv) && - BLI_lasso_is_point_inside( - mcords, moves, screen_uv[0], screen_uv[1], V2D_IS_CLIPPED)) { - uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); - changed = true; - BM_elem_flag_enable(l->v, BM_ELEM_TAG); - has_selected = true; - } - } - } - if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { - UvNearestHit hit = { - .ob = obedit, - .efa = efa, - }; - uv_select_linked_multi( - scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); - } - } - - if (sima->sticky == SI_STICKY_VERTEX) { - uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); - } - } - - if (changed || use_pre_deselect) { - changed_multi = true; - - uv_select_sync_flush(ts, em, select); - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - MEM_freeN(objects); - - return changed_multi; -} - -static int uv_lasso_select_exec(bContext *C, wmOperator *op) -{ - int mcords_tot; - const int(*mcords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcords_tot); - - if (mcords) { - const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); - bool changed = do_lasso_select_mesh_uv(C, mcords, mcords_tot, sel_op); - MEM_freeN((void *)mcords); - - return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; - } - - return OPERATOR_PASS_THROUGH; -} - -static void UV_OT_select_lasso(wmOperatorType *ot) -{ - ot->name = "Lasso Select UV"; - ot->description = "Select UVs using lasso selection"; - ot->idname = "UV_OT_select_lasso"; - - ot->invoke = WM_gesture_lasso_invoke; - ot->modal = WM_gesture_lasso_modal; - ot->exec = uv_lasso_select_exec; - ot->poll = ED_operator_uvedit_space_image; - ot->cancel = WM_gesture_lasso_cancel; - - /* flags */ - ot->flag = OPTYPE_UNDO; - - /* properties */ - WM_operator_properties_gesture_lasso(ot); - WM_operator_properties_select_operation_simple(ot); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Snap Cursor Operator * \{ */ @@ -4379,314 +1473,6 @@ static void UV_OT_pin(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name Select Pinned UV's Operator - * \{ */ - -static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - const ToolSettings *ts = scene->toolsettings; - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - BMFace *efa; - BMLoop *l; - BMIter iter, liter; - MLoopUV *luv; - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - bool changed = false; - - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { - continue; - } - - BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { - luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - - if (luv->flag & MLOOPUV_PINNED) { - uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); - changed = true; - } - } - } - - if (changed) { - uv_select_tag_update_for_object(depsgraph, ts, obedit); - } - } - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static void UV_OT_select_pinned(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Selected Pinned"; - ot->description = "Select all pinned UV vertices"; - ot->idname = "UV_OT_select_pinned"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_pinned_exec; - ot->poll = ED_operator_uvedit; -} - -/** \} */ - -/* -------------------------------------------------------------------- */ -/** \name Select Overlap Operator - * \{ */ - -BLI_INLINE uint overlap_hash(const void *overlap_v) -{ - const BVHTreeOverlap *overlap = overlap_v; - - /* Designed to treat (A,B) and (B,A) as the same. */ - int x = overlap->indexA; - int y = overlap->indexB; - if (x > y) { - SWAP(int, x, y); - } - return BLI_hash_int_2d(x, y); -} - -BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v) -{ - const BVHTreeOverlap *a = a_v; - const BVHTreeOverlap *b = b_v; - return !((a->indexA == b->indexA && a->indexB == b->indexB) || - (a->indexA == b->indexB && a->indexB == b->indexA)); -} - -struct UVOverlapData { - int ob_index; - int face_index; - float tri[3][2]; -}; - -static int uv_select_overlap(bContext *C, const bool extend) -{ - Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); - Scene *scene = CTX_data_scene(C); - ViewLayer *view_layer = CTX_data_view_layer(C); - Image *ima = CTX_data_edit_image(C); - - uint objects_len = 0; - Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( - view_layer, ((View3D *)NULL), &objects_len); - - /* Calculate maximum number of tree nodes and prepare initial selection. */ - uint uv_tri_len = 0; - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - - BM_mesh_elem_table_ensure(em->bm, BM_FACE); - BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); - BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); - if (!extend) { - uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); - } - - BMIter iter; - BMFace *efa; - BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { - if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { - continue; - } - uv_tri_len += efa->len - 2; - } - } - - struct UVOverlapData *overlap_data = MEM_mallocN(sizeof(struct UVOverlapData) * uv_tri_len, - "UvOverlapData"); - BVHTree *uv_tree = BLI_bvhtree_new(uv_tri_len, 0.0f, 4, 6); - - /* Use a global data index when inserting into the BVH. */ - int data_index = 0; - - int face_len_alloc = 3; - float(*uv_verts)[2] = MEM_mallocN(sizeof(*uv_verts) * face_len_alloc, "UvOverlapCoords"); - uint(*indices)[3] = MEM_mallocN(sizeof(*indices) * (face_len_alloc - 2), "UvOverlapTris"); - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - BMEditMesh *em = BKE_editmesh_from_object(obedit); - BMIter iter, liter; - BMFace *efa; - BMLoop *l; - - const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); - - /* Triangulate each UV face and store it inside the BVH. */ - int face_index; - BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) { - - if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { - continue; - } - - const uint face_len = efa->len; - const uint tri_len = face_len - 2; - - if (face_len_alloc < face_len) { - MEM_freeN(uv_verts); - MEM_freeN(indices); - uv_verts = MEM_mallocN(sizeof(*uv_verts) * face_len, "UvOverlapCoords"); - indices = MEM_mallocN(sizeof(*indices) * tri_len, "UvOverlapTris"); - face_len_alloc = face_len; - } - - int vert_index; - BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, vert_index) { - MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); - copy_v2_v2(uv_verts[vert_index], luv->uv); - } - - BLI_polyfill_calc(uv_verts, face_len, 0, indices); - - for (int t = 0; t < tri_len; t++) { - overlap_data[data_index].ob_index = ob_index; - overlap_data[data_index].face_index = face_index; - - /* BVH needs 3D, overlap data uses 2D. */ - const float tri[3][3] = { - {UNPACK2(uv_verts[indices[t][0]]), 0.0f}, - {UNPACK2(uv_verts[indices[t][1]]), 0.0f}, - {UNPACK2(uv_verts[indices[t][2]]), 0.0f}, - }; - - copy_v2_v2(overlap_data[data_index].tri[0], tri[0]); - copy_v2_v2(overlap_data[data_index].tri[1], tri[1]); - copy_v2_v2(overlap_data[data_index].tri[2], tri[2]); - - BLI_bvhtree_insert(uv_tree, data_index, &tri[0][0], 3); - data_index++; - } - } - } - BLI_assert(data_index == uv_tri_len); - - MEM_freeN(uv_verts); - MEM_freeN(indices); - - BLI_bvhtree_balance(uv_tree); - - uint tree_overlap_len; - BVHTreeOverlap *overlap = BLI_bvhtree_overlap(uv_tree, uv_tree, &tree_overlap_len, NULL, NULL); - - if (overlap != NULL) { - GSet *overlap_set = BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, tree_overlap_len); - - for (int i = 0; i < tree_overlap_len; i++) { - /* Skip overlaps against yourself. */ - if (overlap[i].indexA == overlap[i].indexB) { - continue; - } - - /* Skip overlaps that have already been tested. */ - if (!BLI_gset_add(overlap_set, &overlap[i])) { - continue; - } - - const struct UVOverlapData *o_a = &overlap_data[overlap[i].indexA]; - const struct UVOverlapData *o_b = &overlap_data[overlap[i].indexB]; - Object *obedit_a = objects[o_a->ob_index]; - Object *obedit_b = objects[o_b->ob_index]; - BMEditMesh *em_a = BKE_editmesh_from_object(obedit_a); - BMEditMesh *em_b = BKE_editmesh_from_object(obedit_b); - BMFace *face_a = em_a->bm->ftable[o_a->face_index]; - BMFace *face_b = em_b->bm->ftable[o_b->face_index]; - const int cd_loop_uv_offset_a = CustomData_get_offset(&em_a->bm->ldata, CD_MLOOPUV); - const int cd_loop_uv_offset_b = CustomData_get_offset(&em_b->bm->ldata, CD_MLOOPUV); - - /* Skip if both faces are already selected. */ - if (uvedit_face_select_test(scene, face_a, cd_loop_uv_offset_a) && - uvedit_face_select_test(scene, face_b, cd_loop_uv_offset_b)) { - continue; - } - - /* Main tri-tri overlap test. */ - const float endpoint_bias = -1e-4f; - const float(*t1)[2] = o_a->tri; - const float(*t2)[2] = o_b->tri; - float vi[2]; - bool result = ( - /* Don't use 'isect_tri_tri_v2' here - * because it's important to ignore overlap at end-points. */ - isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[0], t2[1], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[1], t2[2], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[2], t2[0], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[0], t2[1], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[1], t2[2], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[2], t2[0], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[0], t2[1], endpoint_bias, vi) == 1 || - isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[1], t2[2], endpoint_bias, vi) == 1 || - isect_point_tri_v2(t1[0], t2[0], t2[1], t2[2]) != 0 || - isect_point_tri_v2(t2[0], t1[0], t1[1], t1[2]) != 0); - - if (result) { - uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a); - uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b); - } - } - - BLI_gset_free(overlap_set, NULL); - MEM_freeN(overlap); - } - - for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - uv_select_tag_update_for_object(depsgraph, scene->toolsettings, objects[ob_index]); - } - - BLI_bvhtree_free(uv_tree); - - MEM_freeN(overlap_data); - MEM_freeN(objects); - - return OPERATOR_FINISHED; -} - -static int uv_select_overlap_exec(bContext *C, wmOperator *op) -{ - bool extend = RNA_boolean_get(op->ptr, "extend"); - return uv_select_overlap(C, extend); -} - -static void UV_OT_select_overlap(wmOperatorType *ot) -{ - /* identifiers */ - ot->name = "Select Overlap"; - ot->description = "Select all UV faces which overlap each other"; - ot->idname = "UV_OT_select_overlap"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - - /* api callbacks */ - ot->exec = uv_select_overlap_exec; - ot->poll = ED_operator_uvedit; - - /* properties */ - RNA_def_boolean(ot->srna, - "extend", - 0, - "Extend", - "Extend selection rather than clearing the existing selection"); -} - -/** \} */ - -/* -------------------------------------------------------------------- */ /** \name Hide Operator * \{ */ @@ -5334,6 +2120,7 @@ static void UV_OT_mark_seam(wmOperatorType *ot) void ED_operatortypes_uvedit(void) { + /* uvedit_select.c */ WM_operatortype_append(UV_OT_select_all); WM_operatortype_append(UV_OT_select); WM_operatortype_append(UV_OT_select_loop); diff --git a/source/blender/editors/uvedit/uvedit_parametrizer.h b/source/blender/editors/uvedit/uvedit_parametrizer.h index 2b80241e6e3..53188ea42bb 100644 --- a/source/blender/editors/uvedit/uvedit_parametrizer.h +++ b/source/blender/editors/uvedit/uvedit_parametrizer.h @@ -21,12 +21,12 @@ * \ingroup eduv */ +#include "BLI_sys_types.h" // for intptr_t support + #ifdef __cplusplus extern "C" { #endif -#include "BLI_sys_types.h" // for intptr_t support - typedef void ParamHandle; /* handle to a set of charts */ typedef intptr_t ParamKey; /* (hash) key for identifying verts and faces */ typedef enum ParamBool { diff --git a/source/blender/editors/uvedit/uvedit_select.c b/source/blender/editors/uvedit/uvedit_select.c new file mode 100644 index 00000000000..6e931b56a85 --- /dev/null +++ b/source/blender/editors/uvedit/uvedit_select.c @@ -0,0 +1,3415 @@ +/* + * 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup eduv + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_image_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_node_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" + +#include "BLI_alloca.h" +#include "BLI_blenlib.h" +#include "BLI_hash.h" +#include "BLI_kdopbvh.h" +#include "BLI_lasso_2d.h" +#include "BLI_math.h" +#include "BLI_polyfill_2d.h" +#include "BLI_utildefines.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_editmesh.h" +#include "BKE_layer.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" +#include "BKE_report.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + +#include "ED_image.h" +#include "ED_mesh.h" +#include "ED_screen.h" +#include "ED_select_utils.h" +#include "ED_uvedit.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "UI_view2d.h" + +#include "uvedit_intern.h" + +static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action); +static void uv_select_all_perform_multi( + Scene *scene, Image *ima, Object **objects, const uint objects_len, int action); +static void uv_select_flush_from_tag_face(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select); +static void uv_select_flush_from_tag_loop(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select); +static void uv_select_tag_update_for_object(Depsgraph *depsgraph, + const ToolSettings *ts, + Object *obedit); + +/* -------------------------------------------------------------------- */ +/** \name Visibility and Selection Utilities + * \{ */ + +static void uv_select_island_limit_default(SpaceImage *sima, float r_limit[2]) +{ + uvedit_pixel_to_float(sima, 0.05f, r_limit); +} + +static void uvedit_vertex_select_tagged(BMEditMesh *em, + Scene *scene, + bool select, + int cd_loop_uv_offset) +{ + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } +} + +bool uvedit_face_visible_nolocal_ex(const ToolSettings *ts, BMFace *efa) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0); + } + else { + return (BM_elem_flag_test(efa, BM_ELEM_HIDDEN) == 0 && BM_elem_flag_test(efa, BM_ELEM_SELECT)); + } +} +bool uvedit_face_visible_nolocal(const Scene *scene, BMFace *efa) +{ + return uvedit_face_visible_nolocal_ex(scene->toolsettings, efa); +} + +bool uvedit_face_visible_test_ex(const ToolSettings *ts, Object *obedit, Image *ima, BMFace *efa) +{ + if (ts->uv_flag & UV_SHOW_SAME_IMAGE) { + Image *face_image; + ED_object_get_active_image(obedit, efa->mat_nr + 1, &face_image, NULL, NULL, NULL); + return (face_image == ima) ? uvedit_face_visible_nolocal_ex(ts, efa) : false; + } + else { + return uvedit_face_visible_nolocal_ex(ts, efa); + } +} +bool uvedit_face_visible_test(const Scene *scene, Object *obedit, Image *ima, BMFace *efa) +{ + return uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa); +} + +bool uvedit_face_select_test_ex(const ToolSettings *ts, BMFace *efa, const int cd_loop_uv_offset) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + return (BM_elem_flag_test(efa, BM_ELEM_SELECT)); + } + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (!(luv->flag & MLOOPUV_VERTSEL)) { + return false; + } + } + + return true; + } +} +bool uvedit_face_select_test(const Scene *scene, BMFace *efa, const int cd_loop_uv_offset) +{ + return uvedit_face_select_test_ex(scene->toolsettings, efa, cd_loop_uv_offset); +} + +bool uvedit_face_select_set(const struct Scene *scene, + struct BMEditMesh *em, + struct BMFace *efa, + const bool select, + const bool do_history, + const int cd_loop_uv_offset) +{ + if (select) { + return uvedit_face_select_enable(scene, em, efa, do_history, cd_loop_uv_offset); + } + else { + return uvedit_face_select_disable(scene, em, efa, cd_loop_uv_offset); + } +} + +bool uvedit_face_select_enable(const Scene *scene, + BMEditMesh *em, + BMFace *efa, + const bool do_history, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + BM_face_select_set(em->bm, efa, true); + if (do_history) { + BM_select_history_store(em->bm, (BMElem *)efa); + } + } + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag |= MLOOPUV_VERTSEL; + } + + return true; + } + + return false; +} + +bool uvedit_face_select_disable(const Scene *scene, + BMEditMesh *em, + BMFace *efa, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + BM_face_select_set(em->bm, efa, false); + } + else { + BMLoop *l; + MLoopUV *luv; + BMIter liter; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag &= ~MLOOPUV_VERTSEL; + } + + return true; + } + + return false; +} + +bool uvedit_edge_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + return BM_elem_flag_test(l->f, BM_ELEM_SELECT); + } + else if (ts->selectmode == SCE_SELECT_EDGE) { + return BM_elem_flag_test(l->e, BM_ELEM_SELECT); + } + else { + return BM_elem_flag_test(l->v, BM_ELEM_SELECT) && + BM_elem_flag_test(l->next->v, BM_ELEM_SELECT); + } + } + else { + MLoopUV *luv1, *luv2; + + luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + return (luv1->flag & MLOOPUV_VERTSEL) && (luv2->flag & MLOOPUV_VERTSEL); + } +} +bool uvedit_edge_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) +{ + return uvedit_edge_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); +} + +void uvedit_edge_select_set(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool select, + const bool do_history, + const int cd_loop_uv_offset) + +{ + if (select) { + uvedit_edge_select_enable(em, scene, l, do_history, cd_loop_uv_offset); + } + else { + uvedit_edge_select_disable(em, scene, l, cd_loop_uv_offset); + } +} + +void uvedit_edge_select_enable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool do_history, + const int cd_loop_uv_offset) + +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, true); + } + else if (ts->selectmode & SCE_SELECT_EDGE) { + BM_edge_select_set(em->bm, l->e, true); + } + else { + BM_vert_select_set(em->bm, l->e->v1, true); + BM_vert_select_set(em->bm, l->e->v2, true); + } + + if (do_history) { + BM_select_history_store(em->bm, (BMElem *)l->e); + } + } + else { + MLoopUV *luv1, *luv2; + + luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + luv1->flag |= MLOOPUV_VERTSEL; + luv2->flag |= MLOOPUV_VERTSEL; + } +} + +void uvedit_edge_select_disable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const int cd_loop_uv_offset) + +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, false); + } + else if (ts->selectmode & SCE_SELECT_EDGE) { + BM_edge_select_set(em->bm, l->e, false); + } + else { + BM_vert_select_set(em->bm, l->e->v1, false); + BM_vert_select_set(em->bm, l->e->v2, false); + } + } + else { + MLoopUV *luv1, *luv2; + + luv1 = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv2 = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + luv1->flag &= ~MLOOPUV_VERTSEL; + luv2->flag &= ~MLOOPUV_VERTSEL; + } +} + +bool uvedit_uv_select_test_ex(const ToolSettings *ts, BMLoop *l, const int cd_loop_uv_offset) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + return BM_elem_flag_test_bool(l->f, BM_ELEM_SELECT); + } + else { + return BM_elem_flag_test_bool(l->v, BM_ELEM_SELECT); + } + } + else { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + return (luv->flag & MLOOPUV_VERTSEL) != 0; + } +} +bool uvedit_uv_select_test(const Scene *scene, BMLoop *l, const int cd_loop_uv_offset) +{ + return uvedit_uv_select_test_ex(scene->toolsettings, l, cd_loop_uv_offset); +} + +void uvedit_uv_select_set(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool select, + const bool do_history, + const int cd_loop_uv_offset) +{ + if (select) { + uvedit_uv_select_enable(em, scene, l, do_history, cd_loop_uv_offset); + } + else { + uvedit_uv_select_disable(em, scene, l, cd_loop_uv_offset); + } +} + +void uvedit_uv_select_enable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const bool do_history, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, true); + } + else { + BM_vert_select_set(em->bm, l->v, true); + } + + if (do_history) { + BM_select_history_remove(em->bm, (BMElem *)l->v); + } + } + else { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag |= MLOOPUV_VERTSEL; + } +} + +void uvedit_uv_select_disable(BMEditMesh *em, + const Scene *scene, + BMLoop *l, + const int cd_loop_uv_offset) +{ + const ToolSettings *ts = scene->toolsettings; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode & SCE_SELECT_FACE) { + BM_face_select_set(em->bm, l->f, false); + } + else { + BM_vert_select_set(em->bm, l->v, false); + } + } + else { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag &= ~MLOOPUV_VERTSEL; + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Find Nearest Elements + * \{ */ + +bool uv_find_nearest_edge( + Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv, *luv_next; + int i; + bool found = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + + const float dist_test_sq = dist_squared_to_line_segment_v2(co, luv->uv, luv_next->uv); + + if (dist_test_sq < hit->dist_sq) { + hit->efa = efa; + + hit->l = l; + hit->luv = luv; + hit->luv_next = luv_next; + hit->lindex = i; + + hit->dist_sq = dist_test_sq; + found = true; + } + } + } + return found; +} + +bool uv_find_nearest_edge_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float co[2], + UvNearestHit *hit_final) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) { + hit_final->ob = obedit; + found = true; + } + } + return found; +} + +bool uv_find_nearest_face( + Scene *scene, Image *ima, Object *obedit, const float co[2], UvNearestHit *hit_final) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + bool found = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { + hit.dist_sq = dist_sq_init; + hit.l = NULL; + hit.luv = hit.luv_next = NULL; + + BMIter iter; + BMFace *efa; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); + + const float dist_test_sq = len_squared_v2v2(co, cent); + + if (dist_test_sq < hit.dist_sq) { + hit.efa = efa; + hit.dist_sq = dist_test_sq; + found = true; + } + } + } + if (found) { + *hit_final = hit; + } + return found; +} + +bool uv_find_nearest_face_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float co[2], + UvNearestHit *hit_final) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) { + hit_final->ob = obedit; + found = true; + } + } + return found; +} + +static bool uv_nearest_between(const BMLoop *l, const float co[2], const int cd_loop_uv_offset) +{ + const float *uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->prev, cd_loop_uv_offset))->uv; + const float *uv_curr = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset))->uv; + const float *uv_next = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset))->uv; + + return ((line_point_side_v2(uv_prev, uv_curr, co) > 0.0f) && + (line_point_side_v2(uv_next, uv_curr, co) <= 0.0f)); +} + +bool uv_find_nearest_vert(Scene *scene, + Image *ima, + Object *obedit, + float const co[2], + const float penalty_dist, + UvNearestHit *hit_final) +{ + bool found = false; + + /* this will fill in hit.vert1 and hit.vert2 */ + float dist_sq_init = hit_final->dist_sq; + UvNearestHit hit = *hit_final; + if (uv_find_nearest_edge(scene, ima, obedit, co, &hit)) { + hit.dist_sq = dist_sq_init; + + hit.l = NULL; + hit.luv = hit.luv_next = NULL; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMIter iter; + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMIter liter; + BMLoop *l; + int i; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + float dist_test_sq; + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (penalty_dist != 0.0f && uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + dist_test_sq = len_v2v2(co, luv->uv) + penalty_dist; + dist_test_sq = square_f(dist_test_sq); + } + else { + dist_test_sq = len_squared_v2v2(co, luv->uv); + } + + if (dist_test_sq <= hit.dist_sq) { + if (dist_test_sq == hit.dist_sq) { + if (!uv_nearest_between(l, co, cd_loop_uv_offset)) { + continue; + } + } + + hit.dist_sq = dist_test_sq; + + hit.l = l; + hit.luv = luv; + hit.luv_next = BM_ELEM_CD_GET_VOID_P(l->next, cd_loop_uv_offset); + hit.efa = efa; + hit.lindex = i; + found = true; + } + } + } + } + + if (found) { + *hit_final = hit; + } + + return found; +} + +bool uv_find_nearest_vert_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + float const co[2], + const float penalty_dist, + UvNearestHit *hit_final) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) { + hit_final->ob = obedit; + found = true; + } + } + return found; +} + +bool ED_uvedit_nearest_uv(const Scene *scene, + Object *obedit, + Image *ima, + const float co[2], + float *dist_sq, + float r_uv[2]) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMIter iter; + BMFace *efa; + const float *uv_best = NULL; + float dist_best = *dist_sq; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + BMLoop *l_iter, *l_first; + l_iter = l_first = BM_FACE_FIRST_LOOP(efa); + do { + const float *uv = ((const MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv; + const float dist_test = len_squared_v2v2(co, uv); + if (dist_best > dist_test) { + dist_best = dist_test; + uv_best = uv; + } + } while ((l_iter = l_iter->next) != l_first); + } + + if (uv_best != NULL) { + copy_v2_v2(r_uv, uv_best); + *dist_sq = dist_best; + return true; + } + else { + return false; + } +} + +bool ED_uvedit_nearest_uv_multi(const Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float co[2], + float *dist_sq, + float r_uv[2]) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (ED_uvedit_nearest_uv(scene, obedit, ima, co, dist_sq, r_uv)) { + found = true; + } + } + return found; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop Select + * \{ */ + +static void uv_select_edgeloop_vertex_loop_flag(UvMapVert *first) +{ + UvMapVert *iterv; + int count = 0; + + for (iterv = first; iterv; iterv = iterv->next) { + if (iterv->separate && iterv != first) { + break; + } + + count++; + } + + if (count < 5) { + first->flag = 1; + } +} + +static UvMapVert *uv_select_edgeloop_vertex_map_get(UvVertMap *vmap, BMFace *efa, BMLoop *l) +{ + UvMapVert *iterv, *first; + first = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + + for (iterv = first; iterv; iterv = iterv->next) { + if (iterv->separate) { + first = iterv; + } + if (iterv->poly_index == BM_elem_index_get(efa)) { + return first; + } + } + + return NULL; +} + +static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, + UvMapVert *first1, + UvMapVert *first2, + int *totface) +{ + UvMapVert *iterv1, *iterv2; + BMFace *efa; + int tot = 0; + + /* count number of faces this edge has */ + for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { + if (iterv1->separate && iterv1 != first1) { + break; + } + + for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { + if (iterv2->separate && iterv2 != first2) { + break; + } + + if (iterv1->poly_index == iterv2->poly_index) { + /* if face already tagged, don't do this edge */ + efa = BM_face_at_index(em->bm, iterv1->poly_index); + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + return false; + } + + tot++; + break; + } + } + } + + if (*totface == 0) { /* start edge */ + *totface = tot; + } + else if (tot != *totface) { /* check for same number of faces as start edge */ + return false; + } + + /* tag the faces */ + for (iterv1 = first1; iterv1; iterv1 = iterv1->next) { + if (iterv1->separate && iterv1 != first1) { + break; + } + + for (iterv2 = first2; iterv2; iterv2 = iterv2->next) { + if (iterv2->separate && iterv2 != first2) { + break; + } + + if (iterv1->poly_index == iterv2->poly_index) { + efa = BM_face_at_index(em->bm, iterv1->poly_index); + BM_elem_flag_enable(efa, BM_ELEM_TAG); + break; + } + } + } + + return true; +} + +static int uv_select_edgeloop(Scene *scene, + Image *ima, + Object *obedit, + UvNearestHit *hit, + const float limit[2], + const bool extend) +{ + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMIter iter, liter; + BMLoop *l; + UvVertMap *vmap; + UvMapVert *iterv_curr; + UvMapVert *iterv_next; + int starttotf; + bool looking, select; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* setup */ + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); + + BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); + + if (!extend) { + uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); + } + + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); + + /* set flags for first face and verts */ + iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); + iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); + uv_select_edgeloop_vertex_loop_flag(iterv_curr); + uv_select_edgeloop_vertex_loop_flag(iterv_next); + + starttotf = 0; + uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf); + + /* sorry, first edge isn't even ok */ + looking = !(iterv_curr->flag == 0 && iterv_next->flag == 0); + + /* iterate */ + while (looking) { + looking = false; + + /* find correct valence edges which are not tagged yet, but connect to tagged one */ + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!BM_elem_flag_test(efa, BM_ELEM_TAG) && + uvedit_face_visible_test(scene, obedit, ima, efa)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + /* check face not hidden and not tagged */ + if (!(iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l))) { + continue; + } + if (!(iterv_next = uv_select_edgeloop_vertex_map_get(vmap, efa, l->next))) { + continue; + } + + /* check if vertex is tagged and has right valence */ + if (iterv_curr->flag || iterv_next->flag) { + if (uv_select_edgeloop_edge_tag_faces(em, iterv_curr, iterv_next, &starttotf)) { + looking = true; + BM_elem_flag_enable(efa, BM_ELEM_TAG); + + uv_select_edgeloop_vertex_loop_flag(iterv_curr); + uv_select_edgeloop_vertex_loop_flag(iterv_next); + break; + } + } + } + } + } + } + + /* do the actual select/deselect */ + iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l); + iterv_next = uv_select_edgeloop_vertex_map_get(vmap, hit->efa, hit->l->next); + iterv_curr->flag = 1; + iterv_next->flag = 1; + + if (extend) { + select = !(uvedit_uv_select_test(scene, hit->l, cd_loop_uv_offset)); + } + else { + select = true; + } + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + iterv_curr = uv_select_edgeloop_vertex_map_get(vmap, efa, l); + + if (iterv_curr->flag) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + + /* cleanup */ + BM_uv_vert_map_free(vmap); + + return (select) ? 1 : -1; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked + * \{ */ + +static void uv_select_linked_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len, + const float limit[2], + UvNearestHit *hit_final, + bool extend, + bool deselect, + bool toggle, + bool select_faces) +{ + /* loop over objects, or just use hit_final->ob */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + if (hit_final && ob_index != 0) { + break; + } + Object *obedit = hit_final ? hit_final->ob : objects[ob_index]; + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + UvVertMap *vmap; + UvMapVert *vlist, *iterv, *startv; + int i, stacksize = 0, *stack; + uint a; + char *flag; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */ + + /* Note, we had 'use winding' so we don't consider overlapping islands as connected, see T44320 + * this made *every* projection split the island into front/back islands. + * Keep 'use_winding' to false, see: T50970. + * + * Better solve this by having a delimit option for select-linked operator, + * keeping island-select working as is. */ + vmap = BM_uv_vert_map_create(em->bm, limit, !select_faces, false); + + if (vmap == NULL) { + continue; + } + + stack = MEM_mallocN(sizeof(*stack) * (em->bm->totface + 1), "UvLinkStack"); + flag = MEM_callocN(sizeof(*flag) * em->bm->totface, "UvLinkFlag"); + + if (hit_final == NULL) { + /* Use existing selection */ + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + if (select_faces) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + } + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + + break; + } + } + } + } + } + } + else { + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + if (efa == hit_final->efa) { + stack[stacksize] = a; + stacksize++; + flag[a] = 1; + break; + } + } + } + + while (stacksize > 0) { + + stacksize--; + a = stack[stacksize]; + + efa = BM_face_at_index(em->bm, a); + + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, i) { + + /* make_uv_vert_map_EM sets verts tmp.l to the indices */ + vlist = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + + startv = vlist; + + for (iterv = vlist; iterv; iterv = iterv->next) { + if (iterv->separate) { + startv = iterv; + } + if (iterv->poly_index == a) { + break; + } + } + + for (iterv = startv; iterv; iterv = iterv->next) { + if ((startv != iterv) && (iterv->separate)) { + break; + } + else if (!flag[iterv->poly_index]) { + flag[iterv->poly_index] = 1; + stack[stacksize] = iterv->poly_index; + stacksize++; + } + } + } + } + + /* Toggling - if any of the linked vertices is selected (and visible), we deselect. */ + if ((toggle == true) && (extend == false) && (deselect == false)) { + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + bool found_selected = false; + if (!flag[a]) { + continue; + } + + if (select_faces) { + if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && !BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) { + found_selected = true; + } + } + else { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + found_selected = true; + } + } + + if (found_selected) { + deselect = true; + break; + } + } + } + } + +#define SET_SELECTION(value) \ + if (select_faces) { \ + BM_face_select_set(em->bm, efa, value); \ + } \ + else { \ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { \ + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); \ + luv->flag = (value) ? (luv->flag | MLOOPUV_VERTSEL) : (luv->flag & ~MLOOPUV_VERTSEL); \ + } \ + } \ + (void)0 + + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, a) { + if (!flag[a]) { + if (!extend && !deselect && !toggle) { + SET_SELECTION(false); + } + continue; + } + + if (!deselect) { + SET_SELECTION(true); + } + else { + SET_SELECTION(false); + } + } + +#undef SET_SELECTION + + MEM_freeN(stack); + MEM_freeN(flag); + BM_uv_vert_map_free(vmap); + } +} + +/** + * \warning This returns first selected UV, + * not ideal in many cases since there could be multiple. + */ +const float *uvedit_first_selected_uv_from_vertex( + Scene *scene, Object *obedit, Image *ima, BMVert *eve, const int cd_loop_uv_offset) +{ + BMIter liter; + BMLoop *l; + + BM_ITER_ELEM (l, &liter, eve, BM_LOOPS_OF_VERT) { + if (!uvedit_face_visible_test(scene, obedit, ima, l->f)) { + continue; + } + + if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + return luv->uv; + } + } + + return NULL; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select More/Less Operator + * \{ */ + +static int uv_select_more_less(bContext *C, const bool select) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + SpaceImage *sima = CTX_wm_space_image(C); + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + const ToolSettings *ts = scene->toolsettings; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + const bool is_uv_face_selectmode = (ts->uv_selectmode == UV_SELECT_FACE); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (select) { + EDBM_select_more(em, true); + } + else { + EDBM_select_less(em, true); + } + + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + continue; + } + + if (is_uv_face_selectmode) { + + /* clear tags */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); + + /* mark loops to be selected */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + +#define IS_SEL 1 +#define IS_UNSEL 2 + + int sel_state = 0; + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (luv->flag & MLOOPUV_VERTSEL) { + sel_state |= IS_SEL; + } + else { + sel_state |= IS_UNSEL; + } + + /* if we have a mixed selection, tag to grow it */ + if (sel_state == (IS_SEL | IS_UNSEL)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + break; + } + } + +#undef IS_SEL +#undef IS_UNSEL + } + } + } + else { + + /* clear tags */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + BM_elem_flag_disable(l, BM_ELEM_TAG); + } + } + + /* mark loops to be selected */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (((luv->flag & MLOOPUV_VERTSEL) != 0) == select) { + BM_elem_flag_enable(l->next, BM_ELEM_TAG); + BM_elem_flag_enable(l->prev, BM_ELEM_TAG); + changed = true; + } + } + } + } + } + + if (changed) { + if (is_uv_face_selectmode) { + /* Select tagged faces. */ + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + else { + /* Select tagged loops. */ + uv_select_flush_from_tag_loop(sima, scene, obedit, select); + } + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + } + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +static int uv_select_more_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return uv_select_more_less(C, true); +} + +void UV_OT_select_more(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select More"; + ot->description = "Select more UV vertices connected to initial selection"; + ot->idname = "UV_OT_select_more"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_more_exec; + ot->poll = ED_operator_uvedit_space_image; +} + +static int uv_select_less_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return uv_select_more_less(C, false); +} + +void UV_OT_select_less(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Less"; + ot->description = "Deselect UV vertices at the boundary of each selection region"; + ot->idname = "UV_OT_select_less"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_less_exec; + ot->poll = ED_operator_uvedit_space_image; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name (De)Select All Operator + * \{ */ + +bool uvedit_select_is_any_selected(Scene *scene, Image *ima, Object *obedit) +{ + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel); + } + else { + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (luv->flag & MLOOPUV_VERTSEL) { + return true; + } + } + } + } + return false; +} + +bool uvedit_select_is_any_selected_multi(Scene *scene, + Image *ima, + Object **objects, + const uint objects_len) +{ + bool found = false; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + if (uvedit_select_is_any_selected(scene, ima, obedit)) { + found = true; + break; + } + } + return found; +} + +static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action) +{ + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if (action == SEL_TOGGLE) { + action = uvedit_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT; + } + + if (ts->uv_flag & UV_SYNC_SELECTION) { + switch (action) { + case SEL_TOGGLE: + EDBM_select_toggle_all(em); + break; + case SEL_SELECT: + EDBM_flag_enable_all(em, BM_ELEM_SELECT); + break; + case SEL_DESELECT: + EDBM_flag_disable_all(em, BM_ELEM_SELECT); + break; + case SEL_INVERT: + EDBM_select_swap(em); + EDBM_selectmode_flush(em); + break; + } + } + else { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + switch (action) { + case SEL_SELECT: + luv->flag |= MLOOPUV_VERTSEL; + break; + case SEL_DESELECT: + luv->flag &= ~MLOOPUV_VERTSEL; + break; + case SEL_INVERT: + luv->flag ^= MLOOPUV_VERTSEL; + break; + } + } + } + } +} + +static void uv_select_all_perform_multi( + Scene *scene, Image *ima, Object **objects, const uint objects_len, int action) +{ + if (action == SEL_TOGGLE) { + action = uvedit_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT : + SEL_SELECT; + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + uv_select_all_perform(scene, ima, obedit, action); + } +} + +static int uv_select_all_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + Image *ima = CTX_data_edit_image(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + + int action = RNA_enum_get(op->ptr, "action"); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + uv_select_all_perform_multi(scene, ima, objects, objects_len, action); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +void UV_OT_select_all(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "(De)select All"; + ot->description = "Change selection of all UV vertices"; + ot->idname = "UV_OT_select_all"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_all_exec; + ot->poll = ED_operator_uvedit; + + WM_operator_properties_select_all(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Mouse Select Operator + * \{ */ + +static bool uv_sticky_select( + float *limit, int hitv[], int v, float *hituv[], float *uv, int sticky, int hitlen) +{ + int i; + + /* this function test if some vertex needs to selected + * in addition to the existing ones due to sticky select */ + if (sticky == SI_STICKY_DISABLE) { + return false; + } + + for (i = 0; i < hitlen; i++) { + if (hitv[i] == v) { + if (sticky == SI_STICKY_LOC) { + if (fabsf(hituv[i][0] - uv[0]) < limit[0] && fabsf(hituv[i][1] - uv[1]) < limit[1]) { + return true; + } + } + else if (sticky == SI_STICKY_VERTEX) { + return true; + } + } + } + + return false; +} + +static int uv_mouse_select_multi(bContext *C, + Object **objects, + uint objects_len, + const float co[2], + const bool extend, + const bool deselect_all, + const bool loop) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + Image *ima = CTX_data_edit_image(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + UvNearestHit hit = UV_NEAREST_HIT_INIT; + int i, selectmode, sticky, sync, *hitv = NULL; + bool select = true; + bool found_item = false; + /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */ + int flush = 0; + int hitlen = 0; + float limit[2], **hituv = NULL; + + /* notice 'limit' is the same no matter the zoom level, since this is like + * remove doubles and could annoying if it joined points when zoomed out. + * 'penalty' is in screen pixel space otherwise zooming in on a uv-vert and + * shift-selecting can consider an adjacent point close enough to add to + * the selection rather than de-selecting the closest. */ + + float penalty_dist; + { + float penalty[2]; + uvedit_pixel_to_float(sima, 0.05f, limit); + uvedit_pixel_to_float(sima, 5.0f / (sima ? sima->zoom : 1.0f), penalty); + penalty_dist = len_v2(penalty); + } + + /* retrieve operation mode */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + sync = 1; + + if (ts->selectmode & SCE_SELECT_FACE) { + selectmode = UV_SELECT_FACE; + } + else if (ts->selectmode & SCE_SELECT_EDGE) { + selectmode = UV_SELECT_EDGE; + } + else { + selectmode = UV_SELECT_VERTEX; + } + + sticky = SI_STICKY_DISABLE; + } + else { + sync = 0; + selectmode = ts->uv_selectmode; + sticky = (sima) ? sima->sticky : 1; + } + + /* find nearest element */ + if (loop) { + /* find edge */ + found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + } + else if (selectmode == UV_SELECT_VERTEX) { + /* find vertex */ + found_item = uv_find_nearest_vert_multi( + scene, ima, objects, objects_len, co, penalty_dist, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + + if (found_item) { + /* mark 1 vertex as being hit */ + hitv = BLI_array_alloca(hitv, hit.efa->len); + hituv = BLI_array_alloca(hituv, hit.efa->len); + copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); + + hitv[hit.lindex] = BM_elem_index_get(hit.l->v); + hituv[hit.lindex] = hit.luv->uv; + + hitlen = hit.efa->len; + } + } + else if (selectmode == UV_SELECT_EDGE) { + /* find edge */ + found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + + if (found_item) { + /* mark 2 edge vertices as being hit */ + hitv = BLI_array_alloca(hitv, hit.efa->len); + hituv = BLI_array_alloca(hituv, hit.efa->len); + copy_vn_i(hitv, hit.efa->len, 0xFFFFFFFF); + + hitv[hit.lindex] = BM_elem_index_get(hit.l->v); + hitv[(hit.lindex + 1) % hit.efa->len] = BM_elem_index_get(hit.l->next->v); + hituv[hit.lindex] = hit.luv->uv; + hituv[(hit.lindex + 1) % hit.efa->len] = hit.luv_next->uv; + + hitlen = hit.efa->len; + } + } + else if (selectmode == UV_SELECT_FACE) { + /* find face */ + found_item = uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + + if (found_item) { + BMEditMesh *em = BKE_editmesh_from_object(hit.ob); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* make active */ + BM_mesh_active_face_set(em->bm, hit.efa); + + /* mark all face vertices as being hit */ + + hitv = BLI_array_alloca(hitv, hit.efa->len); + hituv = BLI_array_alloca(hituv, hit.efa->len); + BM_ITER_ELEM_INDEX (l, &liter, hit.efa, BM_LOOPS_OF_FACE, i) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + hituv[i] = luv->uv; + hitv[i] = BM_elem_index_get(l->v); + } + + hitlen = hit.efa->len; + } + } + else if (selectmode == UV_SELECT_ISLAND) { + found_item = uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit); + found_item = found_item && (!deselect_all || hit.dist_sq < penalty_dist); + } + + if (!found_item) { + if (deselect_all) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; + } + return OPERATOR_CANCELLED; + } + + Object *obedit = hit.ob; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* do selection */ + if (loop) { + if (!extend) { + /* TODO(MULTI_EDIT): We only need to de-select non-active */ + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend); + } + else if (selectmode == UV_SELECT_ISLAND) { + if (!extend) { + /* TODO(MULTI_EDIT): We only need to de-select non-active */ + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + /* Current behavior of 'extend' + * is actually toggling, so pass extend flag as 'toggle' here */ + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, false, false, extend, false); + } + else if (extend) { + if (selectmode == UV_SELECT_VERTEX) { + /* (de)select uv vertex */ + select = !uvedit_uv_select_test(scene, hit.l, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_EDGE) { + /* (de)select edge */ + select = !(uvedit_edge_select_test(scene, hit.l, cd_loop_uv_offset)); + uvedit_edge_select_set(em, scene, hit.l, select, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_FACE) { + /* (de)select face */ + select = !(uvedit_face_select_test(scene, hit.efa, cd_loop_uv_offset)); + uvedit_face_select_set(scene, em, hit.efa, select, true, cd_loop_uv_offset); + flush = -1; + } + + /* de-selecting an edge may deselect a face too - validate */ + if (sync) { + if (select == false) { + BM_select_history_validate(em->bm); + } + } + + /* (de)select sticky uv nodes */ + if (sticky != SI_STICKY_DISABLE) { + + BM_mesh_elem_index_ensure(em->bm, BM_VERT); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (uv_sticky_select( + limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + + flush = select ? 1 : -1; + } + } + else { + /* deselect all */ + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + + if (selectmode == UV_SELECT_VERTEX) { + /* select vertex */ + uvedit_uv_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_EDGE) { + /* select edge */ + uvedit_edge_select_enable(em, scene, hit.l, true, cd_loop_uv_offset); + flush = 1; + } + else if (selectmode == UV_SELECT_FACE) { + /* select face */ + uvedit_face_select_enable(scene, em, hit.efa, true, cd_loop_uv_offset); + } + + /* select sticky uvs */ + if (sticky != SI_STICKY_DISABLE) { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (sticky == SI_STICKY_DISABLE) { + continue; + } + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (uv_sticky_select( + limit, hitv, BM_elem_index_get(l->v), hituv, luv->uv, sticky, hitlen)) { + uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); + } + + flush = 1; + } + } + } + } + + if (sync) { + /* flush for mesh selection */ + + /* before bmesh */ +#if 0 + if (ts->selectmode != SCE_SELECT_FACE) { + if (flush == 1) { + EDBM_select_flush(em); + } + else if (flush == -1) { + EDBM_deselect_flush(em); + } + } +#else + if (flush != 0) { + if (loop) { + /* push vertex -> edge selection */ + if (select) { + EDBM_select_flush(em); + } + else { + EDBM_deselect_flush(em); + } + } + else { + EDBM_selectmode_flush(em); + } + } +#endif + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obiter = objects[ob_index]; + uv_select_tag_update_for_object(depsgraph, ts, obiter); + } + + return OPERATOR_PASS_THROUGH | OPERATOR_FINISHED; +} +static int uv_mouse_select( + bContext *C, const float co[2], const bool extend, const bool deselect_all, const bool loop) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + int ret = uv_mouse_select_multi(C, objects, objects_len, co, extend, deselect_all, loop); + MEM_freeN(objects); + return ret; +} + +static int uv_select_exec(bContext *C, wmOperator *op) +{ + float co[2]; + + RNA_float_get_array(op->ptr, "location", co); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + const bool deselect_all = RNA_boolean_get(op->ptr, "deselect_all"); + const bool loop = false; + + return uv_mouse_select(C, co, extend, deselect_all, loop); +} + +static int uv_select_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const ARegion *region = CTX_wm_region(C); + float co[2]; + + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); + RNA_float_set_array(op->ptr, "location", co); + + return uv_select_exec(C, op); +} + +void UV_OT_select(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select"; + ot->description = "Select UV vertices"; + ot->idname = "UV_OT_select"; + ot->flag = OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_exec; + ot->invoke = uv_select_invoke; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* properties */ + PropertyRNA *prop; + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); + prop = RNA_def_boolean(ot->srna, + "deselect_all", + false, + "Deselect On Nothing", + "Deselect all when nothing under the cursor"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); + + RNA_def_float_vector( + ot->srna, + "location", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", + -100.0f, + 100.0f); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Loop Select Operator + * \{ */ + +static int uv_select_loop_exec(bContext *C, wmOperator *op) +{ + float co[2]; + + RNA_float_get_array(op->ptr, "location", co); + const bool extend = RNA_boolean_get(op->ptr, "extend"); + const bool deselect_all = false; + const bool loop = true; + + return uv_mouse_select(C, co, extend, deselect_all, loop); +} + +static int uv_select_loop_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + const ARegion *region = CTX_wm_region(C); + float co[2]; + + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); + RNA_float_set_array(op->ptr, "location", co); + + return uv_select_loop_exec(C, op); +} + +void UV_OT_select_loop(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Loop Select"; + ot->description = "Select a loop of connected UV vertices"; + ot->idname = "UV_OT_select_loop"; + ot->flag = OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_loop_exec; + ot->invoke = uv_select_loop_invoke; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* properties */ + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); + RNA_def_float_vector( + ot->srna, + "location", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", + -100.0f, + 100.0f); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked Operator + * \{ */ + +static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent *event, bool pick) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + float limit[2]; + bool extend = true; + bool deselect = false; + bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE); + + UvNearestHit hit = UV_NEAREST_HIT_INIT; + + if ((ts->uv_flag & UV_SYNC_SELECTION) && !(ts->selectmode & SCE_SELECT_FACE)) { + BKE_report(op->reports, + RPT_ERROR, + "Select linked only works in face select mode when sync selection is enabled"); + return OPERATOR_CANCELLED; + } + + if (pick) { + extend = RNA_boolean_get(op->ptr, "extend"); + deselect = RNA_boolean_get(op->ptr, "deselect"); + } + uv_select_island_limit_default(sima, limit); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + if (pick) { + float co[2]; + + if (event) { + /* invoke */ + const ARegion *region = CTX_wm_region(C); + + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &co[0], &co[1]); + RNA_float_set_array(op->ptr, "location", co); + } + else { + /* exec */ + RNA_float_get_array(op->ptr, "location", co); + } + + if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) { + MEM_freeN(objects); + return OPERATOR_CANCELLED; + } + } + + if (!extend) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + uv_select_linked_multi(scene, + ima, + objects, + objects_len, + limit, + pick ? &hit : NULL, + extend, + deselect, + false, + select_faces); + + /* weak!, but works */ + Object **objects_free = objects; + if (pick) { + objects = &hit.ob; + objects_len = 1; + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + DEG_id_tag_update(obedit->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); + WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data); + } + + MEM_SAFE_FREE(objects_free); + + return OPERATOR_FINISHED; +} + +static int uv_select_linked_exec(bContext *C, wmOperator *op) +{ + return uv_select_linked_internal(C, op, NULL, false); +} + +void UV_OT_select_linked(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked"; + ot->description = "Select all UV vertices linked to the active UV map"; + ot->idname = "UV_OT_select_linked"; + + /* api callbacks */ + ot->exec = uv_select_linked_exec; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Linked (Cursor Pick) Operator + * \{ */ + +static int uv_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) +{ + return uv_select_linked_internal(C, op, event, true); +} + +static int uv_select_linked_pick_exec(bContext *C, wmOperator *op) +{ + return uv_select_linked_internal(C, op, NULL, true); +} + +void UV_OT_select_linked_pick(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Linked Pick"; + ot->description = "Select all UV vertices linked under the mouse"; + ot->idname = "UV_OT_select_linked_pick"; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->invoke = uv_select_linked_pick_invoke; + ot->exec = uv_select_linked_pick_exec; + ot->poll = ED_operator_uvedit; /* requires space image */ + + /* properties */ + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); + RNA_def_boolean(ot->srna, + "deselect", + 0, + "Deselect", + "Deselect linked UV vertices rather than selecting them"); + RNA_def_float_vector( + ot->srna, + "location", + 2, + NULL, + -FLT_MAX, + FLT_MAX, + "Location", + "Mouse location in normalized coordinates, 0.0 to 1.0 is within the image bounds", + -100.0f, + 100.0f); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Split Operator + * \{ */ + +/** + * \note This is based on similar use case to #MESH_OT_split(), which has a similar effect + * but in this case they are not joined to begin with (only having the behavior of being joined) + * so its best to call this #uv_select_split() instead of just split(), but assigned to the same + * key as #MESH_OT_split - Campbell. + */ +static int uv_select_split_exec(bContext *C, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const ToolSettings *ts = scene->toolsettings; + Image *ima = CTX_data_edit_image(C); + + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + if (ts->uv_flag & UV_SYNC_SELECTION) { + BKE_report(op->reports, RPT_ERROR, "Cannot split selection when sync selection is enabled"); + return OPERATOR_CANCELLED; + } + + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMesh *bm = BKE_editmesh_from_object(obedit)->bm; + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); + + BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { + bool is_sel = false; + bool is_unsel = false; + + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + /* are we all selected? */ + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_VERTSEL) { + is_sel = true; + } + else { + is_unsel = true; + } + + /* we have mixed selection, bail out */ + if (is_sel && is_unsel) { + break; + } + } + + if (is_sel && is_unsel) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + luv->flag &= ~MLOOPUV_VERTSEL; + } + + changed = true; + } + } + + if (changed) { + changed_multi = true; + WM_event_add_notifier(C, NC_SPACE | ND_SPACE_IMAGE, NULL); + } + } + MEM_freeN(objects); + + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void UV_OT_select_split(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Split"; + ot->description = "Select only entirely selected faces"; + ot->idname = "UV_OT_select_split"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_split_exec; + ot->poll = ED_operator_uvedit; /* requires space image */ +} + +static void uv_select_sync_flush(const ToolSettings *ts, BMEditMesh *em, const short select) +{ + /* bmesh API handles flushing but not on de-select */ + if (ts->uv_flag & UV_SYNC_SELECTION) { + if (ts->selectmode != SCE_SELECT_FACE) { + if (select == false) { + EDBM_deselect_flush(em); + } + else { + EDBM_select_flush(em); + } + } + + if (select == false) { + BM_select_history_validate(em->bm); + } + } +} + +static void uv_select_tag_update_for_object(Depsgraph *depsgraph, + const ToolSettings *ts, + Object *obedit) +{ + if (ts->uv_flag & UV_SYNC_SELECTION) { + DEG_id_tag_update(obedit->data, ID_RECALC_SELECT); + WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); + } + else { + Object *obedit_eval = DEG_get_evaluated_object(depsgraph, obedit); + BKE_mesh_batch_cache_dirty_tag(obedit_eval->data, BKE_MESH_BATCH_DIRTY_UVEDIT_SELECT); + /* Only for region redraw. */ + WM_main_add_notifier(NC_GEOM | ND_SELECT, obedit->data); + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select/Tag Flushing Utils + * + * Utility functions to flush the uv-selection from tags. + * \{ */ + +/** + * helper function for #uv_select_flush_from_tag_loop and uv_select_flush_from_tag_face + */ +static void uv_select_flush_from_tag_sticky_loc_internal(Scene *scene, + BMEditMesh *em, + UvVertMap *vmap, + const uint efa_index, + BMLoop *l, + const bool select, + const int cd_loop_uv_offset) +{ + UvMapVert *start_vlist = NULL, *vlist_iter; + BMFace *efa_vlist; + + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + + vlist_iter = BM_uv_vert_map_at_index(vmap, BM_elem_index_get(l->v)); + + while (vlist_iter) { + if (vlist_iter->separate) { + start_vlist = vlist_iter; + } + + if (efa_index == vlist_iter->poly_index) { + break; + } + + vlist_iter = vlist_iter->next; + } + + vlist_iter = start_vlist; + while (vlist_iter) { + + if (vlist_iter != start_vlist && vlist_iter->separate) { + break; + } + + if (efa_index != vlist_iter->poly_index) { + BMLoop *l_other; + efa_vlist = BM_face_at_index(em->bm, vlist_iter->poly_index); + /* tf_vlist = BM_ELEM_CD_GET_VOID_P(efa_vlist, cd_poly_tex_offset); */ /* UNUSED */ + + l_other = BM_iter_at_index( + em->bm, BM_LOOPS_OF_FACE, efa_vlist, vlist_iter->loop_of_poly_index); + + uvedit_uv_select_set(em, scene, l_other, select, false, cd_loop_uv_offset); + } + vlist_iter = vlist_iter->next; + } +} + +/** + * Flush the selection from face tags based on sticky and selection modes. + * + * needed because settings the selection a face is done in a number of places but it also + * needs to respect the sticky modes for the UV verts, so dealing with the sticky modes + * is best done in a separate function. + * + * \note This function is very similar to #uv_select_flush_from_tag_loop, + * be sure to update both upon changing. + */ +static void uv_select_flush_from_tag_face(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select) +{ + /* Selecting UV Faces with some modes requires us to change + * the selection in other faces (depending on the sticky mode). + * + * This only needs to be done when the Mesh is not used for + * selection (so for sticky modes, vertex or location based). */ + + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { + /* Tag all verts as untouched, then touch the ones that have a face center + * in the loop and select all MLoopUV's that use a touched vert. */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } + } + } + + /* now select tagged verts */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + } + else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { + struct UvVertMap *vmap; + float limit[2]; + uint efa_index; + + uv_select_island_limit_default(sima, limit); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); + if (vmap == NULL) { + return; + } + + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + uv_select_flush_from_tag_sticky_loc_internal( + scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); + } + } + } + BM_uv_vert_map_free(vmap); + } + else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (BM_elem_flag_test(efa, BM_ELEM_TAG)) { + uvedit_face_select_set(scene, em, efa, select, false, cd_loop_uv_offset); + } + } + } +} + +/** + * Flush the selection from loop tags based on sticky and selection modes. + * + * needed because settings the selection a face is done in a number of places but it also needs + * to respect the sticky modes for the UV verts, so dealing with the sticky modes is best done + * in a separate function. + * + * \note This function is very similar to #uv_select_flush_from_tag_loop, + * be sure to update both upon changing. + */ +static void uv_select_flush_from_tag_loop(SpaceImage *sima, + Scene *scene, + Object *obedit, + const bool select) +{ + /* Selecting UV Loops with some modes requires us to change + * the selection in other faces (depending on the sticky mode). + * + * This only needs to be done when the Mesh is not used for + * selection (so for sticky modes, vertex or location based). */ + + const ToolSettings *ts = scene->toolsettings; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_VERTEX) { + /* Tag all verts as untouched, then touch the ones that have a face center + * in the loop and select all MLoopUV's that use a touched vert. */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } + } + } + + /* now select tagged verts */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l->v, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + } + else if ((ts->uv_flag & UV_SYNC_SELECTION) == 0 && sima->sticky == SI_STICKY_LOC) { + struct UvVertMap *vmap; + float limit[2]; + uint efa_index; + + uv_select_island_limit_default(sima, limit); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + vmap = BM_uv_vert_map_create(em->bm, limit, false, false); + if (vmap == NULL) { + return; + } + + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, efa_index) { + /* tf = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); */ /* UNUSED */ + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { + uv_select_flush_from_tag_sticky_loc_internal( + scene, em, vmap, efa_index, l, select, cd_loop_uv_offset); + } + } + } + BM_uv_vert_map_free(vmap); + } + else { /* SI_STICKY_DISABLE or ts->uv_flag & UV_SYNC_SELECTION */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if (BM_elem_flag_test(l, BM_ELEM_TAG)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + } + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Box Select Operator + * \{ */ + +static int uv_box_select_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + const ARegion *region = CTX_wm_region(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + rctf rectf; + bool pinned; + float limit[2]; + const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + + /* get rectangle from operator */ + WM_operator_properties_border_to_rctf(op, &rectf); + UI_view2d_region_to_view_rctf(®ion->v2d, &rectf, &rectf); + + const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + const bool select = (sel_op != SEL_OP_SUB); + const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); + + pinned = RNA_boolean_get(op->ptr, "pinned"); + + uv_select_island_limit_default(sima, limit); + + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + if (use_pre_deselect) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + /* don't indent to avoid diff noise! */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* do actual selection */ + if (use_face_center && !pinned) { + /* handle face selection mode */ + float cent[2]; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + /* assume not touched */ + BM_elem_flag_disable(efa, BM_ELEM_TAG); + + if (uvedit_face_visible_test(scene, obedit, ima, efa)) { + uv_poly_center(efa, cent, cd_loop_uv_offset); + if (BLI_rctf_isect_pt_v(&rectf, cent)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (changed) { + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + } + else if (use_edge && !pinned) { + changed = true; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (BLI_rctf_isect_pt_v(&rectf, luv->uv) && + BLI_rctf_isect_pt_v(&rectf, luv_prev->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + else { + /* other selection modes */ + changed = true; + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + if (!pinned || (ts->uv_flag & UV_SYNC_SELECTION)) { + /* UV_SYNC_SELECTION - can't do pinned selection */ + if (BLI_rctf_isect_pt_v(&rectf, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } + } + else if (pinned) { + if ((luv->flag & MLOOPUV_PINNED) && BLI_rctf_isect_pt_v(&rectf, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + } + } + } + } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + + if (changed || use_pre_deselect) { + changed_multi = true; + + uv_select_sync_flush(ts, em, select); + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + + MEM_freeN(objects); + + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void UV_OT_select_box(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Box Select"; + ot->description = "Select UV vertices using box selection"; + ot->idname = "UV_OT_select_box"; + + /* api callbacks */ + ot->invoke = WM_gesture_box_invoke; + ot->exec = uv_box_select_exec; + ot->modal = WM_gesture_box_modal; + ot->poll = ED_operator_uvedit_space_image; /* requires space image */ + ot->cancel = WM_gesture_box_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + RNA_def_boolean(ot->srna, "pinned", 0, "Pinned", "Border select pinned UVs only"); + + WM_operator_properties_gesture_box(ot); + WM_operator_properties_select_operation_simple(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Circle Select Operator + * \{ */ + +static int uv_circle_select_is_point_inside(const float uv[2], + const float offset[2], + const float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + const float co[2] = { + (uv[0] - offset[0]) * ellipse[0], + (uv[1] - offset[1]) * ellipse[1], + }; + return len_squared_v2(co) < 1.0f; +} + +static int uv_circle_select_is_edge_inside(const float uv_a[2], + const float uv_b[2], + const float offset[2], + const float ellipse[2]) +{ + /* normalized ellipse: ell[0] = scaleX, ell[1] = scaleY */ + const float co_a[2] = { + (uv_a[0] - offset[0]) * ellipse[0], + (uv_a[1] - offset[1]) * ellipse[1], + }; + const float co_b[2] = { + (uv_b[0] - offset[0]) * ellipse[0], + (uv_b[1] - offset[1]) * ellipse[1], + }; + return dist_squared_to_line_segment_v2((const float[2]){0.0f, 0.0f}, co_a, co_b) < 1.0f; +} + +static int uv_circle_select_exec(bContext *C, wmOperator *op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + const ToolSettings *ts = scene->toolsettings; + const ARegion *region = CTX_wm_region(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + int x, y, radius, width, height; + float zoomx, zoomy; + float limit[2], offset[2], ellipse[2]; + + const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + + /* get operator properties */ + x = RNA_int_get(op->ptr, "x"); + y = RNA_int_get(op->ptr, "y"); + radius = RNA_int_get(op->ptr, "radius"); + + /* compute ellipse size and location, not a circle since we deal + * with non square image. ellipse is normalized, r = 1.0. */ + ED_space_image_get_size(sima, &width, &height); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); + + ellipse[0] = width * zoomx / radius; + ellipse[1] = height * zoomy / radius; + + UI_view2d_region_to_view(®ion->v2d, x, y, &offset[0], &offset[1]); + + uv_select_island_limit_default(sima, limit); + + bool changed_multi = false; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"), + WM_gesture_is_modal_first(op->customdata)); + const bool select = (sel_op != SEL_OP_SUB); + const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); + + if (use_pre_deselect) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + bool changed = false; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* do selection */ + if (use_face_center) { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); + /* assume not touched */ + if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); + if (uv_circle_select_is_point_inside(cent, offset, ellipse)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (changed) { + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + } + else if (use_edge) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (uv_circle_select_is_edge_inside(luv->uv, luv_prev->uv, offset, ellipse)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + else { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (uv_circle_select_is_point_inside(luv->uv, offset, ellipse)) { + changed = true; + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } + } + } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + + if (changed || use_pre_deselect) { + changed_multi = true; + + uv_select_sync_flush(ts, em, select); + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + MEM_freeN(objects); + + return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + +void UV_OT_select_circle(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Circle Select"; + ot->description = "Select UV vertices using circle selection"; + ot->idname = "UV_OT_select_circle"; + + /* api callbacks */ + ot->invoke = WM_gesture_circle_invoke; + ot->modal = WM_gesture_circle_modal; + ot->exec = uv_circle_select_exec; + ot->poll = ED_operator_uvedit_space_image; /* requires space image */ + ot->cancel = WM_gesture_circle_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_circle(ot); + WM_operator_properties_select_operation_simple(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Lasso Select Operator + * \{ */ + +static bool do_lasso_select_mesh_uv_is_point_inside(const ARegion *region, + const rcti *clip_rect, + const int mcoords[][2], + const int mcoords_len, + const float co_test[2]) +{ + int co_screen[2]; + if (UI_view2d_view_to_region_clip( + ®ion->v2d, co_test[0], co_test[1], &co_screen[0], &co_screen[1]) && + BLI_rcti_isect_pt_v(clip_rect, co_screen) && + BLI_lasso_is_point_inside( + mcoords, mcoords_len, co_screen[0], co_screen[1], V2D_IS_CLIPPED)) { + return true; + } + return false; +} + +static bool do_lasso_select_mesh_uv(bContext *C, + const int mcoords[][2], + const int mcoords_len, + const eSelectOp sel_op) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + const ARegion *region = CTX_wm_region(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + const bool use_face_center = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_FACE) : + (ts->uv_selectmode == UV_SELECT_FACE)); + const bool use_edge = ((ts->uv_flag & UV_SYNC_SELECTION) ? + (ts->selectmode == SCE_SELECT_EDGE) : + (ts->uv_selectmode == UV_SELECT_EDGE)); + + const bool select = (sel_op != SEL_OP_SUB); + const bool use_pre_deselect = SEL_OP_USE_PRE_DESELECT(sel_op); + + BMIter iter, liter; + + BMFace *efa; + BMLoop *l; + float limit[2]; + bool changed_multi = false; + rcti rect; + + uv_select_island_limit_default(sima, limit); + + BLI_lasso_boundbox(&rect, mcoords, mcoords_len); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + if (use_pre_deselect) { + uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT); + } + + /* don't indent to avoid diff noise! */ + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + + bool changed = false; + + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + if (use_face_center) { /* Face Center Sel */ + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + BM_elem_flag_disable(efa, BM_ELEM_TAG); + /* assume not touched */ + if (select != uvedit_face_select_test(scene, efa, cd_loop_uv_offset)) { + float cent[2]; + uv_poly_center(efa, cent, cd_loop_uv_offset); + if (do_lasso_select_mesh_uv_is_point_inside(region, &rect, mcoords, mcoords_len, cent)) { + BM_elem_flag_enable(efa, BM_ELEM_TAG); + changed = true; + } + } + } + + /* (de)selects all tagged faces and deals with sticky modes */ + if (changed) { + uv_select_flush_from_tag_face(sima, scene, obedit, select); + } + } + else if (use_edge) { + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BMLoop *l_prev = BM_FACE_FIRST_LOOP(efa)->prev; + MLoopUV *luv_prev = BM_ELEM_CD_GET_VOID_P(l_prev, cd_loop_uv_offset); + bool luv_select_prev = uvedit_uv_select_test(scene, l_prev, cd_loop_uv_offset); + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + const bool luv_select = uvedit_uv_select_test(scene, l, cd_loop_uv_offset); + if ((select != luv_select) || (select != luv_select_prev)) { + if (do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcoords, mcoords_len, luv->uv) && + do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcoords, mcoords_len, luv_prev->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + uvedit_uv_select_set(em, scene, l_prev, select, false, cd_loop_uv_offset); + changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + BM_elem_flag_enable(l_prev->v, BM_ELEM_TAG); + } + } + l_prev = l; + luv_prev = luv; + luv_select_prev = luv_select; + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + else { /* Vert Sel */ + BM_mesh_elem_hflag_disable_all(em->bm, BM_VERT, BM_ELEM_TAG, false); + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + bool has_selected = false; + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + if ((select) != (uvedit_uv_select_test(scene, l, cd_loop_uv_offset))) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + if (do_lasso_select_mesh_uv_is_point_inside( + region, &rect, mcoords, mcoords_len, luv->uv)) { + uvedit_uv_select_set(em, scene, l, select, false, cd_loop_uv_offset); + changed = true; + BM_elem_flag_enable(l->v, BM_ELEM_TAG); + has_selected = true; + } + } + } + if (has_selected && ts->uv_selectmode == UV_SELECT_ISLAND) { + UvNearestHit hit = { + .ob = obedit, + .efa = efa, + }; + uv_select_linked_multi( + scene, ima, objects, objects_len, limit, &hit, true, !select, false, false); + } + } + + if (sima->sticky == SI_STICKY_VERTEX) { + uvedit_vertex_select_tagged(em, scene, select, cd_loop_uv_offset); + } + } + + if (changed || use_pre_deselect) { + changed_multi = true; + + uv_select_sync_flush(ts, em, select); + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + MEM_freeN(objects); + + return changed_multi; +} + +static int uv_lasso_select_exec(bContext *C, wmOperator *op) +{ + int mcoords_len; + const int(*mcoords)[2] = WM_gesture_lasso_path_to_array(C, op, &mcoords_len); + + if (mcoords) { + const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode"); + bool changed = do_lasso_select_mesh_uv(C, mcoords, mcoords_len, sel_op); + MEM_freeN((void *)mcoords); + + return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED; + } + + return OPERATOR_PASS_THROUGH; +} + +void UV_OT_select_lasso(wmOperatorType *ot) +{ + ot->name = "Lasso Select UV"; + ot->description = "Select UVs using lasso selection"; + ot->idname = "UV_OT_select_lasso"; + + ot->invoke = WM_gesture_lasso_invoke; + ot->modal = WM_gesture_lasso_modal; + ot->exec = uv_lasso_select_exec; + ot->poll = ED_operator_uvedit_space_image; + ot->cancel = WM_gesture_lasso_cancel; + + /* flags */ + ot->flag = OPTYPE_UNDO; + + /* properties */ + WM_operator_properties_gesture_lasso(ot); + WM_operator_properties_select_operation_simple(ot); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Pinned UV's Operator + * \{ */ + +static int uv_select_pinned_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + const ToolSettings *ts = scene->toolsettings; + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + BMFace *efa; + BMLoop *l; + BMIter iter, liter; + MLoopUV *luv; + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + bool changed = false; + + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test(scene, obedit, ima, efa)) { + continue; + } + + BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) { + luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + + if (luv->flag & MLOOPUV_PINNED) { + uvedit_uv_select_enable(em, scene, l, false, cd_loop_uv_offset); + changed = true; + } + } + } + + if (changed) { + uv_select_tag_update_for_object(depsgraph, ts, obedit); + } + } + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +void UV_OT_select_pinned(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Selected Pinned"; + ot->description = "Select all pinned UV vertices"; + ot->idname = "UV_OT_select_pinned"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_pinned_exec; + ot->poll = ED_operator_uvedit; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Select Overlap Operator + * \{ */ + +BLI_INLINE uint overlap_hash(const void *overlap_v) +{ + const BVHTreeOverlap *overlap = overlap_v; + + /* Designed to treat (A,B) and (B,A) as the same. */ + int x = overlap->indexA; + int y = overlap->indexB; + if (x > y) { + SWAP(int, x, y); + } + return BLI_hash_int_2d(x, y); +} + +BLI_INLINE bool overlap_cmp(const void *a_v, const void *b_v) +{ + const BVHTreeOverlap *a = a_v; + const BVHTreeOverlap *b = b_v; + return !((a->indexA == b->indexA && a->indexB == b->indexB) || + (a->indexA == b->indexB && a->indexB == b->indexA)); +} + +struct UVOverlapData { + int ob_index; + int face_index; + float tri[3][2]; +}; + +static int uv_select_overlap(bContext *C, const bool extend) +{ + Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + Image *ima = CTX_data_edit_image(C); + + uint objects_len = 0; + Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs( + view_layer, ((View3D *)NULL), &objects_len); + + /* Calculate maximum number of tree nodes and prepare initial selection. */ + uint uv_tri_len = 0; + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + + BM_mesh_elem_table_ensure(em->bm, BM_FACE); + BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE); + BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false); + if (!extend) { + uv_select_all_perform(scene, ima, obedit, SEL_DESELECT); + } + + BMIter iter; + BMFace *efa; + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { + continue; + } + uv_tri_len += efa->len - 2; + } + } + + struct UVOverlapData *overlap_data = MEM_mallocN(sizeof(struct UVOverlapData) * uv_tri_len, + "UvOverlapData"); + BVHTree *uv_tree = BLI_bvhtree_new(uv_tri_len, 0.0f, 4, 6); + + /* Use a global data index when inserting into the BVH. */ + int data_index = 0; + + int face_len_alloc = 3; + float(*uv_verts)[2] = MEM_mallocN(sizeof(*uv_verts) * face_len_alloc, "UvOverlapCoords"); + uint(*indices)[3] = MEM_mallocN(sizeof(*indices) * (face_len_alloc - 2), "UvOverlapTris"); + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + Object *obedit = objects[ob_index]; + BMEditMesh *em = BKE_editmesh_from_object(obedit); + BMIter iter, liter; + BMFace *efa; + BMLoop *l; + + const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV); + + /* Triangulate each UV face and store it inside the BVH. */ + int face_index; + BM_ITER_MESH_INDEX (efa, &iter, em->bm, BM_FACES_OF_MESH, face_index) { + + if (!uvedit_face_visible_test_ex(scene->toolsettings, obedit, ima, efa)) { + continue; + } + + const uint face_len = efa->len; + const uint tri_len = face_len - 2; + + if (face_len_alloc < face_len) { + MEM_freeN(uv_verts); + MEM_freeN(indices); + uv_verts = MEM_mallocN(sizeof(*uv_verts) * face_len, "UvOverlapCoords"); + indices = MEM_mallocN(sizeof(*indices) * tri_len, "UvOverlapTris"); + face_len_alloc = face_len; + } + + int vert_index; + BM_ITER_ELEM_INDEX (l, &liter, efa, BM_LOOPS_OF_FACE, vert_index) { + MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset); + copy_v2_v2(uv_verts[vert_index], luv->uv); + } + + BLI_polyfill_calc(uv_verts, face_len, 0, indices); + + for (int t = 0; t < tri_len; t++) { + overlap_data[data_index].ob_index = ob_index; + overlap_data[data_index].face_index = face_index; + + /* BVH needs 3D, overlap data uses 2D. */ + const float tri[3][3] = { + {UNPACK2(uv_verts[indices[t][0]]), 0.0f}, + {UNPACK2(uv_verts[indices[t][1]]), 0.0f}, + {UNPACK2(uv_verts[indices[t][2]]), 0.0f}, + }; + + copy_v2_v2(overlap_data[data_index].tri[0], tri[0]); + copy_v2_v2(overlap_data[data_index].tri[1], tri[1]); + copy_v2_v2(overlap_data[data_index].tri[2], tri[2]); + + BLI_bvhtree_insert(uv_tree, data_index, &tri[0][0], 3); + data_index++; + } + } + } + BLI_assert(data_index == uv_tri_len); + + MEM_freeN(uv_verts); + MEM_freeN(indices); + + BLI_bvhtree_balance(uv_tree); + + uint tree_overlap_len; + BVHTreeOverlap *overlap = BLI_bvhtree_overlap(uv_tree, uv_tree, &tree_overlap_len, NULL, NULL); + + if (overlap != NULL) { + GSet *overlap_set = BLI_gset_new_ex(overlap_hash, overlap_cmp, __func__, tree_overlap_len); + + for (int i = 0; i < tree_overlap_len; i++) { + /* Skip overlaps against yourself. */ + if (overlap[i].indexA == overlap[i].indexB) { + continue; + } + + /* Skip overlaps that have already been tested. */ + if (!BLI_gset_add(overlap_set, &overlap[i])) { + continue; + } + + const struct UVOverlapData *o_a = &overlap_data[overlap[i].indexA]; + const struct UVOverlapData *o_b = &overlap_data[overlap[i].indexB]; + Object *obedit_a = objects[o_a->ob_index]; + Object *obedit_b = objects[o_b->ob_index]; + BMEditMesh *em_a = BKE_editmesh_from_object(obedit_a); + BMEditMesh *em_b = BKE_editmesh_from_object(obedit_b); + BMFace *face_a = em_a->bm->ftable[o_a->face_index]; + BMFace *face_b = em_b->bm->ftable[o_b->face_index]; + const int cd_loop_uv_offset_a = CustomData_get_offset(&em_a->bm->ldata, CD_MLOOPUV); + const int cd_loop_uv_offset_b = CustomData_get_offset(&em_b->bm->ldata, CD_MLOOPUV); + + /* Skip if both faces are already selected. */ + if (uvedit_face_select_test(scene, face_a, cd_loop_uv_offset_a) && + uvedit_face_select_test(scene, face_b, cd_loop_uv_offset_b)) { + continue; + } + + /* Main tri-tri overlap test. */ + const float endpoint_bias = -1e-4f; + const float(*t1)[2] = o_a->tri; + const float(*t2)[2] = o_b->tri; + float vi[2]; + bool result = ( + /* Don't use 'isect_tri_tri_v2' here + * because it's important to ignore overlap at end-points. */ + isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[0], t2[1], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[1], t2[2], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[0], t1[1], t2[2], t2[0], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[0], t2[1], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[1], t2[2], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[1], t1[2], t2[2], t2[0], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[0], t2[1], endpoint_bias, vi) == 1 || + isect_seg_seg_v2_point_ex(t1[2], t1[0], t2[1], t2[2], endpoint_bias, vi) == 1 || + isect_point_tri_v2(t1[0], t2[0], t2[1], t2[2]) != 0 || + isect_point_tri_v2(t2[0], t1[0], t1[1], t1[2]) != 0); + + if (result) { + uvedit_face_select_enable(scene, em_a, face_a, false, cd_loop_uv_offset_a); + uvedit_face_select_enable(scene, em_b, face_b, false, cd_loop_uv_offset_b); + } + } + + BLI_gset_free(overlap_set, NULL); + MEM_freeN(overlap); + } + + for (uint ob_index = 0; ob_index < objects_len; ob_index++) { + uv_select_tag_update_for_object(depsgraph, scene->toolsettings, objects[ob_index]); + } + + BLI_bvhtree_free(uv_tree); + + MEM_freeN(overlap_data); + MEM_freeN(objects); + + return OPERATOR_FINISHED; +} + +static int uv_select_overlap_exec(bContext *C, wmOperator *op) +{ + bool extend = RNA_boolean_get(op->ptr, "extend"); + return uv_select_overlap(C, extend); +} + +void UV_OT_select_overlap(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select Overlap"; + ot->description = "Select all UV faces which overlap each other"; + ot->idname = "UV_OT_select_overlap"; + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* api callbacks */ + ot->exec = uv_select_overlap_exec; + ot->poll = ED_operator_uvedit; + + /* properties */ + RNA_def_boolean(ot->srna, + "extend", + 0, + "Extend", + "Extend selection rather than clearing the existing selection"); +} + +/** \} */ diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index ca956dfbbbf..68b5b4baeca 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -25,9 +25,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_map.h" - -extern "C" { #include "RNA_access.h" #include "RNA_types.h" @@ -66,7 +63,6 @@ extern "C" { #include "RE_pipeline.h" #include "render_types.h" -} #include <limits.h> diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h index 9c94228414d..ee29519c849 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.h @@ -21,7 +21,7 @@ * \ingroup freestyle */ -#include "BLI_map.h" +#include "BLI_map.hh" #include "../stroke/StrokeRenderer.h" #include "../system/FreestyleConfig.h" diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h index a4beb1c119c..95612a42722 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h +++ b/source/blender/freestyle/intern/blender_interface/BlenderStyleModule.h @@ -24,11 +24,9 @@ #include "../stroke/StyleModule.h" #include "../system/PythonInterpreter.h" -extern "C" { #include "BLI_utildefines.h" // BLI_assert() struct Text; -} namespace Freestyle { diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h index 0a9fa5dc85a..c1a8dcdb370 100644 --- a/source/blender/freestyle/intern/geometry/Grid.h +++ b/source/blender/freestyle/intern/geometry/Grid.h @@ -33,9 +33,7 @@ #include "../system/FreestyleConfig.h" -extern "C" { #include "BLI_utildefines.h" -} #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" diff --git a/source/blender/freestyle/intern/image/GaussianFilter.h b/source/blender/freestyle/intern/image/GaussianFilter.h index f8e2524fa4f..625e357eddf 100644 --- a/source/blender/freestyle/intern/image/GaussianFilter.h +++ b/source/blender/freestyle/intern/image/GaussianFilter.h @@ -27,9 +27,7 @@ #include "../system/FreestyleConfig.h" -extern "C" { #include "BLI_math.h" -} #ifdef WITH_CXX_GUARDEDALLOC # include "MEM_guardedalloc.h" diff --git a/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h index f220bbfd6f1..2339abe9aed 100644 --- a/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h +++ b/source/blender/freestyle/intern/scene_graph/NodeViewLayer.h @@ -24,9 +24,7 @@ #include "Node.h" -extern "C" { #include "DNA_scene_types.h" /* for Scene and ViewLayer */ -} using namespace std; diff --git a/source/blender/freestyle/intern/stroke/Canvas.cpp b/source/blender/freestyle/intern/stroke/Canvas.cpp index 7d04a55c5d9..4386e64345f 100644 --- a/source/blender/freestyle/intern/stroke/Canvas.cpp +++ b/source/blender/freestyle/intern/stroke/Canvas.cpp @@ -41,10 +41,8 @@ // soc #include <qimage.h> // soc #include <QString> -extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} using namespace std; diff --git a/source/blender/freestyle/intern/stroke/StrokeRep.h b/source/blender/freestyle/intern/stroke/StrokeRep.h index b2bfb805ee6..d6ee1d01279 100644 --- a/source/blender/freestyle/intern/stroke/StrokeRep.h +++ b/source/blender/freestyle/intern/stroke/StrokeRep.h @@ -30,10 +30,8 @@ # include "MEM_guardedalloc.h" #endif -extern "C" { #include "DNA_material_types.h" // for MAX_MTEX struct bNodeTree; -} namespace Freestyle { diff --git a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp index a6a72bfa314..efda4b7fd2a 100644 --- a/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp +++ b/source/blender/freestyle/intern/view_map/SteerableViewMap.cpp @@ -33,10 +33,8 @@ #include "BKE_global.h" #include "BLI_math.h" -extern "C" { #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} namespace Freestyle { diff --git a/source/blender/freestyle/intern/winged_edge/Curvature.cpp b/source/blender/freestyle/intern/winged_edge/Curvature.cpp index 591d6518741..96b313d4e01 100644 --- a/source/blender/freestyle/intern/winged_edge/Curvature.cpp +++ b/source/blender/freestyle/intern/winged_edge/Curvature.cpp @@ -105,16 +105,16 @@ static real angle_from_cotan(WVertex *vo, WVertex *v1, WVertex *v2) } /*! gts_vertex_mean_curvature_normal: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kh: the Mean Curvature Normal at @v. + * \param v: a #WVertex. + * \param s: a #GtsSurface. + * \param Kh: the Mean Curvature Normal at \a v. * - * Computes the Discrete Mean Curvature Normal approximation at @v. - * The mean curvature at @v is half the magnitude of the vector @Kh. + * Computes the Discrete Mean Curvature Normal approximation at \a v. + * The mean curvature at \a v is half the magnitude of the vector \a Kh. * * Note: the normal computed is not unit length, and may point either into or out of the surface, - * depending on the curvature at @v. It is the responsibility of the caller of the function to use - * the mean curvature normal appropriately. + * depending on the curvature at \a v. It is the responsibility of the caller of the function to + * use the mean curvature normal appropriately. * * This approximation is from the paper: * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds @@ -176,11 +176,11 @@ bool gts_vertex_mean_curvature_normal(WVertex *v, Vec3r &Kh) } /*! gts_vertex_gaussian_curvature: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kg: the Discrete Gaussian Curvature approximation at @v. + * \param v: a #WVertex. + * \param s: a #GtsSurface. + * \param Kg: the Discrete Gaussian Curvature approximation at \a v. * - * Computes the Discrete Gaussian Curvature approximation at @v. + * Computes the Discrete Gaussian Curvature approximation at \a v. * * This approximation is from the paper: * Discrete Differential-Geometry Operators for Triangulated 2-Manifolds @@ -280,16 +280,16 @@ static void eigenvector(real a, real b, real c, Vec3r e) } /*! gts_vertex_principal_directions: - * @v: a #WVertex. - * @s: a #GtsSurface. - * @Kh: mean curvature normal (a #Vec3r). - * @Kg: Gaussian curvature (a real). - * @e1: first principal curvature direction (direction of largest curvature). - * @e2: second principal curvature direction. + * \param v: a #WVertex. + * \param s: a #GtsSurface. + * \param Kh: mean curvature normal (a #Vec3r). + * \param Kg: Gaussian curvature (a real). + * \param e1: first principal curvature direction (direction of largest curvature). + * \param e2: second principal curvature direction. * - * Computes the principal curvature directions at a point given @Kh and @Kg, the mean curvature - * normal and Gaussian curvatures at that point, computed with gts_vertex_mean_curvature_normal() - * and gts_vertex_gaussian_curvature(), respectively. + * Computes the principal curvature directions at a point given \a Kh and \a Kg, + * the mean curvature normal and Gaussian curvatures at that point, computed with + * gts_vertex_mean_curvature_normal() and gts_vertex_gaussian_curvature(), respectively. * * Note that this computation is very approximate and tends to be unstable. Smoothing of the * surface or the principal directions may be necessary to achieve reasonable results. diff --git a/source/blender/gpencil_modifiers/CMakeLists.txt b/source/blender/gpencil_modifiers/CMakeLists.txt index 87743911add..d3c85b891c6 100644 --- a/source/blender/gpencil_modifiers/CMakeLists.txt +++ b/source/blender/gpencil_modifiers/CMakeLists.txt @@ -56,6 +56,7 @@ set(SRC intern/MOD_gpencilsimplify.c intern/MOD_gpencilsmooth.c intern/MOD_gpencilsubdiv.c + intern/MOD_gpenciltexture.c intern/MOD_gpencilthick.c intern/MOD_gpenciltime.c intern/MOD_gpenciltint.c diff --git a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h index f5c064c1c07..a7a4333d82e 100644 --- a/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h +++ b/source/blender/gpencil_modifiers/MOD_gpencil_modifiertypes.h @@ -43,6 +43,7 @@ extern GpencilModifierTypeInfo modifierType_Gpencil_Offset; extern GpencilModifierTypeInfo modifierType_Gpencil_Armature; extern GpencilModifierTypeInfo modifierType_Gpencil_Time; extern GpencilModifierTypeInfo modifierType_Gpencil_Multiply; +extern GpencilModifierTypeInfo modifierType_Gpencil_Texture; /* MOD_gpencil_util.c */ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c index 7df0440aa85..f7929b58650 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.c @@ -72,13 +72,14 @@ void gpencil_modifier_type_init(GpencilModifierTypeInfo *types[]) INIT_GP_TYPE(Armature); INIT_GP_TYPE(Time); INIT_GP_TYPE(Multiply); + INIT_GP_TYPE(Texture); #undef INIT_GP_TYPE } /* verify if valid layer, material and pass index */ bool is_stroke_affected_by_modifier(Object *ob, char *mlayername, - char *mmaterialname, + Material *material, const int mpassindex, const int gpl_passindex, const int minpoints, @@ -105,15 +106,15 @@ bool is_stroke_affected_by_modifier(Object *ob, } } } - /* omit if filter by material */ - if (mmaterialname[0] != '\0') { + /* Omit if filter by material. */ + if (material != NULL) { if (inv4 == false) { - if (!STREQ(mmaterialname, ma->id.name + 2)) { + if (material != ma) { return false; } } else { - if (STREQ(mmaterialname, ma->id.name + 2)) { + if (material == ma) { return false; } } diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h index fc4522bc028..5cc3750639b 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencil_util.h @@ -34,7 +34,7 @@ struct bGPDstroke; bool is_stroke_affected_by_modifier(struct Object *ob, char *mlayername, - char *mmaterialname, + struct Material *material, const int mpassindex, const int gpl_passindex, const int minpoints, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c index 59a41901a48..2d5e01ced94 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarmature.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -63,7 +63,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void gpencil_deform_verts(ArmatureGpencilModifierData *mmd, Object *target, bGPDstroke *gps) @@ -127,7 +127,7 @@ static void bakeModifier(Main *bmain, Depsgraph *depsgraph, GpencilModifierData Scene *scene = DEG_get_evaluated_scene(depsgraph); Object *object_eval = DEG_get_evaluated_object(depsgraph, ob); ArmatureGpencilModifierData *mmd = (ArmatureGpencilModifierData *)md; - GpencilModifierData *md_eval = BKE_gpencil_modifiers_findByName(object_eval, md->name); + GpencilModifierData *md_eval = BKE_gpencil_modifiers_findby_name(object_eval, md->name); bGPdata *gpd = (bGPdata *)ob->data; int oldframe = (int)DEG_get_ctime(depsgraph); diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c index 314879927ff..da4c1f71f44 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilarray.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -77,11 +77,12 @@ static void initData(GpencilModifierData *md) gpmd->object = NULL; gpmd->flag |= GP_ARRAY_USE_RELATIVE; gpmd->seed = 1; + gpmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* -------------------------------- */ @@ -163,7 +164,7 @@ static void generate_geometry(GpencilModifierData *md, LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { if (is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -320,6 +321,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ArrayGpencilModifierData *mmd = (ArrayGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Array = { /* name */ "Array", /* structName */ "ArrayGpencilModifierData", @@ -340,6 +350,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Array = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c index 435559f4881..71a051629d8 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilbuild.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -63,7 +63,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static bool dependsOnTime(GpencilModifierData *UNUSED(md)) @@ -406,6 +406,7 @@ static void generate_geometry(GpencilModifierData *md, { BuildGpencilModifierData *mmd = (BuildGpencilModifierData *)md; const bool reverse = (mmd->transition != GP_BUILD_TRANSITION_GROW); + const bool is_percentage = (mmd->flag & GP_BUILD_PERCENTAGE); const float ctime = DEG_get_ctime(depsgraph); @@ -462,8 +463,8 @@ static void generate_geometry(GpencilModifierData *md, } /* Early exit if current frame is outside start/end bounds */ - /* NOTE: If we're beyond the next/prev frames (if existent), then we wouldn't have this problem - * anyway... */ + /* NOTE: If we're beyond the next/previous frames (if existent), + * then we wouldn't have this problem anyway... */ if (ctime < start_frame) { /* Before Start - Animation hasn't started. Display initial state. */ if (reverse) { @@ -500,7 +501,8 @@ static void generate_geometry(GpencilModifierData *md, } /* Determine how far along we are between the keyframes */ - float fac = (ctime - start_frame) / (end_frame - start_frame); + float fac = is_percentage ? mmd->percentage_fac : + (ctime - start_frame) / (end_frame - start_frame); /* Time management mode */ switch (mmd->mode) { diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c index d311e77b9e3..14125d5c8d4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilcolor.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -37,8 +37,10 @@ #include "BKE_colortools.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -50,8 +52,7 @@ static void initData(GpencilModifierData *md) ColorGpencilModifierData *gpmd = (ColorGpencilModifierData *)md; gpmd->pass_index = 0; ARRAY_SET_ITEMS(gpmd->hsv, 0.5f, 1.0f, 1.0f); - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -71,7 +72,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -91,7 +92,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -178,6 +179,13 @@ static void freeData(GpencilModifierData *md) } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ColorGpencilModifierData *mmd = (ColorGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Color = { /* name */ "Hue/Saturation", /* structName */ "ColorGpencilModifierData", @@ -198,6 +206,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Color = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c index 76f22fc9a36..d39c94e06d5 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilhook.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -77,9 +77,7 @@ static void initData(GpencilModifierData *md) { HookGpencilModifierData *gpmd = (HookGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->force = 0.5f; gpmd->falloff_type = eGPHook_Falloff_Smooth; @@ -99,7 +97,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curfalloff = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curfalloff = BKE_curvemapping_copy(gmd->curfalloff); } @@ -208,7 +206,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -338,6 +336,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + HookGpencilModifierData *mmd = (HookGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Hook = { /* name */ "Hook", /* structName */ "HookGpencilModifierData", @@ -358,6 +365,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Hook = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c index 73b3c332a2e..5d5d673ca55 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencillattice.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -55,9 +55,7 @@ static void initData(GpencilModifierData *md) { LatticeGpencilModifierData *gpmd = (LatticeGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->cache_data = NULL; gpmd->strength = 1.0f; @@ -65,7 +63,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void deformStroke(GpencilModifierData *md, @@ -80,7 +78,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -200,6 +198,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + LatticeGpencilModifierData *mmd = (LatticeGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Lattice = { /* name */ "Lattice", /* structName */ "LatticeGpencilModifierData", @@ -220,6 +227,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Lattice = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c index 8740f9407cd..d750853fc94 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmirror.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -57,15 +57,14 @@ static void initData(GpencilModifierData *md) { MirrorGpencilModifierData *gpmd = (MirrorGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->flag |= GP_MIRROR_AXIS_X; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* Mirror is using current object as origin. */ @@ -163,7 +162,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp for (i = 0, gps = gpf->strokes.first; i < tot_strokes; i++, gps = gps->next) { if (is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -246,6 +245,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + MirrorGpencilModifierData *mmd = (MirrorGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Mirror = { /* name */ "Mirror", /* structName */ "MirrorGpencilModifierData", @@ -266,6 +274,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Mirror = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c index 2552f527a5e..22e46626a13 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilmultiply.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -71,11 +71,12 @@ static void initData(GpencilModifierData *md) mmd->fading_center = 0.5f; mmd->fading_thickness = 0.5f; mmd->fading_opacity = 0.5f; + mmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void minter_v3_v3v3v3_ref( @@ -211,7 +212,7 @@ static void bakeModifier(Main *UNUSED(bmain), for (gps = gpf->strokes.first; gps; gps = gps->next) { if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -252,7 +253,7 @@ static void generate_geometry(GpencilModifierData *md, Object *ob, bGPDlayer *gp for (gps = gpf->strokes.first; gps; gps = gps->next) { if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -297,6 +298,13 @@ static void generateStrokes(GpencilModifierData *md, Depsgraph *depsgraph, Objec } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + MultiplyGpencilModifierData *mmd = (MultiplyGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Multiply = { /* name */ "Multiple Strokes", /* structName */ "MultiplyGpencilModifierData", @@ -317,6 +325,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Multiply = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c index 5ed08e39197..82f9d9a323d 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilnoise.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -44,6 +44,8 @@ #include "BKE_gpencil.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "BKE_object.h" #include "DEG_depsgraph.h" @@ -59,9 +61,7 @@ static void initData(GpencilModifierData *md) gpmd->flag |= GP_NOISE_FULL_STROKE; gpmd->flag |= GP_NOISE_USE_RANDOM; gpmd->factor = 0.5f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->step = 4; gpmd->seed = 1; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -91,7 +91,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -135,7 +135,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -259,6 +259,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + NoiseGpencilModifierData *mmd = (NoiseGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Noise = { /* name */ "Noise", /* structName */ "NoiseGpencilModifierData", @@ -279,6 +286,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Noise = { /* updateDepsgraph */ NULL, /* dependsOnTime */ dependsOnTime, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c index a78de314c21..686f589ffe9 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciloffset.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -38,6 +38,8 @@ #include "BKE_deform.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -48,9 +50,7 @@ static void initData(GpencilModifierData *md) { OffsetGpencilModifierData *gpmd = (OffsetGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; ARRAY_SET_ITEMS(gpmd->loc, 0.0f, 0.0f, 0.0f); ARRAY_SET_ITEMS(gpmd->rot, 0.0f, 0.0f, 0.0f); ARRAY_SET_ITEMS(gpmd->scale, 0.0f, 0.0f, 0.0f); @@ -58,7 +58,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* change stroke offsetness */ @@ -77,7 +77,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -129,6 +129,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + OffsetGpencilModifierData *mmd = (OffsetGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Offset = { /* name */ "Offset", /* structName */ "OffsetGpencilModifierData", @@ -149,6 +156,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Offset = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c index 5ca99be0dff..92b2621d211 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilopacity.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -38,8 +38,10 @@ #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" #include "BKE_main.h" #include "BKE_material.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -52,9 +54,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->factor = 1.0f; gpmd->hardeness = 1.0f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->modify_color = GP_MODIFY_COLOR_BOTH; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); if (gpmd->curve_intensity) { @@ -73,7 +73,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -92,7 +92,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -189,6 +189,13 @@ static void freeData(GpencilModifierData *md) } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + OpacityGpencilModifierData *mmd = (OpacityGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Opacity = { /* name */ "Opacity", /* structName */ "OpacityGpencilModifierData", @@ -209,6 +216,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Opacity = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c index 7b914b2a3b0..2cda108682e 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsimplify.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -34,6 +34,8 @@ #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -48,13 +50,12 @@ static void initData(GpencilModifierData *md) gpmd->factor = 0.0f; gpmd->length = 0.1f; gpmd->distance = 0.1f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static void deformStroke(GpencilModifierData *md, @@ -68,7 +69,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, mmd->mode == GP_SIMPLIFY_SAMPLE ? 3 : 4, @@ -123,6 +124,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SimplifyGpencilModifierData *mmd = (SimplifyGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Simplify = { /* name */ "Simplify", /* structName */ "SimplifyGpencilModifierData", @@ -143,6 +151,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Simplify = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c index fb9089ea6cb..e2e13b736e4 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsmooth.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -35,6 +35,8 @@ #include "BKE_deform.h" #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -47,9 +49,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->flag |= GP_SMOOTH_MOD_LOCATION; gpmd->factor = 0.5f; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->step = 1; gpmd->curve_intensity = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); @@ -69,7 +69,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_intensity = BKE_curvemapping_copy(gmd->curve_intensity); } @@ -88,7 +88,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 3, @@ -167,6 +167,13 @@ static void freeData(GpencilModifierData *md) } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SmoothGpencilModifierData *mmd = (SmoothGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Smooth = { /* name */ "Smooth", /* structName */ "SmoothGpencilModifierData", @@ -187,6 +194,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Smooth = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c index 0fdc3694af2..072159136ce 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilsubdiv.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -36,6 +36,8 @@ #include "BKE_gpencil_geom.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -47,13 +49,12 @@ static void initData(GpencilModifierData *md) SubdivGpencilModifierData *gpmd = (SubdivGpencilModifierData *)md; gpmd->pass_index = 0; gpmd->level = 1; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; + gpmd->material = NULL; } static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } /* subdivide stroke to get more control points */ @@ -72,7 +73,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, minimum_vert, @@ -104,6 +105,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SubdivGpencilModifierData *mmd = (SubdivGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = { /* name */ "Subdivide", /* structName */ "SubdivGpencilModifierData", @@ -124,6 +132,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Subdiv = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c new file mode 100644 index 00000000000..a5adf12b617 --- /dev/null +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltexture.c @@ -0,0 +1,172 @@ +/* + * 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) 2017, Blender Foundation + * This is a new part of Blender + */ + +/** \file + * \ingroup modifiers + */ + +#include <stdio.h> + +#include "BLI_listbase.h" +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "DNA_gpencil_modifier_types.h" +#include "DNA_gpencil_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "BKE_colortools.h" +#include "BKE_deform.h" +#include "BKE_gpencil.h" +#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" + +#include "DEG_depsgraph.h" + +#include "MOD_gpencil_modifiertypes.h" +#include "MOD_gpencil_util.h" + +static void initData(GpencilModifierData *md) +{ + TextureGpencilModifierData *gpmd = (TextureGpencilModifierData *)md; + gpmd->fit_method = GP_TEX_CONSTANT_LENGTH; + gpmd->fill_rotation = 0.0f; + gpmd->fill_scale = 1.0f; + gpmd->fill_offset[0] = 0.0f; + gpmd->fill_offset[1] = 0.0f; + gpmd->uv_offset = 0.0f; + gpmd->uv_scale = 1.0f; + gpmd->pass_index = 0; + gpmd->material = NULL; +} + +static void copyData(const GpencilModifierData *md, GpencilModifierData *target) +{ + BKE_gpencil_modifier_copydata_generic(md, target); +} + +/* change stroke uv texture values */ +static void deformStroke(GpencilModifierData *md, + Depsgraph *UNUSED(depsgraph), + Object *ob, + bGPDlayer *gpl, + bGPDframe *UNUSED(gpf), + bGPDstroke *gps) +{ + TextureGpencilModifierData *mmd = (TextureGpencilModifierData *)md; + const int def_nr = BKE_object_defgroup_name_index(ob, mmd->vgname); + + if (!is_stroke_affected_by_modifier(ob, + mmd->layername, + mmd->material, + mmd->pass_index, + mmd->layer_pass, + 1, + gpl, + gps, + mmd->flag & GP_TEX_INVERT_LAYER, + mmd->flag & GP_TEX_INVERT_PASS, + mmd->flag & GP_TEX_INVERT_LAYERPASS, + mmd->flag & GP_TEX_INVERT_MATERIAL)) { + return; + } + if ((mmd->mode == FILL) || (mmd->mode == STROKE_AND_FILL)) { + gps->uv_rotation += mmd->fill_rotation; + gps->uv_translation[0] += mmd->fill_offset[0]; + gps->uv_translation[1] += mmd->fill_offset[1]; + gps->uv_scale *= mmd->fill_scale; + BKE_gpencil_stroke_geometry_update(gps); + } + + if ((mmd->mode == STROKE) || (mmd->mode == STROKE_AND_FILL)) { + float totlen = 1.0f; + if (mmd->fit_method == GP_TEX_FIT_STROKE) { + totlen = 0.0f; + for (int i = 1; i < gps->totpoints; i++) { + totlen += len_v3v3(&gps->points[i - 1].x, &gps->points[i].x); + } + } + + for (int i = 0; i < gps->totpoints; i++) { + bGPDspoint *pt = &gps->points[i]; + MDeformVert *dvert = gps->dvert != NULL ? &gps->dvert[i] : NULL; + /* Verify point is part of vertex group. */ + float weight = get_modifier_point_weight( + dvert, (mmd->flag & GP_TEX_INVERT_VGROUP) != 0, def_nr); + if (weight < 0.0f) { + continue; + } + + pt->uv_fac /= totlen; + pt->uv_fac *= mmd->uv_scale; + pt->uv_fac += mmd->uv_offset; + } + } +} + +static void bakeModifier(struct Main *UNUSED(bmain), + Depsgraph *depsgraph, + GpencilModifierData *md, + Object *ob) +{ + bGPdata *gpd = ob->data; + + LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd->layers) { + LISTBASE_FOREACH (bGPDframe *, gpf, &gpl->frames) { + LISTBASE_FOREACH (bGPDstroke *, gps, &gpf->strokes) { + deformStroke(md, depsgraph, ob, gpl, gpf, gps); + } + } + } +} + +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + TextureGpencilModifierData *mmd = (TextureGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + +GpencilModifierTypeInfo modifierType_Gpencil_Texture = { + /* name */ "Texture Mapping", + /* structName */ "TextureGpencilModifierData", + /* structSize */ sizeof(TextureGpencilModifierData), + /* type */ eGpencilModifierTypeType_Gpencil, + /* flags */ eGpencilModifierTypeFlag_SupportsEditmode, + + /* copyData */ copyData, + + /* deformStroke */ deformStroke, + /* generateStrokes */ NULL, + /* bakeModifier */ bakeModifier, + /* remapTime */ NULL, + + /* initData */ initData, + /* freeData */ NULL, + /* isDisabled */ NULL, + /* updateDepsgraph */ NULL, + /* dependsOnTime */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ NULL, +}; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c index 4d985652a1e..b9fadea7fd0 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpencilthick.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -37,6 +37,8 @@ #include "BKE_deform.h" #include "BKE_gpencil.h" #include "BKE_gpencil_modifier.h" +#include "BKE_lib_query.h" +#include "BKE_modifier.h" #include "DEG_depsgraph.h" @@ -49,9 +51,7 @@ static void initData(GpencilModifierData *md) gpmd->pass_index = 0; gpmd->thickness_fac = 1.0f; gpmd->thickness = 30; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->curve_thickness = BKE_curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f); if (gpmd->curve_thickness) { BKE_curvemapping_initialize(gpmd->curve_thickness); @@ -77,7 +77,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_thickness = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); tgmd->curve_thickness = BKE_curvemapping_copy(gmd->curve_thickness); } @@ -95,7 +95,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -159,6 +159,13 @@ static void bakeModifier(struct Main *UNUSED(bmain), } } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + ThickGpencilModifierData *mmd = (ThickGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); +} + GpencilModifierTypeInfo modifierType_Gpencil_Thick = { /* name */ "Thickness", /* structName */ "ThickGpencilModifierData", @@ -179,6 +186,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Thick = { /* updateDepsgraph */ NULL, /* dependsOnTime */ NULL, /* foreachObjectLink */ NULL, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c index 10463f865e2..85400b56cad 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltime.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -45,7 +45,6 @@ static void initData(GpencilModifierData *md) { TimeGpencilModifierData *gpmd = (TimeGpencilModifierData *)md; - gpmd->layername[0] = '\0'; gpmd->offset = 1; gpmd->frame_scale = 1.0f; gpmd->flag |= GP_TIME_KEEP_LOOP; @@ -55,7 +54,7 @@ static void initData(GpencilModifierData *md) static void copyData(const GpencilModifierData *md, GpencilModifierData *target) { - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); } static int remapTime(struct GpencilModifierData *md, diff --git a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c index 95a7fb53018..c35728bc8b3 100644 --- a/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c +++ b/source/blender/gpencil_modifiers/intern/MOD_gpenciltint.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -61,9 +61,7 @@ static void initData(GpencilModifierData *md) { TintGpencilModifierData *gpmd = (TintGpencilModifierData *)md; gpmd->pass_index = 0; - gpmd->layername[0] = '\0'; - gpmd->materialname[0] = '\0'; - gpmd->vgname[0] = '\0'; + gpmd->material = NULL; gpmd->object = NULL; gpmd->radius = 1.0f; gpmd->factor = 0.5f; @@ -103,7 +101,7 @@ static void copyData(const GpencilModifierData *md, GpencilModifierData *target) tgmd->curve_intensity = NULL; } - BKE_gpencil_modifier_copyData_generic(md, target); + BKE_gpencil_modifier_copydata_generic(md, target); if (gmd->colorband) { tgmd->colorband = MEM_dupallocN(gmd->colorband); @@ -130,7 +128,7 @@ static void deformStroke(GpencilModifierData *md, if (!is_stroke_affected_by_modifier(ob, mmd->layername, - mmd->materialname, + mmd->material, mmd->pass_index, mmd->layer_pass, 1, @@ -323,6 +321,15 @@ static void foreachObjectLink(GpencilModifierData *md, walk(userData, ob, &mmd->object, IDWALK_CB_NOP); } +static void foreachIDLink(GpencilModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + TintGpencilModifierData *mmd = (TintGpencilModifierData *)md; + + walk(userData, ob, (ID **)&mmd->material, IDWALK_CB_USER); + + foreachObjectLink(md, ob, (ObjectWalkFunc)walk, userData); +} + GpencilModifierTypeInfo modifierType_Gpencil_Tint = { /* name */ "Tint", /* structName */ "TintGpencilModifierData", @@ -343,6 +350,6 @@ GpencilModifierTypeInfo modifierType_Gpencil_Tint = { /* updateDepsgraph */ updateDepsgraph, /* dependsOnTime */ NULL, /* foreachObjectLink */ foreachObjectLink, - /* foreachIDLink */ NULL, + /* foreachIDLink */ foreachIDLink, /* foreachTexLink */ NULL, }; diff --git a/source/blender/gpu/GPU_context.h b/source/blender/gpu/GPU_context.h index dd7611fe2fc..9876aa6998c 100644 --- a/source/blender/gpu/GPU_context.h +++ b/source/blender/gpu/GPU_context.h @@ -26,14 +26,14 @@ #ifndef __GPU_CONTEXT_H__ #define __GPU_CONTEXT_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "GPU_batch.h" #include "GPU_common.h" #include "GPU_shader_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct GPUContext GPUContext; GPUContext *GPU_context_create(GLuint default_framebuffer); diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h index f521fa3c702..e5a6a8ffde8 100644 --- a/source/blender/gpu/GPU_draw.h +++ b/source/blender/gpu/GPU_draw.h @@ -24,6 +24,9 @@ #ifndef __GPU_DRAW_H__ #define __GPU_DRAW_H__ +#include "BLI_utildefines.h" +#include "DNA_object_enums.h" + #ifdef __cplusplus extern "C" { #endif @@ -34,9 +37,6 @@ struct Image; struct ImageUser; struct Main; -#include "BLI_utildefines.h" -#include "DNA_object_enums.h" - /* OpenGL drawing functions related to shading. */ /* Initialize diff --git a/source/blender/gpu/GPU_immediate_util.h b/source/blender/gpu/GPU_immediate_util.h index 1cf6475408f..47b44b59461 100644 --- a/source/blender/gpu/GPU_immediate_util.h +++ b/source/blender/gpu/GPU_immediate_util.h @@ -70,6 +70,13 @@ void imm_draw_disk_partial_fill_2d(uint pos, void imm_draw_box_wire_2d(uint pos, float x1, float y1, float x2, float y2); void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2); +void imm_draw_box_checker_2d_ex(float x1, + float y1, + float x2, + float y2, + const float color_primary[4], + const float color_secondary[4], + int checker_size); void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2); void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]); diff --git a/source/blender/gpu/GPU_init_exit.h b/source/blender/gpu/GPU_init_exit.h index 0046eaa942b..3e30a1ddcf5 100644 --- a/source/blender/gpu/GPU_init_exit.h +++ b/source/blender/gpu/GPU_init_exit.h @@ -24,12 +24,12 @@ #ifndef __GPU_INIT_EXIT_H__ #define __GPU_INIT_EXIT_H__ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - void GPU_init(void); void GPU_exit(void); bool GPU_is_initialized(void); diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h index dd64b858b35..0e382f2225f 100644 --- a/source/blender/gpu/GPU_shader.h +++ b/source/blender/gpu/GPU_shader.h @@ -29,9 +29,9 @@ extern "C" { #endif typedef struct GPUShader GPUShader; +struct GPUShaderInterface; struct GPUTexture; struct GPUUniformBuffer; -struct GPUShaderInterface; /* GPU Shader * - only for fragment shaders now diff --git a/source/blender/gpu/intern/gpu_batch_private.h b/source/blender/gpu/intern/gpu_batch_private.h index 42cfc1e2a5c..58d1810ac7a 100644 --- a/source/blender/gpu/intern/gpu_batch_private.h +++ b/source/blender/gpu/intern/gpu_batch_private.h @@ -27,14 +27,14 @@ #ifndef __GPU_BATCH_PRIVATE_H__ #define __GPU_BATCH_PRIVATE_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "GPU_batch.h" #include "GPU_context.h" #include "GPU_shader_interface.h" +#ifdef __cplusplus +extern "C" { +#endif + void gpu_batch_remove_interface_ref(GPUBatch *batch, const GPUShaderInterface *interface); #ifdef __cplusplus diff --git a/source/blender/gpu/intern/gpu_context_private.h b/source/blender/gpu/intern/gpu_context_private.h index c9379e5433f..f64cdf439a1 100644 --- a/source/blender/gpu/intern/gpu_context_private.h +++ b/source/blender/gpu/intern/gpu_context_private.h @@ -26,12 +26,12 @@ #ifndef __GPU_CONTEXT_PRIVATE_H__ #define __GPU_CONTEXT_PRIVATE_H__ +#include "GPU_context.h" + #ifdef __cplusplus extern "C" { #endif -#include "GPU_context.h" - struct GPUFrameBuffer; GLuint GPU_vao_default(void); diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c index 7bcb0a7a552..d95904c0007 100644 --- a/source/blender/gpu/intern/gpu_immediate.c +++ b/source/blender/gpu/intern/gpu_immediate.c @@ -272,6 +272,14 @@ void immBegin(GPUPrimType prim_type, uint vertex_len) /* printf("mapping %u to %u\n", imm.buffer_offset, imm.buffer_offset + bytes_needed - 1); */ +#if TRUST_NO_ONE + { + GLint bufsize; + glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufsize); + assert(active_buffer->buffer_offset + bytes_needed <= bufsize); + } +#endif + active_buffer->buffer_data = glMapBufferRange( GL_ARRAY_BUFFER, active_buffer->buffer_offset, diff --git a/source/blender/gpu/intern/gpu_immediate_util.c b/source/blender/gpu/intern/gpu_immediate_util.c index 7266f595447..e834d6afccb 100644 --- a/source/blender/gpu/intern/gpu_immediate_util.c +++ b/source/blender/gpu/intern/gpu_immediate_util.c @@ -361,25 +361,35 @@ void imm_draw_box_wire_3d(uint pos, float x1, float y1, float x2, float y2) /** * Draw a standard checkerboard to indicate transparent backgrounds. */ -void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2) +void imm_draw_box_checker_2d_ex(float x1, + float y1, + float x2, + float y2, + const float color_primary[4], + const float color_secondary[4], + int checker_size) { uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - float checker_primary[4]; - float checker_secondary[4]; - int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE); immBindBuiltinProgram(GPU_SHADER_2D_CHECKER); - UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary); - UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary); - immUniform4fv("color1", checker_primary); - immUniform4fv("color2", checker_secondary); + immUniform4fv("color1", color_primary); + immUniform4fv("color2", color_secondary); immUniform1i("size", checker_size); immRectf(pos, x1, y1, x2, y2); immUnbindProgram(); } +void imm_draw_box_checker_2d(float x1, float y1, float x2, float y2) +{ + float checker_primary[4]; + float checker_secondary[4]; + UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_PRIMARY, checker_primary); + UI_GetThemeColor4fv(TH_TRANSPARENT_CHECKER_SECONDARY, checker_secondary); + int checker_size = UI_GetThemeValue(TH_TRANSPARENT_CHECKER_SIZE); + imm_draw_box_checker_2d_ex(x1, y1, x2, y2, checker_primary, checker_secondary, checker_size); +} void imm_draw_cube_fill_3d(uint pos, const float co[3], const float aspect[3]) { diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c index cb1cd9a6f6d..1caa88d18ae 100644 --- a/source/blender/gpu/intern/gpu_shader_interface.c +++ b/source/blender/gpu/intern/gpu_shader_interface.c @@ -254,8 +254,12 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program) } /* TODO: reject DOUBLE gl_types */ - input->location = glGetAttribLocation(program, name); + /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */ + if (input->location == -1) { + MEM_freeN(input); + continue; + } shaderface->enabled_attr_mask |= (1 << input->location); diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index 496e8981f2b..f30270b9eed 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -559,10 +559,10 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport, { /** * HACK(fclem): We copy the settings here to avoid use after free if an update frees the scene - * and the viewport stays cached (see T75443). But this means the OCIO curvemapping caching - * (which is based on CurveMap pointer address) cannot operate correctly and it will create - * a different OCIO processor for each viewport. We try to only realloc the curvemap copy if - * needed to avoid uneeded cache invalidation. + * and the viewport stays cached (see T75443). But this means the OCIO curve-mapping caching + * (which is based on #CurveMap pointer address) cannot operate correctly and it will create + * a different OCIO processor for each viewport. We try to only reallocate the curve-map copy + * if needed to avoid unneeded cache invalidation. */ if (view_settings->curve_mapping) { if (viewport->view_settings.curve_mapping) { diff --git a/source/blender/ikplugin/intern/itasc_plugin.cpp b/source/blender/ikplugin/intern/itasc_plugin.cpp index 19a4390598f..66ed0dd0fa5 100644 --- a/source/blender/ikplugin/intern/itasc_plugin.cpp +++ b/source/blender/ikplugin/intern/itasc_plugin.cpp @@ -40,7 +40,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BIK_api.h" #include "BLI_blenlib.h" #include "BLI_math.h" @@ -55,7 +54,6 @@ extern "C" { #include "DNA_constraint_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -}; #include "itasc_plugin.h" diff --git a/source/blender/imbuf/intern/IMB_allocimbuf.h b/source/blender/imbuf/intern/IMB_allocimbuf.h index c252a9a63f8..9f89969cf1c 100644 --- a/source/blender/imbuf/intern/IMB_allocimbuf.h +++ b/source/blender/imbuf/intern/IMB_allocimbuf.h @@ -24,6 +24,10 @@ #ifndef __IMB_ALLOCIMBUF_H__ #define __IMB_ALLOCIMBUF_H__ +#ifdef __cplusplus +extern "C" { +#endif + struct ImBuf; void imb_refcounter_lock_init(void); @@ -44,4 +48,8 @@ void imb_mmap_unlock(void); bool imb_addencodedbufferImBuf(struct ImBuf *ibuf); bool imb_enlargeencodedbufferImBuf(struct ImBuf *ibuf); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index f0e599c1375..79abe8472b9 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -27,6 +27,10 @@ #include "BLI_sys_types.h" #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + struct ImBuf; struct OCIO_ConstProcessorRcPtr; @@ -123,4 +127,8 @@ 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); +#ifdef __cplusplus +} +#endif + #endif /* __IMB_COLORMANAGEMENT_INTERN_H__ */ diff --git a/source/blender/imbuf/intern/cineon/cineonlib.h b/source/blender/imbuf/intern/cineon/cineonlib.h index 461407fcf25..040435e44ee 100644 --- a/source/blender/imbuf/intern/cineon/cineonlib.h +++ b/source/blender/imbuf/intern/cineon/cineonlib.h @@ -26,12 +26,12 @@ #ifndef __CINEONLIB_H__ #define __CINEONLIB_H__ +#include "logImageCore.h" + #ifdef __cplusplus extern "C" { #endif -#include "logImageCore.h" - #define CINEON_FILE_MAGIC 0x802A5FD7 #define CINEON_UNDEFINED_U8 0xFF #define CINEON_UNDEFINED_U16 0xFFFF diff --git a/source/blender/imbuf/intern/cineon/dpxlib.h b/source/blender/imbuf/intern/cineon/dpxlib.h index bf07b8e329d..3a7ebe9dddf 100644 --- a/source/blender/imbuf/intern/cineon/dpxlib.h +++ b/source/blender/imbuf/intern/cineon/dpxlib.h @@ -25,12 +25,12 @@ #ifndef __DPXLIB_H__ #define __DPXLIB_H__ +#include "logImageCore.h" + #ifdef __cplusplus extern "C" { #endif -#include "logImageCore.h" - #define DPX_FILE_MAGIC 0x53445058 #define DPX_UNDEFINED_U8 0xFF #define DPX_UNDEFINED_U16 0xFFFF diff --git a/source/blender/imbuf/intern/dds/dds_api.cpp b/source/blender/imbuf/intern/dds/dds_api.cpp index 832b380bbc2..83d304203a0 100644 --- a/source/blender/imbuf/intern/dds/dds_api.cpp +++ b/source/blender/imbuf/intern/dds/dds_api.cpp @@ -18,9 +18,7 @@ * \ingroup imbdds */ -extern "C" { #include "BLI_utildefines.h" -} #include <DirectDrawSurface.h> #include <FlipDXT.h> @@ -34,8 +32,6 @@ extern "C" { # include "utfconv.h" #endif -extern "C" { - #include "IMB_allocimbuf.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -44,6 +40,8 @@ extern "C" { #include "IMB_colormanagement.h" #include "IMB_colormanagement_intern.h" +extern "C" { + int imb_save_dds(struct ImBuf *ibuf, const char *name, int /*flags*/) { return (0); /* todo: finish this function */ diff --git a/source/blender/imbuf/intern/dds/dds_api.h b/source/blender/imbuf/intern/dds/dds_api.h index 12db8aa6416..e6782e217fc 100644 --- a/source/blender/imbuf/intern/dds/dds_api.h +++ b/source/blender/imbuf/intern/dds/dds_api.h @@ -21,12 +21,12 @@ #ifndef __DDS_API_H__ #define __DDS_API_H__ +#include "../../IMB_imbuf.h" + #ifdef __cplusplus extern "C" { #endif -#include "../../IMB_imbuf.h" - int imb_is_a_dds(const unsigned char *mem); /* use only first 32 bytes of mem */ int imb_save_dds(struct ImBuf *ibuf, const char *name, int flags); struct ImBuf *imb_load_dds(const unsigned char *mem, diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index aa82487d69f..7ebbd1a7409 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -338,9 +338,9 @@ void nearest_interpolation(ImBuf *in, ImBuf *out, float x, float y, int xout, in /*********************** Threaded image processing *************************/ -static void processor_apply_func(TaskPool *__restrict pool, void *taskdata, int UNUSED(threadid)) +static void processor_apply_func(TaskPool *__restrict pool, void *taskdata) { - void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_userdata(pool); + void (*do_thread)(void *) = (void (*)(void *))BLI_task_pool_user_data(pool); do_thread(taskdata); } @@ -353,14 +353,13 @@ void IMB_processor_apply_threaded( { const int lines_per_task = 64; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); TaskPool *task_pool; void *handles; int total_tasks = (buffer_lines + lines_per_task - 1) / lines_per_task; int i, start_line; - task_pool = BLI_task_pool_create(task_scheduler, do_thread, TASK_PRIORITY_LOW); + task_pool = BLI_task_pool_create(do_thread, TASK_PRIORITY_LOW); handles = MEM_callocN(handle_size * total_tasks, "processor apply threaded handles"); @@ -399,11 +398,9 @@ typedef struct ScanlineGlobalData { int total_scanlines; } ScanlineGlobalData; -static void processor_apply_scanline_func(TaskPool *__restrict pool, - void *taskdata, - int UNUSED(threadid)) +static void processor_apply_scanline_func(TaskPool *__restrict pool, void *taskdata) { - ScanlineGlobalData *data = BLI_task_pool_userdata(pool); + ScanlineGlobalData *data = BLI_task_pool_user_data(pool); int start_scanline = POINTER_AS_INT(taskdata); int num_scanlines = min_ii(data->scanlines_per_task, data->total_scanlines - start_scanline); data->do_thread(data->custom_data, start_scanline, num_scanlines); @@ -420,8 +417,7 @@ void IMB_processor_apply_threaded_scanlines(int total_scanlines, data.scanlines_per_task = scanlines_per_task; data.total_scanlines = total_scanlines; const int total_tasks = (total_scanlines + scanlines_per_task - 1) / scanlines_per_task; - TaskScheduler *task_scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool = BLI_task_pool_create(task_scheduler, &data, TASK_PRIORITY_LOW); + TaskPool *task_pool = BLI_task_pool_create(&data, TASK_PRIORITY_LOW); for (int i = 0, start_line = 0; i < total_tasks; i++) { BLI_task_pool_push( task_pool, processor_apply_scanline_func, POINTER_FROM_INT(start_line), false, NULL); diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.cpp b/source/blender/imbuf/intern/oiio/openimageio_api.cpp index 6d3234771e7..df51aada5f0 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.cpp +++ b/source/blender/imbuf/intern/oiio/openimageio_api.cpp @@ -35,7 +35,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_blenlib.h" #include "IMB_allocimbuf.h" @@ -43,7 +42,6 @@ extern "C" { #include "IMB_colormanagement_intern.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -} OIIO_NAMESPACE_USING diff --git a/source/blender/imbuf/intern/oiio/openimageio_api.h b/source/blender/imbuf/intern/oiio/openimageio_api.h index 520ad0c5da5..3dd089d65cb 100644 --- a/source/blender/imbuf/intern/oiio/openimageio_api.h +++ b/source/blender/imbuf/intern/oiio/openimageio_api.h @@ -24,12 +24,12 @@ #ifndef __OPENIMAGEIO_API_H__ #define __OPENIMAGEIO_API_H__ +#include <stdio.h> + #ifdef __cplusplus extern "C" { #endif -#include <stdio.h> - struct ImBuf; int imb_is_a_photoshop(const char *name); diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp index a1719895853..62cc2e605e5 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp @@ -75,7 +75,7 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) { } #endif - +} #include "BLI_blenlib.h" #include "BLI_math_color.h" #include "BLI_threads.h" @@ -84,17 +84,13 @@ _CRTIMP void __cdecl _invalid_parameter_noinfo(void) #include "BKE_image.h" #include "IMB_allocimbuf.h" +#include "IMB_colormanagement.h" +#include "IMB_colormanagement_intern.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" #include "IMB_metadata.h" #include "openexr_multi.h" -} - -extern "C" { -#include "IMB_colormanagement.h" -#include "IMB_colormanagement_intern.h" -} using namespace Imf; using namespace Imath; diff --git a/source/blender/imbuf/intern/openexr/openexr_api.h b/source/blender/imbuf/intern/openexr/openexr_api.h index df03d0d205f..b0835e5082e 100644 --- a/source/blender/imbuf/intern/openexr/openexr_api.h +++ b/source/blender/imbuf/intern/openexr/openexr_api.h @@ -24,12 +24,12 @@ #ifndef __OPENEXR_API_H__ #define __OPENEXR_API_H__ +#include <stdio.h> + #ifdef __cplusplus extern "C" { #endif -#include <stdio.h> - void imb_initopenexr(void); void imb_exitopenexr(void); diff --git a/source/blender/io/alembic/CMakeLists.txt b/source/blender/io/alembic/CMakeLists.txt index cbcdfaf4b77..6de7d327d4e 100644 --- a/source/blender/io/alembic/CMakeLists.txt +++ b/source/blender/io/alembic/CMakeLists.txt @@ -41,6 +41,7 @@ set(INC_SYS ) set(SRC + intern/abc_axis_conversion.cc intern/abc_customdata.cc intern/abc_exporter.cc intern/abc_reader_archive.cc @@ -65,6 +66,7 @@ set(SRC intern/alembic_capi.cc ABC_alembic.h + intern/abc_axis_conversion.h intern/abc_customdata.h intern/abc_exporter.h intern/abc_reader_archive.h diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.cc b/source/blender/io/alembic/intern/abc_axis_conversion.cc new file mode 100644 index 00000000000..17db5e9c99f --- /dev/null +++ b/source/blender/io/alembic/intern/abc_axis_conversion.cc @@ -0,0 +1,166 @@ +/* + * 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. + */ + +/** \file + * \ingroup Alembic + */ + +#include "abc_axis_conversion.h" + +extern "C" { +#include "BLI_assert.h" +#include "DNA_object_types.h" + +#include "BLI_math_geom.h" +} + +void create_swapped_rotation_matrix(float rot_x_mat[3][3], + float rot_y_mat[3][3], + float rot_z_mat[3][3], + const float euler[3], + AbcAxisSwapMode mode) +{ + const float rx = euler[0]; + float ry; + float rz; + + /* Apply transformation */ + switch (mode) { + case ABC_ZUP_FROM_YUP: + ry = -euler[2]; + rz = euler[1]; + break; + case ABC_YUP_FROM_ZUP: + ry = euler[2]; + rz = -euler[1]; + break; + default: + ry = 0.0f; + rz = 0.0f; + BLI_assert(false); + break; + } + + unit_m3(rot_x_mat); + unit_m3(rot_y_mat); + unit_m3(rot_z_mat); + + rot_x_mat[1][1] = cos(rx); + rot_x_mat[2][1] = -sin(rx); + rot_x_mat[1][2] = sin(rx); + rot_x_mat[2][2] = cos(rx); + + rot_y_mat[2][2] = cos(ry); + rot_y_mat[0][2] = -sin(ry); + rot_y_mat[2][0] = sin(ry); + rot_y_mat[0][0] = cos(ry); + + rot_z_mat[0][0] = cos(rz); + rot_z_mat[1][0] = -sin(rz); + rot_z_mat[0][1] = sin(rz); + rot_z_mat[1][1] = cos(rz); +} + +/* Convert matrix from Z=up to Y=up or vice versa. + * Use yup_mat = zup_mat for in-place conversion. */ +void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode) +{ + float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4]; + float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; + float src_trans[3], dst_scale[3], src_scale[3], euler[3]; + + zero_v3(src_trans); + zero_v3(dst_scale); + zero_v3(src_scale); + zero_v3(euler); + unit_m3(src_rot); + unit_m3(dst_rot); + unit_m4(dst_scale_mat); + + /* TODO(Sybren): This code assumes there is no sheer component and no + * homogeneous scaling component, which is not always true when writing + * non-hierarchical (e.g. flat) objects (e.g. when parent has non-uniform + * scale and the child rotates). This is currently not taken into account + * when axis-swapping. */ + + /* Extract translation, rotation, and scale form matrix. */ + mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat); + + /* Get euler angles from rotation matrix. */ + mat3_to_eulO(euler, ROT_MODE_XZY, src_rot); + + /* Create X, Y, Z rotation matrices from euler angles. */ + create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode); + + /* Concatenate rotation matrices. */ + mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat); + mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat); + + mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot); + + /* Start construction of dst_mat from rotation matrix */ + unit_m4(dst_mat); + copy_m4_m3(dst_mat, dst_rot); + + /* Apply translation */ + switch (mode) { + case ABC_ZUP_FROM_YUP: + copy_zup_from_yup(dst_mat[3], src_trans); + break; + case ABC_YUP_FROM_ZUP: + copy_yup_from_zup(dst_mat[3], src_trans); + break; + default: + BLI_assert(false); + } + + /* Apply scale matrix. Swaps y and z, but does not + * negate like translation does. */ + dst_scale[0] = src_scale[0]; + dst_scale[1] = src_scale[2]; + dst_scale[2] = src_scale[1]; + + size_to_mat4(dst_scale_mat, dst_scale); + mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat); +} + +/* Recompute transform matrix of object in new coordinate system + * (from Z-Up to Y-Up). */ +void create_transform_matrix(Object *obj, + float r_yup_mat[4][4], + AbcMatrixMode mode, + Object *proxy_from) +{ + float zup_mat[4][4]; + + /* get local or world matrix. */ + if (mode == ABC_MATRIX_LOCAL && obj->parent) { + /* Note that this produces another matrix than the local matrix, due to + * constraints and modifiers as well as the obj->parentinv matrix. */ + invert_m4_m4(obj->parent->imat, obj->parent->obmat); + mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); + } + else { + copy_m4_m4(zup_mat, obj->obmat); + } + + if (proxy_from) { + mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); + } + + copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); +} diff --git a/source/blender/io/alembic/intern/abc_axis_conversion.h b/source/blender/io/alembic/intern/abc_axis_conversion.h new file mode 100644 index 00000000000..7fde0e92ea4 --- /dev/null +++ b/source/blender/io/alembic/intern/abc_axis_conversion.h @@ -0,0 +1,99 @@ +/* + * 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) 2016 Kévin Dietrich & Blender Foundation. + * All rights reserved. + */ +#pragma once + +/** \file + * \ingroup Alembic + */ + +struct Object; + +#ifdef _MSC_VER +# define ABC_INLINE static __forceinline +#else +# define ABC_INLINE static inline +#endif + +/* TODO(kevin): for now keeping these transformations hardcoded to make sure + * everything works properly, and also because Alembic is almost exclusively + * used in Y-up software, but eventually they'll be set by the user in the UI + * like other importers/exporters do, to support other axis. */ + +/* Copy from Y-up to Z-up. */ + +ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) +{ + const float old_yup1 = yup[1]; /* in case zup == yup */ + zup[0] = yup[0]; + zup[1] = -yup[2]; + zup[2] = old_yup1; +} + +ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) +{ + const short old_yup1 = yup[1]; /* in case zup == yup */ + zup[0] = yup[0]; + zup[1] = -yup[2]; + zup[2] = old_yup1; +} + +/* Copy from Z-up to Y-up. */ + +ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) +{ + const float old_zup1 = zup[1]; /* in case yup == zup */ + yup[0] = zup[0]; + yup[1] = zup[2]; + yup[2] = -old_zup1; +} + +ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) +{ + const short old_zup1 = zup[1]; /* in case yup == zup */ + yup[0] = zup[0]; + yup[1] = zup[2]; + yup[2] = -old_zup1; +} + +/* Names are given in (dst, src) order, just like + * the parameters of copy_m44_axis_swap() */ +typedef enum { + ABC_ZUP_FROM_YUP = 1, + ABC_YUP_FROM_ZUP = 2, +} AbcAxisSwapMode; + +/* Create a rotation matrix for each axis from euler angles. + * Euler angles are swapped to change coordinate system. */ +void create_swapped_rotation_matrix(float rot_x_mat[3][3], + float rot_y_mat[3][3], + float rot_z_mat[3][3], + const float euler[3], + AbcAxisSwapMode mode); + +void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode); + +typedef enum { + ABC_MATRIX_WORLD = 1, + ABC_MATRIX_LOCAL = 2, +} AbcMatrixMode; + +void create_transform_matrix(Object *obj, + float r_transform_mat[4][4], + AbcMatrixMode mode, + Object *proxy_from); diff --git a/source/blender/io/alembic/intern/abc_customdata.cc b/source/blender/io/alembic/intern/abc_customdata.cc index c5f60ac3e29..40a057f9a20 100644 --- a/source/blender/io/alembic/intern/abc_customdata.cc +++ b/source/blender/io/alembic/intern/abc_customdata.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -27,7 +27,6 @@ #include <algorithm> #include <unordered_map> -extern "C" { #include "DNA_customdata_types.h" #include "DNA_meshdata_types.h" @@ -35,7 +34,6 @@ extern "C" { #include "BLI_utildefines.h" #include "BKE_customdata.h" -} /* NOTE: for now only UVs and Vertex Colors are supported for streaming. * Although Alembic only allows for a single UV layer per {I|O}Schema, and does diff --git a/source/blender/io/alembic/intern/abc_customdata.h b/source/blender/io/alembic/intern/abc_customdata.h index 11b005eb66a..04572c736af 100644 --- a/source/blender/io/alembic/intern/abc_customdata.h +++ b/source/blender/io/alembic/intern/abc_customdata.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_exporter.cc b/source/blender/io/alembic/intern/abc_exporter.cc index e3e095463b4..dbf24452b78 100644 --- a/source/blender/io/alembic/intern/abc_exporter.cc +++ b/source/blender/io/alembic/intern/abc_exporter.cc @@ -33,7 +33,6 @@ #include "abc_writer_points.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_camera_types.h" #include "DNA_curve_types.h" #include "DNA_fluid_types.h" @@ -62,7 +61,6 @@ extern "C" { #include "BKE_scene.h" #include "DEG_depsgraph_query.h" -} using Alembic::Abc::OBox3dProperty; using Alembic::Abc::TimeSamplingPtr; @@ -105,7 +103,7 @@ ExportSettings::ExportSettings() static bool object_is_smoke_sim(Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluid); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (md) { FluidModifierData *smd = reinterpret_cast<FluidModifierData *>(md); diff --git a/source/blender/io/alembic/intern/abc_reader_archive.cc b/source/blender/io/alembic/intern/abc_reader_archive.cc index 6ad44553701..563466d81bc 100644 --- a/source/blender/io/alembic/intern/abc_reader_archive.cc +++ b/source/blender/io/alembic/intern/abc_reader_archive.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -23,12 +23,10 @@ #include "abc_reader_archive.h" -extern "C" { #include "BKE_main.h" #include "BLI_path_util.h" #include "BLI_string.h" -} #ifdef WIN32 # include "utfconv.h" diff --git a/source/blender/io/alembic/intern/abc_reader_archive.h b/source/blender/io/alembic/intern/abc_reader_archive.h index bdb53bd0b8c..35273e10108 100644 --- a/source/blender/io/alembic/intern/abc_reader_archive.h +++ b/source/blender/io/alembic/intern/abc_reader_archive.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_reader_camera.cc b/source/blender/io/alembic/intern/abc_reader_camera.cc index ab506f32cbe..0752534f8c2 100644 --- a/source/blender/io/alembic/intern/abc_reader_camera.cc +++ b/source/blender/io/alembic/intern/abc_reader_camera.cc @@ -22,7 +22,6 @@ #include "abc_reader_transform.h" #include "abc_util.h" -extern "C" { #include "DNA_camera_types.h" #include "DNA_object_types.h" @@ -30,7 +29,6 @@ extern "C" { #include "BKE_object.h" #include "BLI_math.h" -} using Alembic::AbcGeom::CameraSample; using Alembic::AbcGeom::ICamera; diff --git a/source/blender/io/alembic/intern/abc_reader_curves.cc b/source/blender/io/alembic/intern/abc_reader_curves.cc index 1be164c7c94..d5e0b694294 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.cc +++ b/source/blender/io/alembic/intern/abc_reader_curves.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -22,6 +22,7 @@ */ #include "abc_reader_curves.h" +#include "abc_axis_conversion.h" #include "abc_reader_transform.h" #include "abc_util.h" @@ -29,7 +30,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" @@ -38,7 +38,6 @@ extern "C" { #include "BKE_curve.h" #include "BKE_mesh.h" #include "BKE_object.h" -} using Alembic::Abc::FloatArraySamplePtr; using Alembic::Abc::Int32ArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_reader_curves.h b/source/blender/io/alembic/intern/abc_reader_curves.h index 763a83f586f..eb0538308f8 100644 --- a/source/blender/io/alembic/intern/abc_reader_curves.h +++ b/source/blender/io/alembic/intern/abc_reader_curves.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index b69a5301d76..8b79a3a0aa0 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -19,6 +19,7 @@ */ #include "abc_reader_mesh.h" +#include "abc_axis_conversion.h" #include "abc_reader_transform.h" #include "abc_util.h" @@ -26,7 +27,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -39,7 +39,6 @@ extern "C" { #include "BKE_mesh.h" #include "BKE_modifier.h" #include "BKE_object.h" -} using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::P3fArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_reader_nurbs.cc b/source/blender/io/alembic/intern/abc_reader_nurbs.cc index 0ada10baba5..10d9a35a8e1 100644 --- a/source/blender/io/alembic/intern/abc_reader_nurbs.cc +++ b/source/blender/io/alembic/intern/abc_reader_nurbs.cc @@ -19,12 +19,12 @@ */ #include "abc_reader_nurbs.h" +#include "abc_axis_conversion.h" #include "abc_reader_transform.h" #include "abc_util.h" #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" @@ -33,7 +33,6 @@ extern "C" { #include "BKE_curve.h" #include "BKE_object.h" -} using Alembic::AbcGeom::FloatArraySamplePtr; using Alembic::AbcGeom::kWrapExisting; diff --git a/source/blender/io/alembic/intern/abc_reader_object.cc b/source/blender/io/alembic/intern/abc_reader_object.cc index 9b0c3237c45..e5bd0771a42 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.cc +++ b/source/blender/io/alembic/intern/abc_reader_object.cc @@ -19,9 +19,9 @@ */ #include "abc_reader_object.h" +#include "abc_axis_conversion.h" #include "abc_util.h" -extern "C" { #include "DNA_cachefile_types.h" #include "DNA_constraint_types.h" #include "DNA_modifier_types.h" @@ -36,7 +36,6 @@ extern "C" { #include "BLI_math_geom.h" #include "BLI_string.h" #include "BLI_utildefines.h" -} using Alembic::AbcGeom::IObject; using Alembic::AbcGeom::IXform; @@ -295,7 +294,7 @@ void AbcObjectReader::read_matrix(float r_mat[4][4] /* local matrix */, void AbcObjectReader::addCacheModifier() { - ModifierData *md = modifier_new(eModifierType_MeshSequenceCache); + ModifierData *md = BKE_modifier_new(eModifierType_MeshSequenceCache); BLI_addtail(&m_object->modifiers, md); MeshSeqCacheModifierData *mcmd = reinterpret_cast<MeshSeqCacheModifierData *>(md); diff --git a/source/blender/io/alembic/intern/abc_reader_object.h b/source/blender/io/alembic/intern/abc_reader_object.h index 94923df2df9..dcc2697e0b5 100644 --- a/source/blender/io/alembic/intern/abc_reader_object.h +++ b/source/blender/io/alembic/intern/abc_reader_object.h @@ -24,9 +24,7 @@ #include <Alembic/Abc/All.h> #include <Alembic/AbcGeom/All.h> -extern "C" { #include "DNA_ID.h" -} struct CacheFile; struct Main; diff --git a/source/blender/io/alembic/intern/abc_reader_points.cc b/source/blender/io/alembic/intern/abc_reader_points.cc index e4dc345f868..c5d08693176 100644 --- a/source/blender/io/alembic/intern/abc_reader_points.cc +++ b/source/blender/io/alembic/intern/abc_reader_points.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -26,14 +26,12 @@ #include "abc_reader_transform.h" #include "abc_util.h" -extern "C" { #include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "BKE_customdata.h" #include "BKE_mesh.h" #include "BKE_object.h" -} using Alembic::AbcGeom::kWrapExisting; using Alembic::AbcGeom::N3fArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_reader_points.h b/source/blender/io/alembic/intern/abc_reader_points.h index bb33afb466f..99881e091f9 100644 --- a/source/blender/io/alembic/intern/abc_reader_points.h +++ b/source/blender/io/alembic/intern/abc_reader_points.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_reader_transform.cc b/source/blender/io/alembic/intern/abc_reader_transform.cc index ce569a9ccb5..3df391f8432 100644 --- a/source/blender/io/alembic/intern/abc_reader_transform.cc +++ b/source/blender/io/alembic/intern/abc_reader_transform.cc @@ -21,13 +21,11 @@ #include "abc_reader_transform.h" #include "abc_util.h" -extern "C" { #include "DNA_object_types.h" #include "BLI_utildefines.h" #include "BKE_object.h" -} using Alembic::Abc::ISampleSelector; diff --git a/source/blender/io/alembic/intern/abc_util.cc b/source/blender/io/alembic/intern/abc_util.cc index b26ef8b3b76..1f3bd2a1aaa 100644 --- a/source/blender/io/alembic/intern/abc_util.cc +++ b/source/blender/io/alembic/intern/abc_util.cc @@ -20,6 +20,7 @@ #include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_reader_camera.h" #include "abc_reader_curves.h" #include "abc_reader_mesh.h" @@ -31,13 +32,11 @@ #include <algorithm> -extern "C" { #include "DNA_object_types.h" #include "BLI_math_geom.h" #include "PIL_time.h" -} std::string get_id_name(const Object *const ob) { @@ -121,144 +120,6 @@ void split(const std::string &s, const char delim, std::vector<std::string> &tok } } -void create_swapped_rotation_matrix(float rot_x_mat[3][3], - float rot_y_mat[3][3], - float rot_z_mat[3][3], - const float euler[3], - AbcAxisSwapMode mode) -{ - const float rx = euler[0]; - float ry; - float rz; - - /* Apply transformation */ - switch (mode) { - case ABC_ZUP_FROM_YUP: - ry = -euler[2]; - rz = euler[1]; - break; - case ABC_YUP_FROM_ZUP: - ry = euler[2]; - rz = -euler[1]; - break; - default: - ry = 0.0f; - rz = 0.0f; - BLI_assert(false); - break; - } - - unit_m3(rot_x_mat); - unit_m3(rot_y_mat); - unit_m3(rot_z_mat); - - rot_x_mat[1][1] = cos(rx); - rot_x_mat[2][1] = -sin(rx); - rot_x_mat[1][2] = sin(rx); - rot_x_mat[2][2] = cos(rx); - - rot_y_mat[2][2] = cos(ry); - rot_y_mat[0][2] = -sin(ry); - rot_y_mat[2][0] = sin(ry); - rot_y_mat[0][0] = cos(ry); - - rot_z_mat[0][0] = cos(rz); - rot_z_mat[1][0] = -sin(rz); - rot_z_mat[0][1] = sin(rz); - rot_z_mat[1][1] = cos(rz); -} - -/* Convert matrix from Z=up to Y=up or vice versa. - * Use yup_mat = zup_mat for in-place conversion. */ -void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode) -{ - float dst_rot[3][3], src_rot[3][3], dst_scale_mat[4][4]; - float rot_x_mat[3][3], rot_y_mat[3][3], rot_z_mat[3][3]; - float src_trans[3], dst_scale[3], src_scale[3], euler[3]; - - zero_v3(src_trans); - zero_v3(dst_scale); - zero_v3(src_scale); - zero_v3(euler); - unit_m3(src_rot); - unit_m3(dst_rot); - unit_m4(dst_scale_mat); - - /* TODO(Sybren): This code assumes there is no sheer component and no - * homogeneous scaling component, which is not always true when writing - * non-hierarchical (e.g. flat) objects (e.g. when parent has non-uniform - * scale and the child rotates). This is currently not taken into account - * when axis-swapping. */ - - /* Extract translation, rotation, and scale form matrix. */ - mat4_to_loc_rot_size(src_trans, src_rot, src_scale, src_mat); - - /* Get euler angles from rotation matrix. */ - mat3_to_eulO(euler, ROT_MODE_XZY, src_rot); - - /* Create X, Y, Z rotation matrices from euler angles. */ - create_swapped_rotation_matrix(rot_x_mat, rot_y_mat, rot_z_mat, euler, mode); - - /* Concatenate rotation matrices. */ - mul_m3_m3m3(dst_rot, dst_rot, rot_z_mat); - mul_m3_m3m3(dst_rot, dst_rot, rot_y_mat); - mul_m3_m3m3(dst_rot, dst_rot, rot_x_mat); - - mat3_to_eulO(euler, ROT_MODE_XZY, dst_rot); - - /* Start construction of dst_mat from rotation matrix */ - unit_m4(dst_mat); - copy_m4_m3(dst_mat, dst_rot); - - /* Apply translation */ - switch (mode) { - case ABC_ZUP_FROM_YUP: - copy_zup_from_yup(dst_mat[3], src_trans); - break; - case ABC_YUP_FROM_ZUP: - copy_yup_from_zup(dst_mat[3], src_trans); - break; - default: - BLI_assert(false); - } - - /* Apply scale matrix. Swaps y and z, but does not - * negate like translation does. */ - dst_scale[0] = src_scale[0]; - dst_scale[1] = src_scale[2]; - dst_scale[2] = src_scale[1]; - - size_to_mat4(dst_scale_mat, dst_scale); - mul_m4_m4m4(dst_mat, dst_mat, dst_scale_mat); -} - -/* Recompute transform matrix of object in new coordinate system - * (from Z-Up to Y-Up). */ -void create_transform_matrix(Object *obj, - float r_yup_mat[4][4], - AbcMatrixMode mode, - Object *proxy_from) -{ - float zup_mat[4][4]; - - /* get local or world matrix. */ - if (mode == ABC_MATRIX_LOCAL && obj->parent) { - /* Note that this produces another matrix than the local matrix, due to - * constraints and modifiers as well as the obj->parentinv matrix. */ - invert_m4_m4(obj->parent->imat, obj->parent->obmat); - mul_m4_m4m4(zup_mat, obj->parent->imat, obj->obmat); - } - else { - copy_m4_m4(zup_mat, obj->obmat); - } - - if (proxy_from) { - mul_m4_m4m4(zup_mat, proxy_from->obmat, zup_mat); - } - - copy_m44_axis_swap(r_yup_mat, zup_mat, ABC_YUP_FROM_ZUP); -} - bool has_property(const Alembic::Abc::ICompoundProperty &prop, const std::string &name) { if (!prop.valid()) { diff --git a/source/blender/io/alembic/intern/abc_util.h b/source/blender/io/alembic/intern/abc_util.h index 0b3462c2132..57b4d9800a5 100644 --- a/source/blender/io/alembic/intern/abc_util.h +++ b/source/blender/io/alembic/intern/abc_util.h @@ -56,15 +56,6 @@ Imath::M44d convert_matrix_datatype(float mat[4][4]); /* Convert from Alembic to float matrix representations. Does NOT convert from Y-up to Z-up. */ void convert_matrix_datatype(const Imath::M44d &xform, float r_mat[4][4]); -typedef enum { - ABC_MATRIX_WORLD = 1, - ABC_MATRIX_LOCAL = 2, -} AbcMatrixMode; -void create_transform_matrix(Object *obj, - float r_transform_mat[4][4], - AbcMatrixMode mode, - Object *proxy_from); - void split(const std::string &s, const char delim, std::vector<std::string> &tokens); template<class TContainer> bool begins_with(const TContainer &input, const TContainer &match) @@ -115,66 +106,6 @@ float get_weight_and_index(float time, AbcObjectReader *create_reader(const Alembic::AbcGeom::IObject &object, ImportSettings &settings); -/* ************************** */ - -/* TODO(kevin): for now keeping these transformations hardcoded to make sure - * everything works properly, and also because Alembic is almost exclusively - * used in Y-up software, but eventually they'll be set by the user in the UI - * like other importers/exporters do, to support other axis. */ - -/* Copy from Y-up to Z-up. */ - -ABC_INLINE void copy_zup_from_yup(float zup[3], const float yup[3]) -{ - const float old_yup1 = yup[1]; /* in case zup == yup */ - zup[0] = yup[0]; - zup[1] = -yup[2]; - zup[2] = old_yup1; -} - -ABC_INLINE void copy_zup_from_yup(short zup[3], const short yup[3]) -{ - const short old_yup1 = yup[1]; /* in case zup == yup */ - zup[0] = yup[0]; - zup[1] = -yup[2]; - zup[2] = old_yup1; -} - -/* Copy from Z-up to Y-up. */ - -ABC_INLINE void copy_yup_from_zup(float yup[3], const float zup[3]) -{ - const float old_zup1 = zup[1]; /* in case yup == zup */ - yup[0] = zup[0]; - yup[1] = zup[2]; - yup[2] = -old_zup1; -} - -ABC_INLINE void copy_yup_from_zup(short yup[3], const short zup[3]) -{ - const short old_zup1 = zup[1]; /* in case yup == zup */ - yup[0] = zup[0]; - yup[1] = zup[2]; - yup[2] = -old_zup1; -} - -/* Names are given in (dst, src) order, just like - * the parameters of copy_m44_axis_swap() */ -typedef enum { - ABC_ZUP_FROM_YUP = 1, - ABC_YUP_FROM_ZUP = 2, -} AbcAxisSwapMode; - -/* Create a rotation matrix for each axis from euler angles. - * Euler angles are swapped to change coordinate system. */ -void create_swapped_rotation_matrix(float rot_x_mat[3][3], - float rot_y_mat[3][3], - float rot_z_mat[3][3], - const float euler[3], - AbcAxisSwapMode mode); - -void copy_m44_axis_swap(float dst_mat[4][4], float src_mat[4][4], AbcAxisSwapMode mode); - /* *************************** */ #undef ABC_DEBUG_TIME diff --git a/source/blender/io/alembic/intern/abc_writer_archive.cc b/source/blender/io/alembic/intern/abc_writer_archive.cc index af18d480a18..5aae1f05f4b 100644 --- a/source/blender/io/alembic/intern/abc_writer_archive.cc +++ b/source/blender/io/alembic/intern/abc_writer_archive.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -22,14 +22,13 @@ */ #include "abc_writer_archive.h" -extern "C" { + #include "BKE_blender_version.h" #include "BLI_path_util.h" #include "BLI_string.h" #include "DNA_scene_types.h" -} #ifdef WIN32 # include "utfconv.h" diff --git a/source/blender/io/alembic/intern/abc_writer_archive.h b/source/blender/io/alembic/intern/abc_writer_archive.h index e261e60990a..82b0e98b376 100644 --- a/source/blender/io/alembic/intern/abc_writer_archive.h +++ b/source/blender/io/alembic/intern/abc_writer_archive.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_writer_camera.cc b/source/blender/io/alembic/intern/abc_writer_camera.cc index e705e5ba911..07ae81e584f 100644 --- a/source/blender/io/alembic/intern/abc_writer_camera.cc +++ b/source/blender/io/alembic/intern/abc_writer_camera.cc @@ -21,10 +21,8 @@ #include "abc_writer_camera.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_camera_types.h" #include "DNA_object_types.h" -} using Alembic::AbcGeom::OCamera; using Alembic::AbcGeom::OFloatProperty; diff --git a/source/blender/io/alembic/intern/abc_writer_curves.cc b/source/blender/io/alembic/intern/abc_writer_curves.cc index 3ab9b365a72..db93ac1920e 100644 --- a/source/blender/io/alembic/intern/abc_writer_curves.cc +++ b/source/blender/io/alembic/intern/abc_writer_curves.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -22,17 +22,16 @@ */ #include "abc_writer_curves.h" +#include "abc_axis_conversion.h" #include "abc_reader_curves.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "BKE_curve.h" #include "BKE_mesh.h" #include "BKE_object.h" -} using Alembic::AbcGeom::OCompoundProperty; using Alembic::AbcGeom::OCurves; diff --git a/source/blender/io/alembic/intern/abc_writer_curves.h b/source/blender/io/alembic/intern/abc_writer_curves.h index e57978ada2a..83f0289dd2d 100644 --- a/source/blender/io/alembic/intern/abc_writer_curves.h +++ b/source/blender/io/alembic/intern/abc_writer_curves.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_writer_hair.cc b/source/blender/io/alembic/intern/abc_writer_hair.cc index f29d195f2ff..ed62889b03d 100644 --- a/source/blender/io/alembic/intern/abc_writer_hair.cc +++ b/source/blender/io/alembic/intern/abc_writer_hair.cc @@ -19,12 +19,11 @@ */ #include "abc_writer_hair.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_writer_transform.h" #include <cstdio> -extern "C" { #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -35,7 +34,6 @@ extern "C" { #include "BKE_mesh.h" #include "BKE_mesh_runtime.h" #include "BKE_particle.h" -} using Alembic::Abc::P3fArraySamplePtr; diff --git a/source/blender/io/alembic/intern/abc_writer_mball.cc b/source/blender/io/alembic/intern/abc_writer_mball.cc index 151848674f9..3593acf18b0 100644 --- a/source/blender/io/alembic/intern/abc_writer_mball.cc +++ b/source/blender/io/alembic/intern/abc_writer_mball.cc @@ -21,7 +21,6 @@ #include "abc_writer_mball.h" #include "abc_writer_mesh.h" -extern "C" { #include "DNA_mesh_types.h" #include "DNA_meta_types.h" #include "DNA_object_types.h" @@ -33,7 +32,6 @@ extern "C" { #include "BKE_object.h" #include "BLI_utildefines.h" -} AbcMBallWriter::AbcMBallWriter(Main *bmain, Object *ob, diff --git a/source/blender/io/alembic/intern/abc_writer_mesh.cc b/source/blender/io/alembic/intern/abc_writer_mesh.cc index f7b575e7b23..89c37dab468 100644 --- a/source/blender/io/alembic/intern/abc_writer_mesh.cc +++ b/source/blender/io/alembic/intern/abc_writer_mesh.cc @@ -19,10 +19,9 @@ */ #include "abc_writer_mesh.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" @@ -40,7 +39,6 @@ extern "C" { #include "bmesh_tools.h" #include "DEG_depsgraph_query.h" -} using Alembic::Abc::FloatArraySample; using Alembic::Abc::Int32ArraySample; @@ -169,7 +167,7 @@ static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) ModifierData *md = static_cast<ModifierData *>(ob->modifiers.last); for (; md; md = md->prev) { - if (!modifier_isEnabled(scene, md, eModifierMode_Render)) { + if (!BKE_modifier_is_enabled(scene, md, eModifierMode_Render)) { continue; } @@ -192,9 +190,9 @@ static ModifierData *get_subsurf_modifier(Scene *scene, Object *ob) static ModifierData *get_liquid_sim_modifier(Scene *scene, Object *ob) { - ModifierData *md = modifiers_findByType(ob, eModifierType_Fluidsim); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Fluidsim); - if (md && (modifier_isEnabled(scene, md, eModifierMode_Render))) { + if (md && (BKE_modifier_is_enabled(scene, md, eModifierMode_Render))) { FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); if (fsmd->fss && fsmd->fss->type == OB_FLUIDSIM_DOMAIN) { diff --git a/source/blender/io/alembic/intern/abc_writer_nurbs.cc b/source/blender/io/alembic/intern/abc_writer_nurbs.cc index d643f5482c0..8b4a1050d33 100644 --- a/source/blender/io/alembic/intern/abc_writer_nurbs.cc +++ b/source/blender/io/alembic/intern/abc_writer_nurbs.cc @@ -19,17 +19,15 @@ */ #include "abc_writer_nurbs.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "BLI_listbase.h" #include "BKE_curve.h" -} using Alembic::AbcGeom::FloatArraySample; using Alembic::AbcGeom::OBoolProperty; diff --git a/source/blender/io/alembic/intern/abc_writer_object.cc b/source/blender/io/alembic/intern/abc_writer_object.cc index 75dc93bd08e..f4a3587f54d 100644 --- a/source/blender/io/alembic/intern/abc_writer_object.cc +++ b/source/blender/io/alembic/intern/abc_writer_object.cc @@ -20,11 +20,9 @@ #include "abc_writer_object.h" -extern "C" { #include "DNA_object_types.h" #include "BKE_object.h" -} AbcObjectWriter::AbcObjectWriter(Object *ob, uint32_t time_sampling, diff --git a/source/blender/io/alembic/intern/abc_writer_object.h b/source/blender/io/alembic/intern/abc_writer_object.h index c3511566372..830c4aee903 100644 --- a/source/blender/io/alembic/intern/abc_writer_object.h +++ b/source/blender/io/alembic/intern/abc_writer_object.h @@ -26,9 +26,7 @@ #include "abc_exporter.h" -extern "C" { #include "DNA_ID.h" -} class AbcTransformWriter; diff --git a/source/blender/io/alembic/intern/abc_writer_points.cc b/source/blender/io/alembic/intern/abc_writer_points.cc index 70a1ead239a..d45af2eed4c 100644 --- a/source/blender/io/alembic/intern/abc_writer_points.cc +++ b/source/blender/io/alembic/intern/abc_writer_points.cc @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. @@ -26,7 +26,6 @@ #include "abc_writer_mesh.h" #include "abc_writer_transform.h" -extern "C" { #include "DNA_object_types.h" #include "DNA_particle_types.h" @@ -36,7 +35,6 @@ extern "C" { #include "BLI_math.h" #include "DEG_depsgraph_query.h" -} using Alembic::AbcGeom::kVertexScope; using Alembic::AbcGeom::OPoints; diff --git a/source/blender/io/alembic/intern/abc_writer_points.h b/source/blender/io/alembic/intern/abc_writer_points.h index c171cddd10e..184a363ae6b 100644 --- a/source/blender/io/alembic/intern/abc_writer_points.h +++ b/source/blender/io/alembic/intern/abc_writer_points.h @@ -10,7 +10,7 @@ * 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, + * 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) 2016 Kévin Dietrich. diff --git a/source/blender/io/alembic/intern/abc_writer_transform.cc b/source/blender/io/alembic/intern/abc_writer_transform.cc index d7bcc46d96f..1ec7db0a1c6 100644 --- a/source/blender/io/alembic/intern/abc_writer_transform.cc +++ b/source/blender/io/alembic/intern/abc_writer_transform.cc @@ -19,17 +19,15 @@ */ #include "abc_writer_transform.h" -#include "abc_util.h" +#include "abc_axis_conversion.h" #include <OpenEXR/ImathBoxAlgo.h> -extern "C" { #include "DNA_object_types.h" #include "BLI_math.h" #include "DEG_depsgraph_query.h" -} using Alembic::AbcGeom::OObject; using Alembic::AbcGeom::OXform; diff --git a/source/blender/io/alembic/intern/alembic_capi.cc b/source/blender/io/alembic/intern/alembic_capi.cc index ced5791e0e8..987a3cacb3b 100644 --- a/source/blender/io/alembic/intern/alembic_capi.cc +++ b/source/blender/io/alembic/intern/alembic_capi.cc @@ -40,7 +40,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_cachefile_types.h" #include "DNA_curve_types.h" #include "DNA_modifier_types.h" @@ -74,7 +73,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" -} using Alembic::Abc::Int32ArraySamplePtr; using Alembic::Abc::ObjectHeader; diff --git a/source/blender/io/collada/AnimationExporter.h b/source/blender/io/collada/AnimationExporter.h index 3e40a485ddf..b4564eb7b2d 100644 --- a/source/blender/io/collada/AnimationExporter.h +++ b/source/blender/io/collada/AnimationExporter.h @@ -23,7 +23,6 @@ #include "BCAnimationCurve.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -48,7 +47,6 @@ extern "C" { #include "BKE_object.h" #include "BKE_scene.h" #include "ED_object.h" -} #include "MEM_guardedalloc.h" diff --git a/source/blender/io/collada/AnimationImporter.h b/source/blender/io/collada/AnimationImporter.h index 263a130d1eb..51041c6ee3e 100644 --- a/source/blender/io/collada/AnimationImporter.h +++ b/source/blender/io/collada/AnimationImporter.h @@ -35,14 +35,14 @@ #include "COLLADAFWNode.h" #include "COLLADAFWUniqueId.h" -extern "C" { #include "BKE_context.h" + #include "DNA_anim_types.h" + #include "DNA_camera_types.h" #include "DNA_light_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} //#include "ArmatureImporter.h" #include "TransformReader.h" diff --git a/source/blender/io/collada/ArmatureExporter.cpp b/source/blender/io/collada/ArmatureExporter.cpp index 660917c2aa1..fc697e1617b 100644 --- a/source/blender/io/collada/ArmatureExporter.cpp +++ b/source/blender/io/collada/ArmatureExporter.cpp @@ -29,11 +29,8 @@ #include "BKE_action.h" #include "BKE_armature.h" - -extern "C" { #include "BKE_global.h" #include "BKE_mesh.h" -} #include "ED_armature.h" diff --git a/source/blender/io/collada/ArmatureImporter.cpp b/source/blender/io/collada/ArmatureImporter.cpp index 4e9f31182f1..a69500432e8 100644 --- a/source/blender/io/collada/ArmatureImporter.cpp +++ b/source/blender/io/collada/ArmatureImporter.cpp @@ -25,14 +25,12 @@ #include "COLLADAFWUniqueId.h" -extern "C" { #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_object.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "ED_armature.h" -} #include "DEG_depsgraph.h" @@ -335,7 +333,7 @@ void ArmatureImporter::connect_bone_chains(bArmature *armature, Bone *parentbone /* * It is possible that the child's head is located on the parents head. * When this happens, then moving the parent's tail to the child's head - * would result in a zero sized bone and Blender would silently remove the bone. + * would result in a zero sized bone and Blender would silently remove the bone. * So we move the tail only when the resulting bone has a minimum length: */ diff --git a/source/blender/io/collada/ArmatureImporter.h b/source/blender/io/collada/ArmatureImporter.h index bafa10ca804..7393b882f4b 100644 --- a/source/blender/io/collada/ArmatureImporter.h +++ b/source/blender/io/collada/ArmatureImporter.h @@ -25,7 +25,6 @@ #include "COLLADAFWNode.h" #include "COLLADAFWUniqueId.h" -extern "C" { #include "BKE_context.h" #include "BKE_key.h" @@ -35,7 +34,6 @@ extern "C" { #include "DNA_scene_types.h" #include "ED_armature.h" -} #include "AnimationImporter.h" #include "ExtraTags.h" diff --git a/source/blender/io/collada/BCAnimationCurve.h b/source/blender/io/collada/BCAnimationCurve.h index 71640ff3013..e0216ee6849 100644 --- a/source/blender/io/collada/BCAnimationCurve.h +++ b/source/blender/io/collada/BCAnimationCurve.h @@ -25,14 +25,13 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_armature.h" #include "BKE_fcurve.h" #include "BKE_material.h" + #include "ED_anim_api.h" #include "ED_keyframes_edit.h" #include "ED_keyframing.h" -} typedef float(TangentPoint)[2]; diff --git a/source/blender/io/collada/BCAnimationSampler.cpp b/source/blender/io/collada/BCAnimationSampler.cpp index 0c19ce9a4c7..fc23a58ccbc 100644 --- a/source/blender/io/collada/BCAnimationSampler.cpp +++ b/source/blender/io/collada/BCAnimationSampler.cpp @@ -27,20 +27,21 @@ #include "ExportSettings.h" #include "collada_utils.h" -extern "C" { #include "BKE_action.h" #include "BKE_constraint.h" #include "BKE_key.h" #include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_material.h" + #include "BLI_listbase.h" + #include "DNA_anim_types.h" #include "DNA_constraint_types.h" #include "DNA_key_types.h" #include "DNA_scene_types.h" + #include "ED_object.h" -} static std::string EMPTY_STRING; static BCAnimationCurveMap BCEmptyAnimationCurves; diff --git a/source/blender/io/collada/BCAnimationSampler.h b/source/blender/io/collada/BCAnimationSampler.h index 96138d0cbca..3273ac8e0a0 100644 --- a/source/blender/io/collada/BCAnimationSampler.h +++ b/source/blender/io/collada/BCAnimationSampler.h @@ -21,12 +21,12 @@ #include "BCSampleData.h" #include "collada_utils.h" -extern "C" { #include "BKE_action.h" #include "BKE_lib_id.h" + #include "BLI_math_rotation.h" + #include "DNA_action_types.h" -} /* Collection of animation curves */ class BCAnimation { diff --git a/source/blender/io/collada/BCMath.h b/source/blender/io/collada/BCMath.h index 9ecea85b08c..38158751740 100644 --- a/source/blender/io/collada/BCMath.h +++ b/source/blender/io/collada/BCMath.h @@ -23,10 +23,9 @@ #include "BlenderTypes.h" -extern "C" { #include "BKE_object.h" + #include "BLI_math.h" -} class BCQuat { private: diff --git a/source/blender/io/collada/BCSampleData.h b/source/blender/io/collada/BCSampleData.h index 877fb49981a..6f3ca9135b3 100644 --- a/source/blender/io/collada/BCSampleData.h +++ b/source/blender/io/collada/BCSampleData.h @@ -28,15 +28,15 @@ #include "BCSampleData.h" #include "ExportSettings.h" -extern "C" { #include "BKE_object.h" + #include "BLI_math_rotation.h" + #include "DNA_armature_types.h" #include "DNA_camera_types.h" #include "DNA_light_types.h" #include "DNA_material_types.h" #include "DNA_object_types.h" -} typedef std::map<Bone *, BCMatrix *> BCBoneMatrixMap; diff --git a/source/blender/io/collada/BlenderContext.h b/source/blender/io/collada/BlenderContext.h index 15ebd671b1a..bf6fde134fa 100644 --- a/source/blender/io/collada/BlenderContext.h +++ b/source/blender/io/collada/BlenderContext.h @@ -21,11 +21,6 @@ #ifndef __BLENDERCONTEXT_H__ #define __BLENDERCONTEXT_H__ -#ifdef __cplusplus - -extern "C" { -#endif - #include "BKE_context.h" #include "BKE_main.h" #include "BLI_linklist.h" @@ -35,6 +30,10 @@ extern "C" { #include "DNA_layer_types.h" #include "DNA_object_types.h" +#ifdef __cplusplus +extern "C" { +#endif + static const BC_global_forward_axis BC_DEFAULT_FORWARD = BC_GLOBAL_FORWARD_Y; static const BC_global_up_axis BC_DEFAULT_UP = BC_GLOBAL_UP_Z; diff --git a/source/blender/io/collada/CameraExporter.cpp b/source/blender/io/collada/CameraExporter.cpp index 74862c44270..246a454eb66 100644 --- a/source/blender/io/collada/CameraExporter.cpp +++ b/source/blender/io/collada/CameraExporter.cpp @@ -22,9 +22,8 @@ #include "COLLADASWCamera.h" -extern "C" { #include "DNA_camera_types.h" -} + #include "CameraExporter.h" #include "collada_internal.h" diff --git a/source/blender/io/collada/CameraExporter.h b/source/blender/io/collada/CameraExporter.h index e4df994354c..0dda6392d03 100644 --- a/source/blender/io/collada/CameraExporter.h +++ b/source/blender/io/collada/CameraExporter.h @@ -24,10 +24,8 @@ #include "COLLADASWLibraryCameras.h" #include "COLLADASWStreamWriter.h" -extern "C" { #include "DNA_object_types.h" #include "DNA_scene_types.h" -} #include "DNA_camera_types.h" #include "ExportSettings.h" diff --git a/source/blender/io/collada/ControllerExporter.cpp b/source/blender/io/collada/ControllerExporter.cpp index c26647d4747..1b8c859f443 100644 --- a/source/blender/io/collada/ControllerExporter.cpp +++ b/source/blender/io/collada/ControllerExporter.cpp @@ -29,13 +29,10 @@ #include "BKE_action.h" #include "BKE_armature.h" - -extern "C" { #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_lib_id.h" #include "BKE_mesh.h" -} #include "ED_armature.h" diff --git a/source/blender/io/collada/DocumentExporter.cpp b/source/blender/io/collada/DocumentExporter.cpp index 7565aa881fd..b890d4cf018 100644 --- a/source/blender/io/collada/DocumentExporter.cpp +++ b/source/blender/io/collada/DocumentExporter.cpp @@ -58,7 +58,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -96,13 +95,12 @@ extern "C" { #include "ED_keyframing.h" #ifdef WITH_BUILDINFO -extern char build_commit_date[]; -extern char build_commit_time[]; -extern char build_hash[]; +extern "C" char build_commit_date[]; +extern "C" char build_commit_time[]; +extern "C" char build_hash[]; #endif #include "RNA_access.h" -} #include "DocumentExporter.h" #include "collada_internal.h" diff --git a/source/blender/io/collada/DocumentExporter.h b/source/blender/io/collada/DocumentExporter.h index f024befbd17..1fe52420534 100644 --- a/source/blender/io/collada/DocumentExporter.h +++ b/source/blender/io/collada/DocumentExporter.h @@ -25,9 +25,7 @@ #include "collada.h" #include "collada_utils.h" -extern "C" { #include "DNA_customdata_types.h" -} class DocumentExporter { public: diff --git a/source/blender/io/collada/DocumentImporter.cpp b/source/blender/io/collada/DocumentImporter.cpp index 281786bb45f..2305072a6eb 100644 --- a/source/blender/io/collada/DocumentImporter.cpp +++ b/source/blender/io/collada/DocumentImporter.cpp @@ -45,7 +45,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_fileops.h" #include "BLI_listbase.h" #include "BLI_math.h" @@ -72,7 +71,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" -} #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" diff --git a/source/blender/io/collada/EffectExporter.cpp b/source/blender/io/collada/EffectExporter.cpp index f21ea57c91c..7f6d3cbdc6f 100644 --- a/source/blender/io/collada/EffectExporter.cpp +++ b/source/blender/io/collada/EffectExporter.cpp @@ -31,7 +31,6 @@ #include "collada_internal.h" #include "collada_utils.h" -extern "C" { #include "DNA_mesh_types.h" #include "DNA_world_types.h" @@ -39,7 +38,6 @@ extern "C" { #include "BKE_customdata.h" #include "BKE_material.h" #include "BKE_mesh.h" -} static std::string getActiveUVLayerName(Object *ob) { diff --git a/source/blender/io/collada/ExportSettings.h b/source/blender/io/collada/ExportSettings.h index 69e260a1e91..477f0b8b678 100644 --- a/source/blender/io/collada/ExportSettings.h +++ b/source/blender/io/collada/ExportSettings.h @@ -21,6 +21,9 @@ #ifndef __EXPORTSETTINGS_H__ #define __EXPORTSETTINGS_H__ +#include "BLI_linklist.h" +#include "BlenderContext.h" + #ifdef __cplusplus # include "BCMath.h" # include <vector> @@ -28,9 +31,6 @@ extern "C" { #endif -#include "BLI_linklist.h" -#include "BlenderContext.h" - typedef enum BC_export_mesh_type { BC_MESH_TYPE_VIEW, BC_MESH_TYPE_RENDER, diff --git a/source/blender/io/collada/GeometryExporter.cpp b/source/blender/io/collada/GeometryExporter.cpp index 469d8601a8b..c7fcc51d42f 100644 --- a/source/blender/io/collada/GeometryExporter.cpp +++ b/source/blender/io/collada/GeometryExporter.cpp @@ -29,7 +29,6 @@ #include "DNA_meshdata_types.h" -extern "C" { #include "BLI_utildefines.h" #include "BKE_customdata.h" @@ -37,7 +36,6 @@ extern "C" { #include "BKE_lib_id.h" #include "BKE_material.h" #include "BKE_mesh.h" -} #include "collada_internal.h" #include "collada_utils.h" diff --git a/source/blender/io/collada/ImageExporter.cpp b/source/blender/io/collada/ImageExporter.cpp index 1cd3301b8a8..1c897e37a4a 100644 --- a/source/blender/io/collada/ImageExporter.cpp +++ b/source/blender/io/collada/ImageExporter.cpp @@ -21,7 +21,6 @@ #include "COLLADABUURI.h" #include "COLLADASWImage.h" -extern "C" { #include "DNA_image_types.h" #include "DNA_meshdata_types.h" #include "DNA_texture_types.h" @@ -37,7 +36,6 @@ extern "C" { #include "BLI_string.h" #include "IMB_imbuf_types.h" -} #include "ImageExporter.h" #include "MaterialExporter.h" diff --git a/source/blender/io/collada/InstanceWriter.cpp b/source/blender/io/collada/InstanceWriter.cpp index a0bea16adfb..6c197823ec2 100644 --- a/source/blender/io/collada/InstanceWriter.cpp +++ b/source/blender/io/collada/InstanceWriter.cpp @@ -23,11 +23,10 @@ #include "COLLADASWInstanceMaterial.h" -extern "C" { #include "BKE_customdata.h" #include "BKE_material.h" + #include "DNA_mesh_types.h" -} #include "InstanceWriter.h" #include "collada_internal.h" diff --git a/source/blender/io/collada/MaterialExporter.h b/source/blender/io/collada/MaterialExporter.h index 8b3d1130fe9..babb113567f 100644 --- a/source/blender/io/collada/MaterialExporter.h +++ b/source/blender/io/collada/MaterialExporter.h @@ -27,12 +27,11 @@ #include "COLLADASWLibraryMaterials.h" #include "COLLADASWStreamWriter.h" -extern "C" { #include "BKE_material.h" + #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} #include "ExportSettings.h" #include "GeometryExporter.h" diff --git a/source/blender/io/collada/Materials.h b/source/blender/io/collada/Materials.h index 86fc4c00073..e1d12246a2b 100644 --- a/source/blender/io/collada/Materials.h +++ b/source/blender/io/collada/Materials.h @@ -20,13 +20,11 @@ #include <map> #include <string> -extern "C" { #include "BKE_context.h" #include "BKE_node.h" #include "BLI_listbase.h" #include "DNA_material_types.h" #include "DNA_node_types.h" -} #include "COLLADAFWEffectCommon.h" #include "collada_utils.h" diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index 6ac87d3d394..6683f07bf65 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -30,7 +30,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BKE_customdata.h" #include "BKE_displist.h" #include "BKE_global.h" @@ -43,7 +42,6 @@ extern "C" { #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_string.h" -} #include "ArmatureImporter.h" #include "MeshImporter.h" diff --git a/source/blender/io/collada/MeshImporter.h b/source/blender/io/collada/MeshImporter.h index 5ad2fb17fce..2f2a18ff11a 100644 --- a/source/blender/io/collada/MeshImporter.h +++ b/source/blender/io/collada/MeshImporter.h @@ -38,14 +38,13 @@ #include "ArmatureImporter.h" #include "collada_utils.h" -extern "C" { #include "BLI_edgehash.h" + #include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -} /* only for ArmatureImporter to "see" MeshImporter::get_object_by_geom_uid */ class MeshImporterBase { diff --git a/source/blender/io/collada/SceneExporter.cpp b/source/blender/io/collada/SceneExporter.cpp index 2f70bc1c26b..1b3bc1b66ea 100644 --- a/source/blender/io/collada/SceneExporter.cpp +++ b/source/blender/io/collada/SceneExporter.cpp @@ -18,13 +18,11 @@ * \ingroup collada */ -extern "C" { #include "BKE_collection.h" #include "BKE_lib_id.h" #include "BKE_object.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" -} #include "BCSampleData.h" #include "SceneExporter.h" diff --git a/source/blender/io/collada/SceneExporter.h b/source/blender/io/collada/SceneExporter.h index 6effb54fd48..3ea6a9fac8e 100644 --- a/source/blender/io/collada/SceneExporter.h +++ b/source/blender/io/collada/SceneExporter.h @@ -25,7 +25,6 @@ #include <stdio.h> #include <stdlib.h> -extern "C" { #include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" @@ -47,7 +46,6 @@ extern "C" { #include "BLI_fileops.h" #include "BLI_path_util.h" #include "ED_keyframing.h" -} #include "COLLADASWAsset.h" #include "COLLADASWBaseInputElement.h" diff --git a/source/blender/io/collada/collada.cpp b/source/blender/io/collada/collada.cpp index 683e64b2647..bf1ebbfa669 100644 --- a/source/blender/io/collada/collada.cpp +++ b/source/blender/io/collada/collada.cpp @@ -27,7 +27,6 @@ #include "ImportSettings.h" #include "collada.h" -extern "C" { #include "BKE_context.h" #include "BKE_scene.h" #include "DEG_depsgraph.h" @@ -37,6 +36,8 @@ extern "C" { #include "BLI_fileops.h" #include "BLI_linklist.h" +extern "C" { + static void print_import_header(ImportSettings &import_settings) { fprintf(stderr, "+-- Collada Import parameters------\n"); diff --git a/source/blender/io/collada/collada.h b/source/blender/io/collada/collada.h index deadbcffcaf..d8e498ef4b2 100644 --- a/source/blender/io/collada/collada.h +++ b/source/blender/io/collada/collada.h @@ -26,14 +26,14 @@ #include "ExportSettings.h" #include "ImportSettings.h" -#ifdef __cplusplus -extern "C" { -#endif - #include "BLI_linklist.h" #include "BLI_path_util.h" #include "RNA_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bContext; /* diff --git a/source/blender/io/collada/collada_utils.cpp b/source/blender/io/collada/collada_utils.cpp index 1df82ed3038..d2e05c7ae5b 100644 --- a/source/blender/io/collada/collada_utils.cpp +++ b/source/blender/io/collada/collada_utils.cpp @@ -30,7 +30,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_armature_types.h" #include "DNA_constraint_types.h" #include "DNA_customdata_types.h" @@ -75,7 +74,6 @@ extern "C" { #if 0 # include "NOD_common.h" #endif -} #include "BlenderContext.h" #include "ExportSettings.h" diff --git a/source/blender/io/collada/collada_utils.h b/source/blender/io/collada/collada_utils.h index 54ba8073679..b1ec2c8b81a 100644 --- a/source/blender/io/collada/collada_utils.h +++ b/source/blender/io/collada/collada_utils.h @@ -33,7 +33,6 @@ #include <set> #include <vector> -extern "C" { #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_constraint_types.h" @@ -57,7 +56,6 @@ extern "C" { #include "BKE_node.h" #include "BKE_object.h" #include "BKE_scene.h" -} #include "DEG_depsgraph_query.h" diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc index d837d3d8dd3..e382fa6bb1d 100644 --- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.cc @@ -24,7 +24,6 @@ #include <stdio.h> #include <string> -extern "C" { #include "BKE_anim_data.h" #include "BKE_duplilist.h" #include "BKE_key.h" @@ -41,7 +40,6 @@ extern "C" { #include "DNA_particle_types.h" #include "DEG_depsgraph_query.h" -} namespace USD { @@ -345,8 +343,11 @@ void AbstractHierarchyIterator::visit_object(Object *object, context->original_export_path = ""; copy_m4_m4(context->matrix_world, object->obmat); + ExportGraph::key_type graph_index = determine_graph_index_object(context); + context_update_for_graph_index(context, graph_index); + // Store this HierarchyContext as child of the export parent. - export_graph_[std::make_pair(export_parent, nullptr)].insert(context); + export_graph_[graph_index].insert(context); // Create an empty entry for this object to indicate it is part of the export. This will be used // by connect_loose_objects(). Having such an "indicator" will make it possible to do an O(log n) @@ -359,38 +360,25 @@ void AbstractHierarchyIterator::visit_object(Object *object, } } +AbstractHierarchyIterator::ExportGraph::key_type AbstractHierarchyIterator:: + determine_graph_index_object(const HierarchyContext *context) +{ + return std::make_pair(context->export_parent, nullptr); +} + void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object, Object *duplicator, const std::set<Object *> &dupli_set) { - ExportGraph::key_type graph_index; - bool animation_check_include_parent = false; - HierarchyContext *context = new HierarchyContext(); context->object = dupli_object->ob; context->duplicator = duplicator; context->weak_export = false; context->export_path = ""; context->original_export_path = ""; + context->export_path = ""; + context->animation_check_include_parent = false; - /* If the dupli-object's parent is also instanced by this object, use that as the - * export parent. Otherwise use the dupli-parent as export parent. */ - Object *parent = dupli_object->ob->parent; - if (parent != nullptr && dupli_set.find(parent) != dupli_set.end()) { - // The parent object is part of the duplicated collection. - context->export_parent = parent; - graph_index = std::make_pair(parent, duplicator); - } - else { - /* The parent object is NOT part of the duplicated collection. This means that the world - * transform of this dupli-object can be influenced by objects that are not part of its - * export graph. */ - animation_check_include_parent = true; - context->export_parent = duplicator; - graph_index = std::make_pair(duplicator, nullptr); - } - - context->animation_check_include_parent = animation_check_include_parent; copy_m4_m4(context->matrix_world, dupli_object->mat); // Construct export name for the dupli-instance. @@ -401,9 +389,39 @@ void AbstractHierarchyIterator::visit_dupli_object(DupliObject *dupli_object, } context->export_name = make_valid_name(get_object_name(context->object) + suffix_stream.str()); + ExportGraph::key_type graph_index = determine_graph_index_dupli(context, dupli_set); + context_update_for_graph_index(context, graph_index); export_graph_[graph_index].insert(context); } +AbstractHierarchyIterator::ExportGraph::key_type AbstractHierarchyIterator:: + determine_graph_index_dupli(const HierarchyContext *context, + const std::set<Object *> &dupli_set) +{ + /* If the dupli-object's parent is also instanced by this object, use that as the + * export parent. Otherwise use the dupli-parent as export parent. */ + + Object *parent = context->object->parent; + if (parent != nullptr && dupli_set.find(parent) != dupli_set.end()) { + // The parent object is part of the duplicated collection. + return std::make_pair(parent, context->duplicator); + } + return std::make_pair(context->duplicator, nullptr); +} + +void AbstractHierarchyIterator::context_update_for_graph_index( + HierarchyContext *context, const ExportGraph::key_type &graph_index) const +{ + // Update the HierarchyContext so that it is consistent with the graph index. + context->export_parent = graph_index.first; + if (context->export_parent != context->object->parent) { + /* The parent object in Blender is NOT used as the export parent. This means + * that the world transform of this object can be influenced by objects that + * are not part of its export graph. */ + context->animation_check_include_parent = true; + } +} + AbstractHierarchyIterator::ExportChildren &AbstractHierarchyIterator::graph_children( const HierarchyContext *context) { @@ -428,8 +446,7 @@ void AbstractHierarchyIterator::determine_export_paths(const HierarchyContext *p duplisource_export_path_[source_ob] = context->export_path; if (context->object->data != nullptr) { - ID *object_data = static_cast<ID *>(context->object->data); - ID *source_data = object_data; + ID *source_data = static_cast<ID *>(context->object->data); duplisource_export_path_[source_data] = get_object_data_path(context); } } @@ -488,6 +505,7 @@ void AbstractHierarchyIterator::make_writers(const HierarchyContext *parent_cont } for (HierarchyContext *context : graph_children(parent_context)) { + // Update the context so that it is correct for this parent-child relation. copy_m4_m4(context->parent_matrix_inv_world, parent_matrix_inv_world); // Get or create the transform writer. @@ -556,7 +574,7 @@ void AbstractHierarchyIterator::make_writers_particle_systems( HierarchyContext hair_context = *transform_context; hair_context.export_path = path_concatenate(transform_context->export_path, - get_id_name(&psys->part->id)); + make_valid_name(psys->name)); hair_context.particle_system = psys; AbstractHierarchyWriter *writer = nullptr; @@ -586,9 +604,10 @@ std::string AbstractHierarchyIterator::get_object_data_name(const Object *object return get_id_name(object_data); } -AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer(const std::string &export_path) +AbstractHierarchyWriter *AbstractHierarchyIterator::get_writer( + const std::string &export_path) const { - WriterMap::iterator it = writers_.find(export_path); + WriterMap::const_iterator it = writers_.find(export_path); if (it == writers_.end()) { return nullptr; diff --git a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h index 08b50e2560d..e31d5c91252 100644 --- a/source/blender/io/usd/intern/abstract_hierarchy_iterator.h +++ b/source/blender/io/usd/intern/abstract_hierarchy_iterator.h @@ -56,7 +56,7 @@ class AbstractHierarchyWriter; * struct contains everything necessary to export a single object to a file. */ struct HierarchyContext { /*********** Determined during hierarchy iteration: ***************/ - Object *object; + Object *object; /* Evaluated object. */ Object *export_parent; Object *duplicator; float matrix_world[4][4]; @@ -188,11 +188,14 @@ class AbstractHierarchyIterator { const std::set<Object *> &dupli_set); ExportChildren &graph_children(const HierarchyContext *parent_context); + void context_update_for_graph_index(HierarchyContext *context, + const ExportGraph::key_type &graph_index) const; void determine_export_paths(const HierarchyContext *parent_context); void determine_duplication_references(const HierarchyContext *parent_context, std::string indent); + /* These three functions create writers and call their write() method. */ void make_writers(const HierarchyContext *parent_context); void make_writer_object_data(const HierarchyContext *context); void make_writers_particle_systems(const HierarchyContext *context); @@ -201,7 +204,7 @@ class AbstractHierarchyIterator { std::string get_object_name(const Object *object) const; std::string get_object_data_name(const Object *object) const; - AbstractHierarchyWriter *get_writer(const std::string &export_path); + AbstractHierarchyWriter *get_writer(const std::string &export_path) const; typedef AbstractHierarchyWriter *(AbstractHierarchyIterator::*create_writer_func)( const HierarchyContext *); @@ -233,12 +236,19 @@ class AbstractHierarchyIterator { virtual bool should_visit_dupli_object(const DupliObject *dupli_object) const; + virtual ExportGraph::key_type determine_graph_index_object(const HierarchyContext *context); + virtual ExportGraph::key_type determine_graph_index_dupli(const HierarchyContext *context, + const std::set<Object *> &dupli_set); + /* These functions should create an AbstractHierarchyWriter subclass instance, or return * nullptr if the object or its data should not be exported. Returning a nullptr for * data/hair/particle will NOT prevent the transform to be written. * * The returned writer is owned by the AbstractHierarchyWriter, and should be freed in - * delete_object_writer(). */ + * delete_object_writer(). + * + * The created AbstractHierarchyWriter instances should NOT keep a copy of the context pointer. + * The context can be stack-allocated and go out of scope. */ virtual AbstractHierarchyWriter *create_transform_writer(const HierarchyContext *context) = 0; virtual AbstractHierarchyWriter *create_data_writer(const HierarchyContext *context) = 0; virtual AbstractHierarchyWriter *create_hair_writer(const HierarchyContext *context) = 0; diff --git a/source/blender/io/usd/intern/usd_capi.cc b/source/blender/io/usd/intern/usd_capi.cc index 60ab3676847..f8e0a03abfa 100644 --- a/source/blender/io/usd/intern/usd_capi.cc +++ b/source/blender/io/usd/intern/usd_capi.cc @@ -26,7 +26,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DEG_depsgraph.h" #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" @@ -44,7 +43,6 @@ extern "C" { #include "WM_api.h" #include "WM_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc index 47f09af7442..56e367dd877 100644 --- a/source/blender/io/usd/intern/usd_hierarchy_iterator.cc +++ b/source/blender/io/usd/intern/usd_hierarchy_iterator.cc @@ -31,7 +31,6 @@ #include <pxr/base/tf/stringUtils.h> -extern "C" { #include "BKE_duplilist.h" #include "BLI_assert.h" @@ -41,7 +40,6 @@ extern "C" { #include "DNA_ID.h" #include "DNA_layer_types.h" #include "DNA_object_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_abstract.h b/source/blender/io/usd/intern/usd_writer_abstract.h index cf0f7e9d437..01b53f4c916 100644 --- a/source/blender/io/usd/intern/usd_writer_abstract.h +++ b/source/blender/io/usd/intern/usd_writer_abstract.h @@ -29,10 +29,9 @@ #include <vector> -extern "C" { #include "DEG_depsgraph_query.h" + #include "DNA_material_types.h" -} struct Material; struct Object; diff --git a/source/blender/io/usd/intern/usd_writer_camera.cc b/source/blender/io/usd/intern/usd_writer_camera.cc index 9b85d69559c..ea551a43c9f 100644 --- a/source/blender/io/usd/intern/usd_writer_camera.cc +++ b/source/blender/io/usd/intern/usd_writer_camera.cc @@ -22,13 +22,11 @@ #include <pxr/usd/usdGeom/camera.h> #include <pxr/usd/usdGeom/tokens.h> -extern "C" { #include "BKE_camera.h" #include "BLI_assert.h" #include "DNA_camera_types.h" #include "DNA_scene_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_hair.cc b/source/blender/io/usd/intern/usd_writer_hair.cc index 9251425c0b8..d38c1032969 100644 --- a/source/blender/io/usd/intern/usd_writer_hair.cc +++ b/source/blender/io/usd/intern/usd_writer_hair.cc @@ -22,11 +22,9 @@ #include <pxr/usd/usdGeom/basisCurves.h> #include <pxr/usd/usdGeom/tokens.h> -extern "C" { #include "BKE_particle.h" #include "DNA_particle_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_light.cc b/source/blender/io/usd/intern/usd_writer_light.cc index e13e2c58a79..0ce3ee5f8ce 100644 --- a/source/blender/io/usd/intern/usd_writer_light.cc +++ b/source/blender/io/usd/intern/usd_writer_light.cc @@ -24,13 +24,11 @@ #include <pxr/usd/usdLux/rectLight.h> #include <pxr/usd/usdLux/sphereLight.h> -extern "C" { #include "BLI_assert.h" #include "BLI_utildefines.h" #include "DNA_light_types.h" #include "DNA_object_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_mesh.cc b/source/blender/io/usd/intern/usd_writer_mesh.cc index 2e6696e12ca..909869d2af1 100644 --- a/source/blender/io/usd/intern/usd_writer_mesh.cc +++ b/source/blender/io/usd/intern/usd_writer_mesh.cc @@ -23,7 +23,6 @@ #include <pxr/usd/usdShade/material.h> #include <pxr/usd/usdShade/materialBindingAPI.h> -extern "C" { #include "BLI_assert.h" #include "BLI_math_vector.h" @@ -42,7 +41,6 @@ extern "C" { #include "DNA_modifier_types.h" #include "DNA_object_fluidsim_types.h" #include "DNA_particle_types.h" -} namespace USD { @@ -441,7 +439,7 @@ void USDGenericMeshWriter::write_surface_velocity(Object *object, /* Only velocities from the fluid simulation are exported. This is the most important case, * though, as the baked mesh changes topology all the time, and thus computing the velocities * at import time in a post-processing step is hard. */ - ModifierData *md = modifiers_findByType(object, eModifierType_Fluidsim); + ModifierData *md = BKE_modifiers_findby_type(object, eModifierType_Fluidsim); if (md == nullptr) { return; } @@ -450,7 +448,7 @@ void USDGenericMeshWriter::write_surface_velocity(Object *object, const bool use_render = (DEG_get_mode(usd_export_context_.depsgraph) == DAG_EVAL_RENDER); const ModifierMode required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime; const Scene *scene = DEG_get_evaluated_scene(usd_export_context_.depsgraph); - if (!modifier_isEnabled(scene, md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, md, required_mode)) { return; } FluidsimModifierData *fsmd = reinterpret_cast<FluidsimModifierData *>(md); diff --git a/source/blender/io/usd/intern/usd_writer_metaball.cc b/source/blender/io/usd/intern/usd_writer_metaball.cc index 25b216d20f3..96bf854d327 100644 --- a/source/blender/io/usd/intern/usd_writer_metaball.cc +++ b/source/blender/io/usd/intern/usd_writer_metaball.cc @@ -23,7 +23,6 @@ #include <pxr/usd/usdShade/material.h> #include <pxr/usd/usdShade/materialBindingAPI.h> -extern "C" { #include "BLI_assert.h" #include "BKE_displist.h" @@ -34,7 +33,6 @@ extern "C" { #include "DNA_mesh_types.h" #include "DNA_meta_types.h" -} namespace USD { diff --git a/source/blender/io/usd/intern/usd_writer_transform.cc b/source/blender/io/usd/intern/usd_writer_transform.cc index 321b516221a..038f2b17b1a 100644 --- a/source/blender/io/usd/intern/usd_writer_transform.cc +++ b/source/blender/io/usd/intern/usd_writer_transform.cc @@ -22,13 +22,11 @@ #include <pxr/base/gf/matrix4f.h> #include <pxr/usd/usdGeom/xform.h> -extern "C" { #include "BKE_object.h" #include "BLI_math_matrix.h" #include "DNA_layer_types.h" -} namespace USD { diff --git a/source/blender/io/usd/usd.h b/source/blender/io/usd/usd.h index 8a5575d53cf..eee98521289 100644 --- a/source/blender/io/usd/usd.h +++ b/source/blender/io/usd/usd.h @@ -20,12 +20,12 @@ #ifndef __USD_H__ #define __USD_H__ +#include "DEG_depsgraph.h" + #ifdef __cplusplus extern "C" { #endif -#include "DEG_depsgraph.h" - struct Scene; struct bContext; diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index 5230cb050f4..39f22fb9555 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -25,14 +25,13 @@ #ifndef __DNA_ID_H__ #define __DNA_ID_H__ +#include "DNA_defs.h" #include "DNA_listBase.h" #ifdef __cplusplus extern "C" { #endif -#include "DNA_defs.h" - struct FileData; struct GHash; struct GPUTexture; @@ -436,6 +435,7 @@ typedef enum ID_Type { ID_HA = MAKE_ID2('H', 'A'), /* Hair */ ID_PT = MAKE_ID2('P', 'T'), /* PointCloud */ ID_VO = MAKE_ID2('V', 'O'), /* Volume */ + ID_SIM = MAKE_ID2('S', 'I'), /* Simulation */ } ID_Type; /* Only used as 'placeholder' in .blend files for directly linked data-blocks. */ @@ -564,9 +564,9 @@ enum { /* RESET_NEVER tag data-block as needing an auto-override execution, if enabled. */ LIB_TAG_OVERRIDE_LIBRARY_AUTOREFRESH = 1 << 17, - /* tag data-block has having an extra user. */ + /* tag data-block as having an extra user. */ LIB_TAG_EXTRAUSER = 1 << 2, - /* tag data-block has having actually increased usercount for the extra virtual user. */ + /* tag data-block as having actually increased usercount for the extra virtual user. */ LIB_TAG_EXTRAUSER_SET = 1 << 7, /* RESET_AFTER_USE tag newly duplicated/copied IDs. @@ -735,6 +735,7 @@ typedef enum IDRecalcFlag { #define FILTER_ID_HA (1ULL << 32) #define FILTER_ID_PT (1ULL << 33) #define FILTER_ID_VO (1ULL << 34) +#define FILTER_ID_SIM (1ULL << 35) #define FILTER_ID_ALL \ (FILTER_ID_AC | FILTER_ID_AR | FILTER_ID_BR | FILTER_ID_CA | FILTER_ID_CU | FILTER_ID_GD | \ @@ -742,7 +743,7 @@ typedef enum IDRecalcFlag { FILTER_ID_MB | FILTER_ID_MC | FILTER_ID_ME | FILTER_ID_MSK | FILTER_ID_NT | FILTER_ID_OB | \ FILTER_ID_PA | FILTER_ID_PAL | FILTER_ID_PC | FILTER_ID_SCE | FILTER_ID_SPK | FILTER_ID_SO | \ FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \ - FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO) + FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM) /* IMPORTANT: this enum matches the order currently use in set_listbasepointers, * keep them in sync! */ @@ -786,6 +787,7 @@ enum { INDEX_ID_WS, INDEX_ID_WM, INDEX_ID_MSK, + INDEX_ID_SIM, INDEX_ID_NULL, INDEX_ID_MAX, }; diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 40c25d39cad..c95a701a78a 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -28,16 +28,16 @@ #ifndef __DNA_ACTION_TYPES_H__ #define __DNA_ACTION_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_listBase.h" #include "DNA_userdef_types.h" /* ThemeWireColor */ #include "DNA_vec_types.h" #include "DNA_view2d_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct Collection; struct GHash; struct Object; diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h index fbffa039ee9..6a024ec9e7e 100644 --- a/source/blender/makesdna/DNA_anim_types.h +++ b/source/blender/makesdna/DNA_anim_types.h @@ -24,15 +24,15 @@ #ifndef __DNA_ANIM_TYPES_H__ #define __DNA_ANIM_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_action_types.h" #include "DNA_curve_types.h" #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + /* ************************************************ */ /* F-Curve DataTypes */ diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index b29816c735b..635c155dec6 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -261,23 +261,23 @@ typedef enum eBone_InheritScaleMode { /* Inherit all scale and shear. */ BONE_INHERIT_SCALE_FULL = 0, /* Inherit scale, but remove final shear. */ - BONE_INHERIT_SCALE_FIX_SHEAR, + BONE_INHERIT_SCALE_FIX_SHEAR = 1, /* Inherit average scale. */ - BONE_INHERIT_SCALE_AVERAGE, + BONE_INHERIT_SCALE_AVERAGE = 2, /* Inherit no scale or shear. */ - BONE_INHERIT_SCALE_NONE, + BONE_INHERIT_SCALE_NONE = 3, /* Inherit effects of shear on parent (same as old disabled Inherit Scale). */ - BONE_INHERIT_SCALE_NONE_LEGACY, + BONE_INHERIT_SCALE_NONE_LEGACY = 4, /* Inherit parent X scale as child X scale etc. */ - BONE_INHERIT_SCALE_ALIGNED, + BONE_INHERIT_SCALE_ALIGNED = 5, } eBone_InheritScaleMode; /* bone->bbone_prev_type, bbone_next_type */ typedef enum eBone_BBoneHandleType { - BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */ - BBONE_HANDLE_ABSOLUTE, /* Custom handle in absolute position mode. */ - BBONE_HANDLE_RELATIVE, /* Custom handle in relative position mode. */ - BBONE_HANDLE_TANGENT, /* Custom handle in tangent mode (use direction, not location). */ + BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */ + BBONE_HANDLE_ABSOLUTE = 1, /* Custom handle in absolute position mode. */ + BBONE_HANDLE_RELATIVE = 2, /* Custom handle in relative position mode. */ + BBONE_HANDLE_TANGENT = 3, /* Custom handle in tangent mode (use direction, not location). */ } eBone_BBoneHandleType; #define MAXBONENAME 64 diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 041943bc5e4..c143c2a442a 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -75,7 +75,7 @@ typedef struct BrushGpencilSettings { short fill_leak; /** Fill zoom factor */ short fill_factor; - char _pad1[4]; + int flag2; /** Number of simplify steps. */ int fill_simplylvl; @@ -118,11 +118,24 @@ typedef struct BrushGpencilSettings { int sculpt_mode_flag; /** Preset type (used to reset brushes - internal). */ short preset_type; - char _pad3[6]; + char _pad3[2]; + + /** Randomness for Hue. */ + float random_hue; + /** Randomness for Saturation. */ + float random_saturation; + /** Randomness for Value. */ + float random_value; struct CurveMapping *curve_sensitivity; struct CurveMapping *curve_strength; struct CurveMapping *curve_jitter; + struct CurveMapping *curve_rand_pressure; + struct CurveMapping *curve_rand_strength; + struct CurveMapping *curve_rand_uv; + struct CurveMapping *curve_rand_hue; + struct CurveMapping *curve_rand_saturation; + struct CurveMapping *curve_rand_value; /* optional link of material to replace default in context */ /** Material. */ @@ -204,6 +217,33 @@ typedef enum eGPDbrush_Flag { GP_BRUSH_TRIM_STROKE = (1 << 16), } eGPDbrush_Flag; +typedef enum eGPDbrush_Flag2 { + /* Brush use random Hue at stroke level */ + GP_BRUSH_USE_HUE_AT_STROKE = (1 << 0), + /* Brush use random Saturation at stroke level */ + GP_BRUSH_USE_SAT_AT_STROKE = (1 << 1), + /* Brush use random Value at stroke level */ + GP_BRUSH_USE_VAL_AT_STROKE = (1 << 2), + /* Brush use random Pressure at stroke level */ + GP_BRUSH_USE_PRESS_AT_STROKE = (1 << 3), + /* Brush use random Strength at stroke level */ + GP_BRUSH_USE_STRENGTH_AT_STROKE = (1 << 4), + /* Brush use random UV at stroke level */ + GP_BRUSH_USE_UV_AT_STROKE = (1 << 5), + /* Brush use Hue random pressure */ + GP_BRUSH_USE_HUE_RAND_PRESS = (1 << 6), + /* Brush use Saturation random pressure */ + GP_BRUSH_USE_SAT_RAND_PRESS = (1 << 7), + /* Brush use Value random pressure */ + GP_BRUSH_USE_VAL_RAND_PRESS = (1 << 8), + /* Brush use Pressure random pressure */ + GP_BRUSH_USE_PRESSURE_RAND_PRESS = (1 << 9), + /* Brush use Strength random pressure */ + GP_BRUSH_USE_STRENGTH_RAND_PRESS = (1 << 10), + /* Brush use UV random pressure */ + GP_BRUSH_USE_UV_RAND_PRESS = (1 << 11), +} eGPDbrush_Flag2; + /* BrushGpencilSettings->gp_fill_draw_mode */ typedef enum eGP_FillDrawModes { GP_FILL_DMODE_BOTH = 0, @@ -805,8 +845,8 @@ typedef enum { /* blur kernel types, Brush.blur_mode */ typedef enum eBlurKernelType { - KERNEL_GAUSSIAN, - KERNEL_BOX, + KERNEL_GAUSSIAN = 0, + KERNEL_BOX = 1, } eBlurKernelType; /* Brush.falloff_shape */ diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index 9efd2116601..65087a6d459 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -735,11 +735,11 @@ typedef enum eConstraint_EulerOrder { /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */ CONSTRAINT_EULER_XYZ = 1, - CONSTRAINT_EULER_XZY, - CONSTRAINT_EULER_YXZ, - CONSTRAINT_EULER_YZX, - CONSTRAINT_EULER_ZXY, - CONSTRAINT_EULER_ZYX, + CONSTRAINT_EULER_XZY = 2, + CONSTRAINT_EULER_YXZ = 3, + CONSTRAINT_EULER_YZX = 4, + CONSTRAINT_EULER_ZXY = 5, + CONSTRAINT_EULER_ZYX = 6, } eConstraint_EulerOrder; /* -------------------------------------- */ @@ -762,13 +762,13 @@ typedef enum eCopyRotation_MixMode { /* Replace rotation channel values. */ ROTLIKE_MIX_REPLACE = 0, /* Legacy Offset mode - don't use. */ - ROTLIKE_MIX_OFFSET, + ROTLIKE_MIX_OFFSET = 1, /* Add Euler components together. */ - ROTLIKE_MIX_ADD, + ROTLIKE_MIX_ADD = 2, /* Multiply the copied rotation on the left. */ - ROTLIKE_MIX_BEFORE, + ROTLIKE_MIX_BEFORE = 3, /* Multiply the copied rotation on the right. */ - ROTLIKE_MIX_AFTER, + ROTLIKE_MIX_AFTER = 4, } eCopyRotation_MixMode; /* bLocateLikeConstraint.flag */ @@ -799,9 +799,9 @@ typedef enum eCopyTransforms_MixMode { /* Replace rotation channel values. */ TRANSLIKE_MIX_REPLACE = 0, /* Multiply the copied transformation on the left, with anti-shear scale handling. */ - TRANSLIKE_MIX_BEFORE, + TRANSLIKE_MIX_BEFORE = 1, /* Multiply the copied transformation on the right, with anti-shear scale handling. */ - TRANSLIKE_MIX_AFTER, + TRANSLIKE_MIX_AFTER = 2, } eCopyTransforms_MixMode; /* bTransformConstraint.to/from */ @@ -816,7 +816,7 @@ typedef enum eTransform_MixModeLoc { /* Add component values together (default). */ TRANS_MIXLOC_ADD = 0, /* Replace component values. */ - TRANS_MIXLOC_REPLACE, + TRANS_MIXLOC_REPLACE = 1, } eTransform_MixModeLoc; /* bTransformConstraint.mix_mode_rot */ @@ -824,11 +824,11 @@ typedef enum eTransform_MixModeRot { /* Add component values together (default). */ TRANS_MIXROT_ADD = 0, /* Replace component values. */ - TRANS_MIXROT_REPLACE, + TRANS_MIXROT_REPLACE = 1, /* Multiply the generated rotation on the left. */ - TRANS_MIXROT_BEFORE, + TRANS_MIXROT_BEFORE = 2, /* Multiply the generated rotation on the right. */ - TRANS_MIXROT_AFTER, + TRANS_MIXROT_AFTER = 3, } eTransform_MixModeRot; /* bTransformConstraint.mix_mode_scale */ @@ -836,7 +836,7 @@ typedef enum eTransform_MixModeScale { /* Replace component values (default). */ TRANS_MIXSCALE_REPLACE = 0, /* Multiply component values together. */ - TRANS_MIXSCALE_MULTIPLY, + TRANS_MIXSCALE_MULTIPLY = 1, } eTransform_MixModeScale; /* bSameVolumeConstraint.free_axis */ @@ -867,9 +867,9 @@ typedef enum eActionConstraint_MixMode { /* Multiply the action transformation on the right. */ ACTCON_MIX_AFTER_FULL = 0, /* Multiply the action transformation on the right, with anti-shear scale handling. */ - ACTCON_MIX_AFTER, + ACTCON_MIX_AFTER = 1, /* Multiply the action transformation on the left, with anti-shear scale handling. */ - ACTCON_MIX_BEFORE, + ACTCON_MIX_BEFORE = 2, } eActionConstraint_MixMode; /* Locked-Axis Values (Locked Track) */ diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h index 5ee16c2631d..e99d7fd5609 100644 --- a/source/blender/makesdna/DNA_customdata_types.h +++ b/source/blender/makesdna/DNA_customdata_types.h @@ -26,12 +26,12 @@ #ifndef __DNA_CUSTOMDATA_TYPES_H__ #define __DNA_CUSTOMDATA_TYPES_H__ +#include "DNA_defs.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_defs.h" - /** Descriptor and storage for a custom data layer. */ typedef struct CustomDataLayer { /** Type of data in layer. */ diff --git a/source/blender/makesdna/DNA_defaults.h b/source/blender/makesdna/DNA_defaults.h index 9b4a05034df..ca5ac649e33 100644 --- a/source/blender/makesdna/DNA_defaults.h +++ b/source/blender/makesdna/DNA_defaults.h @@ -29,12 +29,12 @@ #include "BLI_utildefines.h" +#include "dna_type_offsets.h" + #ifdef __cplusplus extern "C" { #endif -#include "dna_type_offsets.h" - extern const void *DNA_default_table[SDNA_TYPE_MAX]; char *_DNA_struct_default_alloc_impl(const char *data_src, size_t size, const char *alloc_str); diff --git a/source/blender/makesdna/DNA_dynamicpaint_types.h b/source/blender/makesdna/DNA_dynamicpaint_types.h index d949b34cb57..c97e68a6a6b 100644 --- a/source/blender/makesdna/DNA_dynamicpaint_types.h +++ b/source/blender/makesdna/DNA_dynamicpaint_types.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/makesdna/DNA_gpencil_modifier_types.h b/source/blender/makesdna/DNA_gpencil_modifier_types.h index c3425826d36..125423cd061 100644 --- a/source/blender/makesdna/DNA_gpencil_modifier_types.h +++ b/source/blender/makesdna/DNA_gpencil_modifier_types.h @@ -47,6 +47,8 @@ typedef enum GpencilModifierType { eGpencilModifierType_Armature = 15, eGpencilModifierType_Time = 16, eGpencilModifierType_Multiply = 17, + eGpencilModifierType_Texture = 18, + /* Keep last. */ NUM_GREASEPENCIL_MODIFIER_TYPES, } GpencilModifierType; @@ -77,10 +79,12 @@ typedef struct GpencilModifierData { typedef struct NoiseGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -120,10 +124,12 @@ typedef enum eNoiseGpencil_Flag { typedef struct SubdivGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -151,10 +157,12 @@ typedef enum eSubdivGpencil_Type { typedef struct ThickGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -225,10 +233,12 @@ typedef enum eOpacityModesGpencil_Flag { typedef struct ColorGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -255,10 +265,12 @@ typedef enum eColorGpencil_Flag { typedef struct OpacityGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -290,6 +302,8 @@ typedef enum eOpacityGpencil_Flag { typedef struct ArrayGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Number of elements in array. */ int count; /** Several flags. */ @@ -313,7 +327,7 @@ typedef struct ArrayGpencilModifierData { /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Material replace (0 keep default). */ int mat_rpl; /** Custom index for passes. */ @@ -332,13 +346,15 @@ typedef enum eArrayGpencil_Flag { typedef struct BuildGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** If set, restrict modifier to operating on this layer. */ char layername[64]; int pass_index; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int layer_pass; @@ -368,6 +384,9 @@ typedef struct BuildGpencilModifierData { * For the "Concurrent" mode, when should "shorter" strips start/end. */ short time_alignment; + /** Factor of the stroke (used instead of frame evaluation. */ + float percentage_fac; + char _pad[4]; } BuildGpencilModifierData; typedef enum eBuildGpencil_Mode { @@ -403,15 +422,20 @@ typedef enum eBuildGpencil_Flag { /* Restrict modifier to only operating between the nominated frames */ GP_BUILD_RESTRICT_TIME = (1 << 2), GP_BUILD_INVERT_LAYERPASS = (1 << 3), + + /* Use a percentage instead of frame number to evaluate strokes. */ + GP_BUILD_PERCENTAGE = (1 << 4), } eBuildGpencil_Flag; typedef struct LatticeGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -436,10 +460,12 @@ typedef enum eLatticeGpencil_Flag { typedef struct MirrorGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -464,12 +490,14 @@ typedef struct HookGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Optional name of bone target, MAX_ID_NAME-2. */ char subtarget[64]; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -515,10 +543,12 @@ typedef enum eHookGpencil_Falloff { typedef struct SimplifyGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -558,10 +588,12 @@ typedef enum eSimplifyGpencil_Mode { typedef struct OffsetGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -585,10 +617,12 @@ typedef enum eOffsetGpencil_Flag { typedef struct SmoothGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -634,10 +668,12 @@ typedef struct ArmatureGpencilModifierData { typedef struct MultiplyGpencilModifierData { GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Custom index for passes. */ int pass_index; /** Flags. */ @@ -672,10 +708,12 @@ typedef struct TintGpencilModifierData { GpencilModifierData modifier; struct Object *object; + /** Material for filtering. */ + struct Material *material; /** Layer name. */ char layername[64]; /** Material name. */ - char materialname[64]; + char materialname[64] DNA_DEPRECATED; /** Optional vertexgroup name, MAX_VGROUP_NAME. */ char vgname[64]; /** Custom index for passes. */ @@ -713,4 +751,52 @@ typedef enum eTintGpencil_Flag { GP_TINT_CUSTOM_CURVE = (1 << 6), } eTintGpencil_Flag; +typedef struct TextureGpencilModifierData { + GpencilModifierData modifier; + /** Material for filtering. */ + struct Material *material; + /** Layer name. */ + char layername[64]; + /** Material name. */ + char materialname[64] DNA_DEPRECATED; + /** Optional vertexgroup name, MAX_VGROUP_NAME. */ + char vgname[64]; + /** Custom index for passes. */ + int pass_index; + /** Flags. */ + int flag; + /** Offset value to add to uv_fac. */ + float uv_offset; + float uv_scale; + float fill_rotation; + float fill_offset[2]; + float fill_scale; + /** Custom index for passes. */ + int layer_pass; + /** Texture fit options. */ + short fit_method; + short mode; +} TextureGpencilModifierData; + +typedef enum eTextureGpencil_Flag { + GP_TEX_INVERT_LAYER = (1 << 0), + GP_TEX_INVERT_PASS = (1 << 1), + GP_TEX_INVERT_VGROUP = (1 << 2), + GP_TEX_INVERT_LAYERPASS = (1 << 3), + GP_TEX_INVERT_MATERIAL = (1 << 4), +} eTextureGpencil_Flag; + +/* Texture->fit_method */ +typedef enum eTextureGpencil_Fit { + GP_TEX_FIT_STROKE = 0, + GP_TEX_CONSTANT_LENGTH = 1, +} eTextureGpencil_Fit; + +/* Texture->mode */ +typedef enum eTextureGpencil_Mode { + STROKE = 0, + FILL = 1, + STROKE_AND_FILL = 2, +} eTextureGpencil_Mode; + #endif /* __DNA_GPENCIL_MODIFIER_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index d3d7ca1cc3b..c3180ae79db 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -264,6 +264,10 @@ typedef enum eGPDstroke_Flag { /* Flag used to indicate that stroke is used for fill close and must use * fill color for stroke and no fill area */ GP_STROKE_NOFILL = (1 << 8), + /* only for use with stroke-buffer (while drawing arrows) */ + GP_STROKE_USE_ARROW_START = (1 << 12), + /* only for use with stroke-buffer (while drawing arrows) */ + GP_STROKE_USE_ARROW_END = (1 << 13), /* Tag for update geometry */ GP_STROKE_TAG = (1 << 14), /* only for use with stroke-buffer (while drawing eraser) */ @@ -276,9 +280,21 @@ typedef enum eGPDstroke_Caps { GP_STROKE_CAP_ROUND = 0, GP_STROKE_CAP_FLAT = 1, + /* Keeo last. */ GP_STROKE_CAP_MAX, } GPDstroke_Caps; +/* Arrows ----------------------- */ + +/* bGPDataRuntime.arrowstyle */ +typedef enum eGPDstroke_Arrowstyle { + GP_STROKE_ARROWSTYLE_NONE = 0, + GP_STROKE_ARROWSTYLE_SEGMENT = 2, + GP_STROKE_ARROWSTYLE_OPEN = 3, + GP_STROKE_ARROWSTYLE_CLOSED = 4, + GP_STROKE_ARROWSTYLE_SQUARE = 6, +} eGPDstroke_Arrowstyle; + /* ***************************************** */ /* GP Frame */ @@ -504,12 +520,16 @@ typedef struct bGPdata_Runtime { /** Number of total elements available in cache. */ int sbuffer_size; - /** Vertex Color applied to point (while drawing). */ - float vert_color[4]; - /** Vertex Color applied to Fill (while drawing). */ float vert_color_fill[4]; + /** Arrow points for stroke corners **/ + float arrow_start[8]; + float arrow_end[8]; + /* Arrow style for each corner */ + int arrow_start_style; + int arrow_end_style; + /** Number of control-points for stroke. */ int tot_cp_points; char _pad2[4]; diff --git a/source/blender/makesdna/DNA_layer_types.h b/source/blender/makesdna/DNA_layer_types.h index 4676e7fa313..6348dc5f03d 100644 --- a/source/blender/makesdna/DNA_layer_types.h +++ b/source/blender/makesdna/DNA_layer_types.h @@ -21,13 +21,13 @@ #ifndef __DNA_LAYER_TYPES_H__ #define __DNA_LAYER_TYPES_H__ +#include "DNA_freestyle_types.h" +#include "DNA_listBase.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_freestyle_types.h" -#include "DNA_listBase.h" - /** * Render-passes for EEVEE. * #ViewLayerEEVEE.render_passes @@ -115,6 +115,7 @@ typedef struct ViewLayer { ListBase object_bases; /** Default allocated now. */ struct SceneStats *stats; + char footer_str[128]; struct Base *basact; /** A view layer has one top level layer collection, because a scene has only one top level diff --git a/source/blender/makesdna/DNA_lightprobe_types.h b/source/blender/makesdna/DNA_lightprobe_types.h index 66d6e3f4868..5ddfedfed2d 100644 --- a/source/blender/makesdna/DNA_lightprobe_types.h +++ b/source/blender/makesdna/DNA_lightprobe_types.h @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 10a549edc17..357c3260121 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -324,35 +324,35 @@ enum { /* blend_shadow */ enum { MA_BS_NONE = 0, - MA_BS_SOLID, - MA_BS_CLIP, - MA_BS_HASHED, + MA_BS_SOLID = 1, + MA_BS_CLIP = 2, + MA_BS_HASHED = 3, }; /* Grease Pencil Stroke styles */ enum { GP_MATERIAL_STROKE_STYLE_SOLID = 0, - GP_MATERIAL_STROKE_STYLE_TEXTURE, + GP_MATERIAL_STROKE_STYLE_TEXTURE = 1, }; /* Grease Pencil Fill styles */ enum { GP_MATERIAL_FILL_STYLE_SOLID = 0, - GP_MATERIAL_FILL_STYLE_GRADIENT, - GP_MATERIAL_FILL_STYLE_CHECKER, /* DEPRECATED (only for convert old files) */ - GP_MATERIAL_FILL_STYLE_TEXTURE, + GP_MATERIAL_FILL_STYLE_GRADIENT = 1, + GP_MATERIAL_FILL_STYLE_CHECKER = 2, /* DEPRECATED (only for convert old files) */ + GP_MATERIAL_FILL_STYLE_TEXTURE = 3, }; /* Grease Pencil Gradient Types */ enum { GP_MATERIAL_GRADIENT_LINEAR = 0, - GP_MATERIAL_GRADIENT_RADIAL, + GP_MATERIAL_GRADIENT_RADIAL = 1, }; /* Grease Pencil Follow Drawing Modes */ enum { GP_MATERIAL_FOLLOW_PATH = 0, - GP_MATERIAL_FOLLOW_OBJ, - GP_MATERIAL_FOLLOW_FIXED, + GP_MATERIAL_FOLLOW_OBJ = 1, + GP_MATERIAL_FOLLOW_FIXED = 2, }; #endif diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 24e5aa496b9..972ef197954 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -94,6 +94,7 @@ typedef enum ModifierType { eModifierType_WeightedNormal = 54, eModifierType_Weld = 55, eModifierType_Fluid = 56, + eModifierType_Simulation = 57, NUM_MODIFIER_TYPES, } ModifierType; @@ -453,23 +454,23 @@ enum { /* BevelModifierData->face_str_mode */ enum { - MOD_BEVEL_FACE_STRENGTH_NONE, - MOD_BEVEL_FACE_STRENGTH_NEW, - MOD_BEVEL_FACE_STRENGTH_AFFECTED, - MOD_BEVEL_FACE_STRENGTH_ALL, + MOD_BEVEL_FACE_STRENGTH_NONE = 0, + MOD_BEVEL_FACE_STRENGTH_NEW = 1, + MOD_BEVEL_FACE_STRENGTH_AFFECTED = 2, + MOD_BEVEL_FACE_STRENGTH_ALL = 3, }; /* BevelModifier->miter_inner and ->miter_outer */ enum { - MOD_BEVEL_MITER_SHARP, - MOD_BEVEL_MITER_PATCH, - MOD_BEVEL_MITER_ARC, + MOD_BEVEL_MITER_SHARP = 0, + MOD_BEVEL_MITER_PATCH = 1, + MOD_BEVEL_MITER_ARC = 2, }; /* BevelModifier->vmesh_method */ enum { - MOD_BEVEL_VMESH_ADJ, - MOD_BEVEL_VMESH_CUTOFF, + MOD_BEVEL_VMESH_ADJ = 0, + MOD_BEVEL_VMESH_CUTOFF = 1, }; typedef struct FluidModifierData { @@ -595,10 +596,10 @@ enum { }; enum { - MOD_DECIM_MODE_COLLAPSE, - MOD_DECIM_MODE_UNSUBDIV, + MOD_DECIM_MODE_COLLAPSE = 0, + MOD_DECIM_MODE_UNSUBDIV = 1, /** called planar in the UI */ - MOD_DECIM_MODE_DISSOLVE, + MOD_DECIM_MODE_DISSOLVE = 2, }; typedef struct SmoothModifierData { @@ -1695,15 +1696,15 @@ enum { /* Triangulate methods - NGons */ enum { MOD_TRIANGULATE_NGON_BEAUTY = 0, - MOD_TRIANGULATE_NGON_EARCLIP, + MOD_TRIANGULATE_NGON_EARCLIP = 1, }; /* Triangulate methods - Quads */ enum { MOD_TRIANGULATE_QUAD_BEAUTY = 0, - MOD_TRIANGULATE_QUAD_FIXED, - MOD_TRIANGULATE_QUAD_ALTERNATE, - MOD_TRIANGULATE_QUAD_SHORTEDGE, + MOD_TRIANGULATE_QUAD_FIXED = 1, + MOD_TRIANGULATE_QUAD_ALTERNATE = 2, + MOD_TRIANGULATE_QUAD_SHORTEDGE = 3, }; typedef struct LaplacianSmoothModifierData { @@ -2118,6 +2119,13 @@ enum { #define MOD_MESHSEQ_READ_ALL \ (MOD_MESHSEQ_READ_VERT | MOD_MESHSEQ_READ_POLY | MOD_MESHSEQ_READ_UV | MOD_MESHSEQ_READ_COLOR) +typedef struct SimulationModifierData { + ModifierData modifier; + + struct Simulation *simulation; + char data_path[64]; +} SimulationModifierData; + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 557e069a4a6..94d11095108 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -24,14 +24,14 @@ #ifndef __DNA_MOVIECLIP_TYPES_H__ #define __DNA_MOVIECLIP_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_color_types.h" /* for color management */ #include "DNA_tracking_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct ImBuf; struct MovieClipProxy; diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 8029e8ebc13..4ff0e531168 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -154,6 +154,12 @@ typedef enum eNodeSocketDatatype { __SOCK_MESH = 5, /* deprecated */ SOCK_INT = 6, SOCK_STRING = 7, + SOCK_OBJECT = 8, + SOCK_IMAGE = 9, + SOCK_EMITTERS = 10, + SOCK_EVENTS = 11, + SOCK_FORCES = 12, + SOCK_CONTROL_FLOW = 13, } eNodeSocketDatatype; /* socket shape */ @@ -498,6 +504,7 @@ typedef struct bNodeTree { #define NTREE_SHADER 0 #define NTREE_COMPOSIT 1 #define NTREE_TEXTURE 2 +#define NTREE_SIMULATION 3 /* ntree->init, flag */ #define NTREE_TYPE_INIT 1 @@ -565,6 +572,14 @@ typedef struct bNodeSocketValueString { char value[1024]; } bNodeSocketValueString; +typedef struct bNodeSocketValueObject { + struct Object *value; +} bNodeSocketValueObject; + +typedef struct bNodeSocketValueImage { + struct Image *value; +} bNodeSocketValueImage; + /* data structs, for node->storage */ enum { CMP_NODE_MASKTYPE_ADD = 0, @@ -1293,6 +1308,23 @@ enum { NODE_VECTOR_MATH_TANGENT = 23, }; +/* Boolean math node operations. */ +enum { + NODE_BOOLEAN_MATH_AND = 0, + NODE_BOOLEAN_MATH_OR = 1, + NODE_BOOLEAN_MATH_NOT = 2, +}; + +/* Float compare node operations. */ +enum { + NODE_FLOAT_COMPARE_LESS_THAN = 0, + NODE_FLOAT_COMPARE_LESS_EQUAL = 1, + NODE_FLOAT_COMPARE_GREATER_THAN = 2, + NODE_FLOAT_COMPARE_GREATER_EQUAL = 3, + NODE_FLOAT_COMPARE_EQUAL = 4, + NODE_FLOAT_COMPARE_NOT_EQUAL = 5, +}; + /* Clamp node types. */ enum { NODE_CLAMP_MINMAX = 0, @@ -1385,4 +1417,16 @@ typedef enum NodeShaderOutputTarget { SHD_OUTPUT_CYCLES = 2, } NodeShaderOutputTarget; +/* Particle Time Step Event node */ +typedef enum NodeSimParticleTimeStepEventType { + NODE_PARTICLE_TIME_STEP_EVENT_BEGIN = 0, + NODE_PARTICLE_TIME_STEP_EVENT_END = 1, +} NodeSimParticleTimeStepEventType; + +/* Simulation Time node */ +typedef enum NodeSimInputTimeType { + NODE_SIM_INPUT_SIMULATION_TIME = 0, + NODE_SIM_INPUT_SCENE_TIME = 1, +} NodeSimInputTimeType; + #endif diff --git a/source/blender/makesdna/DNA_object_force_types.h b/source/blender/makesdna/DNA_object_force_types.h index 88c712b5b28..73cfcddf984 100644 --- a/source/blender/makesdna/DNA_object_force_types.h +++ b/source/blender/makesdna/DNA_object_force_types.h @@ -24,13 +24,13 @@ #ifndef __DNA_OBJECT_FORCE_TYPES_H__ #define __DNA_OBJECT_FORCE_TYPES_H__ +#include "DNA_defs.h" +#include "DNA_listBase.h" + #ifdef __cplusplus extern "C" { #endif -#include "DNA_defs.h" -#include "DNA_listBase.h" - /* pd->forcefield: Effector Fields types */ typedef enum ePFieldType { /** (this is used for general effector weight). */ @@ -62,6 +62,7 @@ typedef enum ePFieldType { /** Force based on smoke simulation air flow. */ PFIELD_SMOKEFLOW = 13, + /* Keep last. */ NUM_PFIELD_TYPES, } ePFieldType; diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 1a76d32dc2c..47e6db835c9 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -462,6 +462,7 @@ enum { OB_VOLUME = 29, + /* Keep last. */ OB_TYPE_MAX, }; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 2c931e68875..1533b82ad4e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -29,10 +29,6 @@ /* XXX, temp feature - campbell */ #define DURIAN_CAMERA_SWITCH -#ifdef __cplusplus -extern "C" { -#endif - #include "DNA_ID.h" #include "DNA_collection_types.h" #include "DNA_color_types.h" /* color management */ @@ -46,6 +42,10 @@ extern "C" { #include "DNA_vec_types.h" #include "DNA_view3d_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct AnimData; struct Brush; struct Collection; @@ -99,19 +99,19 @@ typedef struct AviCodecData { } AviCodecData; typedef enum eFFMpegPreset { - FFM_PRESET_NONE, + FFM_PRESET_NONE = 0, #ifdef DNA_DEPRECATED_ALLOW /* Previously used by h.264 to control encoding speed vs. file size. */ - FFM_PRESET_ULTRAFAST, /* DEPRECATED */ - FFM_PRESET_SUPERFAST, /* DEPRECATED */ - FFM_PRESET_VERYFAST, /* DEPRECATED */ - FFM_PRESET_FASTER, /* DEPRECATED */ - FFM_PRESET_FAST, /* DEPRECATED */ - FFM_PRESET_MEDIUM, /* DEPRECATED */ - FFM_PRESET_SLOW, /* DEPRECATED */ - FFM_PRESET_SLOWER, /* DEPRECATED */ - FFM_PRESET_VERYSLOW, /* DEPRECATED */ + FFM_PRESET_ULTRAFAST = 1, /* DEPRECATED */ + FFM_PRESET_SUPERFAST = 2, /* DEPRECATED */ + FFM_PRESET_VERYFAST = 3, /* DEPRECATED */ + FFM_PRESET_FASTER = 4, /* DEPRECATED */ + FFM_PRESET_FAST = 5, /* DEPRECATED */ + FFM_PRESET_MEDIUM = 6, /* DEPRECATED */ + FFM_PRESET_SLOW = 7, /* DEPRECATED */ + FFM_PRESET_SLOWER = 8, /* DEPRECATED */ + FFM_PRESET_VERYSLOW = 9, /* DEPRECATED */ #endif /* Used by WEBM/VP9 and h.264 to control encoding speed vs. file size. @@ -121,9 +121,9 @@ typedef enum eFFMpegPreset { /** the default and recommended for most applications */ FFM_PRESET_GOOD = 10, /** recommended if you have lots of time and want the best compression efficiency */ - FFM_PRESET_BEST, + FFM_PRESET_BEST = 11, /** recommended for live / fast encoding */ - FFM_PRESET_REALTIME, + FFM_PRESET_REALTIME = 12, } eFFMpegPreset; /* Mapping from easily-understandable descriptions to CRF values. @@ -2200,14 +2200,14 @@ typedef enum eSculptFlags { /* ImagePaintSettings.mode */ typedef enum eImagePaintMode { - IMAGEPAINT_MODE_MATERIAL, /* detect texture paint slots from the material */ - IMAGEPAINT_MODE_IMAGE, /* select texture paint image directly */ + IMAGEPAINT_MODE_MATERIAL = 0, /* detect texture paint slots from the material */ + IMAGEPAINT_MODE_IMAGE = 1, /* select texture paint image directly */ } eImagePaintMode; /* ImagePaintSettings.interp */ enum { IMAGEPAINT_INTERP_LINEAR = 0, - IMAGEPAINT_INTERP_CLOSEST, + IMAGEPAINT_INTERP_CLOSEST = 1, }; /* ImagePaintSettings.flag */ @@ -2307,17 +2307,17 @@ typedef enum eGPencil_Selectmode_types { /* ToolSettings.gpencil_guide_types */ typedef enum eGPencil_GuideTypes { GP_GUIDE_CIRCULAR = 0, - GP_GUIDE_RADIAL, - GP_GUIDE_PARALLEL, - GP_GUIDE_GRID, - GP_GUIDE_ISO, + GP_GUIDE_RADIAL = 1, + GP_GUIDE_PARALLEL = 2, + GP_GUIDE_GRID = 3, + GP_GUIDE_ISO = 4, } eGPencil_GuideTypes; /* ToolSettings.gpencil_guide_references */ typedef enum eGPencil_Guide_Reference { GP_GUIDE_REF_CURSOR = 0, - GP_GUIDE_REF_CUSTOM, - GP_GUIDE_REF_OBJECT, + GP_GUIDE_REF_CUSTOM = 1, + GP_GUIDE_REF_OBJECT = 2, } eGPencil_Guide_Reference; /* ToolSettings.particle flag */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 9a59b69604d..8497d363179 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -306,8 +306,8 @@ enum GlobalAreaFlag { }; typedef enum GlobalAreaAlign { - GLOBAL_AREA_ALIGN_TOP, - GLOBAL_AREA_ALIGN_BOTTOM, + GLOBAL_AREA_ALIGN_TOP = 0, + GLOBAL_AREA_ALIGN_BOTTOM = 1, } GlobalAreaAlign; typedef struct ScrArea_Runtime { diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h index 17b3528aadf..9fee839f979 100644 --- a/source/blender/makesdna/DNA_sequence_types.h +++ b/source/blender/makesdna/DNA_sequence_types.h @@ -468,6 +468,7 @@ typedef struct SequencerScopes { #define SEQ_SPEED_INTEGRATE (1 << 0) #define SEQ_SPEED_UNUSED_1 (1 << 1) /* cleared */ #define SEQ_SPEED_COMPRESS_IPO_Y (1 << 2) +#define SEQ_SPEED_USE_INTERPOLATION (1 << 3) /* ***************** SEQUENCE ****************** */ #define SEQ_NAME_MAXSTR 64 @@ -634,7 +635,7 @@ enum { seqModifierType_Mask = 5, seqModifierType_WhiteBalance = 6, seqModifierType_Tonemap = 7, - + /* Keep last. */ NUM_SEQUENCE_MODIFIER_TYPES, }; diff --git a/source/blender/makesdna/DNA_shader_fx_types.h b/source/blender/makesdna/DNA_shader_fx_types.h index e0931d8cac3..18a4e8655a3 100644 --- a/source/blender/makesdna/DNA_shader_fx_types.h +++ b/source/blender/makesdna/DNA_shader_fx_types.h @@ -42,6 +42,7 @@ typedef enum ShaderFxType { eShaderFxType_Colorize = 8, eShaderFxType_Shadow = 9, eShaderFxType_Glow = 10, + /* Keep last. */ NUM_SHADER_FX_TYPES, } ShaderFxType; diff --git a/source/blender/makesdna/DNA_simulation_defaults.h b/source/blender/makesdna/DNA_simulation_defaults.h new file mode 100644 index 00000000000..b4cecd861a9 --- /dev/null +++ b/source/blender/makesdna/DNA_simulation_defaults.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +/** \file + * \ingroup DNA + */ + +#ifndef __DNA_SIMULATION_DEFAULTS_H__ +#define __DNA_SIMULATION_DEFAULTS_H__ + +/* Struct members on own line. */ +/* clang-format off */ + +/* -------------------------------------------------------------------- */ +/** \name Simulation Struct + * \{ */ + +#define _DNA_DEFAULT_Simulation \ + { \ + .flag = 0, \ + } + +/** \} */ + +/* clang-format on */ + +#endif /* __DNA_SIMULATION_DEFAULTS_H__ */ diff --git a/source/blender/makesdna/DNA_simulation_types.h b/source/blender/makesdna/DNA_simulation_types.h new file mode 100644 index 00000000000..113c301bb9e --- /dev/null +++ b/source/blender/makesdna/DNA_simulation_types.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/** \file + * \ingroup DNA + */ + +#ifndef __DNA_SIMULATION_TYPES_H__ +#define __DNA_SIMULATION_TYPES_H__ + +#include "DNA_ID.h" + +typedef struct Simulation { + ID id; + struct AnimData *adt; /* animation data (must be immediately after id) */ + + struct bNodeTree *nodetree; + + int flag; + int _pad1[1]; +} Simulation; + +/* Simulation.flag */ +enum { + SIM_DS_EXPAND = (1 << 0), +}; + +#endif /* __DNA_SIMULATION_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 648d35c9a2d..8f4f066efbb 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -212,7 +212,7 @@ typedef enum eSpaceButtons_Context { BCONTEXT_SHADERFX = 15, BCONTEXT_OUTPUT = 16, - /* always as last... */ + /* Keep last. */ BCONTEXT_TOT, } eSpaceButtons_Context; @@ -1075,7 +1075,9 @@ typedef struct SpaceImage { int flag; char pixel_snap_mode; - char _pad2[3]; + char _pad2[7]; + + float uv_opacity; int tile_grid_shape[2]; @@ -1718,7 +1720,7 @@ typedef enum eSpace_Type { SPACE_TOPBAR = 21, SPACE_STATUSBAR = 22, - SPACE_TYPE_LAST = SPACE_STATUSBAR, +#define SPACE_TYPE_LAST SPACE_STATUSBAR } eSpace_Type; /* use for function args */ diff --git a/source/blender/makesdna/DNA_tracking_types.h b/source/blender/makesdna/DNA_tracking_types.h index ab9f3d07849..32a00cc25d1 100644 --- a/source/blender/makesdna/DNA_tracking_types.h +++ b/source/blender/makesdna/DNA_tracking_types.h @@ -70,6 +70,9 @@ typedef struct MovieTrackingCamera { /* Division distortion model coefficients */ float division_k1, division_k2; + + /* Nuke distortion model coefficients */ + float nuke_k1, nuke_k2; } MovieTrackingCamera; typedef struct MovieTrackingMarker { @@ -455,6 +458,7 @@ typedef struct MovieTracking { enum { TRACKING_DISTORTION_MODEL_POLYNOMIAL = 0, TRACKING_DISTORTION_MODEL_DIVISION = 1, + TRACKING_DISTORTION_MODEL_NUKE = 2, }; /* MovieTrackingCamera->units */ diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 7a09059e344..019e4c9ea9e 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -619,9 +619,8 @@ typedef struct UserDef_FileSpaceData { typedef struct UserDef_Experimental { char use_undo_legacy; - char use_menu_search; /** `makesdna` does not allow empty structs. */ - char _pad0[6]; + char _pad0[7]; } UserDef_Experimental; #define USER_EXPERIMENTAL_TEST(userdef, member) \ @@ -874,9 +873,11 @@ typedef struct UserDef { int sequencer_disk_cache_compression; /* eUserpref_DiskCacheCompression */ int sequencer_disk_cache_size_limit; short sequencer_disk_cache_flag; - char _pad5[2]; + float collection_instance_empty_size; + char _pad10[4]; + struct WalkNavigation walk_navigation; /** The UI for the user preferences. */ @@ -1290,8 +1291,8 @@ typedef enum eUserpref_RenderDisplayType { } eUserpref_RenderDisplayType; typedef enum eUserpref_TempSpaceDisplayType { - USER_TEMP_SPACE_DISPLAY_FULLSCREEN, - USER_TEMP_SPACE_DISPLAY_WINDOW, + USER_TEMP_SPACE_DISPLAY_FULLSCREEN = 0, + USER_TEMP_SPACE_DISPLAY_WINDOW = 1, } eUserpref_TempSpaceDisplayType; typedef enum eUserpref_EmulateMMBMod { diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 21def800e4a..e486730ebcf 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -489,6 +489,7 @@ enum { V3D_OVERLAY_HIDE_BONES = (1 << 8), V3D_OVERLAY_HIDE_OBJECT_XTRAS = (1 << 9), V3D_OVERLAY_HIDE_OBJECT_ORIGINS = (1 << 10), + V3D_OVERLAY_STATS = (1 << 11), }; /** #View3DOverlay.edit_flag */ diff --git a/source/blender/makesdna/DNA_volume_types.h b/source/blender/makesdna/DNA_volume_types.h index 1a49df86761..b3615e87a50 100644 --- a/source/blender/makesdna/DNA_volume_types.h +++ b/source/blender/makesdna/DNA_volume_types.h @@ -95,9 +95,9 @@ enum { /* Volume.sequence_mode */ typedef enum VolumeSequenceMode { VOLUME_SEQUENCE_CLIP = 0, - VOLUME_SEQUENCE_EXTEND, - VOLUME_SEQUENCE_REPEAT, - VOLUME_SEQUENCE_PING_PONG, + VOLUME_SEQUENCE_EXTEND = 1, + VOLUME_SEQUENCE_REPEAT = 2, + VOLUME_SEQUENCE_PING_PONG = 3, } VolumeSequenceMode; /* VolumeDisplay.wireframe_type */ diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index a101e96e958..1b0bf086269 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -146,6 +146,7 @@ set(SRC ../DNA_object_defaults.h ../DNA_pointcloud_defaults.h ../DNA_scene_defaults.h + ../DNA_simulation_defaults.h ../DNA_speaker_defaults.h ../DNA_texture_defaults.h ../DNA_vec_defaults.h diff --git a/source/blender/makesdna/intern/dna_defaults.c b/source/blender/makesdna/intern/dna_defaults.c index dadd2fd9d7d..2d86e97debf 100644 --- a/source/blender/makesdna/intern/dna_defaults.c +++ b/source/blender/makesdna/intern/dna_defaults.c @@ -71,6 +71,7 @@ #include "DNA_object_types.h" #include "DNA_pointcloud_types.h" #include "DNA_scene_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" #include "DNA_texture_types.h" @@ -93,6 +94,7 @@ #include "DNA_object_defaults.h" #include "DNA_pointcloud_defaults.h" #include "DNA_scene_defaults.h" +#include "DNA_simulation_defaults.h" #include "DNA_speaker_defaults.h" #include "DNA_texture_defaults.h" #include "DNA_volume_defaults.h" @@ -150,6 +152,9 @@ SDNA_DEFAULT_DECL_STRUCT(PointCloud); SDNA_DEFAULT_DECL_STRUCT(Scene); SDNA_DEFAULT_DECL_STRUCT(ToolSettings); +/* DNA_simulation_defaults.h */ +SDNA_DEFAULT_DECL_STRUCT(Simulation); + /* DNA_speaker_defaults.h */ SDNA_DEFAULT_DECL_STRUCT(Speaker); @@ -260,6 +265,9 @@ const void *DNA_default_table[SDNA_TYPE_MAX] = { SDNA_DEFAULT_DECL_EX(GP_Sculpt_Settings, ToolSettings.gp_sculpt), SDNA_DEFAULT_DECL_EX(GP_Sculpt_Guide, ToolSettings.gp_sculpt.guide), + /* DNA_simulation_defaults.h */ + SDNA_DEFAULT_DECL(Simulation), + /* DNA_speaker_defaults.h */ SDNA_DEFAULT_DECL(Speaker), diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index 39b26fef176..09cfe54e94d 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -136,6 +136,7 @@ static const char *includefiles[] = { "DNA_hair_types.h", "DNA_pointcloud_types.h", "DNA_volume_types.h", + "DNA_simulation_types.h", /* see comment above before editing! */ @@ -1073,8 +1074,8 @@ static int calculate_struct_sizes(int firststruct, FILE *file_verify, const char types_size_native[structtype] = size_native; types_size_32[structtype] = size_32; types_size_64[structtype] = size_64; - /* two ways to detect if a struct contains a pointer: - * has_pointer is set or size_native doesn't match any of 32/64bit lengths*/ + /* Two ways to detect if a struct contains a pointer: + * has_pointer is set or size_native doesn't match any of 32/64bit lengths. */ if (has_pointer || size_64 != size_native || size_32 != size_native) { if (size_64 % 8) { fprintf(stderr, @@ -1590,6 +1591,7 @@ int main(int argc, char **argv) #include "DNA_sdna_types.h" #include "DNA_sequence_types.h" #include "DNA_shader_fx_types.h" +#include "DNA_simulation_types.h" #include "DNA_sound_types.h" #include "DNA_space_types.h" #include "DNA_speaker_types.h" diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 31d1ed54fa1..d2e27bdbcad 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -259,6 +259,7 @@ extern StructRNA RNA_FreestyleLineStyle; extern StructRNA RNA_FreestyleModuleSettings; extern StructRNA RNA_FreestyleSettings; extern StructRNA RNA_Function; +extern StructRNA RNA_FunctionNode; extern StructRNA RNA_GPencilFrame; extern StructRNA RNA_GPencilInterpolateSettings; extern StructRNA RNA_GPencilLayer; @@ -548,6 +549,9 @@ extern StructRNA RNA_ShrinkwrapConstraint; extern StructRNA RNA_ShrinkwrapModifier; extern StructRNA RNA_SimpleDeformModifier; extern StructRNA RNA_SimplifyGpencilModifier; +extern StructRNA RNA_Simulation; +extern StructRNA RNA_SimulationNode; +extern StructRNA RNA_SimulationNodeTree; extern StructRNA RNA_SkinModifier; extern StructRNA RNA_SmoothGpencilModifier; extern StructRNA RNA_SmoothModifier; @@ -930,10 +934,6 @@ void RNA_property_update_main(struct Main *bmain, PropertyRNA *prop); bool RNA_property_update_check(struct PropertyRNA *prop); -void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop); -void RNA_property_update_cache_flush(struct Main *bmain, struct Scene *scene); -void RNA_property_update_cache_free(void); - /* Property Data */ bool RNA_property_boolean_get(PointerRNA *ptr, PropertyRNA *prop); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index fef98f9da4b..b6bae805636 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -23,6 +23,10 @@ #include "RNA_types.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bNodeSocketType; struct bNodeTreeType; struct bNodeType; @@ -191,6 +195,8 @@ extern const EnumPropertyItem rna_enum_node_socket_in_out_items[]; extern const EnumPropertyItem rna_enum_node_math_items[]; extern const EnumPropertyItem rna_enum_mapping_type_items[]; extern const EnumPropertyItem rna_enum_node_vec_math_items[]; +extern const EnumPropertyItem rna_enum_node_boolean_math_items[]; +extern const EnumPropertyItem rna_enum_node_float_compare_items[]; extern const EnumPropertyItem rna_enum_node_filter_items[]; extern const EnumPropertyItem rna_enum_node_map_range_items[]; extern const EnumPropertyItem rna_enum_node_clamp_items[]; @@ -315,4 +321,8 @@ const EnumPropertyItem *RNA_mask_local_itemf(struct bContext *C, /* Non confirming, utility function. */ const EnumPropertyItem *RNA_enum_node_tree_types_itemf_impl(struct bContext *C, bool *r_free); +#ifdef __cplusplus +} +#endif + #endif /* __RNA_ENUM_TYPES_H__ */ diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 64b7a3e70c1..cd05aba8794 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -103,6 +103,13 @@ if(WITH_NEW_OBJECT_TYPES) ) endif() +if (WITH_NEW_SIMULATION_TYPE) + list(APPEND DEFSRC + rna_simulation.c + ) +endif() + + set(APISRC rna_action_api.c rna_animation_api.c @@ -342,6 +349,11 @@ if(WITH_NEW_OBJECT_TYPES) add_definitions(-DWITH_NEW_OBJECT_TYPES) endif() +if (WITH_NEW_SIMULATION_TYPE) + add_definitions(-DWITH_NEW_SIMULATION_TYPE) +endif() + + # Build makesrna executable blender_include_dirs( . diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 46854bc6307..86a088f38ed 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -4302,6 +4302,9 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_screen.c", NULL, RNA_def_screen}, {"rna_sculpt_paint.c", NULL, RNA_def_sculpt_paint}, {"rna_sequencer.c", "rna_sequencer_api.c", RNA_def_sequencer}, +#ifdef WITH_NEW_SIMULATION_TYPE + {"rna_simulation.c", NULL, RNA_def_simulation}, +#endif {"rna_space.c", "rna_space_api.c", RNA_def_space}, {"rna_speaker.c", NULL, RNA_def_speaker}, {"rna_test.c", NULL, RNA_def_test}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 699ce0f041e..891c30af466 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -71,6 +71,9 @@ const EnumPropertyItem rna_enum_id_type_items[] = { {ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""}, {ID_LP, "LIGHT_PROBE", ICON_LIGHTPROBE_CUBEMAP, "Light Probe", ""}, {ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""}, +#ifdef WITH_NEW_SIMULATION_TYPE + {ID_SIM, "SIMULATION", ICON_PHYSICS, "Simulation", ""}, /* TODO: Use correct icon. */ +#endif {ID_SO, "SOUND", ICON_SOUND, "Sound", ""}, {ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""}, {ID_TXT, "TEXT", ICON_TEXT, "Text", ""}, @@ -303,6 +306,11 @@ short RNA_type_to_ID_code(const StructRNA *type) if (base_type == &RNA_Screen) { return ID_SCR; } +# ifdef WITH_NEW_SIMULATION_TYPE + if (base_type == &RNA_Simulation) { + return ID_SIM; + } +# endif if (base_type == &RNA_Sound) { return ID_SO; } @@ -405,6 +413,12 @@ StructRNA *ID_code_to_RNA_type(short idcode) return &RNA_Scene; case ID_SCR: return &RNA_Screen; + case ID_SIM: +# ifdef WITH_NEW_SIMULATION_TYPE + return &RNA_Simulation; +# else + return &RNA_ID; +# endif case ID_SO: return &RNA_Sound; case ID_SPK: diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index b56a18c18a9..85892758a88 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -98,8 +98,6 @@ void RNA_exit(void) { StructRNA *srna; - RNA_property_update_cache_free(); - for (srna = BLENDER_RNA.structs.first; srna; srna = srna->cont.next) { if (srna->cont.prophash) { BLI_ghash_free(srna->cont.prophash, NULL, NULL); @@ -2308,115 +2306,6 @@ void RNA_property_update_main(Main *bmain, Scene *scene, PointerRNA *ptr, Proper rna_property_update(NULL, bmain, scene, ptr, prop); } -/* RNA Updates Cache ------------------------ */ -/* Overview of RNA Update cache system: - * - * RNA Update calls need to be cached in order to maintain reasonable performance - * of the animation system (i.e. maintaining a somewhat interactive framerate) - * while still allowing updates to be called (necessary in particular for modifier - * property updates to actually work). - * - * The cache is structured with a dual-layer structure - * - L1 = PointerRNA used as key; owner_id is used (it should always be defined, - * and most updates end up using just that anyways) - * - L2 = Update functions to be called on those PointerRNA's - */ - -/* cache element */ -typedef struct tRnaUpdateCacheElem { - struct tRnaUpdateCacheElem *next, *prev; - - PointerRNA ptr; /* L1 key - id as primary, data secondary/ignored? */ - ListBase L2Funcs; /* L2 functions (LinkData<RnaUpdateFuncRef>) */ -} tRnaUpdateCacheElem; - -/* cache global (tRnaUpdateCacheElem's) - only accessible using these API calls */ -static ListBase rna_updates_cache = {NULL, NULL}; - -/* ........................... */ - -void RNA_property_update_cache_add(PointerRNA *ptr, PropertyRNA *prop) -{ - const bool is_rna = (prop->magic == RNA_MAGIC); - tRnaUpdateCacheElem *uce = NULL; - UpdateFunc fn = NULL; - LinkData *ld; - - /* sanity check */ - if (NULL == ptr) { - return; - } - - prop = rna_ensure_property(prop); - - /* we can only handle update calls with no context args for now (makes animsys updates easier) */ - if ((is_rna == false) || (prop->update == NULL) || (prop->flag & PROP_CONTEXT_UPDATE)) { - return; - } - fn = prop->update; - - /* find cache element for which key matches... */ - for (uce = rna_updates_cache.first; uce; uce = uce->next) { - /* Just match by id only for now, - * since most update calls that we'll encounter only really care about this. */ - /* TODO: later, the cache might need to have some nesting on L1 to cope better - * with these problems + some tagging to indicate we need this */ - if (uce->ptr.owner_id == ptr->owner_id) { - break; - } - } - if (uce == NULL) { - /* create new instance */ - uce = MEM_callocN(sizeof(tRnaUpdateCacheElem), "tRnaUpdateCacheElem"); - BLI_addtail(&rna_updates_cache, uce); - - /* copy pointer */ - RNA_pointer_create(ptr->owner_id, ptr->type, ptr->data, &uce->ptr); - } - - /* check on the update func */ - for (ld = uce->L2Funcs.first; ld; ld = ld->next) { - /* stop on match - function already cached */ - if (fn == ld->data) { - return; - } - } - /* else... if still here, we need to add it */ - BLI_addtail(&uce->L2Funcs, BLI_genericNodeN(fn)); -} - -void RNA_property_update_cache_flush(Main *bmain, Scene *scene) -{ - tRnaUpdateCacheElem *uce; - - /* TODO: should we check that bmain and scene are valid? The above stuff doesn't! */ - - /* execute the cached updates */ - for (uce = rna_updates_cache.first; uce; uce = uce->next) { - LinkData *ld; - - for (ld = uce->L2Funcs.first; ld; ld = ld->next) { - UpdateFunc fn = (UpdateFunc)ld->data; - fn(bmain, scene, &uce->ptr); - } - } -} - -void RNA_property_update_cache_free(void) -{ - tRnaUpdateCacheElem *uce, *ucn; - - for (uce = rna_updates_cache.first; uce; uce = ucn) { - ucn = uce->next; - - /* free L2 cache */ - BLI_freelistN(&uce->L2Funcs); - - /* remove self */ - BLI_freelinkN(&rna_updates_cache, uce); - } -} - /* ---------------------------------------------------------------------- */ /* Property Data */ @@ -5785,10 +5674,10 @@ static char *rna_idp_path(PointerRNA *ptr, } /** - * Find the path from the structure referenced by the pointer to the IDProperty object. + * Find the path from the structure referenced by the pointer to the #IDProperty object. * - * \param ptr Reference to the object owning the custom property storage. - * \param needle Custom property object to find. + * \param ptr: Reference to the object owning the custom property storage. + * \param needle: Custom property object to find. * \return Relative path or NULL. */ char *RNA_path_from_struct_to_idproperty(PointerRNA *ptr, IDProperty *needle) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index 2c4e221ca8c..d3b607fcb76 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -1296,6 +1296,48 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + prop = RNA_def_property(srna, "curve_random_pressure", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_pressure"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_strength", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_strength"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_uv", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_uv"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_hue", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_hue"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_saturation", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_saturation"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "curve_random_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "curve_rand_value"); + RNA_def_property_struct_type(prop, "CurveMapping"); + RNA_def_property_ui_text(prop, "Random Curve", "Curve used for modulating effect"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + /* fill threshold for transparence */ prop = RNA_def_property(srna, "fill_threshold", PROP_FLOAT, PROP_FACTOR); RNA_def_property_float_sdna(prop, NULL, "fill_threshold"); @@ -1434,6 +1476,30 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Vertex Color Factor", "Factor used to mix vertex color to get final color"); + /* Hue randomness. */ + prop = RNA_def_property(srna, "random_hue_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_hue"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Hue", "Random factor to modify original hue"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + + /* Saturation randomness. */ + prop = RNA_def_property(srna, "random_saturation_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_saturation"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Saturation", "Random factor to modify original saturation"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + + /* Value randomness. */ + prop = RNA_def_property(srna, "random_value_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "random_value"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Value", "Random factor to modify original value"); + RNA_def_parameter_clear_flags(prop, PROP_ANIMATABLE, 0); + /* Flags */ prop = RNA_def_property(srna, "use_pressure", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_USE_PRESSURE); @@ -1457,6 +1523,90 @@ static void rna_def_gpencil_options(BlenderRNA *brna) RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + prop = RNA_def_property(srna, "use_stroke_random_hue", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_HUE_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_sat", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_SAT_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_val", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_VAL_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_radius", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_PRESS_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_strength", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_STRENGTH_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_stroke_random_uv", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_UV_AT_STROKE); + RNA_def_property_ui_icon(prop, ICON_GP_SELECT_STROKES, 0); + RNA_def_property_ui_text(prop, "Stroke Random", "Use randomness at stroke level"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_hue", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_HUE_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_sat", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_SAT_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_val", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_VAL_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_radius", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_PRESSURE_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_strength", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_STRENGTH_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + + prop = RNA_def_property(srna, "use_random_press_uv", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag2", GP_BRUSH_USE_UV_RAND_PRESS); + RNA_def_property_ui_icon(prop, ICON_STYLUS_PRESSURE, 0); + RNA_def_property_ui_text(prop, "Use Pressure", "Use pressure to modulate randomness"); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, NULL); + prop = RNA_def_property(srna, "use_settings_stabilizer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BRUSH_STABILIZE_MOUSE); RNA_def_property_boolean_default(prop, true); diff --git a/source/blender/makesrna/intern/rna_cloth.c b/source/blender/makesrna/intern/rna_cloth.c index 1dae78b9efd..70f219259ef 100644 --- a/source/blender/makesrna/intern/rna_cloth.c +++ b/source/blender/makesrna/intern/rna_cloth.c @@ -63,7 +63,8 @@ static void rna_cloth_pinning_changed(Main *UNUSED(bmain), Scene *UNUSED(scene), { Object *ob = (Object *)ptr->owner_id; /* ClothSimSettings *settings = (ClothSimSettings *)ptr->data; */ - ClothModifierData *clmd = (ClothModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + ClothModifierData *clmd = (ClothModifierData *)BKE_modifiers_findby_type(ob, + eModifierType_Cloth); cloth_free_modifier(clmd); @@ -434,7 +435,7 @@ static void rna_ClothSettings_gravity_set(PointerRNA *ptr, const float *values) static char *rna_ClothSettings_path(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); if (md) { char name_esc[sizeof(md->name) * 2]; @@ -449,7 +450,7 @@ static char *rna_ClothSettings_path(PointerRNA *ptr) static char *rna_ClothCollisionSettings_path(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = modifiers_findByType(ob, eModifierType_Cloth); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Cloth); if (md) { char name_esc[sizeof(md->name) * 2]; diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c index 33f19153e3a..ea8b0cd758b 100644 --- a/source/blender/makesrna/intern/rna_fcurve.c +++ b/source/blender/makesrna/intern/rna_fcurve.c @@ -213,6 +213,7 @@ static StructRNA *rna_FModifierType_refine(struct PointerRNA *ptr) # include "BKE_anim_data.h" # include "BKE_fcurve.h" +# include "BKE_fcurve_driver.h" # include "DEG_depsgraph.h" # include "DEG_depsgraph_build.h" diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c index 03b57a496ef..fff39326ada 100644 --- a/source/blender/makesrna/intern/rna_fluid.c +++ b/source/blender/makesrna/intern/rna_fluid.c @@ -224,7 +224,7 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FLIP); /* Only create a particle system in liquid domain mode. */ @@ -249,7 +249,7 @@ static void rna_Fluid_spray_parts_update(Main *bmain, Scene *UNUSED(scene), Poin { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_SPRAY); if (ob->type == OB_MESH && !exists) { @@ -267,7 +267,7 @@ static void rna_Fluid_bubble_parts_update(Main *bmain, Scene *UNUSED(scene), Poi { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_BUBBLE); if (ob->type == OB_MESH && !exists) { @@ -289,7 +289,7 @@ static void rna_Fluid_foam_parts_update(Main *bmain, Scene *UNUSED(scene), Point { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FOAM); if (ob->type == OB_MESH && !exists) { @@ -307,7 +307,7 @@ static void rna_Fluid_tracer_parts_update(Main *bmain, Scene *UNUSED(scene), Poi { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_TRACER); if (ob->type == OB_MESH && !exists) { @@ -329,7 +329,7 @@ static void rna_Fluid_combined_export_update(Main *bmain, Scene *scene, PointerR { Object *ob = (Object *)ptr->owner_id; FluidModifierData *mmd; - mmd = (FluidModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (mmd->domain->sndparticle_combined_export == SNDPARTICLE_COMBINED_EXPORT_OFF) { rna_Fluid_parts_delete(ptr, PART_FLUID_SPRAYFOAM); @@ -515,7 +515,7 @@ static void rna_Fluid_guide_parent_set(struct PointerRNA *ptr, FluidModifierData *mmd_par = NULL; if (par != NULL) { - mmd_par = (FluidModifierData *)modifiers_findByType(par, eModifierType_Fluid); + mmd_par = (FluidModifierData *)BKE_modifiers_findby_type(par, eModifierType_Fluid); if (mmd_par && mmd_par->domain) { mds->guide_parent = value.data; copy_v3_v3_int(mds->guide_res, mmd_par->domain->res); @@ -2467,7 +2467,7 @@ static void rna_def_fluid_flow_settings(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Random", "Amount of random velocity"); RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, "rna_Fluid_flow_reset"); - prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_XYZ); + prop = RNA_def_property(srna, "velocity_coord", PROP_FLOAT, PROP_VELOCITY); RNA_def_property_float_sdna(prop, NULL, "vel_coord"); RNA_def_property_array(prop, 3); RNA_def_property_range(prop, -1000.1, 1000.1); diff --git a/source/blender/makesrna/intern/rna_gpencil.c b/source/blender/makesrna/intern/rna_gpencil.c index 1c9e9af3f62..33bf174be79 100644 --- a/source/blender/makesrna/intern/rna_gpencil.c +++ b/source/blender/makesrna/intern/rna_gpencil.c @@ -1664,13 +1664,11 @@ static void rna_def_gpencil_layer(BlenderRNA *brna) prop = RNA_def_property(srna, "use_mask_layer", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_MASK); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Mask Layer", "Mask pixels from underlying layers drawing"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); prop = RNA_def_property(srna, "use_lights", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_LAYER_USE_LIGHTS); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text( prop, "Use Lights", "Enable the use of lights on stroke and fill materials"); RNA_def_property_update(prop, NC_GPENCIL | ND_DATA, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_gpencil_modifier.c b/source/blender/makesrna/intern/rna_gpencil_modifier.c index 5475f62cb8c..3a8ded1a275 100644 --- a/source/blender/makesrna/intern/rna_gpencil_modifier.c +++ b/source/blender/makesrna/intern/rna_gpencil_modifier.c @@ -129,6 +129,11 @@ const EnumPropertyItem rna_enum_object_greasepencil_modifier_type_items[] = { "Opacity", "Opacity of the strokes"}, {eGpencilModifierType_Tint, "GP_TINT", ICON_MOD_TINT, "Tint", "Tint strokes with new color"}, + {eGpencilModifierType_Texture, + "GP_TEXTURE", + ICON_TEXTURE, + "Texture Mapping", + "Change stroke uv texture values"}, {0, NULL, 0, NULL, NULL}, }; @@ -234,6 +239,8 @@ static StructRNA *rna_GpencilModifier_refine(struct PointerRNA *ptr) return &RNA_ArmatureGpencilModifier; case eGpencilModifierType_Multiply: return &RNA_MultiplyGpencilModifier; + case eGpencilModifierType_Texture: + return &RNA_TextureGpencilModifier; /* Default */ case eGpencilModifierType_None: case NUM_GREASEPENCIL_MODIFIER_TYPES: @@ -302,6 +309,7 @@ RNA_GP_MOD_VGROUP_NAME_SET(Smooth, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Hook, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Offset, vgname); RNA_GP_MOD_VGROUP_NAME_SET(Armature, vgname); +RNA_GP_MOD_VGROUP_NAME_SET(Texture, vgname); # undef RNA_GP_MOD_VGROUP_NAME_SET @@ -434,9 +442,10 @@ static void rna_def_modifier_gpencilnoise(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -563,9 +572,10 @@ static void rna_def_modifier_gpencilsmooth(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -675,9 +685,10 @@ static void rna_def_modifier_gpencilsubdiv(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "level", PROP_INT, PROP_NONE); @@ -764,9 +775,10 @@ static void rna_def_modifier_gpencilsimplify(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR); @@ -852,9 +864,10 @@ static void rna_def_modifier_gpencilthick(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -946,9 +959,10 @@ static void rna_def_modifier_gpenciloffset(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -1043,9 +1057,10 @@ static void rna_def_modifier_gpenciltint(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -1248,9 +1263,10 @@ static void rna_def_modifier_gpencilcolor(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "hue", PROP_FLOAT, PROP_NONE); @@ -1341,9 +1357,10 @@ static void rna_def_modifier_gpencilopacity(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -1437,9 +1454,10 @@ static void rna_def_modifier_gpencilarray(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); @@ -1663,6 +1681,20 @@ static void rna_def_modifier_gpencilbuild(BlenderRNA *brna) prop, "Restrict Frame Range", "Only modify strokes during the specified frame range"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + /* Use percentage */ + prop = RNA_def_property(srna, "use_percentage", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_BUILD_PERCENTAGE); + RNA_def_property_ui_text( + prop, "Restrict Visible Points", "Use a percentage factor to determine the visible points"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + /* Percentage factor. */ + prop = RNA_def_property(srna, "percentage_factor", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "percentage_fac"); + RNA_def_property_ui_text(prop, "Factor", "Defines how much of the stroke is visible"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "start_frame"); RNA_def_property_ui_text( @@ -1715,9 +1747,10 @@ static void rna_def_modifier_gpencillattice(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -1794,9 +1827,10 @@ static void rna_def_modifier_gpencilmirror(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); @@ -1891,9 +1925,10 @@ static void rna_def_modifier_gpencilhook(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); @@ -2047,9 +2082,10 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Layer", "Layer name"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); - prop = RNA_def_property(srna, "material", PROP_STRING, PROP_NONE); - RNA_def_property_string_sdna(prop, NULL, "materialname"); - RNA_def_property_ui_text(prop, "Material", "Material name"); + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); @@ -2138,6 +2174,142 @@ static void rna_def_modifier_gpencilmultiply(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); } +static void rna_def_modifier_gpenciltexture(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + static const EnumPropertyItem fit_type_items[] = { + {GP_TEX_CONSTANT_LENGTH, + "CONSTANT_LENGTH", + 0, + "Keep Texture at Constant Length", + "Keep the texture at a constant length regardless of the length of each stroke"}, + {GP_TEX_FIT_STROKE, + "FIT_STROKE", + 0, + "Fit Texture to Stroke Length", + "Scale the texture to fit the length of each stroke"}, + {0, NULL, 0, NULL, NULL}, + }; + + static const EnumPropertyItem mode_items[] = { + {STROKE, "STROKE", 0, "Stroke", "Manipulate only stroke texture coordinates"}, + {FILL, "FILL", 0, "Fill", "Manipulate only fill texture coordinates"}, + {STROKE_AND_FILL, + "STROKE_AND_FILL", + 0, + "Stroke and Fill", + "Manipulate both stroke and fill texture coordinates"}, + {0, NULL, 0, NULL, NULL}, + }; + + srna = RNA_def_struct(brna, "TextureGpencilModifier", "GpencilModifier"); + RNA_def_struct_ui_text( + srna, "Texture Modifier", "Transform stroke texture coordinates Modifier"); + RNA_def_struct_sdna(srna, "TextureGpencilModifierData"); + RNA_def_struct_ui_icon(srna, ICON_TEXTURE); + + prop = RNA_def_property(srna, "layer", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "layername"); + RNA_def_property_ui_text(prop, "Layer", "Layer name"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_layers", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_LAYER); + RNA_def_property_ui_text(prop, "Inverse Layers", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "material", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK); + RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); + RNA_def_property_ui_text(prop, "Material", "Material used for filtering effect"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_materials", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_MATERIAL); + RNA_def_property_ui_text(prop, "Inverse Materials", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE); + RNA_def_property_string_sdna(prop, NULL, "vgname"); + RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name for modulating the deform"); + RNA_def_property_string_funcs(prop, NULL, NULL, "rna_TextureGpencilModifier_vgname_set"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_vertex", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_VGROUP); + RNA_def_property_ui_text(prop, "Inverse VertexGroup", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "pass_index", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "pass_index"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pass", "Pass index"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_material_pass", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_PASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "layer_pass", PROP_INT, PROP_NONE); + RNA_def_property_int_sdna(prop, NULL, "layer_pass"); + RNA_def_property_range(prop, 0, 100); + RNA_def_property_ui_text(prop, "Pass", "Layer pass index"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "invert_layer_pass", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", GP_TEX_INVERT_LAYERPASS); + RNA_def_property_ui_text(prop, "Inverse Pass", "Inverse filter"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "uv_offset", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "uv_offset"); + RNA_def_property_range(prop, -FLT_MAX, FLT_MAX); + RNA_def_property_ui_range(prop, -100.0, 100.0, 0.1, 3); + RNA_def_property_float_default(prop, 0.0f); + RNA_def_property_ui_text(prop, "Offset UVs", "Offset value to add to stroke UVs"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "uv_scale", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "uv_scale"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0.0, 100.0, 0.1, 3); + RNA_def_property_float_default(prop, 1.0f); + RNA_def_property_ui_text(prop, "UV Scale", "Factor to scale the UVs"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fill_rotation", PROP_FLOAT, PROP_ANGLE); + RNA_def_property_float_sdna(prop, NULL, "fill_rotation"); + RNA_def_property_ui_text(prop, "Fill Rotation", "Additional rotation of the fill UV"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fill_offset", PROP_FLOAT, PROP_COORDS); + RNA_def_property_float_sdna(prop, NULL, "fill_offset"); + RNA_def_property_array(prop, 2); + RNA_def_property_ui_text(prop, "Fill Offset", "Additional offset of the fill UV"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fill_scale", PROP_FLOAT, PROP_COORDS); + RNA_def_property_float_sdna(prop, NULL, "fill_scale"); + RNA_def_property_range(prop, 0.01f, 100.0f); + RNA_def_property_ui_text(prop, "Fill Scale", "Additional scale of the fill UV"); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_update"); + + prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "fit_method"); + RNA_def_property_enum_items(prop, fit_type_items); + RNA_def_property_ui_text(prop, "Fit Method", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "mode"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", ""); + RNA_def_property_update(prop, 0, "rna_GpencilModifier_dependency_update"); +} + void RNA_def_greasepencil_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -2211,6 +2383,7 @@ void RNA_def_greasepencil_modifier(BlenderRNA *brna) rna_def_modifier_gpencilhook(brna); rna_def_modifier_gpencilarmature(brna); rna_def_modifier_gpencilmultiply(brna); + rna_def_modifier_gpenciltexture(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h index 27097261930..cb59eee6afa 100644 --- a/source/blender/makesrna/intern/rna_internal.h +++ b/source/blender/makesrna/intern/rna_internal.h @@ -185,6 +185,7 @@ void RNA_def_render(struct BlenderRNA *brna); void RNA_def_rigidbody(struct BlenderRNA *brna); void RNA_def_rna(struct BlenderRNA *brna); void RNA_def_scene(struct BlenderRNA *brna); +void RNA_def_simulation(struct BlenderRNA *brna); void RNA_def_view_layer(struct BlenderRNA *brna); void RNA_def_screen(struct BlenderRNA *brna); void RNA_def_sculpt_paint(struct BlenderRNA *brna); @@ -449,6 +450,7 @@ void RNA_def_main_lightprobes(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_hairs(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_pointclouds(BlenderRNA *brna, PropertyRNA *cprop); void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop); +void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop); /* ID Properties */ diff --git a/source/blender/makesrna/intern/rna_main.c b/source/blender/makesrna/intern/rna_main.c index 855d5f46890..2f37e4079c7 100644 --- a/source/blender/makesrna/intern/rna_main.c +++ b/source/blender/makesrna/intern/rna_main.c @@ -134,6 +134,9 @@ RNA_MAIN_LISTBASE_FUNCS_DEF(pointclouds) RNA_MAIN_LISTBASE_FUNCS_DEF(scenes) RNA_MAIN_LISTBASE_FUNCS_DEF(screens) RNA_MAIN_LISTBASE_FUNCS_DEF(shapekeys) +# ifdef WITH_NEW_SIMULATION_TYPE +RNA_MAIN_LISTBASE_FUNCS_DEF(simulations) +# endif RNA_MAIN_LISTBASE_FUNCS_DEF(sounds) RNA_MAIN_LISTBASE_FUNCS_DEF(speakers) RNA_MAIN_LISTBASE_FUNCS_DEF(texts) @@ -402,6 +405,14 @@ void RNA_def_main(BlenderRNA *brna) "Volumes", "Volume data-blocks", RNA_def_main_volumes}, +# ifdef WITH_NEW_SIMULATION_TYPE + {"simulations", + "Simulation", + "rna_Main_simulations_begin", + "Simulations", + "Simulation data-blocks", + RNA_def_main_simulations}, +# endif {NULL, NULL, NULL, NULL, NULL, NULL}, }; diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index 9799054ccd2..c5781175d65 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -69,6 +69,7 @@ # include "BKE_particle.h" # include "BKE_pointcloud.h" # include "BKE_scene.h" +# include "BKE_simulation.h" # include "BKE_sound.h" # include "BKE_speaker.h" # include "BKE_text.h" @@ -98,6 +99,7 @@ # include "DNA_node_types.h" # include "DNA_particle_types.h" # include "DNA_pointcloud_types.h" +# include "DNA_simulation_types.h" # include "DNA_sound_types.h" # include "DNA_speaker_types.h" # include "DNA_text_types.h" @@ -738,6 +740,18 @@ static Volume *rna_Main_volumes_new(Main *bmain, const char *name) return volume; } +# ifdef WITH_NEW_SIMULATION_TYPE +static Simulation *rna_Main_simulations_new(Main *bmain, const char *name) +{ + char safe_name[MAX_ID_NAME - 2]; + rna_idname_validate(name, safe_name); + + Simulation *simulation = BKE_simulation_add(bmain, safe_name); + id_us_min(&simulation->id); + return simulation; +} +# endif + /* tag functions, all the same */ # define RNA_MAIN_ID_TAG_FUNCS_DEF(_func_name, _listbase_name, _id_type) \ static void rna_Main_##_func_name##_tag(Main *bmain, bool value) \ @@ -785,6 +799,9 @@ RNA_MAIN_ID_TAG_FUNCS_DEF(hairs, hairs, ID_HA) RNA_MAIN_ID_TAG_FUNCS_DEF(pointclouds, pointclouds, ID_PT) # endif RNA_MAIN_ID_TAG_FUNCS_DEF(volumes, volumes, ID_VO) +# ifdef WITH_NEW_SIMULATION_TYPE +RNA_MAIN_ID_TAG_FUNCS_DEF(simulations, simulations, ID_SIM) +# endif # undef RNA_MAIN_ID_TAG_FUNCS_DEF @@ -2304,4 +2321,44 @@ void RNA_def_main_volumes(BlenderRNA *brna, PropertyRNA *cprop) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); } +void RNA_def_main_simulations(BlenderRNA *brna, PropertyRNA *cprop) +{ + StructRNA *srna; + FunctionRNA *func; + PropertyRNA *parm; + + RNA_def_property_srna(cprop, "BlendDataSimulations"); + srna = RNA_def_struct(brna, "BlendDataSimulations", NULL); + RNA_def_struct_sdna(srna, "Main"); + RNA_def_struct_ui_text(srna, "Main Simulations", "Collection of simulations"); + + func = RNA_def_function(srna, "new", "rna_Main_simulations_new"); + RNA_def_function_ui_description(func, "Add a new simulation to the main database"); + parm = RNA_def_string(func, "name", "Simulation", 0, "", "New name for the data-block"); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); + /* return type */ + parm = RNA_def_pointer(func, "simulation", "Simulation", "", "New simulation data-block"); + RNA_def_function_return(func, parm); + + func = RNA_def_function(srna, "remove", "rna_Main_ID_remove"); + RNA_def_function_flag(func, FUNC_USE_REPORTS); + RNA_def_function_ui_description(func, "Remove a simulation from the current blendfile"); + parm = RNA_def_pointer(func, "simulation", "Simulation", "", "Simulation to remove"); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR); + RNA_def_parameter_clear_flags(parm, PROP_THICK_WRAP, 0); + RNA_def_boolean( + func, "do_unlink", true, "", "Unlink all usages of this simulation before deleting it"); + RNA_def_boolean(func, + "do_id_user", + true, + "", + "Decrement user counter of all datablocks used by this simulation data"); + RNA_def_boolean( + func, "do_ui_user", true, "", "Make sure interface does not reference this simulation data"); + + func = RNA_def_function(srna, "tag", "rna_Main_simulations_tag"); + parm = RNA_def_boolean(func, "value", 0, "Value", ""); + RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); +} + #endif diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 4dd8053218c..48e3c47208f 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -266,7 +266,7 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { ICON_MOD_WAVE, "Wave", "Adds a ripple-like motion to an object’s geometry"}, - {0, "", 0, N_("Simulate"), ""}, + {0, "", 0, N_("Physics"), ""}, {eModifierType_Cloth, "CLOTH", ICON_MOD_CLOTH, "Cloth", ""}, {eModifierType_Collision, "COLLISION", ICON_MOD_PHYSICS, "Collision", ""}, {eModifierType_DynamicPaint, "DYNAMIC_PAINT", ICON_MOD_DYNAMICPAINT, "Dynamic Paint", ""}, @@ -289,6 +289,13 @@ const EnumPropertyItem rna_enum_object_modifier_type_items[] = { "Spawn particles from the shape"}, {eModifierType_Softbody, "SOFT_BODY", ICON_MOD_SOFT, "Soft Body", ""}, {eModifierType_Surface, "SURFACE", ICON_MODIFIER, "Surface", ""}, +#ifdef WITH_NEW_SIMULATION_TYPE + {eModifierType_Simulation, + "SIMULATION", + ICON_PHYSICS, + "Simulation", + ""}, /* TODO: Use correct icon. */ +#endif {0, NULL, 0, NULL, NULL}, }; @@ -716,6 +723,8 @@ static StructRNA *rna_Modifier_refine(struct PointerRNA *ptr) return &RNA_SurfaceDeformModifier; case eModifierType_WeightedNormal: return &RNA_WeightedNormalModifier; + case eModifierType_Simulation: + return &RNA_SimulationModifier; /* Default */ case eModifierType_Fluidsim: /* deprecated */ case eModifierType_None: @@ -741,7 +750,7 @@ static void rna_Modifier_name_set(PointerRNA *ptr, const char *value) /* make sure the name is truly unique */ if (ptr->owner_id) { Object *ob = (Object *)ptr->owner_id; - modifier_unique_name(&ob->modifiers, md); + BKE_modifier_unique_name(&ob->modifiers, md); } /* fix all the animation data which may link to this */ @@ -920,7 +929,7 @@ static bool rna_HookModifier_object_override_apply(Main *UNUSED(bmain), { BLI_assert(len_dst == len_src && (!ptr_storage || len_dst == len_storage) && len_dst == 0); BLI_assert(opop->operation == IDOVERRIDE_LIBRARY_OP_REPLACE && - "Unsupported RNA override operation on Hook modifier target objet pointer"); + "Unsupported RNA override operation on Hook modifier target object pointer"); UNUSED_VARS_NDEBUG(ptr_storage, len_dst, len_src, len_storage, opop); /* We need a special handling here because setting hook target resets invert parent matrix, @@ -6552,6 +6561,29 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_Modifier_update"); } +static void rna_def_modifier_simulation_access(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "SimulationModifier", "Modifier"); + RNA_def_struct_ui_text(srna, "Simulation Modifier", ""); + RNA_def_struct_sdna(srna, "SimulationModifierData"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */ + +# ifdef WITH_NEW_SIMULATION_TYPE + prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE); + RNA_def_property_ui_text(prop, "Simulation", "Simulation to access"); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); +# endif + + prop = RNA_def_property(srna, "data_path", PROP_STRING, PROP_NONE); + RNA_def_property_ui_text( + prop, "Data Path", "Identifier of the simulation component that should be accessed"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); +} + void RNA_def_modifier(BlenderRNA *brna) { StructRNA *srna; @@ -6677,6 +6709,7 @@ void RNA_def_modifier(BlenderRNA *brna) rna_def_modifier_meshseqcache(brna); rna_def_modifier_surfacedeform(brna); rna_def_modifier_weightednormal(brna); + rna_def_modifier_simulation_access(brna); } #endif diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 5be3db37329..30d1380417f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -81,6 +81,35 @@ static const EnumPropertyItem node_socket_type_items[] = { {SOCK_STRING, "STRING", 0, "String", ""}, {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, {SOCK_SHADER, "SHADER", 0, "Shader", ""}, + {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, + {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, + {SOCK_EMITTERS, "EMITTERS", 0, "Emitters", ""}, + {SOCK_EVENTS, "EVENTS", 0, "Events", ""}, + {SOCK_FORCES, "FORCES", 0, "Forces", ""}, + {SOCK_CONTROL_FLOW, "CONTROL_FLOW", 0, "Control Flow", ""}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem particle_attribute_socket_type_items[] = { + {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, + {SOCK_INT, "INT", 0, "Int", ""}, + {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "RGBA", 0, "Color", ""}, + {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, + {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, + {0, NULL, 0, NULL, NULL}, +}; + +static const EnumPropertyItem node_socket_data_type_items[] = { + {SOCK_FLOAT, "FLOAT", 0, "Float", ""}, + {SOCK_INT, "INT", 0, "Int", ""}, + {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_STRING, "STRING", 0, "String", ""}, + {SOCK_RGBA, "RGBA", 0, "Color", ""}, + {SOCK_OBJECT, "OBJECT", 0, "Object", ""}, + {SOCK_IMAGE, "IMAGE", 0, "Image", ""}, {0, NULL, 0, NULL, NULL}, }; @@ -244,6 +273,47 @@ const EnumPropertyItem rna_enum_node_vec_math_items[] = { {0, NULL, 0, NULL, NULL}, }; +const EnumPropertyItem rna_enum_node_boolean_math_items[] = { + {NODE_BOOLEAN_MATH_AND, "AND", 0, "And", "Outputs true only when both inputs are true"}, + {NODE_BOOLEAN_MATH_OR, "OR", 0, "Or", "Outputs or when at least one of the inputs is true"}, + {NODE_BOOLEAN_MATH_NOT, "NOT", 0, "Not", "Outputs the opposite of the input"}, + {0, NULL, 0, NULL, NULL}, +}; + +const EnumPropertyItem rna_enum_node_float_compare_items[] = { + {NODE_FLOAT_COMPARE_LESS_THAN, + "LESS_THAN", + 0, + "A < B", + "True when the first input is smaller than second input"}, + {NODE_FLOAT_COMPARE_LESS_EQUAL, + "LESS_EQUAL", + 0, + "A <= B", + "True when the first input is smaller than the second input or equal"}, + {NODE_FLOAT_COMPARE_GREATER_THAN, + "GREATER_THAN", + 0, + "A > B", + "True when the first input is greater than the second input"}, + {NODE_FLOAT_COMPARE_GREATER_EQUAL, + "GREATER_EQUAL", + 0, + "A >= B", + "True when the first input is greater than the second input or equal"}, + {NODE_FLOAT_COMPARE_EQUAL, + "EQUAL", + 0, + "A = B", + "True when both inputs are approximately equal"}, + {NODE_FLOAT_COMPARE_NOT_EQUAL, + "NOT_EQUAL", + 0, + "A != B", + "True when both inputs are not approximately equal"}, + {0, NULL, 0, NULL, NULL}, +}; + const EnumPropertyItem rna_enum_node_map_range_items[] = { {NODE_MAP_RANGE_LINEAR, "LINEAR", @@ -669,6 +739,34 @@ static const EnumPropertyItem *rna_node_static_type_itemf(bContext *UNUSED(C), # undef DefNode } + if (RNA_struct_is_a(ptr->type, &RNA_SimulationNode)) { +# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ + if (STREQ(#Category, "SimulationNode")) { \ + tmp.value = ID; \ + tmp.identifier = EnumName; \ + tmp.name = UIName; \ + tmp.description = UIDesc; \ + tmp.icon = ICON_NONE; \ + RNA_enum_item_add(&item, &totitem, &tmp); \ + } +# include "../../nodes/NOD_static_types.h" +# undef DefNode + } + + if (RNA_struct_is_a(ptr->type, &RNA_FunctionNode)) { +# define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ + if (STREQ(#Category, "FunctionNode")) { \ + tmp.value = ID; \ + tmp.identifier = EnumName; \ + tmp.name = UIName; \ + tmp.description = UIDesc; \ + tmp.icon = ICON_NONE; \ + RNA_enum_item_add(&item, &totitem, &tmp); \ + } +# include "../../nodes/NOD_static_types.h" +# undef DefNode + } + RNA_enum_item_end(&item, &totitem); *r_free = true; @@ -1785,6 +1883,50 @@ static StructRNA *rna_TextureNode_register(Main *bmain, return nt->rna_ext.srna; } +static StructRNA *rna_SimulationNode_register(Main *bmain, + ReportList *reports, + void *data, + const char *identifier, + StructValidateFunc validate, + StructCallbackFunc call, + StructFreeFunc free) +{ + bNodeType *nt = rna_Node_register_base( + bmain, reports, &RNA_SimulationNode, data, identifier, validate, call, free); + if (!nt) { + return NULL; + } + + nodeRegisterType(nt); + + /* update while blender is running */ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + + return nt->rna_ext.srna; +} + +static StructRNA *rna_FunctionNode_register(Main *bmain, + ReportList *reports, + void *data, + const char *identifier, + StructValidateFunc validate, + StructCallbackFunc call, + StructFreeFunc free) +{ + bNodeType *nt = rna_Node_register_base( + bmain, reports, &RNA_FunctionNode, data, identifier, validate, call, free); + if (!nt) { + return NULL; + } + + nodeRegisterType(nt); + + /* update while blender is running */ + WM_main_add_notifier(NC_NODE | NA_EDITED, NULL); + + return nt->rna_ext.srna; +} + static IDProperty *rna_Node_idprops(PointerRNA *ptr, bool create) { bNode *node = ptr->data; @@ -3590,6 +3732,15 @@ static void rna_ShaderNode_socket_update(Main *bmain, Scene *scene, PointerRNA * rna_Node_update(bmain, scene, ptr); } +static void rna_FunctionNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA *ptr) { bNodeTree *ntree = (bNodeTree *)ptr->owner_id; @@ -3599,6 +3750,15 @@ static void rna_CompositorNodeScale_update(Main *bmain, Scene *scene, PointerRNA rna_Node_update(bmain, scene, ptr); } +static void rna_SimulationNode_socket_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->owner_id; + bNode *node = (bNode *)ptr->data; + + nodeUpdate(ntree, node); + rna_Node_update(bmain, scene, ptr); +} + static PointerRNA rna_ShaderNodePointDensity_psys_get(PointerRNA *ptr) { bNode *node = ptr->data; @@ -4025,6 +4185,39 @@ static void def_math(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +static void def_boolean_math(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_boolean_math_items); + RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update"); +} + +static void def_float_compare(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "operation", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, rna_enum_node_float_compare_items); + RNA_def_property_ui_text(prop, "Operation", ""); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update"); +} + +static void def_fn_switch(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, node_socket_data_type_items); + RNA_def_property_ui_text(prop, "Data Type", "Data type for inputs and outputs"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNode_socket_update"); +} + static void def_vector_math(StructRNA *srna) { PropertyRNA *prop; @@ -7908,6 +8101,82 @@ static void def_tex_bricks(StructRNA *srna) RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); } +/* -- Simulation Nodes --------------------------------------------------------- */ + +static void def_sim_particle_time_step_event(StructRNA *srna) +{ + static const EnumPropertyItem mode_items[] = { + {NODE_PARTICLE_TIME_STEP_EVENT_BEGIN, + "BEGIN", + 0, + "Begin", + "Execute for every particle at the beginning of each time step"}, + {NODE_PARTICLE_TIME_STEP_EVENT_END, + "END", + 0, + "End", + "Execute for every particle at the end of each time step"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "When in each time step is the event triggered"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); +} + +static void def_sim_particle_attribute(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, particle_attribute_socket_type_items); + RNA_def_property_ui_text( + prop, + "Data Type", + "Expected type of the attribute. A default value is returned if the type is not correct"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); +} + +static void def_sim_set_particle_attribute(StructRNA *srna) +{ + PropertyRNA *prop; + + prop = RNA_def_property(srna, "data_type", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, particle_attribute_socket_type_items); + RNA_def_property_ui_text( + prop, + "Data Type", + "Expected type of the attribute. Nothing is done if the type is not correct"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); +} + +static void def_sim_time(StructRNA *srna) +{ + static const EnumPropertyItem mode_items[] = { + {NODE_SIM_INPUT_SIMULATION_TIME, + "SIMULATION_TIME", + 0, + "Simulation Time", + "Time since start of simulation"}, + {NODE_SIM_INPUT_SCENE_TIME, "SCENE_TIME", 0, "Scene Time", "Time shown in the timeline"}, + {0, NULL, 0, NULL, NULL}, + }; + + PropertyRNA *prop; + + prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "custom1"); + RNA_def_property_enum_items(prop, mode_items); + RNA_def_property_ui_text(prop, "Mode", "The time to output"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_SimulationNode_socket_update"); +} + /* -------------------------------------------------------------------------- */ static void rna_def_shader_node(BlenderRNA *brna) @@ -7945,6 +8214,26 @@ static void rna_def_texture_node(BlenderRNA *brna) RNA_def_struct_register_funcs(srna, "rna_TextureNode_register", "rna_Node_unregister", NULL); } +static void rna_def_simulation_node(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "SimulationNode", "NodeInternal"); + RNA_def_struct_ui_text(srna, "Simulation Node", ""); + RNA_def_struct_sdna(srna, "bNode"); + RNA_def_struct_register_funcs(srna, "rna_SimulationNode_register", "rna_Node_unregister", NULL); +} + +static void rna_def_function_node(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "FunctionNode", "NodeInternal"); + RNA_def_struct_ui_text(srna, "Function Node", ""); + RNA_def_struct_sdna(srna, "bNode"); + RNA_def_struct_register_funcs(srna, "rna_FunctionNode_register", "rna_Node_unregister", NULL); +} + /* -------------------------------------------------------------------------- */ static void rna_def_node_socket(BlenderRNA *brna) @@ -8501,6 +8790,104 @@ static void rna_def_node_socket_virtual(BlenderRNA *brna, const char *identifier RNA_def_struct_sdna(srna, "bNodeSocket"); } +static void rna_def_node_socket_object(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "Object Node Socket", "Object socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); + + /* socket interface */ + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "Object Node Socket Interface", "Object socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueObject", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Object"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); +} + +static void rna_def_node_socket_image(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "Image Node Socket", "Image socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Image"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_update"); + RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE); + + /* socket interface */ + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "Image Node Socket Interface", "Image socket of a node"); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + RNA_def_struct_sdna_from(srna, "bNodeSocketValueImage", "default_value"); + + prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "value"); + RNA_def_property_struct_type(prop, "Image"); + RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update"); +} + +static void rna_def_node_socket_effector(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); +} + +static void rna_def_node_socket_control_flow(BlenderRNA *brna, + const char *identifier, + const char *interface_idname) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, identifier, "NodeSocketStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); + + srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard"); + RNA_def_struct_ui_text(srna, "", ""); + RNA_def_struct_sdna(srna, "bNodeSocket"); +} + static void rna_def_node_socket_standard_types(BlenderRNA *brna) { /* XXX Workaround: Registered functions are not exposed in python by bpy, @@ -8635,6 +9022,17 @@ static void rna_def_node_socket_standard_types(BlenderRNA *brna) rna_def_node_socket_shader(brna, "NodeSocketShader", "NodeSocketInterfaceShader"); rna_def_node_socket_virtual(brna, "NodeSocketVirtual"); + + rna_def_node_socket_object(brna, "NodeSocketObject", "NodeSocketInterfaceObject"); + + rna_def_node_socket_image(brna, "NodeSocketImage", "NodeSocketInterfaceImage"); + + rna_def_node_socket_effector(brna, "NodeSocketEmitters", "NodeSocketInterfaceEmitters"); + rna_def_node_socket_effector(brna, "NodeSocketEvents", "NodeSocketInterfaceEvents"); + rna_def_node_socket_effector(brna, "NodeSocketForces", "NodeSocketInterfaceForces"); + + rna_def_node_socket_control_flow( + brna, "NodeSocketControlFlow", "NodeSocketInterfaceControlFlow"); } static void rna_def_internal_node(BlenderRNA *brna) @@ -9260,6 +9658,7 @@ static void rna_def_nodetree(BlenderRNA *brna) {NTREE_SHADER, "SHADER", ICON_MATERIAL, "Shader", "Shader nodes"}, {NTREE_TEXTURE, "TEXTURE", ICON_TEXTURE, "Texture", "Texture nodes"}, {NTREE_COMPOSIT, "COMPOSITING", ICON_RENDERLAYERS, "Compositing", "Compositing nodes"}, + {NTREE_SIMULATION, "SIMULATION", ICON_PHYSICS, "Simulation", "Simulation nodes"}, {0, NULL, 0, NULL, NULL}, }; @@ -9483,6 +9882,17 @@ static void rna_def_texture_nodetree(BlenderRNA *brna) RNA_def_struct_ui_icon(srna, ICON_TEXTURE); } +static void rna_def_simulation_nodetree(BlenderRNA *brna) +{ + StructRNA *srna; + + srna = RNA_def_struct(brna, "SimulationNodeTree", "NodeTree"); + RNA_def_struct_ui_text( + srna, "Simulation Node Tree", "Node tree consisting of linked nodes used for simulations"); + RNA_def_struct_sdna(srna, "bNodeTree"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */ +} + static StructRNA *define_specific_node(BlenderRNA *brna, const char *struct_name, const char *base_name, @@ -9569,6 +9979,8 @@ void RNA_def_nodetree(BlenderRNA *brna) rna_def_shader_node(brna); rna_def_compositor_node(brna); rna_def_texture_node(brna); + rna_def_simulation_node(brna); + rna_def_function_node(brna); rna_def_nodetree(brna); @@ -9577,6 +9989,7 @@ void RNA_def_nodetree(BlenderRNA *brna) rna_def_composite_nodetree(brna); rna_def_shader_nodetree(brna); rna_def_texture_nodetree(brna); + rna_def_simulation_nodetree(brna); # define DefNode(Category, ID, DefFunc, EnumName, StructName, UIName, UIDesc) \ { \ @@ -9593,12 +10006,13 @@ void RNA_def_nodetree(BlenderRNA *brna) */ # include "../../nodes/NOD_static_types.h" - /* Node group types need to be defined for shader, compositor, texture nodes individually. - * Cannot use the static types header for this, since they share the same int id. + /* Node group types need to be defined for shader, compositor, texture, simulation nodes + * individually. Cannot use the static types header for this, since they share the same int id. */ define_specific_node(brna, "ShaderNodeGroup", "ShaderNode", "Group", "", def_group); define_specific_node(brna, "CompositorNodeGroup", "CompositorNode", "Group", "", def_group); define_specific_node(brna, "TextureNodeGroup", "TextureNode", "Group", "", def_group); + define_specific_node(brna, "SimulationNodeGroup", "SimulationNode", "Group", "", def_group); def_custom_group(brna, "ShaderNodeCustomGroup", "ShaderNode", diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 33048d4b057..c2ee256ad58 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1638,7 +1638,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain, return false; } - /* While it would be nicer to use lower-level modifier_new() here, this one is lacking + /* While it would be nicer to use lower-level BKE_modifier_new() here, this one is lacking * special-cases handling (particles and other physics modifiers mostly), so using the ED version * instead, to avoid duplicating code. */ ModifierData *mod_dst = ED_object_modifier_add( @@ -1653,7 +1653,7 @@ bool rna_Object_modifiers_override_apply(Main *bmain, ParticleSystem *psys_dst = (mod_dst->type == eModifierType_ParticleSystem) ? ((ParticleSystemModifierData *)mod_dst)->psys : NULL; - modifier_copyData(mod_src, mod_dst); + BKE_modifier_copydata(mod_src, mod_dst); if (mod_dst->type == eModifierType_ParticleSystem) { psys_dst->flag &= ~PSYS_DELETE; ((ParticleSystemModifierData *)mod_dst)->psys = psys_dst; @@ -1745,7 +1745,7 @@ bool rna_Object_greasepencil_modifiers_override_apply(Main *bmain, return false; } - /* While it would be nicer to use lower-level modifier_new() here, this one is lacking + /* While it would be nicer to use lower-level BKE_modifier_new() here, this one is lacking * special-cases handling (particles and other physics modifiers mostly), so using the ED version * instead, to avoid duplicating code. */ GpencilModifierData *mod_dst = ED_object_gpencil_modifier_add( @@ -3204,7 +3204,6 @@ static void rna_def_object(BlenderRNA *brna) prop = RNA_def_property(srna, "use_grease_pencil_lights", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "dtx", OB_USE_GPENCIL_LIGHTS); RNA_def_property_boolean_default(prop, true); - RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_ui_text(prop, "Use Lights", "Lights affect grease pencil object"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_GPencil_update"); diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c index bc8f6d4e3ae..2c9bdd31141 100644 --- a/source/blender/makesrna/intern/rna_object_api.c +++ b/source/blender/makesrna/intern/rna_object_api.c @@ -36,7 +36,7 @@ #include "DNA_modifier_types.h" #include "DNA_object_types.h" -#include "BKE_gpencil_geom.h" +#include "BKE_gpencil_curve.h" #include "BKE_layer.h" #include "DEG_depsgraph.h" @@ -951,7 +951,7 @@ void RNA_api_object(StructRNA *srna) RNA_def_function_ui_description(func, "Clears mesh data-block created by to_mesh()"); /* Armature */ - func = RNA_def_function(srna, "find_armature", "modifiers_isDeformedByArmature"); + func = RNA_def_function(srna, "find_armature", "BKE_modifiers_is_deformed_by_armature"); RNA_def_function_ui_description( func, "Find armature influencing this object as a parent or via a modifier"); parm = RNA_def_pointer( diff --git a/source/blender/makesrna/intern/rna_object_force.c b/source/blender/makesrna/intern/rna_object_force.c index 4a34d1465dd..e79c186aae4 100644 --- a/source/blender/makesrna/intern/rna_object_force.c +++ b/source/blender/makesrna/intern/rna_object_force.c @@ -145,7 +145,7 @@ static char *rna_PointCache_path(PointerRNA *ptr) PointCache *cache = ptr->data; for (md = ob->modifiers.first; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + const ModifierTypeInfo *mti = BKE_modifier_get_info(md->type); if (!(mti->flags & eModifierTypeFlag_UsesPointCache)) { continue; @@ -430,7 +430,7 @@ static char *rna_CollisionSettings_path(PointerRNA *UNUSED(ptr)) /* both methods work ok, but return the shorter path */ # if 0 Object *ob = (Object *)ptr->owner_id; - ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Collision); + ModifierData *md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Collision); if (md) { char name_esc[sizeof(md->name) * 2]; @@ -604,7 +604,7 @@ static void rna_SoftBodySettings_spring_vgroup_set(PointerRNA *ptr, const char * static char *rna_SoftBodySettings_path(PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody); + ModifierData *md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Softbody); char name_esc[sizeof(md->name) * 2]; BLI_strescape(name_esc, md->name, sizeof(name_esc)); @@ -780,7 +780,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) ModifierData *md; /* check softbody modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_Softbody); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Softbody); if (md) { /* no pointer from modifier data to actual softbody storage, would be good to add */ if (ob->soft->effector_weights == ew) { @@ -791,7 +791,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) } /* check cloth modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_Cloth); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Cloth); if (md) { ClothModifierData *cmd = (ClothModifierData *)md; if (cmd->sim_parms->effector_weights == ew) { @@ -802,7 +802,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) } /* check smoke modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_Fluid); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid); if (md) { FluidModifierData *mmd = (FluidModifierData *)md; if (mmd->domain->effector_weights == ew) { @@ -813,7 +813,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) } /* check dynamic paint modifier */ - md = (ModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint); + md = (ModifierData *)BKE_modifiers_findby_type(ob, eModifierType_DynamicPaint); if (md) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; @@ -843,7 +843,7 @@ static char *rna_EffectorWeight_path(PointerRNA *ptr) static void rna_CollisionSettings_dependency_update(Main *bmain, Scene *scene, PointerRNA *ptr) { Object *ob = (Object *)ptr->owner_id; - ModifierData *md = modifiers_findByType(ob, eModifierType_Collision); + ModifierData *md = BKE_modifiers_findby_type(ob, eModifierType_Collision); /* add/remove modifier as needed */ if (ob->pd->deflect && !md) { diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index c1fb3232bb3..73b3515030e 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -827,7 +827,7 @@ static void rna_Particle_hair_dynamics_update(Main *bmain, Scene *scene, Pointer ParticleSystem *psys = (ParticleSystem *)ptr->data; if (psys && !psys->clmd) { - psys->clmd = (ClothModifierData *)modifier_new(eModifierType_Cloth); + psys->clmd = (ClothModifierData *)BKE_modifier_new(eModifierType_Cloth); psys->clmd->sim_parms->goalspring = 0.0f; psys->clmd->sim_parms->flags |= CLOTH_SIMSETTINGS_FLAG_RESIST_SPRING_COMPRESS; psys->clmd->coll_parms->flags &= ~CLOTH_COLLSETTINGS_FLAG_SELF; diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b16eb17747b..6423175e2f4 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -924,11 +924,11 @@ static void rna_Scene_volume_update(Main *UNUSED(bmain), Scene *UNUSED(scene), P DEG_id_tag_update(&scene->id, ID_RECALC_AUDIO_VOLUME | ID_RECALC_SEQUENCER_STRIPS); } -static const char *rna_Scene_statistics_string_get(Scene *scene, - Main *bmain, +static const char *rna_Scene_statistics_string_get(Scene *UNUSED(scene), + Main *UNUSED(bmain), ViewLayer *view_layer) { - return ED_info_stats_string(bmain, scene, view_layer); + return ED_info_footer_string(view_layer); } static void rna_Scene_framelen_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *UNUSED(ptr)) @@ -5723,6 +5723,16 @@ static void rna_def_scene_render_data(BlenderRNA *brna) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem meta_input_items[] = { + {0, "SCENE", 0, "Scene", "Use metadata from the current scene"}, + {R_STAMP_STRIPMETA, + "STRIPS", + 0, + "Sequencer Strips", + "Use metadata from the strips in the sequencer"}, + {0, NULL, 0, NULL, NULL}, + }; + rna_def_scene_ffmpeg_settings(brna); srna = RNA_def_struct(brna, "RenderSettings", NULL); @@ -6240,10 +6250,10 @@ static void rna_def_scene_render_data(BlenderRNA *brna) prop, "Stamp Labels", "Display stamp labels (\"Camera\" in front of camera name, etc.)"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); - prop = RNA_def_property(srna, "use_stamp_strip_meta", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "stamp", R_STAMP_STRIPMETA); - RNA_def_property_ui_text( - prop, "Strip Metadata", "Use metadata from the strips in the sequencer"); + prop = RNA_def_property(srna, "metadata_input", PROP_ENUM, PROP_NONE); /* as an enum */ + RNA_def_property_enum_bitflag_sdna(prop, NULL, "stamp"); + RNA_def_property_enum_items(prop, meta_input_items); + RNA_def_property_ui_text(prop, "Metadata Input", "Where to take the metadata from"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); prop = RNA_def_property(srna, "use_stamp_memory", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index d218084fc66..fd8ddfff14f 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -2020,9 +2020,10 @@ static void rna_def_editor(BlenderRNA *brna) prop = RNA_def_property(srna, "use_prefetch", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cache_flag", SEQ_CACHE_PREFETCH_ENABLE); - RNA_def_property_ui_text(prop, - "Prefetch frames", - "Render frames ahead of playhead in background for faster playback"); + RNA_def_property_ui_text( + prop, + "Prefetch Frames", + "Render frames ahead of playhead in the background for faster playback"); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL); prop = RNA_def_property(srna, "recycle_max_cost", PROP_FLOAT, PROP_NONE); @@ -2760,6 +2761,13 @@ static void rna_def_speed_control(StructRNA *srna) prop, "Scale to Length", "Scale values from 0.0 to 1.0 to target sequence length"); RNA_def_property_update( prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); + + prop = RNA_def_property(srna, "frame_interpolation_mode", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flags", SEQ_SPEED_USE_INTERPOLATION); + RNA_def_property_ui_text( + prop, "Frame interpolation", "Do crossfade blending between current and next frame"); + RNA_def_property_update( + prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_invalidate_preprocessed_update"); } static void rna_def_gaussian_blur(StructRNA *srna) diff --git a/source/blender/makesrna/intern/rna_simulation.c b/source/blender/makesrna/intern/rna_simulation.c new file mode 100644 index 00000000000..789ea299feb --- /dev/null +++ b/source/blender/makesrna/intern/rna_simulation.c @@ -0,0 +1,56 @@ +/* + * 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. + */ + +/** \file + * \ingroup RNA + */ + +#include <stdlib.h> + +#include "RNA_define.h" +#include "RNA_enum_types.h" + +#include "DNA_simulation_types.h" + +#include "rna_internal.h" + +#ifdef RNA_RUNTIME + +#else + +static void rna_def_simulation(BlenderRNA *brna) +{ + StructRNA *srna; + PropertyRNA *prop; + + srna = RNA_def_struct(brna, "Simulation", "ID"); + RNA_def_struct_ui_text(srna, "Simulation", "Simulation data-block"); + RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */ + + prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE); + RNA_def_property_pointer_sdna(prop, NULL, "nodetree"); + RNA_def_property_ui_text(prop, "Node Tree", "Node tree defining the simulation"); + + /* common */ + rna_def_animdata_common(srna); +} + +void RNA_def_simulation(BlenderRNA *brna) +{ + rna_def_simulation(brna); +} + +#endif diff --git a/source/blender/makesrna/intern/rna_sound_api.c b/source/blender/makesrna/intern/rna_sound_api.c index 2be0ed966f1..418205426d2 100644 --- a/source/blender/makesrna/intern/rna_sound_api.c +++ b/source/blender/makesrna/intern/rna_sound_api.c @@ -10,7 +10,7 @@ * 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, + * 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) 2015 by the Blender Foundation. diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index d4d35e07c2a..181d4529ef1 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -45,6 +45,7 @@ #include "DNA_node_types.h" #include "DNA_object_types.h" #include "DNA_sequence_types.h" +#include "DNA_simulation_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_workspace_types.h" @@ -531,7 +532,7 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) { SpaceLink *space = (SpaceLink *)ptr->data; - switch (space->spacetype) { + switch ((eSpace_Type)space->spacetype) { case SPACE_VIEW3D: return &RNA_SpaceView3D; case SPACE_GRAPH: @@ -562,9 +563,16 @@ static StructRNA *rna_Space_refine(struct PointerRNA *ptr) return &RNA_SpacePreferences; case SPACE_CLIP: return &RNA_SpaceClipEditor; - default: - return &RNA_Space; + + /* Currently no type info. */ + case SPACE_SCRIPT: + case SPACE_EMPTY: + case SPACE_TOPBAR: + case SPACE_STATUSBAR: + break; } + + return &RNA_Space; } static ScrArea *rna_area_from_space(PointerRNA *ptr) @@ -2166,6 +2174,40 @@ static void rna_SpaceNodeEditor_node_tree_update(const bContext *C, PointerRNA * ED_node_tree_update(C); } +# ifdef WITH_NEW_SIMULATION_TYPE +static PointerRNA rna_SpaceNodeEditor_simulation_get(PointerRNA *ptr) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + ID *id = snode->id; + if (id && GS(id->name) == ID_SIM) { + return rna_pointer_inherit_refine(ptr, &RNA_Simulation, snode->id); + } + else { + return PointerRNA_NULL; + } +} + +static void rna_SpaceNodeEditor_simulation_set(PointerRNA *ptr, + const PointerRNA value, + struct ReportList *UNUSED(reports)) +{ + SpaceNode *snode = (SpaceNode *)ptr->data; + if (!STREQ(snode->tree_idname, "SimulationNodeTree")) { + return; + } + + Simulation *sim = (Simulation *)value.data; + if (sim != NULL) { + bNodeTree *ntree = sim->nodetree; + ED_node_tree_start(snode, ntree, NULL, NULL); + } + else { + ED_node_tree_start(snode, NULL, NULL, NULL); + } + snode->id = &sim->id; +} +# endif + static int rna_SpaceNodeEditor_tree_type_get(PointerRNA *ptr) { SpaceNode *snode = (SpaceNode *)ptr->data; @@ -2935,6 +2977,12 @@ static void rna_def_space_image_uv(BlenderRNA *brna) prop, "Tile Grid Shape", "How many tiles will be shown in the background"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + prop = RNA_def_property(srna, "uv_opacity", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_float_sdna(prop, NULL, "uv_opacity"); + RNA_def_property_range(prop, 0.0f, 1.0f); + RNA_def_property_ui_text(prop, "UV Opacity", "Opacity of UV overlays"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_IMAGE, NULL); + /* todo: move edge and face drawing options here from G.f */ prop = RNA_def_property(srna, "pixel_snap_mode", PROP_ENUM, PROP_NONE); @@ -3563,6 +3611,11 @@ static void rna_def_space_view3d_overlay(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Show Text", "Display overlay text"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_stats", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "overlay.flag", V3D_OVERLAY_STATS); + RNA_def_property_ui_text(prop, "Show Statistics", "Display scene statistics overlay text"); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); + prop = RNA_def_property(srna, "show_extras", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna( prop, NULL, "overlay.flag", V3D_OVERLAY_HIDE_OBJECT_XTRAS); @@ -5521,6 +5574,13 @@ static void rna_def_fileselect_idfilter(BlenderRNA *brna) "Show/hide Point Cloud data-blocks"}, # endif {FILTER_ID_SCE, "filter_scene", ICON_SCENE_DATA, "Scenes", "Show Scene data-blocks"}, +# ifdef WITH_NEW_SIMULATION_TYPE + {FILTER_ID_SIM, + "filter_simulation", + ICON_PHYSICS, + "Simulations", + "Show Simulation data-blocks"}, /* TODO: Use correct icon. */ +# endif {FILTER_ID_SPK, "filter_speaker", ICON_SPEAKER, "Speakers", "Show Speaker data-blocks"}, {FILTER_ID_SO, "filter_sound", ICON_SOUND, "Sounds", "Show Sound data-blocks"}, {FILTER_ID_TE, "filter_texture", ICON_TEXTURE_DATA, "Textures", "Show Texture data-blocks"}, @@ -6202,6 +6262,19 @@ static void rna_def_space_node(BlenderRNA *brna) RNA_def_property_ui_text( prop, "ID From", "Data-block from which the edited data-block is linked"); +# ifdef WITH_NEW_SIMULATION_TYPE + prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE); + RNA_def_property_flag(prop, PROP_EDITABLE); + RNA_def_property_struct_type(prop, "Simulation"); + RNA_def_property_ui_text(prop, "Simulation", "Simulation that is being edited"); + RNA_def_property_pointer_funcs(prop, + "rna_SpaceNodeEditor_simulation_get", + "rna_SpaceNodeEditor_simulation_set", + NULL, + NULL); + RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL); +# endif + prop = RNA_def_property(srna, "path", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "treepath", NULL); RNA_def_property_struct_type(prop, "NodeTreePath"); diff --git a/source/blender/makesrna/intern/rna_tracking.c b/source/blender/makesrna/intern/rna_tracking.c index 131c13c4d90..507d06482df 100644 --- a/source/blender/makesrna/intern/rna_tracking.c +++ b/source/blender/makesrna/intern/rna_tracking.c @@ -1149,6 +1149,7 @@ static void rna_def_trackingCamera(BlenderRNA *brna) "Divisions", "Division distortion model which " "better represents wide-angle cameras"}, + {TRACKING_DISTORTION_MODEL_NUKE, "NUKE", 0, "Nuke", "Nuke distortion model"}, {0, NULL, 0, NULL, NULL}, }; @@ -1252,6 +1253,19 @@ static void rna_def_trackingCamera(BlenderRNA *brna) RNA_def_property_ui_text(prop, "K2", "First coefficient of second order division distortion"); RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); + /* Nuke distortion parameters */ + prop = RNA_def_property(srna, "nuke_k1", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_range(prop, -10, 10, 0.1, 3); + RNA_def_property_ui_text(prop, "K1", "First coefficient of second order Nuke distortion"); + RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); + + prop = RNA_def_property(srna, "nuke_k2", PROP_FLOAT, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_ui_range(prop, -10, 10, 0.1, 3); + RNA_def_property_ui_text(prop, "K2", "Second coefficient of second order Nuke distortion"); + RNA_def_property_update(prop, NC_MOVIECLIP | NA_EDITED, "rna_tracking_flushUpdate"); + /* pixel aspect */ prop = RNA_def_property(srna, "pixel_aspect", PROP_FLOAT, PROP_XYZ); RNA_def_property_float_sdna(prop, NULL, "pixel_aspect"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index a169e81237d..2a64ffa73cd 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -693,7 +693,7 @@ void RNA_api_ui_layout(StructRNA *srna) static float node_socket_color_default[] = {0.0f, 0.0f, 0.0f, 1.0f}; /* simple layout specifiers */ - func = RNA_def_function(srna, "row", "uiLayoutRow"); + func = RNA_def_function(srna, "row", "uiLayoutRowWithHeading"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description( @@ -701,8 +701,14 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed next to each other " "in a row"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + RNA_def_string(func, + "heading", + NULL, + UI_MAX_NAME_STR, + "Heading", + "Label to insert into the layout for this row"); - func = RNA_def_function(srna, "column", "uiLayoutColumn"); + func = RNA_def_function(srna, "column", "uiLayoutColumnWithHeading"); parm = RNA_def_pointer(func, "layout", "UILayout", "", "Sub-layout to put items in"); RNA_def_function_return(func, parm); RNA_def_function_ui_description( @@ -710,6 +716,12 @@ void RNA_api_ui_layout(StructRNA *srna) "Sub-layout. Items placed in this sublayout are placed under each other " "in a column"); RNA_def_boolean(func, "align", false, "", "Align buttons to each other"); + RNA_def_string(func, + "heading", + NULL, + UI_MAX_NAME_STR, + "Heading", + "Label to insert into the layout for this column"); 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); @@ -887,6 +899,20 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); api_ui_item_common(func); + func = RNA_def_function(srna, "prop_decorator", "uiItemDecoratorR"); + api_ui_item_rna_common(func); + RNA_def_int(func, + "index", + /* RNA_NO_INDEX == -1 */ + -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); + for (int is_menu_hold = 0; is_menu_hold < 2; is_menu_hold++) { func = (is_menu_hold) ? RNA_def_function(srna, "operator_menu_hold", "rna_uiItemOMenuHold") : RNA_def_function(srna, "operator", "rna_uiItemO"); @@ -1492,6 +1518,7 @@ void RNA_api_ui_layout(StructRNA *srna) RNA_def_function_flag(func, FUNC_USE_CONTEXT); func = RNA_def_function(srna, "template_node_link", "uiTemplateNodeLink"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); parm = RNA_def_pointer(func, "ntree", "NodeTree", "", ""); RNA_def_parameter_flags(parm, 0, PARM_REQUIRED); parm = RNA_def_pointer(func, "node", "Node", "", ""); diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index c08a95d7e16..00d3189dcbe 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -4840,6 +4840,12 @@ static void rna_def_userdef_edit(BlenderRNA *brna) RNA_def_property_ui_text( prop, "Enter Edit Mode", "Enter Edit Mode automatically after adding a new object"); + prop = RNA_def_property(srna, "collection_instance_empty_size", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.001f, FLT_MAX); + RNA_def_property_ui_text(prop, + "Collection Instance Empty Size", + "Display size of the empty when new collection instances are created"); + /* Undo */ prop = RNA_def_property(srna, "undo_steps", PROP_INT, PROP_NONE); @@ -6063,10 +6069,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna) prop, "Undo Legacy", "Use legacy undo (slower than the new default one, but may be more stable in some cases)"); - - prop = RNA_def_property(srna, "use_menu_search", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "use_menu_search", 1); - RNA_def_property_ui_text(prop, "Menu Search", "Search actions by menus instead of operators"); } static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop) diff --git a/source/blender/makesrna/intern/rna_vfont_api.c b/source/blender/makesrna/intern/rna_vfont_api.c index a85dde5d8b1..1bf61db4871 100644 --- a/source/blender/makesrna/intern/rna_vfont_api.c +++ b/source/blender/makesrna/intern/rna_vfont_api.c @@ -10,7 +10,7 @@ * 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, + * 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) 2015 by the Blender Foundation. diff --git a/source/blender/makesrna/intern/rna_xr.c b/source/blender/makesrna/intern/rna_xr.c index b08e48a4b17..04a8500d136 100644 --- a/source/blender/makesrna/intern/rna_xr.c +++ b/source/blender/makesrna/intern/rna_xr.c @@ -45,6 +45,16 @@ static bool rna_XrSessionState_is_running(bContext *C) # endif } +static void rna_XrSessionState_reset_to_base_pose(bContext *C) +{ +# ifdef WITH_XR_OPENXR + wmWindowManager *wm = CTX_wm_manager(C); + WM_xr_session_base_pose_reset(&wm->xr); +# else + UNUSED_VARS(C); +# endif +} + # ifdef WITH_XR_OPENXR static wmXrData *rna_XrSessionState_wm_xr_data_get(PointerRNA *ptr) { @@ -197,6 +207,12 @@ static void rna_def_xr_session_state(BlenderRNA *brna) parm = RNA_def_boolean(func, "result", 0, "Result", ""); RNA_def_function_return(func, parm); + func = RNA_def_function(srna, "reset_to_base_pose", "rna_XrSessionState_reset_to_base_pose"); + RNA_def_function_ui_description(func, "Force resetting of position and rotation deltas"); + RNA_def_function_flag(func, FUNC_NO_SELF); + parm = RNA_def_pointer(func, "context", "Context", "", ""); + RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED); + prop = RNA_def_property(srna, "viewer_pose_location", PROP_FLOAT, PROP_TRANSLATION); RNA_def_property_array(prop, 3); RNA_def_property_float_funcs(prop, "rna_XrSessionState_viewer_pose_location_get", NULL, NULL); diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt index 48acbdc17f3..8ab7d35070b 100644 --- a/source/blender/modifiers/CMakeLists.txt +++ b/source/blender/modifiers/CMakeLists.txt @@ -78,6 +78,7 @@ set(SRC intern/MOD_shapekey.c intern/MOD_shrinkwrap.c intern/MOD_simpledeform.c + intern/MOD_simulation.cc intern/MOD_skin.c intern/MOD_smooth.c intern/MOD_softbody.c diff --git a/source/blender/modifiers/MOD_modifiertypes.h b/source/blender/modifiers/MOD_modifiertypes.h index 5dc4adf4393..ba676bbe459 100644 --- a/source/blender/modifiers/MOD_modifiertypes.h +++ b/source/blender/modifiers/MOD_modifiertypes.h @@ -86,6 +86,7 @@ extern ModifierTypeInfo modifierType_CorrectiveSmooth; extern ModifierTypeInfo modifierType_MeshSequenceCache; extern ModifierTypeInfo modifierType_SurfaceDeform; extern ModifierTypeInfo modifierType_WeightedNormal; +extern ModifierTypeInfo modifierType_Simulation; /* MOD_util.c */ void modifier_type_init(ModifierTypeInfo *types[]); diff --git a/source/blender/modifiers/intern/MOD_armature.c b/source/blender/modifiers/intern/MOD_armature.c index 275c16873a8..29d456e5126 100644 --- a/source/blender/modifiers/intern/MOD_armature.c +++ b/source/blender/modifiers/intern/MOD_armature.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -61,7 +61,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif ArmatureModifierData *tamd = (ArmatureModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tamd->prevCos = NULL; } @@ -244,7 +244,7 @@ ModifierTypeInfo modifierType_Armature = { /* structName */ "ArmatureModifierData", /* structSize */ sizeof(ArmatureModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -253,7 +253,10 @@ ModifierTypeInfo modifierType_Armature = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ deformMatricesEM, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index bad1d7d3cf9..fc127c48fc9 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -503,7 +503,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, } if (offset_is_too_small) { - modifier_setError( + BKE_modifier_set_error( &amd->modifier, "The offset is too small, we cannot generate the amount of geometry it would require"); } @@ -514,9 +514,9 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, else if (((size_t)count * (size_t)chunk_nverts + (size_t)start_cap_nverts + (size_t)end_cap_nverts) > max_num_vertices) { count = 1; - modifier_setError(&amd->modifier, - "The amount of copies is too high, we cannot generate the amount of " - "geometry it would require"); + BKE_modifier_set_error(&amd->modifier, + "The amount of copies is too high, we cannot generate the amount of " + "geometry it would require"); } if (count < 1) { @@ -791,7 +791,7 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { ArrayModifierData *amd = (ArrayModifierData *)md; return arrayModifier_doArray(amd, ctx, mesh); @@ -831,13 +831,16 @@ ModifierTypeInfo modifierType_Array = { eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index bd2f8a6dca3..fb1b3cd219e 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -72,7 +72,7 @@ static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int const BevelModifierData *bmd_src = (const BevelModifierData *)md_src; BevelModifierData *bmd_dst = (BevelModifierData *)md_dst; - modifier_copyData_generic(md_src, md_dst, flag); + BKE_modifier_copydata_generic(md_src, md_dst, flag); bmd_dst->custom_profile = BKE_curveprofile_copy(bmd_src->custom_profile); } @@ -91,7 +91,7 @@ static void requiredDataMask(Object *UNUSED(ob), /* * This calls the new bevel code (added since 2.64) */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; BMesh *bm; @@ -206,7 +206,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes Object *ob = ctx->object; if (harden_normals && (ob->type == OB_MESH) && !(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) { - modifier_setError(md, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error(md, "Enable 'Auto Smooth' in Object Data Properties"); harden_normals = false; } @@ -275,7 +275,10 @@ ModifierTypeInfo modifierType_Bevel = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ freeData, diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 67610e8cd29..d8b375b0ee9 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -153,7 +153,7 @@ static int bm_face_isect_pair(BMFace *f, void *UNUSED(user_data)) return BM_elem_flag_test(f, BM_FACE_TAG) ? 1 : 0; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BooleanModifierData *bmd = (BooleanModifierData *)md; Mesh *result = mesh; @@ -330,7 +330,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes /* if new mesh returned, return it; otherwise there was * an error, so delete the modifier object */ if (result == NULL) { - modifier_setError(md, "Cannot execute boolean operation"); + BKE_modifier_set_error(md, "Cannot execute boolean operation"); } } @@ -353,13 +353,16 @@ ModifierTypeInfo modifierType_Boolean = { /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_build.c b/source/blender/modifiers/intern/MOD_build.c index 3c1a5744b33..2cd52005362 100644 --- a/source/blender/modifiers/intern/MOD_build.c +++ b/source/blender/modifiers/intern/MOD_build.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -55,7 +55,7 @@ static bool dependsOnTime(ModifierData *UNUSED(md)) return true; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, struct Mesh *mesh) { Mesh *result; BuildModifierData *bmd = (BuildModifierData *)md; @@ -282,13 +282,16 @@ ModifierTypeInfo modifierType_Build = { /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_cast.c b/source/blender/modifiers/intern/MOD_cast.c index eb6292e5e46..5f2043d8c09 100644 --- a/source/blender/modifiers/intern/MOD_cast.c +++ b/source/blender/modifiers/intern/MOD_cast.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -523,16 +523,19 @@ ModifierTypeInfo modifierType_Cast = { /* structName */ "CastModifierData", /* structSize */ sizeof(CastModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_cloth.c b/source/blender/modifiers/intern/MOD_cloth.c index 0cab6144de8..da7485b5a2d 100644 --- a/source/blender/modifiers/intern/MOD_cloth.c +++ b/source/blender/modifiers/intern/MOD_cloth.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -267,7 +267,10 @@ ModifierTypeInfo modifierType_Cloth = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_collision.c b/source/blender/modifiers/intern/MOD_collision.c index e1595488d08..0c6133ed7a6 100644 --- a/source/blender/modifiers/intern/MOD_collision.c +++ b/source/blender/modifiers/intern/MOD_collision.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -254,7 +254,10 @@ ModifierTypeInfo modifierType_Collision = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_correctivesmooth.c b/source/blender/modifiers/intern/MOD_correctivesmooth.c index 52003f8b1d8..6224cf6b1fc 100644 --- a/source/blender/modifiers/intern/MOD_correctivesmooth.c +++ b/source/blender/modifiers/intern/MOD_correctivesmooth.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -79,7 +79,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const CorrectiveSmoothModifierData *csmd = (const CorrectiveSmoothModifierData *)md; CorrectiveSmoothModifierData *tcsmd = (CorrectiveSmoothModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); if (csmd->bind_coords) { tcsmd->bind_coords = MEM_dupallocN(csmd->bind_coords); @@ -602,12 +602,12 @@ static void correctivesmooth_modifier_do(ModifierData *md, BLI_assert(csmd->bind_coords != NULL); /* Copy bound data to the original modifier. */ CorrectiveSmoothModifierData *csmd_orig = (CorrectiveSmoothModifierData *) - modifier_get_original(&csmd->modifier); + BKE_modifier_get_original(&csmd->modifier); csmd_orig->bind_coords = MEM_dupallocN(csmd->bind_coords); csmd_orig->bind_coords_num = csmd->bind_coords_num; } else { - modifier_setError(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); } } @@ -617,14 +617,14 @@ static void correctivesmooth_modifier_do(ModifierData *md, } if ((csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) && (csmd->bind_coords == NULL)) { - modifier_setError(md, "Bind data required"); + BKE_modifier_set_error(md, "Bind data required"); goto error; } /* If the number of verts has changed, the bind is invalid, so we do nothing */ if (csmd->rest_source == MOD_CORRECTIVESMOOTH_RESTSOURCE_BIND) { if (csmd->bind_coords_num != numVerts) { - modifier_setError( + BKE_modifier_set_error( md, "Bind vertex count mismatch: %u to %u", csmd->bind_coords_num, numVerts); goto error; } @@ -632,14 +632,15 @@ static void correctivesmooth_modifier_do(ModifierData *md, else { /* MOD_CORRECTIVESMOOTH_RESTSOURCE_ORCO */ if (ob->type != OB_MESH) { - modifier_setError(md, "Object is not a mesh"); + BKE_modifier_set_error(md, "Object is not a mesh"); goto error; } else { uint me_numVerts = (uint)((em) ? em->bm->totvert : ((Mesh *)ob->data)->totvert); if (me_numVerts != numVerts) { - modifier_setError(md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); + BKE_modifier_set_error( + md, "Original vertex count mismatch: %u to %u", me_numVerts, numVerts); goto error; } } @@ -776,7 +777,10 @@ ModifierTypeInfo modifierType_CorrectiveSmooth = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_curve.c b/source/blender/modifiers/intern/MOD_curve.c index e287685a9e5..238c8223799 100644 --- a/source/blender/modifiers/intern/MOD_curve.c +++ b/source/blender/modifiers/intern/MOD_curve.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -154,16 +154,19 @@ ModifierTypeInfo modifierType_Curve = { /* structName */ "CurveModifierData", /* structSize */ sizeof(CurveModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 72cbe197251..dea4bad6999 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -10,7 +10,7 @@ * 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, + * 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) 2014 Blender Foundation. @@ -156,7 +156,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), (DT_TYPE_BWEIGHT_VERT | DT_TYPE_BWEIGHT_EDGE | DT_TYPE_CREASE | DT_TYPE_SHARP_EDGE | \ DT_TYPE_LNOR | DT_TYPE_SHARP_FACE) -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me_mod) { DataTransferModifierData *dtmd = (DataTransferModifierData *)md; struct Scene *scene = DEG_get_evaluated_scene(ctx->depsgraph); @@ -217,16 +217,15 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes &reports); if (BKE_reports_contain(&reports, RPT_ERROR)) { - modifier_setError(md, "%s", BKE_reports_string(&reports, RPT_ERROR)); + BKE_modifier_set_error(md, "%s", BKE_reports_string(&reports, RPT_ERROR)); } else if ((dtmd->data_types & DT_TYPE_LNOR) && !(me->flag & ME_AUTOSMOOTH)) { - modifier_setError((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error((ModifierData *)dtmd, "Enable 'Auto Smooth' in Object Data Properties"); } else if (result->totvert > HIGH_POLY_WARNING || ((Mesh *)(ob_source->data))->totvert > HIGH_POLY_WARNING) { - modifier_setError( - md, - "You are using a rather high poly as source or destination, computation might be slow"); + BKE_modifier_set_error( + md, "Source or destination object has a high polygon count, computation might be slow"); } return result; @@ -243,13 +242,16 @@ ModifierTypeInfo modifierType_DataTransfer = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_decimate.c b/source/blender/modifiers/intern/MOD_decimate.c index cf07b5460e1..3958713f7a8 100644 --- a/source/blender/modifiers/intern/MOD_decimate.c +++ b/source/blender/modifiers/intern/MOD_decimate.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -73,7 +73,7 @@ static DecimateModifierData *getOriginalModifierData(const DecimateModifierData const ModifierEvalContext *ctx) { Object *ob_orig = DEG_get_original_object(ctx->object); - return (DecimateModifierData *)modifiers_findByName(ob_orig, dmd->modifier.name); + return (DecimateModifierData *)BKE_modifiers_findny_name(ob_orig, dmd->modifier.name); } static void updateFaceCount(const ModifierEvalContext *ctx, @@ -89,7 +89,7 @@ static void updateFaceCount(const ModifierEvalContext *ctx, } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) { DecimateModifierData *dmd = (DecimateModifierData *)md; Mesh *mesh = meshData, *result = NULL; @@ -128,7 +128,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes } if (dmd->face_count <= 3) { - modifier_setError(md, "Modifier requires more than 3 input faces"); + BKE_modifier_set_error(md, "Modifier requires more than 3 input faces"); return mesh; } @@ -222,13 +222,16 @@ ModifierTypeInfo modifierType_Decimate = { /* type */ eModifierTypeType_Nonconstructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_displace.c b/source/blender/modifiers/intern/MOD_displace.c index 19a4e855153..514ea185ede 100644 --- a/source/blender/modifiers/intern/MOD_displace.c +++ b/source/blender/modifiers/intern/MOD_displace.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -421,13 +421,16 @@ ModifierTypeInfo modifierType_Displace = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_dynamicpaint.c b/source/blender/modifiers/intern/MOD_dynamicpaint.c index d36fce3752b..3cace5745e6 100644 --- a/source/blender/modifiers/intern/MOD_dynamicpaint.c +++ b/source/blender/modifiers/intern/MOD_dynamicpaint.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -101,7 +101,7 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)md; @@ -187,7 +187,10 @@ ModifierTypeInfo modifierType_DynamicPaint = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_edgesplit.c b/source/blender/modifiers/intern/MOD_edgesplit.c index 69ba4aa2795..dd5669cd10c 100644 --- a/source/blender/modifiers/intern/MOD_edgesplit.c +++ b/source/blender/modifiers/intern/MOD_edgesplit.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -113,7 +113,7 @@ static void initData(ModifierData *md) emd->flags = MOD_EDGESPLIT_FROMANGLE | MOD_EDGESPLIT_FROMFLAG; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { Mesh *result; EdgeSplitModifierData *emd = (EdgeSplitModifierData *)md; @@ -136,13 +136,16 @@ ModifierTypeInfo modifierType_EdgeSplit = { eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index d380747eb31..747269f4c80 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -67,7 +67,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif ExplodeModifierData *temd = (ExplodeModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); temd->facepa = NULL; } @@ -1123,7 +1123,7 @@ static ParticleSystemModifierData *findPrecedingParticlesystem(Object *ob, Modif } return psmd; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { ExplodeModifierData *emd = (ExplodeModifierData *)md; ParticleSystemModifierData *psmd = findPrecedingParticlesystem(ctx->object, md); @@ -1186,7 +1186,10 @@ ModifierTypeInfo modifierType_Explode = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_fluid.c b/source/blender/modifiers/intern/MOD_fluid.c index 1c2f0a413a7..4880bd06ee9 100644 --- a/source/blender/modifiers/intern/MOD_fluid.c +++ b/source/blender/modifiers/intern/MOD_fluid.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -101,7 +101,7 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *me) { #ifndef WITH_FLUID UNUSED_VARS(md, ctx); @@ -207,7 +207,10 @@ ModifierTypeInfo modifierType_Fluid = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_hook.c b/source/blender/modifiers/intern/MOD_hook.c index 1ae2c5e4424..d93b3c56e5a 100644 --- a/source/blender/modifiers/intern/MOD_hook.c +++ b/source/blender/modifiers/intern/MOD_hook.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -59,7 +59,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const HookModifierData *hmd = (const HookModifierData *)md; HookModifierData *thmd = (HookModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); thmd->curfalloff = BKE_curvemapping_copy(hmd->curfalloff); @@ -393,7 +393,7 @@ ModifierTypeInfo modifierType_Hook = { /* structName */ "HookModifierData", /* structSize */ sizeof(HookModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -401,7 +401,10 @@ ModifierTypeInfo modifierType_Hook = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_laplaciandeform.c b/source/blender/modifiers/intern/MOD_laplaciandeform.c index 683696b0725..095ca95594b 100644 --- a/source/blender/modifiers/intern/MOD_laplaciandeform.c +++ b/source/blender/modifiers/intern/MOD_laplaciandeform.c @@ -10,7 +10,7 @@ * 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, + * 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 the Blender Foundation. @@ -667,17 +667,17 @@ static void LaplacianDeformModifier_do( } else { if (sysdif == LAPDEFORM_SYSTEM_CHANGE_VERTEXES) { - modifier_setError( + BKE_modifier_set_error( &lmd->modifier, "Vertices changed from %d to %d", lmd->total_verts, numVerts); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_EDGES) { - modifier_setError( + BKE_modifier_set_error( &lmd->modifier, "Edges changed from %d to %d", sys->total_edges, mesh->totedge); } else if (sysdif == LAPDEFORM_SYSTEM_CHANGE_NOT_VALID_GROUP) { - modifier_setError(&lmd->modifier, - "Vertex group '%s' is not valid, or maybe empty", - sys->anchor_grp_name); + BKE_modifier_set_error(&lmd->modifier, + "Vertex group '%s' is not valid, or maybe empty", + sys->anchor_grp_name); } } } @@ -688,7 +688,7 @@ static void LaplacianDeformModifier_do( } else { if (!isValidVertexGroup(lmd, ob, mesh)) { - modifier_setError( + BKE_modifier_set_error( &lmd->modifier, "Vertex group '%s' is not valid, or maybe empty", lmd->anchor_grp_name); lmd->flag &= ~MOD_LAPLACIANDEFORM_BIND; } @@ -709,7 +709,7 @@ static void LaplacianDeformModifier_do( } } if (sys && sys->is_matrix_computed && !sys->has_solution) { - modifier_setError(&lmd->modifier, "The system did not find a solution"); + BKE_modifier_set_error(&lmd->modifier, "The system did not find a solution"); } } @@ -729,7 +729,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const LaplacianDeformModifierData *lmd = (const LaplacianDeformModifierData *)md; LaplacianDeformModifierData *tlmd = (LaplacianDeformModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tlmd->vertexco = MEM_dupallocN(lmd->vertexco); tlmd->cache_system = NULL; @@ -814,7 +814,10 @@ ModifierTypeInfo modifierType_LaplacianDeform = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_laplaciansmooth.c b/source/blender/modifiers/intern/MOD_laplaciansmooth.c index 97e94c46340..2fefca68bad 100644 --- a/source/blender/modifiers/intern/MOD_laplaciansmooth.c +++ b/source/blender/modifiers/intern/MOD_laplaciansmooth.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -574,13 +574,16 @@ ModifierTypeInfo modifierType_LaplacianSmooth = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ init_data, /* requiredDataMask */ required_data_mask, diff --git a/source/blender/modifiers/intern/MOD_lattice.c b/source/blender/modifiers/intern/MOD_lattice.c index 2b39f40a2b9..8dd507d51a4 100644 --- a/source/blender/modifiers/intern/MOD_lattice.c +++ b/source/blender/modifiers/intern/MOD_lattice.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -137,16 +137,19 @@ ModifierTypeInfo modifierType_Lattice = { /* structName */ "LatticeModifierData", /* structSize */ sizeof(LatticeModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_mask.cc b/source/blender/modifiers/intern/MOD_mask.cc index 3bdb5a3fd54..a458e4dd8bc 100644 --- a/source/blender/modifiers/intern/MOD_mask.cc +++ b/source/blender/modifiers/intern/MOD_mask.cc @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -46,14 +46,14 @@ #include "MOD_modifiertypes.h" -#include "BLI_array_cxx.h" -#include "BLI_listbase_wrapper.h" -#include "BLI_vector.h" +#include "BLI_array.hh" +#include "BLI_listbase_wrapper.hh" +#include "BLI_vector.hh" using BLI::Array; using BLI::ArrayRef; using BLI::IndexRange; -using BLI::IntrusiveListBaseWrapper; +using BLI::ListBaseWrapper; using BLI::MutableArrayRef; using BLI::Vector; @@ -93,7 +93,7 @@ static void compute_vertex_mask__armature_mode(MDeformVert *dvert, /* Element i is true if there is a selected bone that uses vertex group i. */ Vector<bool> selected_bone_uses_group; - for (bDeformGroup *def : IntrusiveListBaseWrapper<bDeformGroup>(ob->defbase)) { + for (bDeformGroup *def : ListBaseWrapper<bDeformGroup>(ob->defbase)) { bPoseChannel *pchan = BKE_pose_channel_find_name(armature_ob->pose, def->name); bool bone_for_group_exists = pchan && pchan->bone && (pchan->bone->flag & BONE_SELECTED); selected_bone_uses_group.append(bone_for_group_exists); @@ -293,7 +293,7 @@ static void copy_masked_polys_to_new_mesh(const Mesh &src_mesh, * 2. Find edges and polygons only using those vertices. * 3. Create a new mesh that only uses the found vertices, edges and polygons. */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { MaskModifierData *mmd = (MaskModifierData *)md; Object *ob = ctx->object; @@ -395,13 +395,16 @@ ModifierTypeInfo modifierType_Mask = { (ModifierTypeFlag)(eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode), - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_meshcache.c b/source/blender/modifiers/intern/MOD_meshcache.c index c2cbddf806c..219de1569b3 100644 --- a/source/blender/modifiers/intern/MOD_meshcache.c +++ b/source/blender/modifiers/intern/MOD_meshcache.c @@ -167,13 +167,13 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* we could support any object type */ if (UNLIKELY(ob->type != OB_MESH)) { - modifier_setError(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); + BKE_modifier_set_error(&mcmd->modifier, "'Integrate' only valid for Mesh objects"); } else if (UNLIKELY(me->totvert != numVerts)) { - modifier_setError(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); + BKE_modifier_set_error(&mcmd->modifier, "'Integrate' original mesh vertex mismatch"); } else if (UNLIKELY(me->totpoly == 0)) { - modifier_setError(&mcmd->modifier, "'Integrate' requires faces"); + BKE_modifier_set_error(&mcmd->modifier, "'Integrate' requires faces"); } else { /* the moons align! */ @@ -212,7 +212,7 @@ static void meshcache_do(MeshCacheModifierData *mcmd, /* -------------------------------------------------------------------- */ /* Apply the transformation matrix (if needed) */ if (UNLIKELY(err_str)) { - modifier_setError(&mcmd->modifier, "%s", err_str); + BKE_modifier_set_error(&mcmd->modifier, "%s", err_str); } else if (ok) { bool use_matrix = false; @@ -292,16 +292,19 @@ ModifierTypeInfo modifierType_MeshCache = { /* structName */ "MeshCacheModifierData", /* structSize */ sizeof(MeshCacheModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_meshdeform.c b/source/blender/modifiers/intern/MOD_meshdeform.c index d1fa496c3e5..c5ed6363415 100644 --- a/source/blender/modifiers/intern/MOD_meshdeform.c +++ b/source/blender/modifiers/intern/MOD_meshdeform.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -93,7 +93,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const MeshDeformModifierData *mmd = (const MeshDeformModifierData *)md; MeshDeformModifierData *tmmd = (MeshDeformModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); if (mmd->bindinfluences) { tmmd->bindinfluences = MEM_dupallocN(mmd->bindinfluences); @@ -363,7 +363,7 @@ static void meshdeformModifier_do(ModifierData *md, Object *ob_target = mmd->object; cagemesh = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (cagemesh == NULL) { - modifier_setError(md, "Cannot get mesh from cage object"); + BKE_modifier_set_error(md, "Cannot get mesh from cage object"); return; } @@ -378,7 +378,7 @@ static void meshdeformModifier_do(ModifierData *md, if (!mmd->bindcagecos) { /* progress bar redraw can make this recursive .. */ if (!DEG_is_active(ctx->depsgraph)) { - modifier_setError(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); goto finally; } if (!recursive_bind_sentinel) { @@ -395,15 +395,15 @@ static void meshdeformModifier_do(ModifierData *md, totcagevert = cagemesh->totvert; if (mmd->totvert != totvert) { - modifier_setError(md, "Verts changed from %d to %d", mmd->totvert, totvert); + BKE_modifier_set_error(md, "Verts changed from %d to %d", mmd->totvert, totvert); goto finally; } else if (mmd->totcagevert != totcagevert) { - modifier_setError(md, "Cage verts changed from %d to %d", mmd->totcagevert, totcagevert); + BKE_modifier_set_error(md, "Cage verts changed from %d to %d", mmd->totcagevert, totcagevert); goto finally; } else if (mmd->bindcagecos == NULL) { - modifier_setError(md, "Bind data missing"); + BKE_modifier_set_error(md, "Bind data missing"); goto finally; } @@ -488,7 +488,7 @@ static void deformVertsEM(ModifierData *md, #define MESHDEFORM_MIN_INFLUENCE 0.00001f -void modifier_mdef_compact_influences(ModifierData *md) +void BKE_modifier_mdef_compact_influences(ModifierData *md) { MeshDeformModifierData *mmd = (MeshDeformModifierData *)md; float weight, *weights, totweight; @@ -558,7 +558,7 @@ ModifierTypeInfo modifierType_MeshDeform = { /* structName */ "MeshDeformModifierData", /* structSize */ sizeof(MeshDeformModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -567,7 +567,10 @@ ModifierTypeInfo modifierType_MeshDeform = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_meshsequencecache.c b/source/blender/modifiers/intern/MOD_meshsequencecache.c index 7357f18eb6a..51275c4e58f 100644 --- a/source/blender/modifiers/intern/MOD_meshsequencecache.c +++ b/source/blender/modifiers/intern/MOD_meshsequencecache.c @@ -64,7 +64,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif MeshSeqCacheModifierData *tmcmd = (MeshSeqCacheModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tmcmd->reader = NULL; tmcmd->reader_object_path[0] = '\0'; @@ -90,7 +90,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (mcmd->cache_file == NULL) || (mcmd->object_path[0] == '\0'); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { #ifdef WITH_ALEMBIC MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; @@ -109,7 +109,8 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes STRNCPY(mcmd->reader_object_path, mcmd->object_path); BKE_cachefile_reader_open(cache_file, &mcmd->reader, ctx->object, mcmd->object_path); if (!mcmd->reader) { - modifier_setError(md, "Could not create Alembic reader for file %s", cache_file->filepath); + BKE_modifier_set_error( + md, "Could not create Alembic reader for file %s", cache_file->filepath); return mesh; } } @@ -141,7 +142,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes Mesh *result = ABC_read_mesh(mcmd->reader, ctx->object, mesh, time, &err_str, mcmd->read_flag); if (err_str) { - modifier_setError(md, "%s", err_str); + BKE_modifier_set_error(md, "%s", err_str); } if (!ELEM(result, NULL, mesh) && (mesh != org_mesh)) { @@ -197,7 +198,10 @@ ModifierTypeInfo modifierType_MeshSequenceCache = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_mirror.c b/source/blender/modifiers/intern/MOD_mirror.c index 3b3dfa2bda2..bbbcac262ca 100644 --- a/source/blender/modifiers/intern/MOD_mirror.c +++ b/source/blender/modifiers/intern/MOD_mirror.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -100,7 +100,7 @@ static Mesh *mirrorModifier__doMirror(MirrorModifierData *mmd, return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; MirrorModifierData *mmd = (MirrorModifierData *)md; @@ -124,13 +124,16 @@ ModifierTypeInfo modifierType_Mirror = { /* this is only the case when 'MOD_MIR_VGROUP' is used */ eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_multires.c b/source/blender/modifiers/intern/MOD_multires.c index f9d53d08c2e..5174a996480 100644 --- a/source/blender/modifiers/intern/MOD_multires.c +++ b/source/blender/modifiers/intern/MOD_multires.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -66,7 +66,7 @@ static void initData(ModifierData *md) static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int flag) { - modifier_copyData_generic(md_src, md_dst, flag); + BKE_modifier_copydata_generic(md_src, md_dst, flag); } static void freeRuntimeData(void *runtime_data_v) @@ -172,11 +172,11 @@ static Mesh *multires_as_ccg(MultiresModifierData *mmd, return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return result; #endif MultiresModifierData *mmd = (MultiresModifierData *)md; @@ -245,7 +245,7 @@ static void deformMatrices(ModifierData *md, { #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return; #endif @@ -286,7 +286,10 @@ ModifierTypeInfo modifierType_Multires = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_none.c b/source/blender/modifiers/intern/MOD_none.c index 9be422afab9..84c9fc1d726 100644 --- a/source/blender/modifiers/intern/MOD_none.c +++ b/source/blender/modifiers/intern/MOD_none.c @@ -51,7 +51,10 @@ ModifierTypeInfo modifierType_None = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 0b101b26906..1521cfab356 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -464,7 +464,7 @@ static bool is_valid_target(NormalEditModifierData *enmd) else if ((enmd->mode == MOD_NORMALEDIT_MODE_DIRECTIONAL) && enmd->target) { return true; } - modifier_setError((ModifierData *)enmd, "Invalid target settings"); + BKE_modifier_set_error((ModifierData *)enmd, "Invalid target settings"); return false; } @@ -494,7 +494,7 @@ static Mesh *normalEditModifier_do(NormalEditModifierData *enmd, if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - modifier_setError((ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error((ModifierData *)enmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } @@ -684,7 +684,7 @@ static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphConte } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { return normalEditModifier_do((NormalEditModifierData *)md, ctx, ctx->object, mesh); } @@ -697,13 +697,16 @@ ModifierTypeInfo modifierType_NormalEdit = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_ocean.c b/source/blender/modifiers/intern/MOD_ocean.c index fddfc74f267..4c7c644952b 100644 --- a/source/blender/modifiers/intern/MOD_ocean.c +++ b/source/blender/modifiers/intern/MOD_ocean.c @@ -46,7 +46,7 @@ #ifdef WITH_OCEANSIM static void init_cache_data(Object *ob, struct OceanModifierData *omd) { - const char *relbase = modifier_path_relbase_from_global(ob); + const char *relbase = BKE_modifier_path_relbase_from_global(ob); omd->oceancache = BKE_ocean_init_cache(omd->cachepath, relbase, @@ -100,7 +100,7 @@ static void initData(ModifierData *md) omd->repeat_x = 1; omd->repeat_y = 1; - modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); + BKE_modifier_path_init(omd->cachepath, sizeof(omd->cachepath), "cache_ocean"); omd->cached = 0; omd->bakestart = 1; @@ -141,7 +141,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla # endif OceanModifierData *tomd = (OceanModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); /* The oceancache object will be recreated for this copy * automatically when cached=true */ @@ -482,7 +482,7 @@ static Mesh *doOcean(ModifierData *UNUSED(md), const ModifierEvalContext *UNUSED } #endif /* WITH_OCEANSIM */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; @@ -509,7 +509,10 @@ ModifierTypeInfo modifierType_Ocean = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index 8a4468ec91e..644962ab71c 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -110,7 +110,7 @@ static bool isDisabled(const struct Scene *scene, ModifierData *md, bool useRend required_mode = eModifierMode_Realtime; } - if (!modifier_isEnabled(scene, ob_md, required_mode)) { + if (!BKE_modifier_is_enabled(scene, ob_md, required_mode)) { return true; } @@ -204,7 +204,7 @@ static void store_float_in_vcol(MLoopCol *vcol, float float_value) vcol->a = 1.0f; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; @@ -554,13 +554,16 @@ ModifierTypeInfo modifierType_ParticleInstance = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_particlesystem.c b/source/blender/modifiers/intern/MOD_particlesystem.c index 05bfe9aeff0..fc5359c953f 100644 --- a/source/blender/modifiers/intern/MOD_particlesystem.c +++ b/source/blender/modifiers/intern/MOD_particlesystem.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -61,7 +61,7 @@ static void freeData(ModifierData *md) psmd->totdmvert = psmd->totdmedge = psmd->totdmface = 0; /* ED_object_modifier_remove may have freed this first before calling - * modifier_free (which calls this function) */ + * BKE_modifier_free (which calls this function) */ if (psmd->psys) { psmd->psys->flag |= PSYS_DELETE; } @@ -74,7 +74,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif ParticleSystemModifierData *tpsmd = (ParticleSystemModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tpsmd->mesh_final = NULL; tpsmd->mesh_original = NULL; @@ -216,7 +216,7 @@ static void deformVerts(ModifierData *md, if (DEG_is_active(ctx->depsgraph)) { Object *object_orig = DEG_get_original_object(ctx->object); - ModifierData *md_orig = modifiers_findByName(object_orig, psmd->modifier.name); + ModifierData *md_orig = BKE_modifiers_findny_name(object_orig, psmd->modifier.name); BLI_assert(md_orig != NULL); ParticleSystemModifierData *psmd_orig = (ParticleSystemModifierData *)md_orig; psmd_orig->flag = psmd->flag; @@ -264,7 +264,10 @@ ModifierTypeInfo modifierType_ParticleSystem = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_remesh.c b/source/blender/modifiers/intern/MOD_remesh.c index 2fa8dc973a1..cdb513595a1 100644 --- a/source/blender/modifiers/intern/MOD_remesh.c +++ b/source/blender/modifiers/intern/MOD_remesh.c @@ -136,7 +136,7 @@ static void dualcon_add_quad(void *output_v, const int vert_indices[4]) output->curface++; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { RemeshModifierData *rmd; DualConOutput *output; @@ -210,9 +210,9 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(c #else /* !WITH_MOD_REMESH */ -static Mesh *applyModifier(ModifierData *UNUSED(md), - const ModifierEvalContext *UNUSED(ctx), - Mesh *mesh) +static Mesh *modifyMesh(ModifierData *UNUSED(md), + const ModifierEvalContext *UNUSED(ctx), + Mesh *mesh) { return mesh; } @@ -227,13 +227,16 @@ ModifierTypeInfo modifierType_Remesh = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_screw.c b/source/blender/modifiers/intern/MOD_screw.c index e832a23b4ed..d3d42068812 100644 --- a/source/blender/modifiers/intern/MOD_screw.c +++ b/source/blender/modifiers/intern/MOD_screw.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -178,7 +178,7 @@ static void initData(ModifierData *md) ltmd->merge_dist = 0.01f; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *meshData) { Mesh *mesh = meshData; Mesh *result; @@ -1165,13 +1165,16 @@ ModifierTypeInfo modifierType_Screw = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shapekey.c b/source/blender/modifiers/intern/MOD_shapekey.c index 25f702bf696..abab0aff927 100644 --- a/source/blender/modifiers/intern/MOD_shapekey.c +++ b/source/blender/modifiers/intern/MOD_shapekey.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -122,7 +122,7 @@ ModifierTypeInfo modifierType_ShapeKey = { /* structName */ "ShapeKeyModifierData", /* structSize */ sizeof(ShapeKeyModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ NULL, @@ -131,7 +131,10 @@ ModifierTypeInfo modifierType_ShapeKey = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ deformMatricesEM, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_shrinkwrap.c b/source/blender/modifiers/intern/MOD_shrinkwrap.c index 842ec46f364..bb8519b01ea 100644 --- a/source/blender/modifiers/intern/MOD_shrinkwrap.c +++ b/source/blender/modifiers/intern/MOD_shrinkwrap.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -204,16 +204,19 @@ ModifierTypeInfo modifierType_Shrinkwrap = { /* structSize */ sizeof(ShrinkwrapModifierData), /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_simpledeform.c b/source/blender/modifiers/intern/MOD_simpledeform.c index 65ea6b95824..0bd16a318ae 100644 --- a/source/blender/modifiers/intern/MOD_simpledeform.c +++ b/source/blender/modifiers/intern/MOD_simpledeform.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -454,16 +454,19 @@ ModifierTypeInfo modifierType_SimpleDeform = { /* type */ eModifierTypeType_OnlyDeform, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | - eModifierTypeFlag_AcceptsLattice | eModifierTypeFlag_SupportsEditmode | + eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_simulation.cc b/source/blender/modifiers/intern/MOD_simulation.cc new file mode 100644 index 00000000000..f52daf53186 --- /dev/null +++ b/source/blender/modifiers/intern/MOD_simulation.cc @@ -0,0 +1,109 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 by the Blender Foundation. + * All rights reserved. + */ + +/** \file + * \ingroup modifiers + */ + +#include <iostream> +#include <string> + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_pointcloud_types.h" +#include "DNA_scene_types.h" +#include "DNA_simulation_types.h" + +#include "BKE_customdata.h" +#include "BKE_lib_query.h" +#include "BKE_mesh.h" +#include "BKE_modifier.h" + +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + +#include "MOD_modifiertypes.h" + +static void updateDepsgraph(ModifierData *md, const ModifierUpdateDepsgraphContext *ctx) +{ + SimulationModifierData *smd = (SimulationModifierData *)md; + if (smd->simulation) { + DEG_add_simulation_relation(ctx->node, smd->simulation, "Accessed Simulation"); + } +} + +static void foreachIDLink(ModifierData *md, Object *ob, IDWalkFunc walk, void *userData) +{ + SimulationModifierData *smd = (SimulationModifierData *)md; + walk(userData, ob, (ID **)&smd->simulation, IDWALK_CB_USER); +} + +static bool isDisabled(const struct Scene *UNUSED(scene), + ModifierData *md, + bool UNUSED(useRenderParams)) +{ + SimulationModifierData *smd = (SimulationModifierData *)md; + return smd->simulation == nullptr; +} + +static PointCloud *modifyPointCloud(ModifierData *md, + const ModifierEvalContext *UNUSED(ctx), + PointCloud *pointcloud) +{ + SimulationModifierData *smd = (SimulationModifierData *)md; + UNUSED_VARS(smd); + return pointcloud; +} + +ModifierTypeInfo modifierType_Simulation = { + /* name */ "Simulation", + /* structName */ "SimulationModifierData", + /* structSize */ sizeof(SimulationModifierData), + /* type */ eModifierTypeType_None, + /* flags */ (ModifierTypeFlag)0, + + /* copyData */ BKE_modifier_copydata_generic, + + /* deformVerts */ NULL, + /* deformMatrices */ NULL, + /* deformVertsEM */ NULL, + /* deformMatricesEM */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ modifyPointCloud, + /* modifyVolume */ NULL, + + /* initData */ NULL, + /* requiredDataMask */ NULL, + /* freeData */ NULL, + /* isDisabled */ isDisabled, + /* updateDepsgraph */ updateDepsgraph, + /* dependsOnTime */ NULL, + /* dependsOnNormals */ NULL, + /* foreachObjectLink */ NULL, + /* foreachIDLink */ foreachIDLink, + /* foreachTexLink */ NULL, + /* freeRuntimeData */ NULL, +}; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index ec7c2b5b1a4..98c7d809f33 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -1779,7 +1779,7 @@ static BMesh *build_skin(SkinNode *skin_nodes, skin_update_merged_vertices(skin_nodes, totvert); if (!skin_output_branch_hulls(&so, skin_nodes, totvert, emap, medge)) { - modifier_setError(&smd->modifier, "Hull error"); + BKE_modifier_set_error(&smd->modifier, "Hull error"); } /* Merge triangles here in the hope of providing better target @@ -1862,7 +1862,7 @@ static Mesh *base_skin(Mesh *origmesh, SkinModifierData *smd) MEM_freeN(emapmem); if (!has_valid_root) { - modifier_setError( + BKE_modifier_set_error( &smd->modifier, "No valid root vertex found (you need one per mesh island you want to skin)"); } @@ -1911,7 +1911,7 @@ static void initData(ModifierData *md) smd->symmetry_axes = MOD_SKIN_SYMM_X; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { Mesh *result; @@ -1935,13 +1935,16 @@ ModifierTypeInfo modifierType_Skin = { /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_smooth.c b/source/blender/modifiers/intern/MOD_smooth.c index 2a0376fd291..5b13bee7dac 100644 --- a/source/blender/modifiers/intern/MOD_smooth.c +++ b/source/blender/modifiers/intern/MOD_smooth.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -231,13 +231,16 @@ ModifierTypeInfo modifierType_Smooth = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_softbody.c b/source/blender/modifiers/intern/MOD_softbody.c index efe6b188fa0..92516d3d417 100644 --- a/source/blender/modifiers/intern/MOD_softbody.c +++ b/source/blender/modifiers/intern/MOD_softbody.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -78,7 +78,7 @@ ModifierTypeInfo modifierType_Softbody = { /* structName */ "SoftbodyModifierData", /* structSize */ sizeof(SoftbodyModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_RequiresOriginalData | eModifierTypeFlag_Single | eModifierTypeFlag_UsesPointCache, @@ -88,7 +88,10 @@ ModifierTypeInfo modifierType_Softbody = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ NULL, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index fc9719a5fb4..01277facacf 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -70,14 +70,14 @@ static void requiredDataMask(Object *UNUSED(ob), } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { const SolidifyModifierData *smd = (SolidifyModifierData *)md; switch (smd->mode) { case MOD_SOLIDIFY_MODE_EXTRUDE: - return MOD_solidify_extrude_applyModifier(md, ctx, mesh); + return MOD_solidify_extrude_modifyMesh(md, ctx, mesh); case MOD_SOLIDIFY_MODE_NONMANIFOLD: - return MOD_solidify_nonmanifold_applyModifier(md, ctx, mesh); + return MOD_solidify_nonmanifold_modifyMesh(md, ctx, mesh); default: BLI_assert(0); } @@ -94,13 +94,16 @@ ModifierTypeInfo modifierType_Solidify = { eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index fee1b552d89..75d2be5292e 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -183,9 +183,7 @@ static void mesh_calc_hq_normal(Mesh *mesh, float (*poly_nors)[3], float (*r_ver /** \name Main Solidify Function * \{ */ -Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh) +Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index e42207081ed..423a6b4458a 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -132,9 +132,9 @@ static int comp_float_int_pair(const void *a, const void *b) return (int)(x->angle > y->angle) - (int)(x->angle < y->angle); } -Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh) +Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh) { Mesh *result; const SolidifyModifierData *smd = (SolidifyModifierData *)md; @@ -2424,15 +2424,15 @@ Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, MEM_freeN(face_edges); } if (edge_index != numNewEdges) { - modifier_setError( + BKE_modifier_set_error( md, "Internal Error: edges array wrong size: %u instead of %u", numNewEdges, edge_index); } if (poly_index != numNewPolys) { - modifier_setError( + BKE_modifier_set_error( md, "Internal Error: polys array wrong size: %u instead of %u", numNewPolys, poly_index); } if (loop_index != numNewLoops) { - modifier_setError( + BKE_modifier_set_error( md, "Internal Error: loops array wrong size: %u instead of %u", numNewLoops, loop_index); } BLI_assert(edge_index == numNewEdges); diff --git a/source/blender/modifiers/intern/MOD_solidify_util.h b/source/blender/modifiers/intern/MOD_solidify_util.h index 3a9608861dc..6ab4734c451 100644 --- a/source/blender/modifiers/intern/MOD_solidify_util.h +++ b/source/blender/modifiers/intern/MOD_solidify_util.h @@ -22,13 +22,13 @@ #define __MOD_SOLIDIFY_UTIL_H__ /* MOD_solidify_extrude.c */ -Mesh *MOD_solidify_extrude_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh); +Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh); /* MOD_solidify_nonmanifold.c */ -Mesh *MOD_solidify_nonmanifold_applyModifier(ModifierData *md, - const ModifierEvalContext *ctx, - Mesh *mesh); +Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, + const ModifierEvalContext *ctx, + Mesh *mesh); #endif /* __MOD_SOLIDIFY_UTIL_H__ */ diff --git a/source/blender/modifiers/intern/MOD_subsurf.c b/source/blender/modifiers/intern/MOD_subsurf.c index b3bc5a66e8c..e054e3478ea 100644 --- a/source/blender/modifiers/intern/MOD_subsurf.c +++ b/source/blender/modifiers/intern/MOD_subsurf.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -68,7 +68,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla #endif SubsurfModifierData *tsmd = (SubsurfModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); tsmd->emCache = tsmd->mCache = NULL; } @@ -206,11 +206,11 @@ static SubsurfRuntimeData *subsurf_ensure_runtime(SubsurfModifierData *smd) /* Modifier itself. */ -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result = mesh; #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return result; #endif SubsurfModifierData *smd = (SubsurfModifierData *)md; @@ -249,7 +249,7 @@ static void deformMatrices(ModifierData *md, int num_verts) { #if !defined(WITH_OPENSUBDIV) - modifier_setError(md, "Disabled, built without OpenSubdiv"); + BKE_modifier_set_error(md, "Disabled, built without OpenSubdiv"); return; #endif @@ -290,7 +290,10 @@ ModifierTypeInfo modifierType_Subsurf = { /* deformMatrices */ deformMatrices, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surface.c b/source/blender/modifiers/intern/MOD_surface.c index 0e318e9b092..b7449cbe91c 100644 --- a/source/blender/modifiers/intern/MOD_surface.c +++ b/source/blender/modifiers/intern/MOD_surface.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -56,7 +56,7 @@ static void copyData(const ModifierData *md_src, ModifierData *md_dst, const int { SurfaceModifierData *surmd_dst = (SurfaceModifierData *)md_dst; - modifier_copyData_generic(md_src, md_dst, flag); + BKE_modifier_copydata_generic(md_src, md_dst, flag); surmd_dst->bvhtree = NULL; surmd_dst->mesh = NULL; @@ -196,7 +196,10 @@ ModifierTypeInfo modifierType_Surface = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, diff --git a/source/blender/modifiers/intern/MOD_surfacedeform.c b/source/blender/modifiers/intern/MOD_surfacedeform.c index 4ef1f32462a..4169c76272e 100644 --- a/source/blender/modifiers/intern/MOD_surfacedeform.c +++ b/source/blender/modifiers/intern/MOD_surfacedeform.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Copyright 2017, Blender Foundation. @@ -112,7 +112,7 @@ typedef struct SDefDeformData { const SDefVert *const bind_verts; float (*const targetCos)[3]; float (*const vertexCos)[3]; - float(*const weights); + float *const weights; float const strength; } SDefDeformData; @@ -180,7 +180,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const SurfaceDeformModifierData *smd = (const SurfaceDeformModifierData *)md; SurfaceDeformModifierData *tsmd = (SurfaceDeformModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); if (smd->verts) { tsmd->verts = MEM_dupallocN(smd->verts); @@ -1017,20 +1017,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, vert_edges = MEM_calloc_arrayN(tnumverts, sizeof(*vert_edges), "SDefVertEdgeMap"); if (vert_edges == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); return false; } adj_array = MEM_malloc_arrayN(tnumedges, 2 * sizeof(*adj_array), "SDefVertEdge"); if (adj_array == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); return false; } edge_polys = MEM_calloc_arrayN(tnumedges, sizeof(*edge_polys), "SDefEdgeFaceMap"); if (edge_polys == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); MEM_freeN(vert_edges); MEM_freeN(adj_array); return false; @@ -1038,14 +1038,14 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, smd_orig->verts = MEM_malloc_arrayN(numverts, sizeof(*smd_orig->verts), "SDefBindVerts"); if (smd_orig->verts == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); return false; } BKE_bvhtree_from_mesh_get(&treeData, target, BVHTREE_FROM_LOOPTRI, 2); if (treeData.tree == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); MEM_freeN(smd_orig->verts); smd_orig->verts = NULL; @@ -1056,7 +1056,8 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, mpoly, medge, mloop, tnumpoly, tnumedges, vert_edges, adj_array, edge_polys); if (adj_result == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target has edges with more than two polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, + "Target has edges with more than two polygons"); freeAdjacencyMap(vert_edges, adj_array, edge_polys); free_bvhtree_from_mesh(&treeData); MEM_freeN(smd_orig->verts); @@ -1083,7 +1084,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, }; if (data.targetCos == NULL) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); return false; } @@ -1102,19 +1103,20 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, MEM_freeN(data.targetCos); if (data.success == MOD_SDEF_BIND_RESULT_MEM_ERR) { - modifier_setError((ModifierData *)smd_eval, "Out of memory"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Out of memory"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_NONMANY_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target has edges with more than two polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, + "Target has edges with more than two polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_CONCAVE_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target contains concave polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains concave polygons"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_OVERLAP_ERR) { - modifier_setError((ModifierData *)smd_eval, "Target contains overlapping verts"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains overlapping verts"); freeData((ModifierData *)smd_orig); } else if (data.success == MOD_SDEF_BIND_RESULT_GENERIC_ERR) { @@ -1122,7 +1124,7 @@ static bool surfacedeformBind(SurfaceDeformModifierData *smd_orig, * to explain this with a reasonably sized message. * Though it shouldn't really matter all that much, * because this is very unlikely to occur */ - modifier_setError((ModifierData *)smd_eval, "Target contains invalid polygons"); + BKE_modifier_set_error((ModifierData *)smd_eval, "Target contains invalid polygons"); freeData((ModifierData *)smd_orig); } @@ -1219,10 +1221,10 @@ static void surfacedeformModifier_do(ModifierData *md, if (!(smd->flags & MOD_SDEF_BIND)) { if (smd->verts != NULL) { if (!DEG_is_active(ctx->depsgraph)) { - modifier_setError(md, "Attempt to bind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to bind from inactive dependency graph"); return; } - ModifierData *md_orig = modifier_get_original(md); + ModifierData *md_orig = BKE_modifier_get_original(md); freeData(md_orig); } return; @@ -1231,7 +1233,7 @@ static void surfacedeformModifier_do(ModifierData *md, Object *ob_target = smd->target; target = BKE_modifier_get_evaluated_mesh_from_evaluated_object(ob_target, false); if (!target) { - modifier_setError(md, "No valid target mesh"); + BKE_modifier_set_error(md, "No valid target mesh"); return; } @@ -1241,11 +1243,12 @@ static void surfacedeformModifier_do(ModifierData *md, /* If not bound, execute bind. */ if (smd->verts == NULL) { if (!DEG_is_active(ctx->depsgraph)) { - modifier_setError(md, "Attempt to unbind from inactive dependency graph"); + BKE_modifier_set_error(md, "Attempt to unbind from inactive dependency graph"); return; } - SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)modifier_get_original(md); + SurfaceDeformModifierData *smd_orig = (SurfaceDeformModifierData *)BKE_modifier_get_original( + md); float tmp_mat[4][4]; invert_m4_m4(tmp_mat, ob->obmat); @@ -1260,11 +1263,11 @@ static void surfacedeformModifier_do(ModifierData *md, /* Poly count checks */ if (smd->numverts != numverts) { - modifier_setError(md, "Verts changed from %u to %u", smd->numverts, numverts); + BKE_modifier_set_error(md, "Verts changed from %u to %u", smd->numverts, numverts); return; } else if (smd->numpoly != tnumpoly) { - modifier_setError(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); + BKE_modifier_set_error(md, "Target polygons changed from %u to %u", smd->numpoly, tnumpoly); return; } @@ -1395,7 +1398,10 @@ ModifierTypeInfo modifierType_SurfaceDeform = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_triangulate.c b/source/blender/modifiers/intern/MOD_triangulate.c index 1e6bc2e1819..bb88bda6394 100644 --- a/source/blender/modifiers/intern/MOD_triangulate.c +++ b/source/blender/modifiers/intern/MOD_triangulate.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -103,7 +103,7 @@ static void initData(ModifierData *md) tmd->min_vertices = 4; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx), Mesh *mesh) { TriangulateModifierData *tmd = (TriangulateModifierData *)md; Mesh *result; @@ -124,13 +124,16 @@ ModifierTypeInfo modifierType_Triangulate = { eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ NULL, // requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_util.c b/source/blender/modifiers/intern/MOD_util.c index f6b7c829c13..bd453c24a31 100644 --- a/source/blender/modifiers/intern/MOD_util.c +++ b/source/blender/modifiers/intern/MOD_util.c @@ -337,5 +337,6 @@ void modifier_type_init(ModifierTypeInfo *types[]) INIT_TYPE(MeshSequenceCache); INIT_TYPE(SurfaceDeform); INIT_TYPE(WeightedNormal); + INIT_TYPE(Simulation); #undef INIT_TYPE } diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index 242f31b6434..580a065f35e 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -303,7 +303,7 @@ static Mesh *uvprojectModifier_do(UVProjectModifierData *umd, return mesh; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { Mesh *result; UVProjectModifierData *umd = (UVProjectModifierData *)md; @@ -321,13 +321,16 @@ ModifierTypeInfo modifierType_UVProject = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_uvwarp.c b/source/blender/modifiers/intern/MOD_uvwarp.c index 6545159bdde..4ece36d82a4 100644 --- a/source/blender/modifiers/intern/MOD_uvwarp.c +++ b/source/blender/modifiers/intern/MOD_uvwarp.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -126,7 +126,7 @@ static void uv_warp_compute(void *__restrict userdata, } } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { UVWarpModifierData *umd = (UVWarpModifierData *)md; int numPolys, numLoops; @@ -253,13 +253,16 @@ ModifierTypeInfo modifierType_UVWarp = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_warp.c b/source/blender/modifiers/intern/MOD_warp.c index 30d45d1fc65..458e2d0caea 100644 --- a/source/blender/modifiers/intern/MOD_warp.c +++ b/source/blender/modifiers/intern/MOD_warp.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -64,7 +64,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const WarpModifierData *wmd = (const WarpModifierData *)md; WarpModifierData *twmd = (WarpModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); twmd->curfalloff = BKE_curvemapping_copy(wmd->curfalloff); } @@ -393,7 +393,7 @@ ModifierTypeInfo modifierType_Warp = { /* structName */ "WarpModifierData", /* structSize */ sizeof(WarpModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, /* copyData */ copyData, @@ -401,7 +401,10 @@ ModifierTypeInfo modifierType_Warp = { /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_wave.c b/source/blender/modifiers/intern/MOD_wave.c index fd481018cc2..fc4b65a7e5c 100644 --- a/source/blender/modifiers/intern/MOD_wave.c +++ b/source/blender/modifiers/intern/MOD_wave.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -365,16 +365,19 @@ ModifierTypeInfo modifierType_Wave = { /* structName */ "WaveModifierData", /* structSize */ sizeof(WaveModifierData), /* type */ eModifierTypeType_OnlyDeform, - /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsLattice | + /* flags */ eModifierTypeFlag_AcceptsCVs | eModifierTypeFlag_AcceptsVertexCosOnly | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ deformVerts, /* deformMatrices */ NULL, /* deformVertsEM */ deformVertsEM, /* deformMatricesEM */ NULL, - /* applyModifier */ NULL, + /* modifyMesh */ NULL, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weighted_normal.c b/source/blender/modifiers/intern/MOD_weighted_normal.c index 04b503e588b..3baf7c878dc 100644 --- a/source/blender/modifiers/intern/MOD_weighted_normal.c +++ b/source/blender/modifiers/intern/MOD_weighted_normal.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -546,7 +546,7 @@ static void wn_face_with_angle(WeightedNormalModifierData *wnmd, WeightedNormalD apply_weights_vertex_normal(wnmd, wn_data); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { WeightedNormalModifierData *wnmd = (WeightedNormalModifierData *)md; Object *ob = ctx->object; @@ -562,7 +562,7 @@ static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mes if (!(((Mesh *)ob->data)->flag & ME_AUTOSMOOTH)) #endif { - modifier_setError((ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); + BKE_modifier_set_error((ModifierData *)wnmd, "Enable 'Auto Smooth' in Object Data Properties"); return mesh; } @@ -708,13 +708,16 @@ ModifierTypeInfo modifierType_WeightedNormal = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.c b/source/blender/modifiers/intern/MOD_weightvg_util.c index 633bbb1421b..5dae6bb8505 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.c +++ b/source/blender/modifiers/intern/MOD_weightvg_util.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. diff --git a/source/blender/modifiers/intern/MOD_weightvg_util.h b/source/blender/modifiers/intern/MOD_weightvg_util.h index 6a43ac69fe9..09a6a1afb3e 100644 --- a/source/blender/modifiers/intern/MOD_weightvg_util.h +++ b/source/blender/modifiers/intern/MOD_weightvg_util.h @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. diff --git a/source/blender/modifiers/intern/MOD_weightvgedit.c b/source/blender/modifiers/intern/MOD_weightvgedit.c index 006191e29fc..1ff8dfbdcca 100644 --- a/source/blender/modifiers/intern/MOD_weightvgedit.c +++ b/source/blender/modifiers/intern/MOD_weightvgedit.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. @@ -80,7 +80,7 @@ static void copyData(const ModifierData *md, ModifierData *target, const int fla const WeightVGEditModifierData *wmd = (const WeightVGEditModifierData *)md; WeightVGEditModifierData *twmd = (WeightVGEditModifierData *)target; - modifier_copyData_generic(md, target, flag); + BKE_modifier_copydata_generic(md, target, flag); twmd->cmap_curve = BKE_curvemapping_copy(wmd->cmap_curve); } @@ -164,7 +164,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (wmd->defgrp_name[0] == '\0'); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); @@ -315,7 +315,10 @@ ModifierTypeInfo modifierType_WeightVGEdit = { /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weightvgmix.c b/source/blender/modifiers/intern/MOD_weightvgmix.c index f256045f53a..f1db8502d74 100644 --- a/source/blender/modifiers/intern/MOD_weightvgmix.c +++ b/source/blender/modifiers/intern/MOD_weightvgmix.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. @@ -210,7 +210,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (wmd->defgrp_name_a[0] == '\0'); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); @@ -436,13 +436,16 @@ ModifierTypeInfo modifierType_WeightVGMix = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weightvgproximity.c b/source/blender/modifiers/intern/MOD_weightvgproximity.c index 7b7aaaeb654..3e746403050 100644 --- a/source/blender/modifiers/intern/MOD_weightvgproximity.c +++ b/source/blender/modifiers/intern/MOD_weightvgproximity.c @@ -10,7 +10,7 @@ * 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, + * 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) 2011 by Bastien Montagne. @@ -410,7 +410,7 @@ static bool isDisabled(const struct Scene *UNUSED(scene), return (wmd->proximity_ob_target == NULL); } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { BLI_assert(mesh != NULL); @@ -636,13 +636,16 @@ ModifierTypeInfo modifierType_WeightVGProximity = { /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsMapping | eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_UsesPreview, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c index 90b71b2d504..e21410ad63d 100644 --- a/source/blender/modifiers/intern/MOD_weld.c +++ b/source/blender/modifiers/intern/MOD_weld.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2005 by the Blender Foundation. @@ -1902,7 +1902,7 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex return result; } -static Mesh *applyModifier(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh *mesh) { WeldModifierData *wmd = (WeldModifierData *)md; return weldModifier_doWeld(wmd, ctx, mesh); @@ -1938,13 +1938,16 @@ ModifierTypeInfo modifierType_Weld = { eModifierTypeFlag_SupportsEditmode | eModifierTypeFlag_EnableInEditmode | eModifierTypeFlag_AcceptsCVs, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/modifiers/intern/MOD_wireframe.c b/source/blender/modifiers/intern/MOD_wireframe.c index 04473b30585..4e2e97a2b8b 100644 --- a/source/blender/modifiers/intern/MOD_wireframe.c +++ b/source/blender/modifiers/intern/MOD_wireframe.c @@ -10,7 +10,7 @@ * 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, + * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @@ -99,9 +99,7 @@ static Mesh *WireframeModifier_do(WireframeModifierData *wmd, Object *ob, Mesh * return result; } -static Mesh *applyModifier(ModifierData *md, - const struct ModifierEvalContext *ctx, - struct Mesh *mesh) +static Mesh *modifyMesh(ModifierData *md, const struct ModifierEvalContext *ctx, struct Mesh *mesh) { return WireframeModifier_do((WireframeModifierData *)md, ctx->object, mesh); } @@ -113,13 +111,16 @@ ModifierTypeInfo modifierType_Wireframe = { /* type */ eModifierTypeType_Constructive, /* flags */ eModifierTypeFlag_AcceptsMesh | eModifierTypeFlag_SupportsEditmode, - /* copyData */ modifier_copyData_generic, + /* copyData */ BKE_modifier_copydata_generic, /* deformVerts */ NULL, /* deformMatrices */ NULL, /* deformVertsEM */ NULL, /* deformMatricesEM */ NULL, - /* applyModifier */ applyModifier, + /* modifyMesh */ modifyMesh, + /* modifyHair */ NULL, + /* modifyPointCloud */ NULL, + /* modifyVolume */ NULL, /* initData */ initData, /* requiredDataMask */ requiredDataMask, diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index a2f825ee454..80bf0f7c5e2 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -21,8 +21,10 @@ set(INC . composite + function intern shader + simulation texture ../blenkernel ../blenlib @@ -127,6 +129,13 @@ set(SRC composite/node_composite_tree.c composite/node_composite_util.c + function/nodes/node_fn_boolean_math.cc + function/nodes/node_fn_combine_strings.cc + function/nodes/node_fn_float_compare.cc + function/nodes/node_fn_group_instance_id.cc + function/nodes/node_fn_switch.cc + function/node_function_util.cc + shader/nodes/node_shader_add_shader.c shader/nodes/node_shader_ambient_occlusion.c shader/nodes/node_shader_attribute.c @@ -220,6 +229,22 @@ set(SRC shader/node_shader_tree.c shader/node_shader_util.c + simulation/nodes/node_sim_common.cc + simulation/nodes/node_sim_emit_particles.cc + simulation/nodes/node_sim_execute_condition.cc + simulation/nodes/node_sim_force.cc + simulation/nodes/node_sim_multi_execute.cc + simulation/nodes/node_sim_particle_attribute.cc + simulation/nodes/node_sim_particle_birth_event.cc + simulation/nodes/node_sim_particle_mesh_collision_event.cc + simulation/nodes/node_sim_particle_mesh_emitter.cc + simulation/nodes/node_sim_particle_simulation.cc + simulation/nodes/node_sim_particle_time_step_event.cc + simulation/nodes/node_sim_set_particle_attribute.cc + simulation/nodes/node_sim_simulation_time.cc + simulation/node_simulation_tree.cc + simulation/node_simulation_util.cc + texture/nodes/node_texture_at.c texture/nodes/node_texture_bricks.c texture/nodes/node_texture_checker.c @@ -252,12 +277,16 @@ set(SRC intern/node_util.c composite/node_composite_util.h + function/node_function_util.h shader/node_shader_util.h + simulation/node_simulation_util.h texture/node_texture_util.h NOD_common.h NOD_composite.h + NOD_function.h NOD_shader.h + NOD_simulation.h NOD_socket.h NOD_static_types.h NOD_texture.h diff --git a/source/blender/nodes/NOD_common.h b/source/blender/nodes/NOD_common.h index 26c78eab4ec..dcc4f4d0b76 100644 --- a/source/blender/nodes/NOD_common.h +++ b/source/blender/nodes/NOD_common.h @@ -26,6 +26,10 @@ #include "BKE_node.h" +#ifdef __cplusplus +extern "C" { +#endif + void register_node_type_frame(void); void register_node_type_reroute(void); @@ -42,4 +46,8 @@ struct bNodeSocket *node_group_output_find_socket(struct bNode *node, const char void node_group_input_update(struct bNodeTree *ntree, struct bNode *node); void node_group_output_update(struct bNodeTree *ntree, struct bNode *node); +#ifdef __cplusplus +} +#endif + #endif /* __NOD_COMMON_H__ */ diff --git a/source/blender/nodes/NOD_function.h b/source/blender/nodes/NOD_function.h new file mode 100644 index 00000000000..377ae8bfb84 --- /dev/null +++ b/source/blender/nodes/NOD_function.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef __NOD_FUNCTION_H__ +#define __NOD_FUNCTION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void register_node_type_fn_boolean_math(void); +void register_node_type_fn_float_compare(void); +void register_node_type_fn_switch(void); +void register_node_type_fn_group_instance_id(void); +void register_node_type_fn_combine_strings(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NOD_FUNCTION_H__ */ diff --git a/source/blender/nodes/NOD_simulation.h b/source/blender/nodes/NOD_simulation.h new file mode 100644 index 00000000000..2947d38fe83 --- /dev/null +++ b/source/blender/nodes/NOD_simulation.h @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef __NOD_SIMULATION_H__ +#define __NOD_SIMULATION_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct bNodeTreeType *ntreeType_Simulation; + +void register_node_tree_type_sim(void); + +void register_node_type_sim_group(void); + +void register_node_type_sim_particle_simulation(void); +void register_node_type_sim_force(void); +void register_node_type_sim_set_particle_attribute(void); +void register_node_type_sim_particle_birth_event(void); +void register_node_type_sim_particle_time_step_event(void); +void register_node_type_sim_execute_condition(void); +void register_node_type_sim_multi_execute(void); +void register_node_type_sim_particle_mesh_emitter(void); +void register_node_type_sim_particle_mesh_collision_event(void); +void register_node_type_sim_emit_particles(void); +void register_node_type_sim_time(void); +void register_node_type_sim_particle_attribute(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __NOD_SIMULATION_H__ */ diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 7fec3324aab..91aa11566d3 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -258,6 +258,26 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_NOISE, 0, "TEX_NO DefNode(TextureNode, TEX_NODE_PROC+TEX_STUCCI, 0, "TEX_STUCCI", TexStucci, "Stucci", "" ) DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DISTNOISE", TexDistNoise, "Distorted Noise", "" ) +DefNode(SimulationNode, SIM_NODE_PARTICLE_SIMULATION, 0, "PARTICLE_SIMULATION", ParticleSimulation, "Particle Simulation", "") +DefNode(SimulationNode, SIM_NODE_FORCE, 0, "FORCE", Force, "Force", "") +DefNode(SimulationNode, SIM_NODE_SET_PARTICLE_ATTRIBUTE, def_sim_set_particle_attribute, "SET_PARTICLE_ATTRIBUTE", SetParticleAttribute, "Set Particle Attribute", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_BIRTH_EVENT, 0, "PARTICLE_BIRTH_EVENT", ParticleBirthEvent, "Particle Birth Event", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_TIME_STEP_EVENT, def_sim_particle_time_step_event, "PARTICLE_TIME_STEP_EVENT", ParticleTimeStepEvent, "Particle Time Step Event", "") +DefNode(SimulationNode, SIM_NODE_EXECUTE_CONDITION, 0, "EXECUTE_CONDITION", ExecuteCondition, "Execute Condition", "") +DefNode(SimulationNode, SIM_NODE_MULTI_EXECUTE, 0, "MULTI_EXECUTE", MultiExecute, "Multi Execute", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_EMITTER, 0, "PARTICLE_MESH_EMITTER", ParticleMeshEmitter, "Particle Mesh Emitter", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, 0, "PARTICLE_MESH_COLLISION_EVENT", ParticleMeshCollisionEvent, "Particle Mesh Collision Event", "") +DefNode(SimulationNode, SIM_NODE_EMIT_PARTICLES, 0, "EMIT_PARTICLES", EmitParticles, "Emit Particles", "") +DefNode(SimulationNode, SIM_NODE_TIME, def_sim_time, "TIME", Time, "Time", "") +DefNode(SimulationNode, SIM_NODE_PARTICLE_ATTRIBUTE, def_sim_particle_attribute, "PARTICLE_ATTRIBUTE", ParticleAttribute, "Particle Attribute", "") + +DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, def_boolean_math, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "") +DefNode(FunctionNode, FN_NODE_FLOAT_COMPARE, def_float_compare, "FLOAT_COMPARE", FloatCompare, "Float Compare", "") +DefNode(FunctionNode, FN_NODE_SWITCH, def_fn_switch, "SWITCH", Switch, "Switch", "") +DefNode(FunctionNode, FN_NODE_GROUP_INSTANCE_ID, 0, "GROUP_INSTANCE_ID", GroupInstanceID, "Group Instance ID", "") +DefNode(FunctionNode, FN_NODE_COMBINE_STRINGS, 0, "COMBINE_STRINGS", CombineStrings, "Combine Strings", "") + + /* undefine macros */ #undef DefNode diff --git a/source/blender/nodes/function/node_function_util.cc b/source/blender/nodes/function/node_function_util.cc new file mode 100644 index 00000000000..0927ba335fe --- /dev/null +++ b/source/blender/nodes/function/node_function_util.cc @@ -0,0 +1,30 @@ +/* + * 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. + */ + +#include "node_function_util.h" +#include "node_util.h" + +bool fn_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + /* Function nodes are only supported in simulation node trees so far. */ + return STREQ(ntree->idname, "SimulationNodeTree"); +} + +void fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + ntype->poll = fn_node_poll_default; +} diff --git a/source/blender/nodes/function/node_function_util.h b/source/blender/nodes/function/node_function_util.h new file mode 100644 index 00000000000..85e252f9bdd --- /dev/null +++ b/source/blender/nodes/function/node_function_util.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#ifndef __NODE_FUNCTION_UTIL_H__ +#define __NODE_FUNCTION_UTIL_H__ + +#include <string.h> + +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_node_types.h" + +#include "BKE_node.h" + +#include "BLT_translation.h" + +#include "NOD_function.h" + +#include "node_util.h" + +void fn_node_type_base( + struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +bool fn_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); + +#endif /* __NODE_FUNCTION_UTIL_H__ */ diff --git a/source/blender/nodes/function/nodes/node_fn_boolean_math.cc b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc new file mode 100644 index 00000000000..615ad4c6733 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_boolean_math.cc @@ -0,0 +1,62 @@ +/* + * 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. + */ + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_boolean_math_in[] = { + {SOCK_BOOLEAN, N_("Boolean")}, + {SOCK_BOOLEAN, N_("Boolean")}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_boolean_math_out[] = { + {SOCK_BOOLEAN, N_("Boolean")}, + {-1, ""}, +}; + +static void node_boolean_math_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockB = (bNodeSocket *)BLI_findlink(&node->inputs, 1); + + nodeSetSocketAvailability(sockB, + ELEM(node->custom1, NODE_BOOLEAN_MATH_AND, NODE_BOOLEAN_MATH_OR)); +} + +static void node_boolean_math_label(bNodeTree *UNUSED(ntree), bNode *node, char *label, int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_boolean_math_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +void register_node_type_fn_boolean_math() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_BOOLEAN_MATH, "Boolean Math", 0, 0); + node_type_socket_templates(&ntype, fn_node_boolean_math_in, fn_node_boolean_math_out); + node_type_label(&ntype, node_boolean_math_label); + node_type_update(&ntype, node_boolean_math_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_combine_strings.cc b/source/blender/nodes/function/nodes/node_fn_combine_strings.cc new file mode 100644 index 00000000000..1b6091451d9 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_combine_strings.cc @@ -0,0 +1,21 @@ +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_combine_strings_in[] = { + {SOCK_STRING, N_("A")}, + {SOCK_STRING, N_("B")}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_combine_strings_out[] = { + {SOCK_STRING, N_("Result")}, + {-1, ""}, +}; + +void register_node_type_fn_combine_strings() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_COMBINE_STRINGS, "Combine Strings", 0, 0); + node_type_socket_templates(&ntype, fn_node_combine_strings_in, fn_node_combine_strings_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_float_compare.cc b/source/blender/nodes/function/nodes/node_fn_float_compare.cc new file mode 100644 index 00000000000..9788402850b --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_float_compare.cc @@ -0,0 +1,66 @@ +/* + * 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. + */ + +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "RNA_enum_types.h" + +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_float_compare_in[] = { + {SOCK_FLOAT, N_("A"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_FLOAT, N_("B"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_FLOAT, N_("Epsilon"), 0.001f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_float_compare_out[] = { + {SOCK_BOOLEAN, N_("Result")}, + {-1, ""}, +}; + +static void node_float_compare_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + bNodeSocket *sockEpsilon = (bNodeSocket *)BLI_findlink(&node->inputs, 2); + + nodeSetSocketAvailability( + sockEpsilon, ELEM(node->custom1, NODE_FLOAT_COMPARE_EQUAL, NODE_FLOAT_COMPARE_NOT_EQUAL)); +} + +static void node_float_compare_label(bNodeTree *UNUSED(ntree), + bNode *node, + char *label, + int maxlen) +{ + const char *name; + bool enum_label = RNA_enum_name(rna_enum_node_float_compare_items, node->custom1, &name); + if (!enum_label) { + name = "Unknown"; + } + BLI_strncpy(label, IFACE_(name), maxlen); +} + +void register_node_type_fn_float_compare() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_FLOAT_COMPARE, "Boolean Math", 0, 0); + node_type_socket_templates(&ntype, fn_node_float_compare_in, fn_node_float_compare_out); + node_type_label(&ntype, node_float_compare_label); + node_type_update(&ntype, node_float_compare_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc new file mode 100644 index 00000000000..2ac86ee2407 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_group_instance_id.cc @@ -0,0 +1,15 @@ +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_group_instance_id_out[] = { + {SOCK_STRING, N_("Identifier")}, + {-1, ""}, +}; + +void register_node_type_fn_group_instance_id() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_GROUP_INSTANCE_ID, "Group Instance ID", 0, 0); + node_type_socket_templates(&ntype, nullptr, fn_node_group_instance_id_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/function/nodes/node_fn_switch.cc b/source/blender/nodes/function/nodes/node_fn_switch.cc new file mode 100644 index 00000000000..cb721058875 --- /dev/null +++ b/source/blender/nodes/function/nodes/node_fn_switch.cc @@ -0,0 +1,76 @@ +/* + * 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. + */ + +#include "BLI_listbase.h" +#include "node_function_util.h" + +static bNodeSocketTemplate fn_node_switch_in[] = { + {SOCK_BOOLEAN, N_("Switch")}, + + {SOCK_FLOAT, N_("If False"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_INT, N_("If False"), 0, 0, 0, 0, -10000, 10000}, + {SOCK_BOOLEAN, N_("If False")}, + {SOCK_VECTOR, N_("If False"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_STRING, N_("If False")}, + {SOCK_RGBA, N_("If False"), 0.8f, 0.8f, 0.8f, 1.0f}, + {SOCK_OBJECT, N_("If False")}, + {SOCK_IMAGE, N_("If False")}, + + {SOCK_FLOAT, N_("If True"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_INT, N_("If True"), 0, 0, 0, 0, -10000, 10000}, + {SOCK_BOOLEAN, N_("If True")}, + {SOCK_VECTOR, N_("If True"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_STRING, N_("If True")}, + {SOCK_RGBA, N_("If True"), 0.8f, 0.8f, 0.8f, 1.0f}, + {SOCK_OBJECT, N_("If True")}, + {SOCK_IMAGE, N_("If True")}, + + {-1, ""}, +}; + +static bNodeSocketTemplate fn_node_switch_out[] = { + {SOCK_FLOAT, N_("Result")}, + {SOCK_INT, N_("Result")}, + {SOCK_BOOLEAN, N_("Result")}, + {SOCK_VECTOR, N_("Result")}, + {SOCK_STRING, N_("Result")}, + {SOCK_RGBA, N_("Result")}, + {SOCK_OBJECT, N_("Result")}, + {SOCK_IMAGE, N_("Result")}, + {-1, ""}, +}; + +static void fn_node_switch_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + int index = 0; + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + nodeSetSocketAvailability(sock, index == 0 || sock->type == node->custom1); + index++; + } + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + nodeSetSocketAvailability(sock, sock->type == node->custom1); + } +} + +void register_node_type_fn_switch() +{ + static bNodeType ntype; + + fn_node_type_base(&ntype, FN_NODE_SWITCH, "Switch", 0, 0); + node_type_socket_templates(&ntype, fn_node_switch_in, fn_node_switch_out); + node_type_update(&ntype, fn_node_switch_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/intern/node_common.h b/source/blender/nodes/intern/node_common.h index c3314ae3c28..7810e9f1f14 100644 --- a/source/blender/nodes/intern/node_common.h +++ b/source/blender/nodes/intern/node_common.h @@ -26,6 +26,10 @@ #include "DNA_listBase.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bNodeTree; void node_group_label(struct bNodeTree *ntree, struct bNode *node, char *label, int maxlen); @@ -33,4 +37,8 @@ bool node_group_poll_instance(struct bNode *node, struct bNodeTree *nodetree); void ntree_update_reroute_nodes(struct bNodeTree *ntree); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 199b469781d..668dd3829cc 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -30,6 +30,7 @@ #include "BLI_string.h" #include "BLI_utildefines.h" +#include "BKE_lib_id.h" #include "BKE_node.h" #include "RNA_access.h" @@ -259,6 +260,22 @@ void node_socket_init_default_value(bNodeSocket *sock) sock->default_value = dval; break; } + case SOCK_OBJECT: { + bNodeSocketValueObject *dval = MEM_callocN(sizeof(bNodeSocketValueObject), + "node socket value object"); + dval->value = NULL; + + sock->default_value = dval; + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *dval = MEM_callocN(sizeof(bNodeSocketValueImage), + "node socket value image"); + dval->value = NULL; + + sock->default_value = dval; + break; + } } } @@ -317,6 +334,20 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from) *toval = *fromval; break; } + case SOCK_OBJECT: { + bNodeSocketValueObject *toval = to->default_value; + bNodeSocketValueObject *fromval = from->default_value; + *toval = *fromval; + id_us_plus(&toval->value->id); + break; + } + case SOCK_IMAGE: { + bNodeSocketValueImage *toval = to->default_value; + bNodeSocketValueImage *fromval = from->default_value; + *toval = *fromval; + id_us_plus(&toval->value->id); + break; + } } to->flag |= (from->flag & SOCK_HIDE_VALUE); @@ -467,6 +498,19 @@ static bNodeSocketType *make_socket_type_virtual(void) return stype; } +static bNodeSocketType *make_socket_type_effector(int type) +{ + bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE); + stype->input_link_limit = 0xFFF; + return stype; +} + +static bNodeSocketType *make_socket_type_control_flow(int type) +{ + bNodeSocketType *stype = make_standard_socket_type(type, PROP_NONE); + return stype; +} + void register_standard_node_socket_types(void) { /* draw callbacks are set in drawnode.c to avoid bad-level calls */ @@ -499,5 +543,15 @@ void register_standard_node_socket_types(void) nodeRegisterSocketType(make_standard_socket_type(SOCK_SHADER, PROP_NONE)); + nodeRegisterSocketType(make_standard_socket_type(SOCK_OBJECT, PROP_NONE)); + + nodeRegisterSocketType(make_standard_socket_type(SOCK_IMAGE, PROP_NONE)); + + nodeRegisterSocketType(make_socket_type_effector(SOCK_EMITTERS)); + nodeRegisterSocketType(make_socket_type_effector(SOCK_EVENTS)); + nodeRegisterSocketType(make_socket_type_effector(SOCK_FORCES)); + + nodeRegisterSocketType(make_socket_type_control_flow(SOCK_CONTROL_FLOW)); + nodeRegisterSocketType(make_socket_type_virtual()); } diff --git a/source/blender/nodes/intern/node_util.h b/source/blender/nodes/intern/node_util.h index a7f09d24a70..61f8fe6809d 100644 --- a/source/blender/nodes/intern/node_util.h +++ b/source/blender/nodes/intern/node_util.h @@ -38,6 +38,10 @@ #include "RNA_access.h" +#ifdef __cplusplus +extern "C" { +#endif + struct bNode; struct bNodeTree; @@ -103,4 +107,8 @@ void node_socket_set_vector(struct bNodeTree *ntree, struct bNodeSocket *sock, const float *value); +#ifdef __cplusplus +} +#endif + #endif diff --git a/source/blender/nodes/shader/node_shader_util.c b/source/blender/nodes/shader/node_shader_util.c index 93d03720058..4464a61c48c 100644 --- a/source/blender/nodes/shader/node_shader_util.c +++ b/source/blender/nodes/shader/node_shader_util.c @@ -32,6 +32,11 @@ bool sh_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) return STREQ(ntree->idname, "ShaderNodeTree"); } +static bool sh_fn_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return STREQ(ntree->idname, "ShaderNodeTree") || STREQ(ntree->idname, "SimulationNodeTree"); +} + void sh_node_type_base( struct bNodeType *ntype, int type, const char *name, short nclass, short flag) { @@ -42,6 +47,12 @@ void sh_node_type_base( ntype->update_internal_links = node_update_internal_links_default; } +void sh_fn_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + sh_node_type_base(ntype, type, name, nclass, flag); + ntype->poll = sh_fn_poll_default; +} + /* ****** */ void nodestack_get_vec(float *in, short type_in, bNodeStack *ns) diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index 8d525c8f23c..8834de0633e 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -72,6 +72,8 @@ bool sh_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); void sh_node_type_base( struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +void sh_fn_node_type_base( + struct bNodeType *ntype, int type, const char *name, short nclass, short flag); /* ********* exec data struct, remains internal *********** */ diff --git a/source/blender/nodes/shader/nodes/node_shader_brightness.c b/source/blender/nodes/shader/nodes/node_shader_brightness.c index d8f560277f2..cc1968cb1b1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_brightness.c +++ b/source/blender/nodes/shader/nodes/node_shader_brightness.c @@ -46,7 +46,7 @@ void register_node_type_sh_brightcontrast(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_BRIGHTCONTRAST, "Bright/Contrast", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_brightcontrast_in, sh_node_brightcontrast_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_clamp.c b/source/blender/nodes/shader/nodes/node_shader_clamp.c index c49cfcea8d3..808f9686f0a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_clamp.c +++ b/source/blender/nodes/shader/nodes/node_shader_clamp.c @@ -54,7 +54,7 @@ void register_node_type_sh_clamp(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_CLAMP, "Clamp", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_clamp_in, sh_node_clamp_out); node_type_init(&ntype, node_shader_init_clamp); node_type_gpu(&ntype, gpu_shader_clamp); diff --git a/source/blender/nodes/shader/nodes/node_shader_gamma.c b/source/blender/nodes/shader/nodes/node_shader_gamma.c index b48838e5f56..747979522d1 100644 --- a/source/blender/nodes/shader/nodes/node_shader_gamma.c +++ b/source/blender/nodes/shader/nodes/node_shader_gamma.c @@ -62,7 +62,7 @@ void register_node_type_sh_gamma(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_GAMMA, "Gamma", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_gamma_in, sh_node_gamma_out); node_type_init(&ntype, NULL); node_type_storage(&ntype, "", NULL, NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c index 7a05fc95eec..57ef51c65f6 100644 --- a/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c +++ b/source/blender/nodes/shader/nodes/node_shader_hueSatVal.c @@ -89,7 +89,7 @@ void register_node_type_sh_hue_sat(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_HUE_SAT, "Hue Saturation Value", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_hue_sat_in, sh_node_hue_sat_out); node_type_size_preset(&ntype, NODE_SIZE_MIDDLE); node_type_exec(&ntype, NULL, NULL, node_shader_exec_hue_sat); diff --git a/source/blender/nodes/shader/nodes/node_shader_invert.c b/source/blender/nodes/shader/nodes/node_shader_invert.c index 0d6709a1968..19fa0b0309d 100644 --- a/source/blender/nodes/shader/nodes/node_shader_invert.c +++ b/source/blender/nodes/shader/nodes/node_shader_invert.c @@ -69,7 +69,7 @@ void register_node_type_sh_invert(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_INVERT, "Invert", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_invert_in, sh_node_invert_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_invert); node_type_gpu(&ntype, gpu_shader_invert); diff --git a/source/blender/nodes/shader/nodes/node_shader_map_range.c b/source/blender/nodes/shader/nodes/node_shader_map_range.c index d59540cb8fa..5db7983e752 100644 --- a/source/blender/nodes/shader/nodes/node_shader_map_range.c +++ b/source/blender/nodes/shader/nodes/node_shader_map_range.c @@ -81,7 +81,7 @@ void register_node_type_sh_map_range(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_MAP_RANGE, "Map Range", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_map_range_in, sh_node_map_range_out); node_type_init(&ntype, node_shader_init_map_range); node_type_update(&ntype, node_shader_update_map_range); diff --git a/source/blender/nodes/shader/nodes/node_shader_math.c b/source/blender/nodes/shader/nodes/node_shader_math.c index 08578e0e11e..8abebbf5081 100644 --- a/source/blender/nodes/shader/nodes/node_shader_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_math.c @@ -105,7 +105,7 @@ void register_node_type_sh_math(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_MATH, "Math", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_math_in, sh_node_math_out); node_type_label(&ntype, node_math_label); node_type_gpu(&ntype, gpu_shader_math); diff --git a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c index 9c318073304..93e88664d1a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_mixRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_mixRgb.c @@ -107,7 +107,7 @@ void register_node_type_sh_mix_rgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_MIX_RGB, "Mix", NODE_CLASS_OP_COLOR, 0); node_type_socket_templates(&ntype, sh_node_mix_rgb_in, sh_node_mix_rgb_out); node_type_label(&ntype, node_blend_label); node_type_exec(&ntype, NULL, NULL, node_shader_exec_mix_rgb); diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c index 951755be4f3..2c9b77530a2 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombHSV.c @@ -61,7 +61,7 @@ void register_node_type_sh_sephsv(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_SEPHSV, "Separate HSV", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_sephsv_in, sh_node_sephsv_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_sephsv); node_type_gpu(&ntype, gpu_shader_sephsv); @@ -109,7 +109,7 @@ void register_node_type_sh_combhsv(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_COMBHSV, "Combine HSV", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combhsv_in, sh_node_combhsv_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_combhsv); node_type_gpu(&ntype, gpu_shader_combhsv); diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c index f10f80d5c2d..d0dc45dcedd 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombRGB.c @@ -63,7 +63,7 @@ void register_node_type_sh_seprgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_SEPRGB, "Separate RGB", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_seprgb_in, sh_node_seprgb_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_seprgb); node_type_gpu(&ntype, gpu_shader_seprgb); @@ -113,7 +113,7 @@ void register_node_type_sh_combrgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_COMBRGB, "Combine RGB", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combrgb_in, sh_node_combrgb_out); node_type_exec(&ntype, NULL, NULL, node_shader_exec_combrgb); node_type_gpu(&ntype, gpu_shader_combrgb); diff --git a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c index 55d5084b132..429b1a3e818 100644 --- a/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c +++ b/source/blender/nodes/shader/nodes/node_shader_sepcombXYZ.c @@ -48,7 +48,7 @@ void register_node_type_sh_sepxyz(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_SEPXYZ, "Separate XYZ", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_sepxyz_in, sh_node_sepxyz_out); node_type_gpu(&ntype, gpu_shader_sepxyz); @@ -80,7 +80,7 @@ void register_node_type_sh_combxyz(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_COMBXYZ, "Combine XYZ", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_combxyz_in, sh_node_combxyz_out); node_type_gpu(&ntype, gpu_shader_combxyz); diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c index fa98f9efb74..420c5b75926 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_musgrave.c @@ -137,6 +137,9 @@ static void node_shader_update_tex_musgrave(bNodeTree *UNUSED(ntree), bNode *nod nodeSetSocketAvailability(inGainSock, tex->musgrave_type == SHD_MUSGRAVE_HYBRID_MULTIFRACTAL || tex->musgrave_type == SHD_MUSGRAVE_RIDGED_MULTIFRACTAL); + + bNodeSocket *outFacSock = nodeFindSocket(node, SOCK_OUT, "Fac"); + node_sock_label(outFacSock, "Height"); } void register_node_type_sh_tex_musgrave(void) diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c index 7b67c2d1f2e..67268c102c5 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_noise.c @@ -91,7 +91,7 @@ void register_node_type_sh_tex_noise(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); + sh_fn_node_type_base(&ntype, SH_NODE_TEX_NOISE, "Noise Texture", NODE_CLASS_TEXTURE, 0); node_type_socket_templates(&ntype, sh_node_tex_noise_in, sh_node_tex_noise_out); node_type_init(&ntype, node_shader_init_tex_noise); node_type_storage( diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c index 1789dc44bf1..817ccdc8b6a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c +++ b/source/blender/nodes/shader/nodes/node_shader_tex_white_noise.c @@ -72,7 +72,8 @@ void register_node_type_sh_tex_white_noise(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0); + sh_fn_node_type_base( + &ntype, SH_NODE_TEX_WHITE_NOISE, "White Noise Texture", NODE_CLASS_TEXTURE, 0); node_type_socket_templates(&ntype, sh_node_tex_white_noise_in, sh_node_tex_white_noise_out); node_type_init(&ntype, node_shader_init_tex_white_noise); node_type_gpu(&ntype, gpu_shader_tex_white_noise); diff --git a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c index 49f9befdce3..20f280d00c3 100644 --- a/source/blender/nodes/shader/nodes/node_shader_valToRgb.c +++ b/source/blender/nodes/shader/nodes/node_shader_valToRgb.c @@ -125,7 +125,7 @@ void register_node_type_sh_valtorgb(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_VALTORGB, "ColorRamp", NODE_CLASS_CONVERTOR, 0); node_type_socket_templates(&ntype, sh_node_valtorgb_in, sh_node_valtorgb_out); node_type_init(&ntype, node_shader_init_valtorgb); node_type_size_preset(&ntype, NODE_SIZE_LARGE); diff --git a/source/blender/nodes/shader/nodes/node_shader_vector_math.c b/source/blender/nodes/shader/nodes/node_shader_vector_math.c index 3a6e273eb20..b719fe03d9b 100644 --- a/source/blender/nodes/shader/nodes/node_shader_vector_math.c +++ b/source/blender/nodes/shader/nodes/node_shader_vector_math.c @@ -134,7 +134,7 @@ void register_node_type_sh_vect_math(void) { static bNodeType ntype; - sh_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); + sh_fn_node_type_base(&ntype, SH_NODE_VECTOR_MATH, "Vector Math", NODE_CLASS_OP_VECTOR, 0); node_type_socket_templates(&ntype, sh_node_vector_math_in, sh_node_vector_math_out); node_type_label(&ntype, node_vector_math_label); node_type_gpu(&ntype, gpu_shader_vector_math); diff --git a/source/blender/nodes/simulation/node_simulation_tree.cc b/source/blender/nodes/simulation/node_simulation_tree.cc new file mode 100644 index 00000000000..3f0e70259d6 --- /dev/null +++ b/source/blender/nodes/simulation/node_simulation_tree.cc @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "NOD_simulation.h" + +#include "BKE_node.h" + +#include "BLT_translation.h" + +#include "DNA_node_types.h" + +#include "RNA_access.h" + +bNodeTreeType *ntreeType_Simulation; + +void register_node_tree_type_sim(void) +{ + bNodeTreeType *tt = ntreeType_Simulation = (bNodeTreeType *)MEM_callocN( + sizeof(bNodeTreeType), "simulation node tree type"); + tt->type = NTREE_SIMULATION; + strcpy(tt->idname, "SimulationNodeTree"); + strcpy(tt->ui_name, N_("Simulation Editor")); + tt->ui_icon = 0; /* defined in drawnode.c */ + strcpy(tt->ui_description, N_("Simulation nodes")); + tt->rna_ext.srna = &RNA_SimulationNodeTree; + + ntreeTypeAdd(tt); +} diff --git a/source/blender/nodes/simulation/node_simulation_util.cc b/source/blender/nodes/simulation/node_simulation_util.cc new file mode 100644 index 00000000000..ae875335da8 --- /dev/null +++ b/source/blender/nodes/simulation/node_simulation_util.cc @@ -0,0 +1,29 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" +#include "node_util.h" + +bool sim_node_poll_default(bNodeType *UNUSED(ntype), bNodeTree *ntree) +{ + return STREQ(ntree->idname, "SimulationNodeTree"); +} + +void sim_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag) +{ + node_type_base(ntype, type, name, nclass, flag); + ntype->poll = sim_node_poll_default; +} diff --git a/source/blender/nodes/simulation/node_simulation_util.h b/source/blender/nodes/simulation/node_simulation_util.h new file mode 100644 index 00000000000..adbe2ad5e8f --- /dev/null +++ b/source/blender/nodes/simulation/node_simulation_util.h @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#ifndef __NODE_SIM_UTIL_H__ +#define __NODE_SIM_UTIL_H__ + +#include <string.h> + +#include "BLI_utildefines.h" + +#include "MEM_guardedalloc.h" + +#include "DNA_node_types.h" + +#include "BKE_node.h" + +#include "BLT_translation.h" + +#include "NOD_simulation.h" + +#include "node_util.h" + +void sim_node_type_base( + struct bNodeType *ntype, int type, const char *name, short nclass, short flag); +bool sim_node_poll_default(struct bNodeType *ntype, struct bNodeTree *ntree); + +#endif /* __NODE_SIM_UTIL_H__ */ diff --git a/source/blender/nodes/simulation/nodes/node_sim_common.cc b/source/blender/nodes/simulation/nodes/node_sim_common.cc new file mode 100644 index 00000000000..fbc03905d4f --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_common.cc @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#include "BKE_node.h" + +#include "NOD_simulation.h" + +#include "NOD_common.h" +#include "node_common.h" +#include "node_simulation_util.h" + +void register_node_type_sim_group(void) +{ + static bNodeType ntype; + + node_type_base_custom(&ntype, "SimulationNodeGroup", "Group", 0, 0); + ntype.type = NODE_GROUP; + ntype.poll = sim_node_poll_default; + ntype.poll_instance = node_group_poll_instance; + ntype.insert_link = node_insert_link_default; + ntype.update_internal_links = node_update_internal_links_default; + ntype.rna_ext.srna = RNA_struct_find("SimulationNodeGroup"); + BLI_assert(ntype.rna_ext.srna != NULL); + RNA_struct_blender_type_set(ntype.rna_ext.srna, &ntype); + + node_type_socket_templates(&ntype, NULL, NULL); + node_type_size(&ntype, 140, 60, 400); + node_type_label(&ntype, node_group_label); + node_type_group_update(&ntype, node_group_update); + + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc new file mode 100644 index 00000000000..e23984dbf34 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_emit_particles.cc @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_emit_particle_in[] = { + {SOCK_INT, N_("Amount"), 10, 0, 0, 0, 0, 10000000}, + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_emit_particle_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {SOCK_EMITTERS, N_("Emitter")}, + {-1, ""}, +}; + +void register_node_type_sim_emit_particles() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_EMIT_PARTICLES, "Emit Particles", 0, 0); + node_type_socket_templates(&ntype, sim_node_emit_particle_in, sim_node_emit_particle_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc new file mode 100644 index 00000000000..69f30d1ad0d --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_execute_condition.cc @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_execute_condition_in[] = { + {SOCK_BOOLEAN, N_("Condition")}, + {SOCK_CONTROL_FLOW, N_("If True")}, + {SOCK_CONTROL_FLOW, N_("If False")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_execute_condition_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +void register_node_type_sim_execute_condition() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_EXECUTE_CONDITION, "Execute Condition", 0, 0); + node_type_socket_templates( + &ntype, sim_node_execute_condition_in, sim_node_execute_condition_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_force.cc b/source/blender/nodes/simulation/nodes/node_sim_force.cc new file mode 100644 index 00000000000..eccd2e4e2ab --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_force.cc @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_force_in[] = { + {SOCK_VECTOR, N_("Force"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_force_out[] = { + {SOCK_FORCES, N_("Force")}, + {-1, ""}, +}; + +void register_node_type_sim_force() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_FORCE, "Force", 0, 0); + node_type_socket_templates(&ntype, sim_node_force_in, sim_node_force_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc new file mode 100644 index 00000000000..5944db7e2bc --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_multi_execute.cc @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_multi_execute_in[] = { + {SOCK_CONTROL_FLOW, "1"}, + {SOCK_CONTROL_FLOW, "2"}, + {SOCK_CONTROL_FLOW, "3"}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_multi_execute_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +void register_node_type_sim_multi_execute() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_MULTI_EXECUTE, "Multi Execute", 0, 0); + node_type_socket_templates(&ntype, sim_node_multi_execute_in, sim_node_multi_execute_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc new file mode 100644 index 00000000000..b6b67ee334e --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_attribute.cc @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#include "BLI_listbase.h" +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_attribute_in[] = { + {SOCK_STRING, N_("Name")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_attribute_out[] = { + {SOCK_FLOAT, N_("Float")}, + {SOCK_INT, N_("Int")}, + {SOCK_BOOLEAN, N_("Boolean")}, + {SOCK_VECTOR, N_("Vector")}, + {SOCK_RGBA, N_("Color")}, + {SOCK_OBJECT, N_("Object")}, + {SOCK_IMAGE, N_("Image")}, + {-1, ""}, +}; + +static void sim_node_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + LISTBASE_FOREACH (bNodeSocket *, sock, &node->outputs) { + nodeSetSocketAvailability(sock, sock->type == node->custom1); + } +} + +void register_node_type_sim_particle_attribute() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_ATTRIBUTE, "Particle Attribute", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_attribute_in, sim_node_particle_attribute_out); + node_type_update(&ntype, sim_node_particle_attribute_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc new file mode 100644 index 00000000000..8332a3ecd9f --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_birth_event.cc @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_birth_event_in[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_birth_event_out[] = { + {SOCK_EVENTS, N_("Event")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_birth_event() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_BIRTH_EVENT, "Particle Birth Event", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_birth_event_in, sim_node_particle_birth_event_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc new file mode 100644 index 00000000000..48671172136 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_collision_event.cc @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_mesh_collision_event_in[] = { + {SOCK_OBJECT, N_("Object")}, + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_mesh_collision_event_out[] = { + {SOCK_EVENTS, N_("Event")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_mesh_collision_event() +{ + static bNodeType ntype; + + sim_node_type_base( + &ntype, SIM_NODE_PARTICLE_MESH_COLLISION_EVENT, "Particle Mesh Collision Event", 0, 0); + node_type_socket_templates(&ntype, + sim_node_particle_mesh_collision_event_in, + sim_node_particle_mesh_collision_event_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc new file mode 100644 index 00000000000..2de7be2d3eb --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_mesh_emitter.cc @@ -0,0 +1,40 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +#include "float.h" + +static bNodeSocketTemplate sim_node_particle_mesh_emitter_in[] = { + {SOCK_OBJECT, N_("Object")}, + {SOCK_FLOAT, N_("Rate"), 10.0f, 0.0f, 0.0f, 0.0f, 0.0f, FLT_MAX}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_mesh_emitter_out[] = { + {SOCK_EMITTERS, N_("Emitter")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_mesh_emitter() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_MESH_EMITTER, "Mesh Emitter", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_mesh_emitter_in, sim_node_particle_mesh_emitter_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc new file mode 100644 index 00000000000..159c9b23da1 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_simulation.cc @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_simulation_in[] = { + {SOCK_EMITTERS, N_("Emitters")}, + {SOCK_EVENTS, N_("Events")}, + {SOCK_FORCES, N_("Forces")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_simulation_out[] = { + {-1, ""}, +}; + +void register_node_type_sim_particle_simulation() +{ + static bNodeType ntype; + + sim_node_type_base( + &ntype, SIM_NODE_PARTICLE_SIMULATION, "Particle Simulation", NODE_CLASS_OUTPUT, 0); + node_type_socket_templates( + &ntype, sim_node_particle_simulation_in, sim_node_particle_simulation_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc new file mode 100644 index 00000000000..cda8ddeb644 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_particle_time_step_event.cc @@ -0,0 +1,37 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_particle_time_step_event_in[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_particle_time_step_event_out[] = { + {SOCK_EVENTS, N_("Event")}, + {-1, ""}, +}; + +void register_node_type_sim_particle_time_step_event() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_PARTICLE_TIME_STEP_EVENT, "Particle Time Step Event", 0, 0); + node_type_socket_templates( + &ntype, sim_node_particle_time_step_event_in, sim_node_particle_time_step_event_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc new file mode 100644 index 00000000000..8696dbe340c --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_set_particle_attribute.cc @@ -0,0 +1,57 @@ +/* + * 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. + */ + +#include "BLI_listbase.h" +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_set_particle_attribute_in[] = { + {SOCK_STRING, N_("Name")}, + {SOCK_FLOAT, N_("Float"), 0.0f, 0.0f, 0.0f, 0.0f, -10000.0f, 10000.0f}, + {SOCK_INT, N_("Int"), 0, 0, 0, 0, -10000, 10000}, + {SOCK_BOOLEAN, N_("Boolean")}, + {SOCK_VECTOR, N_("Vector")}, + {SOCK_RGBA, N_("Color")}, + {SOCK_OBJECT, N_("Object")}, + {SOCK_IMAGE, N_("Image")}, + {-1, ""}, +}; + +static bNodeSocketTemplate sim_node_set_particle_attribute_out[] = { + {SOCK_CONTROL_FLOW, N_("Execute")}, + {-1, ""}, +}; + +static void sim_node_set_particle_attribute_update(bNodeTree *UNUSED(ntree), bNode *node) +{ + int index = 0; + LISTBASE_FOREACH (bNodeSocket *, sock, &node->inputs) { + if (index >= 1) { + nodeSetSocketAvailability(sock, sock->type == node->custom1); + } + index++; + } +} + +void register_node_type_sim_set_particle_attribute() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_SET_PARTICLE_ATTRIBUTE, "Set Particle Attribute", 0, 0); + node_type_socket_templates( + &ntype, sim_node_set_particle_attribute_in, sim_node_set_particle_attribute_out); + node_type_update(&ntype, sim_node_set_particle_attribute_update); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc new file mode 100644 index 00000000000..40e1c43fb69 --- /dev/null +++ b/source/blender/nodes/simulation/nodes/node_sim_simulation_time.cc @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#include "node_simulation_util.h" + +static bNodeSocketTemplate sim_node_time_out[] = { + {SOCK_FLOAT, N_("Time")}, + {-1, ""}, +}; + +void register_node_type_sim_time() +{ + static bNodeType ntype; + + sim_node_type_base(&ntype, SIM_NODE_TIME, "Time", 0, 0); + node_type_socket_templates(&ntype, nullptr, sim_node_time_out); + nodeRegisterType(&ntype); +} diff --git a/source/blender/nodes/texture/node_texture_tree.c b/source/blender/nodes/texture/node_texture_tree.c index 31f67cb1ffa..b3d595cc69b 100644 --- a/source/blender/nodes/texture/node_texture_tree.c +++ b/source/blender/nodes/texture/node_texture_tree.c @@ -282,7 +282,7 @@ int ntreeTexExecTree(bNodeTree *nodes, float dyt[3], int osatex, const short thread, - Tex *UNUSED(tex), + const Tex *UNUSED(tex), short which_output, int cfra, int preview, diff --git a/source/blender/physics/intern/BPH_mass_spring.cpp b/source/blender/physics/intern/BPH_mass_spring.cpp index 76f0f8c8b55..6a951519730 100644 --- a/source/blender/physics/intern/BPH_mass_spring.cpp +++ b/source/blender/physics/intern/BPH_mass_spring.cpp @@ -23,7 +23,6 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "DNA_cloth_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -38,7 +37,6 @@ extern "C" { #include "BKE_cloth.h" #include "BKE_collision.h" #include "BKE_effect.h" -} #include "BPH_mass_spring.h" #include "implicit.h" diff --git a/source/blender/physics/intern/hair_volume.cpp b/source/blender/physics/intern/hair_volume.cpp index b8783c51fe8..6246bf54f75 100644 --- a/source/blender/physics/intern/hair_volume.cpp +++ b/source/blender/physics/intern/hair_volume.cpp @@ -23,14 +23,12 @@ #include "MEM_guardedalloc.h" -extern "C" { #include "BLI_math.h" #include "BLI_utildefines.h" #include "DNA_texture_types.h" #include "BKE_effect.h" -} #include "eigen_utils.h" #include "implicit.h" diff --git a/source/blender/python/BPY_extern.h b/source/blender/python/BPY_extern.h index d4e57f0beb6..18d4c7da534 100644 --- a/source/blender/python/BPY_extern.h +++ b/source/blender/python/BPY_extern.h @@ -35,12 +35,12 @@ struct bContext; struct bContextDataResult; struct bPythonConstraint; /* DNA_constraint_types.h */ +#include "BLI_utildefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "BLI_utildefines.h" - void BPY_pyconstraint_exec(struct bPythonConstraint *con, struct bConstraintOb *cob, struct ListBase *targets); diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 726599ff06e..50ae05694eb 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -33,7 +33,7 @@ #include "BLI_math_base.h" #include "BLI_string.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "BKE_global.h" #include "bpy_rna_driver.h" /* for pyrna_driver_get_variable_value */ diff --git a/source/blender/python/intern/bpy_rna_driver.c b/source/blender/python/intern/bpy_rna_driver.c index a8d8252b231..9240e34bbab 100644 --- a/source/blender/python/intern/bpy_rna_driver.c +++ b/source/blender/python/intern/bpy_rna_driver.c @@ -26,7 +26,7 @@ #include "BLI_utildefines.h" -#include "BKE_fcurve.h" +#include "BKE_fcurve_driver.h" #include "RNA_access.h" diff --git a/source/blender/python/mathutils/mathutils_Vector.c b/source/blender/python/mathutils/mathutils_Vector.c index 6ea0dd52ed7..ace7480ee81 100644 --- a/source/blender/python/mathutils/mathutils_Vector.c +++ b/source/blender/python/mathutils/mathutils_Vector.c @@ -930,7 +930,7 @@ PyDoc_STRVAR(Vector_dot_doc, " :arg other: The other vector to perform the dot product with.\n" " :type other: :class:`Vector`\n" " :return: The dot product.\n" - " :rtype: :class:`Vector`\n"); + " :rtype: float\n"); static PyObject *Vector_dot(VectorObject *self, PyObject *value) { float *tvec; diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 54296e16834..b963021dfd9 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -40,6 +40,10 @@ struct StampData; struct ViewLayer; struct bMovieHandle; +#ifdef __cplusplus +extern "C" { +#endif + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is what is exposed of render to outside world */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -386,4 +390,8 @@ struct RenderView *RE_RenderViewGetByName(struct RenderResult *res, const char * RenderResult *RE_DuplicateRenderResult(RenderResult *rr); +#ifdef __cplusplus +} +#endif + #endif /* __RE_PIPELINE_H__ */ diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index bca3b749192..bdf81354b8d 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -33,18 +33,16 @@ struct ImagePool; struct MTex; /* render_texture.c */ -/* used by particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ -int externtex(const struct MTex *mtex, - const float vec[3], - float *tin, - float *tr, - float *tg, - float *tb, - float *ta, - const int thread, - struct ImagePool *pool, - const bool skip_load_image, - const bool texnode_preview); +bool RE_texture_evaluate(const struct MTex *mtex, + const float vec[3], + const int thread, + struct ImagePool *pool, + const bool skip_load_image, + const bool texnode_preview, + /* Return arguments. */ + float *r_intensity, + float r_rgba[4]) ATTR_NONNULL(1, 2, 7, 8); + void texture_rgb_blend( float in[3], const float tex[3], const float out[3], float fact, float facg, int blendtype); float texture_value_blend(float tex, float out, float fact, float facg, int blendtype); diff --git a/source/blender/render/extern/include/RE_shader_ext.h b/source/blender/render/extern/include/RE_shader_ext.h index 792b2b7e071..f69ae4dfd5c 100644 --- a/source/blender/render/extern/include/RE_shader_ext.h +++ b/source/blender/render/extern/include/RE_shader_ext.h @@ -23,6 +23,10 @@ #ifndef __RE_SHADER_EXT_H__ #define __RE_SHADER_EXT_H__ +#ifdef __cplusplus +extern "C" { +#endif + /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* this include is for texture exports */ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ @@ -75,4 +79,8 @@ int multitex_nodes(struct Tex *tex, struct MTex *mtex, struct ImagePool *pool); +#ifdef __cplusplus +} +#endif + #endif /* __RE_SHADER_EXT_H__ */ diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index f7901ebb7d0..77a482f8546 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -2514,7 +2514,7 @@ void RE_RenderAnim(Render *re, { float ctime = BKE_scene_frame_get(scene); AnimData *adt = BKE_animdata_from_id(&scene->id); - BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, ADT_RECALC_ALL, false); + BKE_animsys_evaluate_animdata(&scene->id, adt, ctime, ADT_RECALC_ALL, false); } render_update_depsgraph(re); diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index eabba94ef29..ee484924bf9 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -79,7 +79,7 @@ void RE_texture_rng_exit(void) /* ------------------------------------------------------------------------- */ /* this allows colorbanded textures to control normals as well */ -static void tex_normal_derivate(Tex *tex, TexResult *texres) +static void tex_normal_derivate(const Tex *tex, TexResult *texres) { if (tex->flag & TEX_COLORBAND) { float col[4]; @@ -106,7 +106,7 @@ static void tex_normal_derivate(Tex *tex, TexResult *texres) texres->nor[2] = texres->tin - texres->nor[2]; } -static int blend(Tex *tex, const float texvec[3], TexResult *texres) +static int blend(const Tex *tex, const float texvec[3], TexResult *texres) { float x, y, t; @@ -170,7 +170,7 @@ static int blend(Tex *tex, const float texvec[3], TexResult *texres) /* newnoise: all noisebased types now have different noisebases to choose from */ -static int clouds(Tex *tex, const float texvec[3], TexResult *texres) +static int clouds(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -271,7 +271,7 @@ static float tex_tri(float a) } /* computes basic wood intensity value at x,y,z */ -static float wood_int(Tex *tex, float x, float y, float z) +static float wood_int(const Tex *tex, float x, float y, float z) { float wi = 0; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */ @@ -308,7 +308,7 @@ static float wood_int(Tex *tex, float x, float y, float z) return wi; } -static int wood(Tex *tex, const float texvec[3], TexResult *texres) +static int wood(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -329,7 +329,7 @@ static int wood(Tex *tex, const float texvec[3], TexResult *texres) } /* computes basic marble intensity at x,y,z */ -static float marble_int(Tex *tex, float x, float y, float z) +static float marble_int(const Tex *tex, float x, float y, float z) { float n, mi; short wf = tex->noisebasis2; /* wave form: TEX_SIN=0, TEX_SAW=1, TEX_TRI=2 */ @@ -367,7 +367,7 @@ static float marble_int(Tex *tex, float x, float y, float z) return mi; } -static int marble(Tex *tex, const float texvec[3], TexResult *texres) +static int marble(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -391,7 +391,7 @@ static int marble(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ -static int magic(Tex *tex, const float texvec[3], TexResult *texres) +static int magic(const Tex *tex, const float texvec[3], TexResult *texres) { float x, y, z, turb; int n; @@ -467,7 +467,7 @@ static int magic(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: stucci also modified to use different noisebasis */ -static int stucci(Tex *tex, const float texvec[3], TexResult *texres) +static int stucci(const Tex *tex, const float texvec[3], TexResult *texres) { float nor[3], b2, ofs; int retval = TEX_INT; @@ -533,7 +533,7 @@ static int stucci(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ /* newnoise: musgrave terrain noise types */ -static float mg_mFractalOrfBmTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_mFractalOrfBmTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float (*mgravefunc)(float, float, float, float, float, float, int); @@ -588,7 +588,7 @@ static float mg_mFractalOrfBmTex(Tex *tex, const float texvec[3], TexResult *tex return rv; } -static float mg_ridgedOrHybridMFTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_ridgedOrHybridMFTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float (*mgravefunc)(float, float, float, float, float, float, float, float, int); @@ -651,7 +651,7 @@ static float mg_ridgedOrHybridMFTex(Tex *tex, const float texvec[3], TexResult * return rv; } -static float mg_HTerrainTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_HTerrainTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -702,7 +702,7 @@ static float mg_HTerrainTex(Tex *tex, const float texvec[3], TexResult *texres) return rv; } -static float mg_distNoiseTex(Tex *tex, const float texvec[3], TexResult *texres) +static int mg_distNoiseTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; @@ -747,7 +747,7 @@ static float mg_distNoiseTex(Tex *tex, const float texvec[3], TexResult *texres) * probably the slowest, especially with minkovsky, bumpmapping, could be done another way. */ -static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) +static int voronoiTex(const Tex *tex, const float texvec[3], TexResult *texres) { int rv = TEX_INT; float da[4], pa[12]; /* distance and point coordinate arrays of 4 nearest neighbors */ @@ -761,8 +761,7 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) } voronoi(texvec[0], texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->tin = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->tin = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); if (tex->vn_coltype) { float ca[3]; /* cell color */ @@ -809,14 +808,11 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) /* calculate bumpnormal */ voronoi(texvec[0] + offs, texvec[1], texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[0] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->nor[0] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); voronoi(texvec[0], texvec[1] + offs, texvec[2], da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[1] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->nor[1] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); voronoi(texvec[0], texvec[1], texvec[2] + offs, da, pa, tex->vn_mexp, tex->vn_distm); - texres->nor[2] = sc * fabsf(tex->vn_w1 * da[0] + tex->vn_w2 * da[1] + tex->vn_w3 * da[2] + - tex->vn_w4 * da[3]); + texres->nor[2] = sc * fabsf(dot_v4v4(&tex->vn_w1, da)); tex_normal_derivate(tex, texres); rv |= TEX_NOR; @@ -835,7 +831,7 @@ static float voronoiTex(Tex *tex, const float texvec[3], TexResult *texres) /* ------------------------------------------------------------------------- */ -static int texnoise(Tex *tex, TexResult *texres, int thread) +static int texnoise(const Tex *tex, TexResult *texres, int thread) { float div = 3.0; int val, ran, loop, shift = 29; @@ -1724,17 +1720,20 @@ float texture_value_blend(float tex, float out, float fact, float facg, int blen /* ------------------------------------------------------------------------- */ -int externtex(const MTex *mtex, - const float vec[3], - float *tin, - float *tr, - float *tg, - float *tb, - float *ta, - const int thread, - struct ImagePool *pool, - const bool skip_load_image, - const bool texnode_preview) +/** + * \param pool: Thread pool, may be NULL. + * + * \return True if the texture has color, otherwise false. + */ +bool RE_texture_evaluate(const MTex *mtex, + const float vec[3], + const int thread, + struct ImagePool *pool, + const bool skip_load_image, + const bool texnode_preview, + /* Return arguments. */ + float *r_intensity, + float r_rgba[4]) { Tex *tex; TexResult texr; @@ -1796,11 +1795,11 @@ int externtex(const MTex *mtex, texr.tb = mtex->b; } - *tin = texr.tin; - *tr = texr.tr; - *tg = texr.tg; - *tb = texr.tb; - *ta = texr.ta; + *r_intensity = texr.tin; + r_rgba[0] = texr.tr; + r_rgba[1] = texr.tg; + r_rgba[2] = texr.tb; + r_rgba[3] = texr.ta; return (rgb != 0); } diff --git a/source/blender/shader_fx/intern/FX_shader_blur.c b/source/blender/shader_fx/intern/FX_shader_blur.c index e98205897aa..8881f147af8 100644 --- a/source/blender/shader_fx/intern/FX_shader_blur.c +++ b/source/blender/shader_fx/intern/FX_shader_blur.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -38,7 +38,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Blur = { diff --git a/source/blender/shader_fx/intern/FX_shader_colorize.c b/source/blender/shader_fx/intern/FX_shader_colorize.c index 7438fbf7fa7..5fea2cd0ff8 100644 --- a/source/blender/shader_fx/intern/FX_shader_colorize.c +++ b/source/blender/shader_fx/intern/FX_shader_colorize.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -40,7 +40,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Colorize = { diff --git a/source/blender/shader_fx/intern/FX_shader_flip.c b/source/blender/shader_fx/intern/FX_shader_flip.c index ddf4d201ca7..b915fb8e591 100644 --- a/source/blender/shader_fx/intern/FX_shader_flip.c +++ b/source/blender/shader_fx/intern/FX_shader_flip.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -39,7 +39,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Flip = { diff --git a/source/blender/shader_fx/intern/FX_shader_glow.c b/source/blender/shader_fx/intern/FX_shader_glow.c index a81e69e00a1..1194e95ce79 100644 --- a/source/blender/shader_fx/intern/FX_shader_glow.c +++ b/source/blender/shader_fx/intern/FX_shader_glow.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -47,7 +47,7 @@ static void initData(ShaderFxData *md) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Glow = { diff --git a/source/blender/shader_fx/intern/FX_shader_light.c b/source/blender/shader_fx/intern/FX_shader_light.c index c81d959ebe0..17d2f518d44 100644 --- a/source/blender/shader_fx/intern/FX_shader_light.c +++ b/source/blender/shader_fx/intern/FX_shader_light.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -48,7 +48,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } static void updateDepsgraph(ShaderFxData *md, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/shader_fx/intern/FX_shader_pixel.c b/source/blender/shader_fx/intern/FX_shader_pixel.c index f39649bba07..04bf9ae5b6d 100644 --- a/source/blender/shader_fx/intern/FX_shader_pixel.c +++ b/source/blender/shader_fx/intern/FX_shader_pixel.c @@ -10,7 +10,7 @@ * 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, + * 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) 2017, Blender Foundation @@ -36,7 +36,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Pixel = { diff --git a/source/blender/shader_fx/intern/FX_shader_rim.c b/source/blender/shader_fx/intern/FX_shader_rim.c index a81d2ff2a09..16c6a6716a0 100644 --- a/source/blender/shader_fx/intern/FX_shader_rim.c +++ b/source/blender/shader_fx/intern/FX_shader_rim.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -43,7 +43,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Rim = { diff --git a/source/blender/shader_fx/intern/FX_shader_shadow.c b/source/blender/shader_fx/intern/FX_shader_shadow.c index 6887e988fc7..dcf66ec89e0 100644 --- a/source/blender/shader_fx/intern/FX_shader_shadow.c +++ b/source/blender/shader_fx/intern/FX_shader_shadow.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -59,7 +59,7 @@ static void initData(ShaderFxData *md) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } static void updateDepsgraph(ShaderFxData *fx, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/shader_fx/intern/FX_shader_swirl.c b/source/blender/shader_fx/intern/FX_shader_swirl.c index 8e1e4a5e9fe..990b43748da 100644 --- a/source/blender/shader_fx/intern/FX_shader_swirl.c +++ b/source/blender/shader_fx/intern/FX_shader_swirl.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -48,7 +48,7 @@ static void initData(ShaderFxData *md) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } static void updateDepsgraph(ShaderFxData *fx, const ModifierUpdateDepsgraphContext *ctx) diff --git a/source/blender/shader_fx/intern/FX_shader_wave.c b/source/blender/shader_fx/intern/FX_shader_wave.c index a4ad108bc94..7dc72bcb669 100644 --- a/source/blender/shader_fx/intern/FX_shader_wave.c +++ b/source/blender/shader_fx/intern/FX_shader_wave.c @@ -10,7 +10,7 @@ * 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, + * 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) 2018, Blender Foundation @@ -42,7 +42,7 @@ static void initData(ShaderFxData *fx) static void copyData(const ShaderFxData *md, ShaderFxData *target) { - BKE_shaderfx_copyData_generic(md, target); + BKE_shaderfx_copydata_generic(md, target); } ShaderFxTypeInfo shaderfx_Type_Wave = { diff --git a/source/blender/windowmanager/CMakeLists.txt b/source/blender/windowmanager/CMakeLists.txt index 90ff7bb8f85..22fd55cd49a 100644 --- a/source/blender/windowmanager/CMakeLists.txt +++ b/source/blender/windowmanager/CMakeLists.txt @@ -153,8 +153,8 @@ endif() if(WITH_HEADLESS) add_definitions(-DWITH_HEADLESS) -elseif(WITH_X11) - add_definitions(-DWITH_X11) +elseif(WITH_GHOST_X11) + add_definitions(-DWITH_GHOST_X11) endif() if(WITH_PYTHON) diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index bd534c51c9a..219a6b7365a 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -618,7 +618,7 @@ int WM_gesture_lasso_modal(struct bContext *C, struct wmOperator *op, const stru void WM_gesture_lasso_cancel(struct bContext *C, struct wmOperator *op); const int (*WM_gesture_lasso_path_to_array(struct bContext *C, struct wmOperator *op, - int *mcords_tot))[2]; + int *mcoords_len))[2]; int WM_gesture_straightline_invoke(struct bContext *C, struct wmOperator *op, const struct wmEvent *event); @@ -875,6 +875,7 @@ void WM_generic_user_data_free(struct wmGenericUserData *user_data); bool WM_xr_session_exists(const wmXrData *xr); bool WM_xr_session_is_ready(const wmXrData *xr); struct wmXrSessionState *WM_xr_session_state_handle_get(const wmXrData *xr); +void WM_xr_session_base_pose_reset(wmXrData *xr); bool WM_xr_session_state_viewer_pose_location_get(const wmXrData *xr, float r_location[3]); bool WM_xr_session_state_viewer_pose_rotation_get(const wmXrData *xr, float r_rotation[4]); bool WM_xr_session_state_viewer_pose_matrix_info_get(const wmXrData *xr, diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index c7d1c4992e3..4acce793707 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -109,10 +109,6 @@ #ifndef __WM_TYPES_H__ #define __WM_TYPES_H__ -#ifdef __cplusplus -extern "C" { -#endif - struct ID; struct ImBuf; struct bContext; @@ -133,6 +129,10 @@ struct wmWindowManager; /* Include external gizmo API's */ #include "gizmo/WM_gizmo_api.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct wmGenericUserData { void *data; /** When NULL, use #MEM_freeN. */ @@ -310,7 +310,7 @@ typedef struct wmNotifier { #define ND_HISTORY (4 << 16) #define ND_JOB (5 << 16) #define ND_UNDO (6 << 16) -#define ND_XR_DATA_CHANGED (7 << 17) +#define ND_XR_DATA_CHANGED (7 << 16) /* NC_SCREEN */ #define ND_LAYOUTBROWSE (1 << 16) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 302de6609d0..63ad2e446ea 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -625,8 +625,7 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo) bScreen *screen = WM_window_get_active_screen(win); /* Draw screen areas into own frame buffer. */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { CTX_wm_area_set(C, area); /* Compute UI layouts for dynamically size regions. */ @@ -741,8 +740,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) #endif /* Blit non-overlapping area regions. */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->visible && region->overlap == false) { /* Blit from offscreen buffer. */ @@ -753,8 +751,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) /* Draw paint cursors. */ if (wm->paintcursors.first) { - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->visible && region == screen->active_region) { CTX_wm_area_set(C, area); @@ -773,8 +770,7 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view) } /* Blend in overlapping area regions */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { if (region->visible && region->overlap) { wm_draw_region_blend(region, 0, true); @@ -914,8 +910,7 @@ static bool wm_draw_update_test_window(Main *bmain, bContext *C, wmWindow *win) } } - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { for (region = area->regionbase.first; region; region = region->next) { wm_region_test_gizmo_do_draw(C, area, region, true); wm_region_test_render_do_draw(scene, depsgraph, area, region); @@ -962,8 +957,7 @@ static void wm_draw_update_clear_window(bContext *C, wmWindow *win) { bScreen *screen = WM_window_get_active_screen(win); - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { LISTBASE_FOREACH (ARegion *, region, &area->regionbase) { wm_region_test_gizmo_do_draw(C, area, region, false); } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e1a723f9f75..2123a424be8 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -524,8 +524,7 @@ void wm_event_do_notifiers(bContext *C) ED_region_do_listen(win, NULL, region, note, scene); } - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { ED_area_do_listen(win, area, note, scene); for (region = area->regionbase.first; region; region = region->next) { ED_region_do_listen(win, area, region, note, scene); @@ -1655,8 +1654,7 @@ static void wm_handler_op_context(bContext *C, wmEventHandler_Op *handler, const else { ScrArea *area = NULL; - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { if (area_iter == handler->context.area) { area = area_iter; break; @@ -2989,8 +2987,7 @@ static ScrArea *area_event_inside(bContext *C, const int xy[2]) bScreen *screen = CTX_wm_screen(C); if (screen) { - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { if (BLI_rcti_isect_pt_v(&area->totrct, xy)) { return area; } @@ -3189,9 +3186,9 @@ void wm_event_do_handlers(bContext *C) } if (is_playing_sound == 0) { - const float time = BKE_sound_sync_scene(scene_eval); + const double time = BKE_sound_sync_scene(scene_eval); if (isfinite(time)) { - int ncfra = time * (float)FPS + 0.5f; + int ncfra = time * FPS + 0.5; if (ncfra != scene->r.cfra) { scene->r.cfra = ncfra; ED_update_for_newframe(CTX_data_main(C), depsgraph); @@ -3287,8 +3284,7 @@ void wm_event_do_handlers(bContext *C) } #endif - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { /* after restoring a screen from SCREENMAXIMIZED we have to wait * with the screen handling till the region coordinates are updated */ if (screen->skip_handling == true) { @@ -3460,8 +3456,7 @@ void WM_event_add_fileselect(bContext *C, wmOperator *op) bool cancel_handler = true; /* find the area with the file selector for this handler */ - ED_screen_areas_iter(win, screen, area) - { + ED_screen_areas_iter (win, screen, area) { if (area->spacetype == SPACE_FILE) { SpaceFile *sfile = area->spacedata.first; @@ -4963,8 +4958,7 @@ void WM_window_cursor_keymap_status_refresh(bContext *C, wmWindow *win) } ScrArea *area = NULL; - ED_screen_areas_iter(win, screen, area_iter) - { + ED_screen_areas_iter (win, screen, area_iter) { if (BLI_findindex(&area_iter->regionbase, region) != -1) { area = area_iter; break; diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 71ae44297e7..9aa401722b7 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -320,24 +320,24 @@ static void draw_filled_lasso_px_cb(int x, int x_end, int y, void *user_data) static void draw_filled_lasso(wmGesture *gt) { const short *lasso = (short *)gt->customdata; - const int tot = gt->points; - int(*moves)[2] = MEM_mallocN(sizeof(*moves) * (tot + 1), __func__); + const int mcoords_len = gt->points; + int(*mcoords)[2] = MEM_mallocN(sizeof(*mcoords) * (mcoords_len + 1), __func__); int i; rcti rect; float red[4] = {1.0f, 0.0f, 0.0f, 0.0f}; - for (i = 0; i < tot; i++, lasso += 2) { - moves[i][0] = lasso[0]; - moves[i][1] = lasso[1]; + for (i = 0; i < mcoords_len; i++, lasso += 2) { + mcoords[i][0] = lasso[0]; + mcoords[i][1] = lasso[1]; } - BLI_lasso_boundbox(&rect, (const int(*)[2])moves, tot); + BLI_lasso_boundbox(&rect, (const int(*)[2])mcoords, mcoords_len); BLI_rcti_translate(&rect, gt->winrct.xmin, gt->winrct.ymin); BLI_rcti_isect(>->winrct, &rect, &rect); BLI_rcti_translate(&rect, -gt->winrct.xmin, -gt->winrct.ymin); - /* highly unlikely this will fail, but could crash if (tot == 0) */ + /* Highly unlikely this will fail, but could crash if (mcoords_len == 0). */ if (BLI_rcti_is_empty(&rect) == false) { const int w = BLI_rcti_size_x(&rect); const int h = BLI_rcti_size_y(&rect); @@ -348,8 +348,8 @@ static void draw_filled_lasso(wmGesture *gt) rect.ymin, rect.xmax, rect.ymax, - (const int(*)[2])moves, - tot, + (const int(*)[2])mcoords, + mcoords_len, draw_filled_lasso_px_cb, &lasso_fill_data); @@ -390,7 +390,7 @@ static void draw_filled_lasso(wmGesture *gt) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - MEM_freeN(moves); + MEM_freeN(mcoords); } static void wm_gesture_draw_lasso(wmGesture *gt, bool filled) diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 11beb7d2fd5..9fb368a02b4 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -718,10 +718,10 @@ void WM_gesture_lines_cancel(bContext *C, wmOperator *op) */ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), wmOperator *op, - int *mcords_tot))[2] + int *r_mcoords_len))[2] { PropertyRNA *prop = RNA_struct_find_property(op->ptr, "path"); - int(*mcords)[2] = NULL; + int(*mcoords)[2] = NULL; BLI_assert(prop != NULL); if (prop) { @@ -729,26 +729,26 @@ const int (*WM_gesture_lasso_path_to_array(bContext *UNUSED(C), if (len) { int i = 0; - mcords = MEM_mallocN(sizeof(int) * 2 * len, __func__); + mcoords = MEM_mallocN(sizeof(int[2]) * len, __func__); RNA_PROP_BEGIN (op->ptr, itemptr, prop) { float loc[2]; RNA_float_get_array(&itemptr, "loc", loc); - mcords[i][0] = (int)loc[0]; - mcords[i][1] = (int)loc[1]; + mcoords[i][0] = (int)loc[0]; + mcoords[i][1] = (int)loc[1]; i++; } RNA_PROP_END; } - *mcords_tot = len; + *r_mcoords_len = len; } else { - *mcords_tot = 0; + *r_mcoords_len = 0; } /* cast for 'const' */ - return (const int(*)[2])mcords; + return mcoords; } #if 0 diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 17d697840a0..a93d4c7bf37 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -44,6 +44,7 @@ #include "BLI_listbase.h" #include "BLI_path_util.h" #include "BLI_string.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLI_timer.h" #include "BLI_utildefines.h" @@ -198,7 +199,7 @@ void WM_init_opengl(Main *bmain) opengl_is_init = true; } -static void sound_jack_sync_callback(Main *bmain, int mode, float time) +static void sound_jack_sync_callback(Main *bmain, int mode, double time) { /* Ugly: Blender doesn't like it when the animation is played back during rendering. */ if (G.is_rendering) { @@ -648,6 +649,7 @@ void WM_exit_ex(bContext *C, const bool do_python) DNA_sdna_current_free(); BLI_threadapi_exit(); + BLI_task_scheduler_exit(); /* No need to call this early, rather do it late so that other * pieces of Blender using sound may exit cleanly, see also T50676. */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index a7578291a21..39811d67b9a 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -1349,17 +1349,8 @@ static uiBlock *wm_block_create_redo(bContext *C, ARegion *region, void *arg_op) } uiLayout *col = uiLayoutColumn(layout, false); - - if (op->type->flag & OPTYPE_MACRO) { - for (op = op->macro.first; op; op = op->next) { - uiTemplateOperatorPropertyButs( - C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } - } - else { - uiTemplateOperatorPropertyButs( - C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); - } + uiTemplateOperatorPropertyButs( + C, col, op, UI_BUT_LABEL_ALIGN_NONE, UI_TEMPLATE_OP_PROPS_SHOW_TITLE); UI_block_bounds_set_popup(block, 6 * U.dpi_fac, NULL); @@ -1794,13 +1785,12 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve } } - PropertyRNA *prop = op->type->prop; int search_type; - if (RNA_property_is_set(op->ptr, prop)) { - search_type = RNA_property_enum_get(op->ptr, prop); + if (STREQ(op->type->idname, "WM_OT_search_menu")) { + search_type = SEARCH_TYPE_MENU; } else { - search_type = U.experimental.use_menu_search ? SEARCH_TYPE_MENU : SEARCH_TYPE_OPERATOR; + search_type = SEARCH_TYPE_OPERATOR; } static struct SearchPopupInit_Data data; @@ -1809,7 +1799,7 @@ static int wm_search_menu_invoke(bContext *C, wmOperator *op, const wmEvent *eve .size = {UI_searchbox_size_x() * 2, UI_searchbox_size_y()}, }; - UI_popup_block_invoke(C, wm_block_search_menu, &data, NULL); + UI_popup_block_invoke_ex(C, wm_block_search_menu, &data, NULL, false); return OPERATOR_INTERFACE; } @@ -1818,20 +1808,22 @@ static void WM_OT_search_menu(wmOperatorType *ot) { ot->name = "Search Menu"; ot->idname = "WM_OT_search_menu"; - ot->description = "Pop-up a search menu over all available operators in current context"; + ot->description = "Pop-up a search over all menus in the current context"; ot->invoke = wm_search_menu_invoke; ot->exec = wm_search_menu_exec; ot->poll = WM_operator_winactive; +} - static const EnumPropertyItem search_type_items[] = { - {SEARCH_TYPE_OPERATOR, "OPERATOR", 0, "Operator", "Search all operators"}, - {SEARCH_TYPE_MENU, "MENU", 0, "Menu", "Search active menu items"}, - {0, NULL, 0, NULL, NULL}, - }; +static void WM_OT_search_operator(wmOperatorType *ot) +{ + ot->name = "Search Operator"; + ot->idname = "WM_OT_search_operator"; + ot->description = "Pop-up a search over all available operators in current context"; - /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", search_type_items, SEARCH_TYPE_OPERATOR, "Type", ""); + ot->invoke = wm_search_menu_invoke; + ot->exec = wm_search_menu_exec; + ot->poll = WM_operator_winactive; } static int wm_call_menu_exec(bContext *C, wmOperator *op) @@ -3805,7 +3797,9 @@ void wm_operatortypes_register(void) WM_operatortype_append(WM_OT_debug_menu); WM_operatortype_append(WM_OT_operator_defaults); WM_operatortype_append(WM_OT_splash); + WM_operatortype_append(WM_OT_splash_about); WM_operatortype_append(WM_OT_search_menu); + WM_operatortype_append(WM_OT_search_operator); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_call_menu_pie); WM_operatortype_append(WM_OT_call_panel); diff --git a/source/blender/windowmanager/intern/wm_playanim.c b/source/blender/windowmanager/intern/wm_playanim.c index 84f099b0dbc..948e8d9fb74 100644 --- a/source/blender/windowmanager/intern/wm_playanim.c +++ b/source/blender/windowmanager/intern/wm_playanim.c @@ -317,7 +317,13 @@ static void playanim_toscreen( GPU_blend(true); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - imm_draw_box_checker_2d(offs_x, offs_y, offs_x + span_x, offs_y + span_y); + imm_draw_box_checker_2d_ex(offs_x, + offs_y, + offs_x + span_x, + offs_y + span_y, + (const float[4]){0.15, 0.15, 0.15, 1.0}, + (const float[4]){0.20, 0.20, 0.20, 1.0}, + 8); } IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_COLOR); diff --git a/source/blender/windowmanager/intern/wm_splash_screen.c b/source/blender/windowmanager/intern/wm_splash_screen.c index f209a2f31a3..8445fac0498 100644 --- a/source/blender/windowmanager/intern/wm_splash_screen.c +++ b/source/blender/windowmanager/intern/wm_splash_screen.c @@ -48,6 +48,8 @@ #include "BKE_context.h" #include "BKE_screen.h" +#include "BLT_translation.h" + #include "BLF_api.h" #include "IMB_imbuf.h" @@ -56,6 +58,7 @@ #include "ED_screen.h" #include "UI_interface.h" +#include "UI_interface_icons.h" #include "UI_resources.h" #include "WM_api.h" @@ -63,21 +66,19 @@ #include "wm.h" -static void wm_block_splash_close(bContext *C, void *arg_block, void *UNUSED(arg)) +static void wm_block_close(bContext *C, void *arg_block, void *UNUSED(arg)) { wmWindow *win = CTX_wm_window(C); UI_popup_block_close(C, win, arg_block); } -static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *arg_unused); - static void wm_block_splash_refreshmenu(bContext *C, void *UNUSED(arg_block), void *UNUSED(arg)) { ARegion *region_menu = CTX_wm_menu(C); ED_region_tag_refresh_ui(region_menu); } -static void wm_block_splash_add_label(uiBlock *block, const char *label, int x, int *y) +static void wm_block_splash_add_label(uiBlock *block, const char *label, int x, int y) { if (!(label && label[0])) { return; @@ -86,21 +87,19 @@ static void wm_block_splash_add_label(uiBlock *block, const char *label, int x, UI_block_emboss_set(block, UI_EMBOSS_NONE); uiBut *but = uiDefBut( - block, UI_BTYPE_LABEL, 0, label, 0, *y, x, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); + block, UI_BTYPE_LABEL, 0, label, 0, y, x, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); UI_but_drawflag_disable(but, UI_BUT_TEXT_LEFT); UI_but_drawflag_enable(but, UI_BUT_TEXT_RIGHT); /* 1 = UI_SELECT, internal flag to draw in white. */ UI_but_flag_enable(but, 1); UI_block_emboss_set(block, UI_EMBOSS); - *y -= 12 * U.dpi_fac; } -static void wm_block_splash_add_labels(uiBlock *block, int x, int y) +static void get_version_string(char *ver, const int max_length) { /* Version number. */ const char *version_cycle = NULL; - bool show_build_info = true; if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) { version_cycle = " Alpha"; @@ -110,11 +109,9 @@ static void wm_block_splash_add_labels(uiBlock *block, int x, int y) } else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) { version_cycle = " Release Candidate"; - show_build_info = false; } else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) { version_cycle = STRINGIFY(BLENDER_VERSION_CHAR); - show_build_info = false; } const char *version_cycle_number = ""; @@ -122,46 +119,14 @@ static void wm_block_splash_add_labels(uiBlock *block, int x, int y) version_cycle_number = " " STRINGIFY(BLENDER_VERSION_CYCLE_NUMBER); } - char version_buf[256] = "\0"; - BLI_snprintf(version_buf, - sizeof(version_buf), - "v %d.%d%s%s", + BLI_snprintf(ver, + max_length, + "%d.%d.%d%s%s", BLENDER_VERSION / 100, BLENDER_VERSION % 100, + BLENDER_SUBVERSION, version_cycle, version_cycle_number); - - wm_block_splash_add_label(block, version_buf, x, &y); - -#ifdef WITH_BUILDINFO - if (show_build_info) { - extern unsigned long build_commit_timestamp; - extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[]; - - /* Date, hidden for builds made from tag. */ - if (build_commit_timestamp != 0) { - char date_buf[256] = "\0"; - BLI_snprintf( - date_buf, sizeof(date_buf), "Date: %s %s", build_commit_date, build_commit_time); - wm_block_splash_add_label(block, date_buf, x, &y); - } - - /* Hash. */ - char hash_buf[256] = "\0"; - BLI_snprintf(hash_buf, sizeof(hash_buf), "Hash: %s", build_hash); - wm_block_splash_add_label(block, hash_buf, x, &y); - - /* Branch. */ - if (!STREQ(build_branch, "master")) { - char branch_buf[256] = "\0"; - BLI_snprintf(branch_buf, sizeof(branch_buf), "Branch: %s", build_branch); - - wm_block_splash_add_label(block, branch_buf, x, &y); - } - } -#else - UNUSED_VARS(show_build_info); -#endif /* WITH_BUILDINFO */ } static void wm_block_splash_image_roundcorners_add(ImBuf *ibuf) @@ -281,10 +246,12 @@ static uiBlock *wm_block_create_splash(bContext *C, ARegion *region, void *UNUSE but = uiDefButImage(block, ibuf, 0, 0.5f * U.widget_unit, splash_width, splash_height, NULL); - UI_but_func_set(but, wm_block_splash_close, block, NULL); + UI_but_func_set(but, wm_block_close, block, NULL); UI_block_func_set(block, wm_block_splash_refreshmenu, block, NULL); - wm_block_splash_add_labels(block, splash_width, splash_height - 13 * U.dpi_fac); + char version_buf[256] = "\0"; + get_version_string(version_buf, sizeof(version_buf)); + wm_block_splash_add_label(block, version_buf, splash_width, splash_height - 13.0 * U.dpi_fac); const int layout_margin_x = U.dpi_fac * 26; uiLayout *layout = UI_block_layout(block, @@ -323,3 +290,93 @@ void WM_OT_splash(wmOperatorType *ot) ot->invoke = wm_splash_invoke; ot->poll = WM_operator_winactive; } + +static uiBlock *wm_block_create_about(bContext *C, ARegion *region, void *UNUSED(arg)) +{ + uiBlock *block; + const uiStyle *style = UI_style_get_dpi(); + const int dialog_width = U.widget_unit * 24; + const short logo_size = 128 * U.dpi_fac; + + /* Calculate icon column factor. */ + const float split_factor = (float)logo_size / (float)(dialog_width - style->columnspace); + + block = UI_block_begin(C, region, "about", UI_EMBOSS); + + UI_block_flag_enable( + block, UI_BLOCK_KEEP_OPEN | UI_BLOCK_LOOP | UI_BLOCK_NO_WIN_CLIP | UI_BLOCK_NUMSELECT); + UI_block_theme_style_set(block, UI_BLOCK_THEME_STYLE_POPUP); + UI_block_emboss_set(block, UI_EMBOSS); + + uiLayout *block_layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, dialog_width, 0, 0, style); + + /* Split layout to put Blender logo on left side. */ + uiLayout *split_block = uiLayoutSplit(block_layout, split_factor, false); + + /* Blender Logo. */ + uiLayout *layout = uiLayoutColumn(split_block, false); + uiDefButAlert(block, ALERT_ICON_BLENDER, 0, 0, 0, logo_size); + + /* The rest of the content on the right. */ + layout = uiLayoutColumn(split_block, false); + + uiLayoutSetScaleY(layout, 0.7f); + + uiItemS_ex(layout, 1.0f); + + /* Title. */ + uiItemL_ex(layout, "Blender", ICON_NONE, true, false); + + /* Version. */ + char str_buf[256] = "\0"; + get_version_string(str_buf, sizeof(str_buf)); + uiItemL(layout, str_buf, ICON_NONE); + + uiItemS_ex(layout, 3.0f); + +#ifdef WITH_BUILDINFO + + extern char build_hash[], build_commit_date[], build_commit_time[], build_branch[]; + + BLI_snprintf(str_buf, sizeof(str_buf), "Date: %s %s", build_commit_date, build_commit_time); + uiItemL(layout, str_buf, ICON_NONE); + + BLI_snprintf(str_buf, sizeof(str_buf), "Hash: %s", build_hash); + uiItemL(layout, str_buf, ICON_NONE); + + BLI_snprintf(str_buf, sizeof(str_buf), "Branch: %s", build_branch); + uiItemL(layout, str_buf, ICON_NONE); + +#endif /* WITH_BUILDINFO */ + + uiItemS_ex(layout, 1.5f); + + MenuType *mt = WM_menutype_find("WM_MT_splash_about", true); + if (mt) { + UI_menutype_draw(C, mt, layout); + } + + uiItemS_ex(layout, 2.0f); + + UI_block_bounds_set_centered(block, 14 * U.dpi_fac); + + return block; +} + +static int wm_about_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event)) +{ + UI_popup_block_invoke(C, wm_block_create_about, NULL, NULL); + + return OPERATOR_FINISHED; +} + +void WM_OT_splash_about(wmOperatorType *ot) +{ + ot->name = "About Blender"; + ot->idname = "WM_OT_splash_about"; + ot->description = "Open a window with information about Blender"; + + ot->invoke = wm_about_invoke; + ot->poll = WM_operator_winactive; +} diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 8fb7e47cd45..b1eee7509b7 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -769,19 +769,6 @@ void wm_window_ghostwindows_ensure(wmWindowManager *wm) * in practice the window manager will likely move to the correct monitor */ wm_init_state.start_x = 0; wm_init_state.start_y = 0; - -#ifdef WITH_X11 /* X11 */ - /* X11, don't start maximized because we can't figure out the dimensions - * of a single display yet if there are multiple, due to lack of Xinerama - * handling in GHOST. */ - wm_init_state.size_x = min_ii(wm_init_state.size_x, WM_WIN_INIT_SIZE_X); - wm_init_state.size_y = min_ii(wm_init_state.size_y, WM_WIN_INIT_SIZE_Y); - /* pad */ - wm_init_state.start_x = WM_WIN_INIT_PAD; - wm_init_state.start_y = WM_WIN_INIT_PAD; - wm_init_state.size_x -= WM_WIN_INIT_PAD * 2; - wm_init_state.size_y -= WM_WIN_INIT_PAD * 2; -#endif } LISTBASE_FOREACH (wmWindow *, win, &wm->windows) { diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h index e5df4a44bd4..16aa5cb44db 100644 --- a/source/blender/windowmanager/wm.h +++ b/source/blender/windowmanager/wm.h @@ -80,6 +80,7 @@ void wm_autosave_location(char *filepath); /* wm_splash_screen.c */ void WM_OT_splash(wmOperatorType *ot); +void WM_OT_splash_about(wmOperatorType *ot); /* wm_stereo.c */ void wm_stereo3d_draw_sidebyside(wmWindow *win, int view); @@ -96,4 +97,4 @@ void wm_stereo3d_set_cancel(bContext *C, wmOperator *op); void wm_open_init_load_ui(wmOperator *op, bool use_prefs); void wm_open_init_use_scripts(wmOperator *op, bool use_prefs); -#endif
\ No newline at end of file +#endif diff --git a/source/blender/windowmanager/wm_window.h b/source/blender/windowmanager/wm_window.h index ce9d79b8e59..45cfe1431d7 100644 --- a/source/blender/windowmanager/wm_window.h +++ b/source/blender/windowmanager/wm_window.h @@ -82,11 +82,4 @@ int wm_window_new_main_exec(bContext *C, struct wmOperator *op); void wm_test_autorun_warning(bContext *C); -/* Initial (unmaximized) size to start with for - * systems that can't find it for themselves (X11). - * Clamped by real desktop limits */ -#define WM_WIN_INIT_SIZE_X 1800 -#define WM_WIN_INIT_SIZE_Y 1000 -#define WM_WIN_INIT_PAD 40 - #endif /* __WM_WINDOW_H__ */ diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h index b53ae45a29f..9b7e9a15948 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h +++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h @@ -34,11 +34,16 @@ typedef struct wmXrSessionState { float viewer_viewmat[4][4]; float focal_len; + /** Copy of XrSessionSettings.base_pose_ data to detect changes that need + * resetting to base pose. */ + char prev_base_pose_type; /* eXRSessionBasePoseType */ + Object *prev_base_pose_object; /** Copy of XrSessionSettings.flag created on the last draw call, stored to detect changes. */ int prev_settings_flag; /** Copy of wmXrDrawData.eye_position_ofs. */ float prev_eye_position_ofs[3]; + bool force_reset_to_base_pose; bool is_view_data_set; } wmXrSessionState; diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c index dc228d1b18b..e9ff38c5a92 100644 --- a/source/blender/windowmanager/xr/intern/wm_xr_session.c +++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c @@ -95,6 +95,11 @@ bool WM_xr_session_exists(const wmXrData *xr) return xr->runtime && xr->runtime->context && xr->runtime->session_state.is_started; } +void WM_xr_session_base_pose_reset(wmXrData *xr) +{ + xr->runtime->session_state.force_reset_to_base_pose = true; +} + /** * Check if the session is running, according to the OpenXR definition. */ @@ -154,6 +159,17 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data, wm_xr_session_base_pose_calc(r_draw_data->scene, settings, &r_draw_data->base_pose); } +static bool wm_xr_session_draw_data_needs_reset_to_base_pose(const wmXrSessionState *state, + const XrSessionSettings *settings) +{ + if (state->force_reset_to_base_pose) { + return true; + } + return ((settings->flag & XR_SESSION_USE_POSITION_TRACKING) == 0) && + ((state->prev_base_pose_type != settings->base_pose_type) || + (state->prev_base_pose_object != settings->base_pose_object)); +} + void wm_xr_session_draw_data_update(const wmXrSessionState *state, const XrSessionSettings *settings, const GHOST_XrDrawViewInfo *draw_view, @@ -166,7 +182,8 @@ void wm_xr_session_draw_data_update(const wmXrSessionState *state, /* Set the eye position offset, it's used to offset the base pose when changing positional * tracking. */ - if (!state->is_view_data_set) { + if (!state->is_view_data_set || + wm_xr_session_draw_data_needs_reset_to_base_pose(state, settings)) { /* Always use the exact base pose with no offset when starting the session. */ copy_v3_fl(draw_data->eye_position_ofs, 0.0f); } @@ -223,6 +240,8 @@ void wm_xr_session_state_update(const XrSessionSettings *settings, copy_v3_v3(state->prev_eye_position_ofs, draw_data->eye_position_ofs); state->prev_settings_flag = settings->flag; + state->prev_base_pose_type = settings->base_pose_type; + state->prev_base_pose_object = settings->base_pose_object; state->is_view_data_set = true; } diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 4b51f9738b3..b3e83b1412f 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -687,6 +687,17 @@ elseif(WIN32) ) endif() + if(WITH_WINDOWS_PDB) + if(WITH_WINDOWS_STRIPPED_PDB) + # Icky hack for older cmake from https://stackoverflow.com/a/21198501 + # $<CONFIG> will work in newer cmake but the version currently (3.12) + # on the buildbot does not support this endavour. + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}/blender_public.pdb DESTINATION . RENAME blender.pdb) + else() + install(FILES $<TARGET_PDB_FILE:blender> DESTINATION . RENAME blender.pdb) + endif() + endif() + if(WITH_PYTHON) string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) @@ -803,7 +814,20 @@ elseif(WIN32) DESTINATION "." ) endif() - + if(WITH_TBB) + install( + FILES + ${LIBDIR}/tbb/lib/tbb.dll + DESTINATION "." + CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel + ) + install( + FILES + ${LIBDIR}/tbb/lib/debug/tbb_debug.dll + DESTINATION "." + CONFIGURATIONS Debug + ) + endif() if(WITH_TBB_MALLOC_PROXY) install( FILES @@ -1085,6 +1109,20 @@ endif() # the use of vcpkg if(WIN32) set_target_properties(blender PROPERTIES VS_GLOBAL_VcpkgEnabled "false") + set_target_properties(blender PROPERTIES + PDB_NAME "blender_private" + PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>") + if (WITH_WINDOWS_PDB AND WITH_WINDOWS_STRIPPED_PDB) + # This is slightly messy, but single target generators like ninja will not have the + # CMAKE_CFG_INTDIR variable and multitarget generators like msbuild will not have + # CMAKE_BUILD_TYPE. This can be simplified by target_link_options and the $<CONFIG> + # generator expression in newer cmake (2.13+) but until that time this fill have suffice. + if(CMAKE_BUILD_TYPE) + set_property(TARGET blender APPEND PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/blender_public.pdb") + else() + set_property(TARGET blender APPEND PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/blender_public.pdb") + endif() + endif() endif() # ----------------------------------------------------------------------------- diff --git a/source/creator/creator.c b/source/creator/creator.c index 6c4af7be95e..ea64184c826 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -43,6 +43,7 @@ #include "BLI_args.h" #include "BLI_string.h" #include "BLI_system.h" +#include "BLI_task.h" #include "BLI_threads.h" #include "BLI_utildefines.h" @@ -401,6 +402,9 @@ int main(int argc, G.factory_startup = true; #endif + /* After parsing number of threads argument. */ + BLI_task_scheduler_init(); + #ifdef WITH_FFMPEG IMB_ffmpeg_init(); #endif diff --git a/source/creator/creator_signals.c b/source/creator/creator_signals.c index 7f7a03f0465..dbf947a86fd 100644 --- a/source/creator/creator_signals.c +++ b/source/creator/creator_signals.c @@ -190,97 +190,25 @@ static void sig_handle_crash(int signum) } # ifdef WIN32 -LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) +extern LONG WINAPI windows_exception_handler(EXCEPTION_POINTERS *ExceptionInfo) { - switch (ExceptionInfo->ExceptionRecord->ExceptionCode) { - case EXCEPTION_ACCESS_VIOLATION: - fputs("Error : EXCEPTION_ACCESS_VIOLATION\n", stderr); - break; - case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: - fputs("Error : EXCEPTION_ARRAY_BOUNDS_EXCEEDED\n", stderr); - break; - case EXCEPTION_BREAKPOINT: - fputs("Error : EXCEPTION_BREAKPOINT\n", stderr); - break; - case EXCEPTION_DATATYPE_MISALIGNMENT: - fputs("Error : EXCEPTION_DATATYPE_MISALIGNMENT\n", stderr); - break; - case EXCEPTION_FLT_DENORMAL_OPERAND: - fputs("Error : EXCEPTION_FLT_DENORMAL_OPERAND\n", stderr); - break; - case EXCEPTION_FLT_DIVIDE_BY_ZERO: - fputs("Error : EXCEPTION_FLT_DIVIDE_BY_ZERO\n", stderr); - break; - case EXCEPTION_FLT_INEXACT_RESULT: - fputs("Error : EXCEPTION_FLT_INEXACT_RESULT\n", stderr); - break; - case EXCEPTION_FLT_INVALID_OPERATION: - fputs("Error : EXCEPTION_FLT_INVALID_OPERATION\n", stderr); - break; - case EXCEPTION_FLT_OVERFLOW: - fputs("Error : EXCEPTION_FLT_OVERFLOW\n", stderr); - break; - case EXCEPTION_FLT_STACK_CHECK: - fputs("Error : EXCEPTION_FLT_STACK_CHECK\n", stderr); - break; - case EXCEPTION_FLT_UNDERFLOW: - fputs("Error : EXCEPTION_FLT_UNDERFLOW\n", stderr); - break; - case EXCEPTION_ILLEGAL_INSTRUCTION: - fputs("Error : EXCEPTION_ILLEGAL_INSTRUCTION\n", stderr); - break; - case EXCEPTION_IN_PAGE_ERROR: - fputs("Error : EXCEPTION_IN_PAGE_ERROR\n", stderr); - break; - case EXCEPTION_INT_DIVIDE_BY_ZERO: - fputs("Error : EXCEPTION_INT_DIVIDE_BY_ZERO\n", stderr); - break; - case EXCEPTION_INT_OVERFLOW: - fputs("Error : EXCEPTION_INT_OVERFLOW\n", stderr); - break; - case EXCEPTION_INVALID_DISPOSITION: - fputs("Error : EXCEPTION_INVALID_DISPOSITION\n", stderr); - break; - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - fputs("Error : EXCEPTION_NONCONTINUABLE_EXCEPTION\n", stderr); - break; - case EXCEPTION_PRIV_INSTRUCTION: - fputs("Error : EXCEPTION_PRIV_INSTRUCTION\n", stderr); - break; - case EXCEPTION_SINGLE_STEP: - fputs("Error : EXCEPTION_SINGLE_STEP\n", stderr); - break; - case EXCEPTION_STACK_OVERFLOW: - fputs("Error : EXCEPTION_STACK_OVERFLOW\n", stderr); - break; - default: - fputs("Error : Unrecognized Exception\n", stderr); - break; - } - - fflush(stderr); - - /* If this is a stack overflow then we can't walk the stack, so just show + /* If this is a stack overflow then we can't walk the stack, so just try to show * where the error happened */ - if (EXCEPTION_STACK_OVERFLOW != ExceptionInfo->ExceptionRecord->ExceptionCode) { + if (ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_STACK_OVERFLOW) { HMODULE mod; CHAR modulename[MAX_PATH]; LPVOID address = ExceptionInfo->ExceptionRecord->ExceptionAddress; - + fprintf(stderr, "Error : EXCEPTION_STACK_OVERFLOW\n"); fprintf(stderr, "Address : 0x%p\n", address); if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, address, &mod)) { if (GetModuleFileName(mod, modulename, MAX_PATH)) { fprintf(stderr, "Module : %s\n", modulename); } } - - fflush(stderr); - -# ifdef NDEBUG - TerminateProcess(GetCurrentProcess(), SIGSEGV); -# else + } + else { + BLI_windows_handle_exception(ExceptionInfo); sig_handle_crash(SIGSEGV); -# endif } return EXCEPTION_EXECUTE_HANDLER; diff --git a/source/tools b/source/tools -Subproject 35dd27ded664b1068e773c27988ee221f3ce39d +Subproject 8a36c2833db48ed78c436ee19534ce5cf3b2eee |